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 @@
11 #build directories
22 build/
33
4+#ide
5+.atom*
46
57 # Prerequisites
68 *.d
Minclude/cutils/byte_array.h
@@ -54,4 +54,3 @@ size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)
5454 #define bytearray_push(bytearray, item) bytearray_insert(bytearray, ((Bytearray*)bytearray)->length, item)
5555
5656 #endif /* CUTILS_BYTE_ARRAY_H */
57-
Minclude/cutils/linked-list.h
@@ -12,7 +12,19 @@ typedef struct SLnode
1212
1313 typedef struct DLnode
1414 {
15- struct SLnode sl;
15+ #if __STDC_VERSION__ >= 201112L
16+ union
17+ {
18+ #endif
19+ struct SLnode sl;
20+ #if __STDC_VERSION__ >= 201112L
21+ struct
22+ {
23+ void* item;
24+ void* next;
25+ };
26+ };
27+ #endif
1628 struct DLnode* prev;
1729 } DLnode;
1830
Minclude/cutils/math.h
@@ -13,4 +13,3 @@ Bytearray* primesieve(uintmax_t limit);
1313
1414
1515 #endif /* CUTILS_MATH_H */
16-
Minclude/cutils/misc.h
@@ -18,6 +18,7 @@
1818 #include <stdlib.h>
1919 #include <cutils/common.h>
2020 #include <ctype.h>
21+#include <stdarg.h>
2122
2223 typedef unsigned char byte;
2324
@@ -26,21 +27,104 @@ typedef unsigned char uchar;
2627 typedef unsigned short ushort;
2728 typedef unsigned int uint;
2829 typedef unsigned long ulong;
30+#ifdef ULLONG_MAX
2931 typedef unsigned long long ullong;
32+#endif /* ULLONG_MAX */
3033 #endif /* CUTILS_NO_SHORTHANDLES */
3134
32-#ifndef CUTILS_NO_MACROS
33-#define MAX(x,y) ((x) > (y) ? (x) : (y))
34-#define MIN(x,y) ((x) < (y) ? (x) : (y))
35-#define LOOP while(1)
36-#define RANGE(i, start, end) \
35+#define CUTIL_MAX(x,y) ((x) > (y) ? (x) : (y))
36+#define CUTIL_MIN(x,y) ((x) < (y) ? (x) : (y))
37+#define CUTIL_LOOP while(1)
38+#define CUTIL_RANGE(i, start, end) \
3739 for(((i) = (start)); ((start) < (end)) ? ((i) < (end)) : ((i) > (end)); ((start) < (end)) ? (i++) : (i--))
40+#define CUTIL_NEW(type) (malloc(sizeof(type)))
41+#define CUTIL_NEW_N(type, n) (malloc(n * sizeof(type)))
42+
43+#ifndef CUTILS_NO_MACROS
44+#define MAX(x,y) CUTIL_MAX(x,y)
45+#define MIN(x,y) CUTIL_MIN(x,y)
46+#define LOOP CUTIL_LOOP
47+#define RANGE(i, start, end) CUTIL_RANGE(i, start, end)
48+#define NEW(type) CUTIL_NEW(type)
49+#define NEW_N(type, n) CUTIL_NEW_N(type, n)
3850 #endif /* CUTILS_NO_MACROS */
3951
52+#ifdef DEBUG
53+ #define DEBUG_ASSERT(x) assert(x)
54+#else
55+ #define DEBUG_ASSERT(x)
56+#endif /* DEBUG */
57+
4058
4159 #if __STDC_VERSION__ >= 199901L
60+ #ifdef UINT64_MAX
61+
62+ enum endianess {CUTIL_ENDIAN_ERROR = 0, CUTIL_BIG_ENDIAN = 1, CUTIL_LITTLE_ENDIAN = 2, CUTIL_MID_BIG_ENDIAN = 3, CUTIL_MID_LITTLE_ENDIAN = 4};
63+ static const char** endianess_strings = (const char *[]){"ENDIAN_ERROR","BIG_ENDIAN","LITTLE_ENDIAN","MID_BIG_ENDIAN","MID_LITTLE_ENDIAN"};
64+ HEDLEY_INLINE
65+ static enum endianess check_endianess(void)
66+ {
67+ union
68+ {
69+ uint32_t t1;
70+ uint8_t t2[4];
71+ } test;
72+ test.t1 = 255;
73+
74+ if(test.t2[0] == 255)
75+ {
76+ return CUTIL_LITTLE_ENDIAN;
77+ } else if(test.t2[1] == 255) {
78+ return CUTIL_MID_LITTLE_ENDIAN;
79+ } else if(test.t2[2] == 255) {
80+ return CUTIL_MID_BIG_ENDIAN;
81+ } else if(test.t2[3] == 255) {
82+ return CUTIL_BIG_ENDIAN;
83+ } else {
84+ return CUTIL_ENDIAN_ERROR;
85+ }
86+ }
87+
88+ HEDLEY_INLINE
89+ static uint64_t nethost64(uint64_t const from)
90+ {
91+ uint8_t data[4];
92+ memcpy(&data, &from, sizeof(data));
93+
94+ return ((uint64_t) data[7] << 0)
95+ | ((uint64_t) data[6] << 8)
96+ | ((uint64_t) data[5] << 16)
97+ | ((uint64_t) data[4] << 24)
98+ | ((uint64_t) data[3] << 32)
99+ | ((uint64_t) data[2] << 40)
100+ | ((uint64_t) data[1] << 48)
101+ | ((uint64_t) data[0] << 54);
102+ }
103+ #endif
42104 #ifdef UINT32_MAX
43- uint32_t nethost32(uint32_t const net);
105+ HEDLEY_INLINE
106+ static uint32_t nethost32(uint32_t const from)
107+ {
108+ uint8_t data[4];
109+ memcpy(&data, &from, sizeof(data));
110+
111+ return ((uint32_t) data[3] << 0)
112+ | ((uint32_t) data[2] << 8)
113+ | ((uint32_t) data[1] << 16)
114+ | ((uint32_t) data[0] << 24);
115+ }
116+ #endif
117+ #ifdef UINT16_MAX
118+ HEDLEY_INLINE
119+ static uint16_t nethost16(uint16_t const from)
120+ {
121+ uint8_t data[2];
122+ memcpy(&data, &from, sizeof(data));
123+
124+ return (uint16_t)(
125+ ((uint16_t) data[1] << 0)
126+ | ((uint16_t) data[0] << 8));
127+ }
44128 #endif
45129 HEDLEY_INLINE
46130 static void memqswap_stack(void* item1, void* item2, size_t length)
@@ -87,7 +171,11 @@ void sleep_ms(unsigned int milliseconds);
87171 /* subtracts ts2 from ts1, if ts2 > ts1 then zero is returned */
88172 struct timespec timespec_diff(const struct timespec* ts1, const struct timespec* ts2);
89173 struct timespec timespec_add(const struct timespec* ts_1, const struct timespec* ts_2);
90- uintmax_t timespec_ms(const struct timespec* ts);
174+ HEDLEY_INLINE
175+ static uintmax_t timespec_ms(const struct timespec* ts)
176+ {
177+ return (uintmax_t)ts->tv_sec * 1000 + (uintmax_t)ts->tv_nsec/1000000;
178+ }
91179 #endif
92180
93181 #endif /* CUTILS_MISC_H */
Msrc/dyn_string.c
@@ -98,7 +98,7 @@ bool string_find_char(const String* haystack, char needle, size_t* pos)
9898
9999 int string_cmp(const String* s1, const String* s2)
100100 {
101- int ret = memcmp(s1->chars, s2->chars, s1->length < s2->length ? s1->length : s2->length);
101+ int ret = memcmp(s1->chars, s2->chars, CUTIL_MIN(s1->length, s2->length));
102102 if(ret == 0 && s1->length != s2->length)
103103 return s1->length < s2->length ? -1 : 1;
104104 else
Msrc/extensions.c
@@ -56,9 +56,11 @@ char* cutil_strndup(const char* s, size_t n)
5656 char* ret;
5757 size_t len = cutil_strnlen(s, n);
5858
59- len = MIN(len, n);
59+ len = CUTIL_MIN(len, n);
6060
6161 ret = malloc(len+1);
62+ if(!ret)
63+ return NULL;
6264 memcpy(ret, s, len+1);
6365
6466 return ret;
@@ -70,8 +72,10 @@ bool cutil_memmem(const void* haystack, size_t haystacklen, const void* needle,
7072 const byte* haystackb = haystack;
7173 const byte* needleb = needle;
7274
75+ if(needlelen == 0)
76+ return true;
7377
74- if(HEDLEY_UNLIKELY(haystacklen == 0 || needlelen == 0 || haystacklen < needlelen))
78+ if(HEDLEY_UNLIKELY((haystacklen == 0 && needlelen != 0 )|| haystacklen < needlelen))
7579 return false;
7680 //TODO: use memchr as base search
7781 for(i = 0; i < haystacklen; i++)
Msrc/linked-list.c
@@ -79,20 +79,33 @@ bool sll_insert(LinkedList* ll, size_t index, void* item)
7979 current = current->next;
8080 }
8181
82- if(current)
82+
83+ if(index == 0) /*first item*/
8384 {
85+ ll->head = newnode;
86+ if(ll->length == 0) /* only item*/
87+ {
88+ ll->tail = newnode;
89+ if(ll->circularly_linked)
90+ newnode->next = newnode;
91+ else
92+ newnode->next = NULL;
93+ } else { /*at least one other item after this*/
94+ newnode->next = current;
95+ if(ll->circularly_linked)
96+ ((SLnode*)ll->tail)->next = ll->head;
97+ }
98+ } else if(index < ll->length) { /*middle*/
99+ prev->next = newnode;
84100 newnode->next = current;
85- if(index == 0)
86- ll->head = newnode;
87- else
88- prev->next = newnode;
89- } else {
101+ } else { /*end*/
90102 ll->tail = newnode;
91- newnode->next = NULL;
92- if(index == 0)
93- ll->head = newnode;
94- if(prev)
95- prev->next = newnode;
103+ prev->next = newnode;
104+
105+ if(ll->circularly_linked)
106+ newnode->next = ll->head;
107+ else
108+ newnode->next = NULL;
96109 }
97110
98111 ll->length++;
@@ -117,40 +130,54 @@ bool dll_insert(LinkedList* ll, size_t index, void* item)
117130 current = current->sl.next;
118131 }
119132
120- if(current)
133+ if(index == 0) /*first item*/
121134 {
122- newnode->sl.next = current;
123- if(index == 0)
135+ ll->head = newnode;
136+ if(ll->length == 0) /* only item*/
124137 {
125- ll->head = newnode;
126- newnode->prev = NULL;
127- } else {
128- prev->sl.next = newnode;
129- newnode->prev = prev;
138+ ll->tail = newnode;
139+ if(ll->circularly_linked)
140+ {
141+ newnode->prev = newnode;
142+ newnode->sl.next = newnode;
143+ } else {
144+ newnode->prev = NULL;
145+ newnode->sl.next = NULL;
146+ }
147+ } else { /* at least one other item after this*/
148+ newnode->sl.next = current;
149+ current->prev = newnode;
150+ if(ll->circularly_linked)
151+ {
152+ ((DLnode*)ll->tail)->sl.next = ll->head;
153+ newnode->prev = ll->tail;
154+ } else {
155+ newnode->prev = NULL;
156+ }
130157 }
158+ } else if(index < ll->length) { /*middle*/
159+ prev->sl.next = newnode;
160+ newnode->prev = prev;
161+ newnode->sl.next = current;
131162 current->prev = newnode;
132- } else {
163+ } else { /*end*/
133164 ll->tail = newnode;
134- newnode->sl.next = NULL;
135- if(index == 0)
136- {
137- ll->head = newnode;
138- newnode->prev = NULL;
139- }
140- if(prev)
165+ prev->sl.next = newnode;
166+ newnode->prev = prev;
167+
168+ if(ll->circularly_linked)
141169 {
142- prev->sl.next = newnode;
143- newnode->prev = prev;
170+ newnode->sl.next = ll->head;
171+ ((DLnode*)ll->head)->prev = newnode;
172+ } else {
173+ newnode->sl.next = NULL;
144174 }
145-
146175 }
147176
148177 ll->length++;
149178 return true;
150179 }
151180
152-
153-
154181 void sll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
155182 {
156183 size_t i;
@@ -168,13 +195,20 @@ void sll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
168195 if(rmv)
169196 rmv(current->item);
170197
171- if(!current->next)
172- ll->tail = prev;
173-
174- if(prev)
198+ if(index == 0) /*beginning*/
199+ {
200+ if(ll->length == 1) /*only item*/
201+ {
202+ ll->head = ll->tail = NULL;
203+ } else {
204+ ll->head = current->next;
205+ if(ll->circularly_linked && ll->tail) ((SLnode*)ll->tail)->next = ll->head;
206+ }
207+ } else { /*middle or ned*/
175208 prev->next = current->next;
176- else
177- ll->head = current->next;
209+ if(index == ll->length-1) /*at end*/
210+ ll->tail = prev;
211+ }
178212
179213 free(current);
180214 ll->length--;
@@ -197,15 +231,30 @@ void dll_remove(LinkedList* ll, size_t index, void (*rmv)(void*))
197231 if(rmv)
198232 rmv(current->sl.item);
199233
200- if(current->sl.next)
201- ((DLnode*)(current->sl.next))->prev = prev;
202- else
203- ll->tail = prev;
204-
205- if(prev)
234+ if(index == 0) /* beginning*/
235+ {
236+ if(ll->length == 1) /*only item*/
237+ {
238+ ll->head = ll->tail = NULL;
239+ } else {
240+ ll->head = current->sl.next;
241+ if(ll->circularly_linked && ll->tail)
242+ {
243+ ((DLnode*)(current->sl.next))->prev = ll->tail;
244+ ((DLnode*)ll->tail)->sl.next = ll->head;
245+ } else {
246+ ((DLnode*)(current->sl.next))->prev = NULL;
247+ }
248+ }
249+ } else { /*middle or end*/
206250 prev->sl.next = current->sl.next;
207- else
208- ll->head = current->sl.next;
251+ if(index == ll->length-1) /*at end*/
252+ {
253+ ll->tail = prev;
254+ if(ll->circularly_linked)
255+ ((DLnode*)(ll->head))->prev = ll->tail;
256+ }
257+ }
209258
210259 free(current);
211260 ll->length--;
@@ -235,13 +284,34 @@ void sll_remove_range(LinkedList* ll, size_t index, size_t length, void (*rmv)(v
235284 current = tmp;
236285 }
237286
238- if(!current)
239- ll->tail = prev;
240-
241- if(prev)
242- prev->next = current;
243- else
287+ if(index == 0) /* beginning */
244288 ll->head = current;
289+
290+ if(index+length == ll->length) /* removed last item */
291+ {
292+ if(index == 0)
293+ {
294+ ll->head = NULL;
295+ ll->tail = NULL;
296+ } else {
297+ ll->tail = prev;
298+ if(ll->circularly_linked)
299+ {
300+ prev->next = ll->head;
301+ } else {
302+ prev->next = NULL;
303+ }
304+ }
305+ } else {
306+ if(index == 0)
307+ {
308+ ll->head = current;
309+ if(ll->circularly_linked) ((SLnode*)(ll->tail))->next = ll->head;
310+ } else {
311+ prev->next = current;
312+ }
313+ }
314+
245315 ll->length -= length;
246316 }
247317
@@ -267,17 +337,46 @@ void dll_remove_range(LinkedList* ll, size_t index, size_t length, void (*rmv)(v
267337 free(current);
268338 current = tmp;
269339 }
270- if(current)
271- current->prev = prev;
272- else
273- ll->tail = prev;
274340
275- if(prev)
341+ if(index == 0) /* beginning */
276342 {
277- prev->sl.next = current;
278- } else {
279343 ll->head = current;
344+ current->prev = ll->circularly_linked ? ll->tail : NULL;
345+ }
346+
347+ if(index+length == ll->length) /* removed last item */
348+ {
349+ if(index == 0)
350+ {
351+ ll->head = NULL;
352+ ll->tail = NULL;
353+ } else {
354+ ll->tail = prev;
355+ if(ll->circularly_linked)
356+ {
357+ prev->sl.next = ll->head;
358+ ((DLnode*)(ll->head))->prev = ll->tail;
359+ } else {
360+ prev->sl.next = NULL;
361+ }
362+ }
363+ } else {
364+ if(index == 0)
365+ {
366+ ll->head = current;
367+ if(ll->circularly_linked)
368+ {
369+ ((SLnode*)(ll->tail))->next = ll->head;
370+ current->prev = ll->tail;
371+ } else {
372+ current->prev = NULL;
373+ }
374+ } else {
375+ prev->sl.next = current;
376+ current->prev = prev;
377+ }
280378 }
379+
281380 ll->length -= length;
282381 }
283382
Msrc/misc.c
@@ -2,7 +2,7 @@
22
33 void sleep_ms(unsigned int milliseconds)
44 {
5- #ifdef __unix__
5+ #ifdef __unix__
66 usleep(milliseconds * 1000);
77 #endif
88 #ifdef _WIN32
@@ -10,21 +10,6 @@ void sleep_ms(unsigned int milliseconds)
1010 #endif
1111 }
1212
13-#if __STDC_VERSION__ >= 199901L
14-#ifdef UINT32_MAX
15-uint32_t nethost32(uint32_t const net)
16-{
17- uint8_t data[4];
18- memcpy(&data, &net, sizeof(data));
19-
20- return ((uint32_t) data[3] << 0)
21- | ((uint32_t) data[2] << 8)
22- | ((uint32_t) data[1] << 16)
23- | ((uint32_t) data[0] << 24);
24-}
25-#endif
26-#endif
27-
2813 #if __STDC_VERSION__ >= 201112L
2914
3015 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*
10792 return res;
10893 }
10994
110-
111-uintmax_t timespec_ms(const struct timespec* ts)
112-{
113- return (uintmax_t)ts->tv_sec * 1000 + (uintmax_t)ts->tv_nsec/1000000;
114-}
11595 #endif
Msrc/test.c
@@ -367,7 +367,7 @@ int main(int argc, char** argv)
367367 test_bitfuncs();
368368
369369 /* misc tests */
370- sleep_ms(1000);
370+ sleep_ms(250);
371371 assert(cutil_strcasecmp("ASD", "aSd") == 0);
372372 assert(cutil_strcasecmp("BSD", "asd") > 0);
373373 assert(cutil_strcasecmp("ASD", "bsd") < 0);
@@ -381,6 +381,7 @@ int main(int argc, char** argv)
381381 assert(*(uintmax_t*)bytearray_at(bt, 312312) == 4444697);
382382
383383 delete_bytearray(bt, NULL);
384+ puts(endianess_strings[check_endianess()]);
384385
385386 return 0;
386387 }