implemented doubly linked list
This commit is contained in:
parent
3a7f09bb49
commit
f2ce18b16d
@ -4,8 +4,6 @@
|
||||
#include "Array.h"
|
||||
#include "List.h"
|
||||
|
||||
typedef void (*FreeFunction)(void*);
|
||||
|
||||
typedef struct HashMapKeyHash {
|
||||
str key;
|
||||
u32 hash;
|
||||
@ -20,14 +18,14 @@ typedef struct HashMapBucket {
|
||||
|
||||
typedef struct HashMap_ {
|
||||
NULLABLE(HashMapBucket*) table;
|
||||
NULLABLE(FreeFunction) value_destructor;
|
||||
NULLABLE(Destructor_t) value_destructor;
|
||||
u32 value_t_size;
|
||||
u32 height;
|
||||
u16 height_n;
|
||||
} HashMap_;
|
||||
|
||||
#define HashMap_construct(SELF, T, VALUE_DESTRUCTOR) HashMap_construct_size(SELF, sizeof(T), VALUE_DESTRUCTOR)
|
||||
void HashMap_construct_size(HashMap_* self, u32 value_t_size, FreeFunction NULLABLE(value_destructor));
|
||||
void HashMap_construct_size(HashMap_* self, u32 value_t_size, Destructor_t NULLABLE(value_destructor));
|
||||
void HashMap_destroy(HashMap_* self);
|
||||
|
||||
bool HashMap_tryPush(HashMap_* self, const str key, void* value_ptr);
|
||||
@ -36,7 +34,7 @@ NULLABLE(void*) HashMap_tryGetPtr(const HashMap_* self, const str key);
|
||||
bool HashMap_tryDelete(HashMap_* self, const str key);
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct HashMapIter {
|
||||
const HashMap_* map;
|
||||
i32 bucket_n;
|
||||
i32 elem_n;
|
||||
|
||||
91
include/tlibc/collections/LList.h
Normal file
91
include/tlibc/collections/LList.h
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
#include "../std.h"
|
||||
|
||||
/*
|
||||
Doubly linked list
|
||||
*/
|
||||
|
||||
#define LLNode(T) LLNode_##T
|
||||
#define LList(T) LList_##T
|
||||
|
||||
#define LList_declare(T) \
|
||||
typedef struct LLNode(T) LLNode(T);\
|
||||
typedef struct LLNode(T) { \
|
||||
LLNode(T)* prev; \
|
||||
LLNode(T)* next; \
|
||||
T value; \
|
||||
} LLNode(T); \
|
||||
\
|
||||
static inline LLNode(T)* LLNode_##T##_createZero(){ \
|
||||
LLNode(T)* n = (LLNode(T)*)malloc(sizeof(LLNode(T))); \
|
||||
n->prev = NULL; \
|
||||
n->next = NULL; \
|
||||
memset(&n->value, 0, sizeof(T)); \
|
||||
return n; \
|
||||
} \
|
||||
\
|
||||
typedef struct LList(T) { \
|
||||
LLNode(T)* first; \
|
||||
LLNode(T)* last; \
|
||||
u32 count; \
|
||||
NULLABLE(void (*value_destructor)(T*)); \
|
||||
} LList(T); \
|
||||
\
|
||||
/* Peek node from list. Detatched nodes can be inserted in different place. */ \
|
||||
static inline LLNode(T)* LList_##T##_detatch(LList(T)* l, LLNode(T)* n) \
|
||||
{ return _LList_detatch((void*)l, (void*)n); } \
|
||||
\
|
||||
/* @param detatched must have null .next and .prev */ \
|
||||
/* @param target can be null only if it is l->first or l->last */ \
|
||||
static inline void LList_##T##_insertAfter( \
|
||||
LList(T)* l, LLNode(T)* target, LLNode(T)* detatched) \
|
||||
{ _LList_insertAfter((void*)l, (void*)target, (void*)detatched); } \
|
||||
\
|
||||
/* @param detatched must have null .next and .prev */ \
|
||||
/* @param target can be null only if it is l->first or l->last */ \
|
||||
static inline void LList_##T##_insertBefore( \
|
||||
LList(T)* l, LLNode(T)* target, LLNode(T)* detatched) \
|
||||
{ _LList_insertBefore((void*)l, (void*)target, (void*)detatched); } \
|
||||
\
|
||||
static inline void LList_##T##_destroy(LList(T)* l){ \
|
||||
if(!l) \
|
||||
return; \
|
||||
LLNode(T)* n = l->first; \
|
||||
while(n){ \
|
||||
if(l->value_destructor) \
|
||||
l->value_destructor(&n->value); \
|
||||
LLNode(T)* next = n->next; \
|
||||
free(n); \
|
||||
n = next; \
|
||||
} \
|
||||
} \
|
||||
|
||||
#define LList_construct(T, VALUE_DESTRUCTOR) ((LList(T)){ \
|
||||
.first = NULL, .last = NULL, .count = 0, .value_destructor = VALUE_DESTRUCTOR })
|
||||
|
||||
|
||||
|
||||
typedef struct LLNode_ LLNode_;
|
||||
typedef struct LLNode_ {
|
||||
LLNode_* prev;
|
||||
LLNode_* next;
|
||||
/* value of unknown type */
|
||||
} LLNode_;
|
||||
|
||||
typedef struct LList_ {
|
||||
LLNode_* first;
|
||||
LLNode_* last;
|
||||
u32 count;
|
||||
NULLABLE(Destructor_t) value_destructor;
|
||||
} LList_;
|
||||
|
||||
/* Peek node from list. Detatched nodes can be inserted in different place. */
|
||||
LLNode_* _LList_detatch(LList_* l, LLNode_* n);
|
||||
|
||||
/* @param detatched must have null .next and .prev */
|
||||
/* @param target can be null only if it is l->first or l->last */
|
||||
void _LList_insertAfter(LList_* l, NULLABLE(LLNode_*) target, LLNode_* detatched);
|
||||
|
||||
/* @param detatched must have null .next and .prev */
|
||||
/* @param target can be null only if it is l->first or l->last */
|
||||
void _LList_insertBefore(LList_* l, NULLABLE(LLNode_*) target, LLNode_* detatched);
|
||||
@ -20,8 +20,10 @@ static inline List_ List_construct_size(void* data_ptr, u32 occupied_size, u32 a
|
||||
#define List_alloc(T, INITIAL_COUNT) List_alloc_size((INITIAL_COUNT) * sizeof(T))
|
||||
List_ List_alloc_size(u32 initial_size);
|
||||
|
||||
static inline void List_destroy(List_ self){
|
||||
free(self.data);
|
||||
static inline void List_destroy(List_* self){
|
||||
if(!self)
|
||||
return;
|
||||
free(self->data);
|
||||
}
|
||||
|
||||
List_ List_copy(List_ src);
|
||||
|
||||
@ -84,9 +84,11 @@ typedef struct Result_ {
|
||||
#define _rname(N) __r_##N
|
||||
|
||||
#define try(VAR, RESULT_FIELD, RSLT_CALL) _try(VAR, RESULT_FIELD, RSLT_CALL, __LINE__)
|
||||
#define try_void(RSLT_CALL) _try_void(RSLT_CALL, __LINE__)
|
||||
#define try_fatal(VAR, RESULT_FIELD, RSLT_CALL) _try_fatal(VAR, RESULT_FIELD, RSLT_CALL, __LINE__)
|
||||
#define try_void(RSLT_CALL) _try_void(RSLT_CALL, __LINE__)
|
||||
#define try_fatal_void(RSLT_CALL) _try_fatal_void(RSLT_CALL, __LINE__)
|
||||
#define try_stderrcode(RSLT_CALL) _try_stderrcode(RSLT_CALL, __LINE__)
|
||||
#define try_fatal_stderrcode(RSLT_CALL) _try_fatal_stderrcode(RSLT_CALL, __LINE__)
|
||||
|
||||
#define _try(VAR, RESULT_FIELD, RSLT_CALL, N) \
|
||||
Result_ _rname(N) = RSLT_CALL;\
|
||||
@ -120,10 +122,20 @@ typedef struct Result_ {
|
||||
};\
|
||||
} while(0)
|
||||
|
||||
#define try_stderrcode(CALL) do {\
|
||||
int r = CALL;\
|
||||
if(r != 0){\
|
||||
Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror_malloc(r), true);\
|
||||
#define _try_stderrcode(CALL, N) do {\
|
||||
int _rname(N) = CALL;\
|
||||
if(_rname(N) != 0){\
|
||||
Return RESULT_ERROR_CODE(LIBC_ERRNO, _rname(N), strerror_malloc(_rname(N)), true);\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
#define _try_fatal_stderrcode(CALL, N) do {\
|
||||
int _rname(N) = CALL;\
|
||||
if(_rname(N) != 0){\
|
||||
Error_printAndExit(Error_create(\
|
||||
strerror_malloc(_rname(N)), true, ErrorCallPos_here(), \
|
||||
ErrorCodePage_name(LIBC_ERRNO), _rname(N)\
|
||||
));\
|
||||
}\
|
||||
} while(0)
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ typedef u8 bool;
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
typedef void (*Destructor_t)(void* self);
|
||||
|
||||
#define FMT_i8 "%"PRIi8
|
||||
#define FMT_i16 "%"PRIi16
|
||||
|
||||
@ -13,7 +13,7 @@ static const Array(u32) __HashMap_heights = ARRAY(u32, {
|
||||
});
|
||||
|
||||
|
||||
void HashMap_construct_size(HashMap_* self, u32 value_t_size, FreeFunction NULLABLE(value_destructor)){
|
||||
void HashMap_construct_size(HashMap_* self, u32 value_t_size, Destructor_t NULLABLE(value_destructor)){
|
||||
self->value_t_size = value_t_size;
|
||||
self->value_destructor = value_destructor;
|
||||
self->height_n = 0;
|
||||
|
||||
58
src/collections/LList.c
Normal file
58
src/collections/LList.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "tlibc/collections/LList.h"
|
||||
|
||||
LLNode_* _LList_detatch(LList_* l, LLNode_* n){
|
||||
if(n == l->first){
|
||||
l->first = n->next;
|
||||
}
|
||||
else {
|
||||
assert(n->prev != NULL);
|
||||
n->prev->next = n->next;
|
||||
}
|
||||
|
||||
if(n == l->last){
|
||||
l->last = n->prev;
|
||||
}
|
||||
else {
|
||||
assert(n->next != NULL);
|
||||
n->next->prev = n->prev;
|
||||
}
|
||||
|
||||
l->count--;
|
||||
n->prev = NULL;
|
||||
n->next = NULL;
|
||||
return n;
|
||||
}
|
||||
|
||||
void _LList_insertAfter(LList_* l, NULLABLE(LLNode_*) target, LLNode_* detatched)
|
||||
{
|
||||
if(target == NULL){
|
||||
assert(l->first == NULL && l->last == NULL);
|
||||
l->first = detatched;
|
||||
l->last = detatched;
|
||||
return;
|
||||
}
|
||||
|
||||
detatched->prev = target;
|
||||
detatched->next = target->next;
|
||||
target->next = detatched;
|
||||
if(detatched->next){
|
||||
detatched->next->prev = detatched;
|
||||
}
|
||||
}
|
||||
|
||||
void _LList_insertBefore(LList_* l, NULLABLE(LLNode_*) target, LLNode_* detatched)
|
||||
{
|
||||
if(target == NULL){
|
||||
assert(l->first == NULL && l->last == NULL);
|
||||
l->first = detatched;
|
||||
l->last = detatched;
|
||||
return;
|
||||
}
|
||||
|
||||
detatched->prev = target->prev;
|
||||
detatched->next = target;
|
||||
target->prev = detatched;
|
||||
if(detatched->prev){
|
||||
detatched->prev->next = detatched;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user