added anonymous unions&struct access in linked list for c11

added internal, always defined macro definitions
added debug assert
added endianess check
moved nethost conversion and timespec to ms to header (can be completly
optimized away)
added 16 and 64 bit nethost conversions
fixed linked list and added circular linked support
AuthorKonata <konata@posteo.jp>
Date
Commite2601f079dea85e51fe617cf7ac48712da1fb515
Parent8a6a9d2
10 files changed, 278 insertions(+), 94 deletions(-)
▾M.gitignore
@@ -1,6 +1,8 @@
#build directories
build/
#ide
.atom*
# Prerequisites
*.d
▾Minclude/cutils/byte_array.h
@@ -54,4 +54,3 @@ size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)
#define bytearray_push(bytearray, item) bytearray_insert(bytearray, ((Bytearray*)bytearray)->length, item)
#endif /* CUTILS_BYTE_ARRAY_H */
▾Minclude/cutils/linked-list.h
@@ -12,7 +12,19 @@ typedef struct SLnode
typedef struct DLnode
{
struct SLnode sl;
#if __STDC_VERSION__ >= 201112L
union
{
#endif
struct SLnode sl;
#if __STDC_VERSION__ >= 201112L
struct
{
void* item;
void* next;
};
};
#endif
struct DLnode* prev;
} DLnode;
▾Minclude/cutils/math.h
@@ -13,4 +13,3 @@ Bytearray* primesieve(uintmax_t limit);
#endif /* CUTILS_MATH_H */
▾Minclude/cutils/misc.h
@@ -18,6 +18,7 @@
#include <stdlib.h>
#include <cutils/common.h>
#include <ctype.h>
#include <stdarg.h>
typedef unsigned char byte;
@@ -26,21 +27,104 @@ typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#ifdef ULLONG_MAX
typedef unsigned long long ullong;
#endif /* ULLONG_MAX */
#endif /* CUTILS_NO_SHORTHANDLES */
#ifndef CUTILS_NO_MACROS
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define LOOP while(1)
#define RANGE(i, start, end) \
#define CUTIL_MAX(x,y) ((x) > (y) ? (x) : (y))
#define CUTIL_MIN(x,y) ((x) < (y) ? (x) : (y))
#define CUTIL_LOOP while(1)
#define CUTIL_RANGE(i, start, end) \
for(((i) = (start)); ((start) < (end)) ? ((i) < (end)) : ((i) > (end)); ((start) < (end)) ? (i++) : (i--))
#define CUTIL_NEW(type) (malloc(sizeof(type)))
#define CUTIL_NEW_N(type, n) (malloc(n * sizeof(type)))
#ifndef CUTILS_NO_MACROS
#define MAX(x,y) CUTIL_MAX(x,y)
#define MIN(x,y) CUTIL_MIN(x,y)
#define LOOP CUTIL_LOOP
#define RANGE(i, start, end) CUTIL_RANGE(i, start, end)
#define NEW(type) CUTIL_NEW(type)
#define NEW_N(type, n) CUTIL_NEW_N(type, n)
#endif /* CUTILS_NO_MACROS */
#ifdef DEBUG
#define DEBUG_ASSERT(x) assert(x)
#else
#define DEBUG_ASSERT(x)
#endif /* DEBUG */
#if __STDC_VERSION__ >= 199901L
#ifdef UINT64_MAX
enum endianess {CUTIL_ENDIAN_ERROR = 0, CUTIL_BIG_ENDIAN = 1, CUTIL_LITTLE_ENDIAN = 2, CUTIL_MID_BIG_ENDIAN = 3, CUTIL_MID_LITTLE_ENDIAN = 4};
static const char** endianess_strings = (const char *[]){"ENDIAN_ERROR","BIG_ENDIAN","LITTLE_ENDIAN","MID_BIG_ENDIAN","MID_LITTLE_ENDIAN"};
HEDLEY_INLINE
static enum endianess check_endianess(void)
{
union
{
uint32_t t1;
uint8_t t2[4];
} test;
test.t1 = 255;
if(test.t2[0] == 255)
{
return CUTIL_LITTLE_ENDIAN;
} else if(test.t2[1] == 255) {
return CUTIL_MID_LITTLE_ENDIAN;
} else if(test.t2[2] == 255) {
return CUTIL_MID_BIG_ENDIAN;
} else if(test.t2[3] == 255) {
return CUTIL_BIG_ENDIAN;
} else {
return CUTIL_ENDIAN_ERROR;
}
}
HEDLEY_INLINE
static uint64_t nethost64(uint64_t const from)
{
uint8_t data[4];
memcpy(&data, &from, sizeof(data));
return ((uint64_t) data[7] << 0)
| ((uint64_t) data[6] << 8)
| ((uint64_t) data[5] << 16)
| ((uint64_t) data[4] << 24)
| ((uint64_t) data[3] << 32)
| ((uint64_t) data[2] << 40)
| ((uint64_t) data[1] << 48)
| ((uint64_t) data[0] << 54);
}
#endif
#ifdef UINT32_MAX
uint32_t nethost32(uint32_t const net);
HEDLEY_INLINE
static uint32_t nethost32(uint32_t const from)
{
uint8_t data[4];
memcpy(&data, &from, sizeof(data));
return ((uint32_t) data[3] << 0)
| ((uint32_t) data[2] << 8)
| ((uint32_t) data[1] << 16)
| ((uint32_t) data[0] << 24);
}
#endif
#ifdef UINT16_MAX
HEDLEY_INLINE
static uint16_t nethost16(uint16_t const from)
{
uint8_t data[2];
memcpy(&data, &from, sizeof(data));
return (uint16_t)(
((uint16_t) data[1] << 0)
| ((uint16_t) data[0] << 8));
}
#endif
HEDLEY_INLINE
static void memqswap_stack(void* item1, void* item2, size_t length)
@@ -87,7 +171,11 @@ void sleep_ms(unsigned int milliseconds);
/* subtracts ts2 from ts1, if ts2 > ts1 then zero is returned */
struct timespec timespec_diff(const struct timespec* ts1, const struct timespec* ts2);
struct timespec timespec_add(const struct timespec* ts_1, const struct timespec* ts_2);
uintmax_t timespec_ms(const struct timespec* ts);
HEDLEY_INLINE
static uintmax_t timespec_ms(const struct timespec* ts)
{
return (uintmax_t)ts->tv_sec * 1000 + (uintmax_t)ts->tv_nsec/1000000;
}
#endif
#endif /* CUTILS_MISC_H */
▾Msrc/dyn_string.c
@@ -98,7 +98,7 @@ bool string_find_char(const String* haystack, char needle, size_t* pos)
int string_cmp(const String* s1, const String* s2)
{
int ret = memcmp(s1->chars, s2->chars, s1->length < s2->length ? s1->length : s2->length);
int ret = memcmp(s1->chars, s2->chars, CUTIL_MIN(s1->length, s2->length));
if(ret == 0 && s1->length != s2->length)
return s1->length < s2->length ? -1 : 1;
else
▾Msrc/extensions.c
@@ -56,9 +56,11 @@ char* cutil_strndup(const char* s, size_t n)
char* ret;
size_t len = cutil_strnlen(s, n);
len = MIN(len, n);
len = CUTIL_MIN(len, n);
ret = malloc(len+1);
if(!ret)
return NULL;
memcpy(ret, s, len+1);
return ret;
@@ -70,8 +72,10 @@ bool cutil_memmem(const void* haystack, size_t haystacklen, const void* needle,
const byte* haystackb = haystack;
const byte* needleb = needle;
if(needlelen == 0)
return true;
if(HEDLEY_UNLIKELY(haystacklen == 0 || needlelen == 0 || haystacklen < needlelen))
if(HEDLEY_UNLIKELY((haystacklen == 0 && needlelen != 0 )|| haystacklen < needlelen))
return false;
//TODO: use memchr as base search
for(i = 0; i < haystacklen; i++)
▾Msrc/linked-list.c
@@ -79,20 +79,33 @@ bool sll_insert(LinkedList* ll, size_t index, void* item)
current = current->next;
}
if(current)
if(index == 0) /*first item*/
{
ll->head = newnode;
if(ll->length == 0) /* only item*/
{
ll->tail = newnode;
if(ll->circularly_linked)
newnode->next = newnode;
else
newnode->next = NULL;
} else { /*at least one other item after this*/
newnode->next = current;
if(ll->circularly_linked)
((SLnode*)ll->tail)->next = ll->head;
}
} else if(index < ll->length) { /*middle*/
prev->next = newnode;
newnode->next = current;
if(index == 0)
ll->head = newnode;
else
prev->next = newnode;
} else {
} else { /*end*/
ll->tail = newnode;
newnode->next = NULL;
if(index == 0)
ll->head = newnode;
if(prev)
prev->next = newnode;
prev->next = newnode;
if(ll->circularly_linked)
newnode->next = ll->head;
else
newnode->next = NULL;
}
ll->length++;
@@ -117,40 +130,54 @@ bool dll_insert(LinkedList* ll, size_t index, void* item)
current = current->sl.next;
}
if(current)
if(index == 0) /*first item*/
{
newnode->sl.next = current;
if(index == 0)
ll->head = newnode;
if(ll->length == 0) /* only item*/
{
ll->head = newnode;
newnode->prev = NULL;
} else {
prev->sl.next = newnode;
newnode->prev = prev;
ll->tail = newnode;
if(ll->circularly_linked)
{
newnode->prev = newnode;
newnode->sl.next = newnode;
} else {
newnode->prev = NULL;
newnode->sl.next = NULL;
}
} else { /* at least one other item after this*/
newnode->sl.next = current;
current->prev = newnode;
if(ll->circularly_linked)
{
((DLnode*)ll->tail)->sl.next = ll->head;
newnode->prev = ll->tail;
} else {
newnode->prev = NULL;
}
}
} else if(index < ll->length) { /*middle*/
prev->sl.next = newnode;
newnode->prev = prev;
newnode->sl.next = current;
current->prev = newnode;
} else {
} else { /*end*/
ll->tail = newnode;
newnode->sl.next = NULL;
if(index == 0)
{
ll->head = newnode;
newnode->prev = NULL;
}
if(prev)
prev->sl.next = newnode;
newnode->prev = prev;
if(ll->circularly_linked)
{
prev->sl.next = newnode;
newnode->prev = prev;
newnode->sl.next = ll->head;
((DLnode*)ll->head)->prev = newnode;
} else {
newnode->sl.next = NULL;
}
}
ll->length++;
return true;
}
void sll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
{
size_t i;
@@ -168,13 +195,20 @@ void sll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
if(rmv)
rmv(current->item);
if(!current->next)
ll->tail = prev;
if(prev)
if(index == 0) /*beginning*/
{
if(ll->length == 1) /*only item*/
{
ll->head = ll->tail = NULL;
} else {
ll->head = current->next;
if(ll->circularly_linked && ll->tail) ((SLnode*)ll->tail)->next = ll->head;
}
} else { /*middle or ned*/
prev->next = current->next;
else
ll->head = current->next;
if(index == ll->length-1) /*at end*/
ll->tail = prev;
}
free(current);
ll->length--;
@@ -197,15 +231,30 @@ void dll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
if(rmv)
rmv(current->sl.item);
if(current->sl.next)
((DLnode*)(current->sl.next))->prev = prev;
else
ll->tail = prev;
if(prev)
if(index == 0) /* beginning*/
{
if(ll->length == 1) /*only item*/
{
ll->head = ll->tail = NULL;
} else {
ll->head = current->sl.next;
if(ll->circularly_linked && ll->tail)
{
((DLnode*)(current->sl.next))->prev = ll->tail;
((DLnode*)ll->tail)->sl.next = ll->head;
} else {
((DLnode*)(current->sl.next))->prev = NULL;
}
}
} else { /*middle or end*/
prev->sl.next = current->sl.next;
else
ll->head = current->sl.next;
if(index == ll->length-1) /*at end*/
{
ll->tail = prev;
if(ll->circularly_linked)
((DLnode*)(ll->head))->prev = ll->tail;
}
}
free(current);
ll->length--;
@@ -235,13 +284,34 @@ void sll_remove_range(LinkedList* ll, size_t index, size_t length, void (*rmv)(v
current = tmp;
}
if(!current)
ll->tail = prev;
if(prev)
prev->next = current;
else
if(index == 0) /* beginning */
ll->head = current;
if(index+length == ll->length) /* removed last item */
{
if(index == 0)
{
ll->head = NULL;
ll->tail = NULL;
} else {
ll->tail = prev;
if(ll->circularly_linked)
{
prev->next = ll->head;
} else {
prev->next = NULL;
}
}
} else {
if(index == 0)
{
ll->head = current;
if(ll->circularly_linked) ((SLnode*)(ll->tail))->next = ll->head;
} else {
prev->next = current;
}
}
ll->length -= length;
}
@@ -267,17 +337,46 @@ void dll_remove_range(LinkedList* ll, size_t index, size_t length, void (*rmv)(v
free(current);
current = tmp;
}
if(current)
current->prev = prev;
else
ll->tail = prev;
if(prev)
if(index == 0) /* beginning */
{
prev->sl.next = current;
} else {
ll->head = current;
current->prev = ll->circularly_linked ? ll->tail : NULL;
}
if(index+length == ll->length) /* removed last item */
{
if(index == 0)
{
ll->head = NULL;
ll->tail = NULL;
} else {
ll->tail = prev;
if(ll->circularly_linked)
{
prev->sl.next = ll->head;
((DLnode*)(ll->head))->prev = ll->tail;
} else {
prev->sl.next = NULL;
}
}
} else {
if(index == 0)
{
ll->head = current;
if(ll->circularly_linked)
{
((SLnode*)(ll->tail))->next = ll->head;
current->prev = ll->tail;
} else {
current->prev = NULL;
}
} else {
prev->sl.next = current;
current->prev = prev;
}
}
ll->length -= length;
}
▾Msrc/misc.c
@@ -2,7 +2,7 @@
void sleep_ms(unsigned int milliseconds)
{
#ifdef __unix__
#ifdef __unix__
usleep(milliseconds * 1000);
#endif
#ifdef _WIN32
@@ -10,21 +10,6 @@ void sleep_ms(unsigned int milliseconds)
#endif
}
#if __STDC_VERSION__ >= 199901L
#ifdef UINT32_MAX
uint32_t nethost32(uint32_t const net)
{
uint8_t data[4];
memcpy(&data, &net, sizeof(data));
return ((uint32_t) data[3] << 0)
| ((uint32_t) data[2] << 8)
| ((uint32_t) data[1] << 16)
| ((uint32_t) data[0] << 24);
}
#endif
#endif
#if __STDC_VERSION__ >= 201112L
bool timespec_bigger(const struct timespec* ts1, const struct timespec* ts2)
@@ -107,9 +92,4 @@ struct timespec timespec_add(const struct timespec* ts_1, const struct timespec*
return res;
}
uintmax_t timespec_ms(const struct timespec* ts)
{
return (uintmax_t)ts->tv_sec * 1000 + (uintmax_t)ts->tv_nsec/1000000;
}
#endif
▾Msrc/test.c
@@ -367,7 +367,7 @@ int main(int argc, char** argv)
test_bitfuncs();
/* misc tests */
sleep_ms(1000);
sleep_ms(250);
assert(cutil_strcasecmp("ASD", "aSd") == 0);
assert(cutil_strcasecmp("BSD", "asd") > 0);
assert(cutil_strcasecmp("ASD", "bsd") < 0);
@@ -381,6 +381,7 @@ int main(int argc, char** argv)
assert(*(uintmax_t*)bytearray_at(bt, 312312) == 4444697);
delete_bytearray(bt, NULL);
puts(endianess_strings[check_endianess()]);
return 0;
}