implemented doubly linked list
This commit is contained in:
parent
3a7f09bb49
commit
f2ce18b16d
@ -4,8 +4,6 @@
|
|||||||
#include "Array.h"
|
#include "Array.h"
|
||||||
#include "List.h"
|
#include "List.h"
|
||||||
|
|
||||||
typedef void (*FreeFunction)(void*);
|
|
||||||
|
|
||||||
typedef struct HashMapKeyHash {
|
typedef struct HashMapKeyHash {
|
||||||
str key;
|
str key;
|
||||||
u32 hash;
|
u32 hash;
|
||||||
@ -20,14 +18,14 @@ typedef struct HashMapBucket {
|
|||||||
|
|
||||||
typedef struct HashMap_ {
|
typedef struct HashMap_ {
|
||||||
NULLABLE(HashMapBucket*) table;
|
NULLABLE(HashMapBucket*) table;
|
||||||
NULLABLE(FreeFunction) value_destructor;
|
NULLABLE(Destructor_t) value_destructor;
|
||||||
u32 value_t_size;
|
u32 value_t_size;
|
||||||
u32 height;
|
u32 height;
|
||||||
u16 height_n;
|
u16 height_n;
|
||||||
} HashMap_;
|
} HashMap_;
|
||||||
|
|
||||||
#define HashMap_construct(SELF, T, VALUE_DESTRUCTOR) HashMap_construct_size(SELF, sizeof(T), VALUE_DESTRUCTOR)
|
#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);
|
void HashMap_destroy(HashMap_* self);
|
||||||
|
|
||||||
bool HashMap_tryPush(HashMap_* self, const str key, void* value_ptr);
|
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);
|
bool HashMap_tryDelete(HashMap_* self, const str key);
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct HashMapIter {
|
||||||
const HashMap_* map;
|
const HashMap_* map;
|
||||||
i32 bucket_n;
|
i32 bucket_n;
|
||||||
i32 elem_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))
|
#define List_alloc(T, INITIAL_COUNT) List_alloc_size((INITIAL_COUNT) * sizeof(T))
|
||||||
List_ List_alloc_size(u32 initial_size);
|
List_ List_alloc_size(u32 initial_size);
|
||||||
|
|
||||||
static inline void List_destroy(List_ self){
|
static inline void List_destroy(List_* self){
|
||||||
free(self.data);
|
if(!self)
|
||||||
|
return;
|
||||||
|
free(self->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
List_ List_copy(List_ src);
|
List_ List_copy(List_ src);
|
||||||
|
|||||||
@ -84,9 +84,11 @@ typedef struct Result_ {
|
|||||||
#define _rname(N) __r_##N
|
#define _rname(N) __r_##N
|
||||||
|
|
||||||
#define try(VAR, RESULT_FIELD, RSLT_CALL) _try(VAR, RESULT_FIELD, RSLT_CALL, __LINE__)
|
#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_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_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) \
|
#define _try(VAR, RESULT_FIELD, RSLT_CALL, N) \
|
||||||
Result_ _rname(N) = RSLT_CALL;\
|
Result_ _rname(N) = RSLT_CALL;\
|
||||||
@ -120,10 +122,20 @@ typedef struct Result_ {
|
|||||||
};\
|
};\
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
#define try_stderrcode(CALL) do {\
|
#define _try_stderrcode(CALL, N) do {\
|
||||||
int r = CALL;\
|
int _rname(N) = CALL;\
|
||||||
if(r != 0){\
|
if(_rname(N) != 0){\
|
||||||
Return RESULT_ERROR_CODE(LIBC_ERRNO, r, strerror_malloc(r), true);\
|
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)
|
} while(0)
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ typedef u8 bool;
|
|||||||
#define false 0
|
#define false 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef void (*Destructor_t)(void* self);
|
||||||
|
|
||||||
#define FMT_i8 "%"PRIi8
|
#define FMT_i8 "%"PRIi8
|
||||||
#define FMT_i16 "%"PRIi16
|
#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_t_size = value_t_size;
|
||||||
self->value_destructor = value_destructor;
|
self->value_destructor = value_destructor;
|
||||||
self->height_n = 0;
|
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