remove cmp checks, added bytearray, added tests for bytearray

AuthorKonata <konata@posteo.jp>
Date
Commit9a24c67450aac327d8eb0368001de882dd581227
Parent06304b4
9 files changed, 361 insertions(+), 46 deletions(-)
Ainclude/cutils/byte_array.h
@@ -0,0 +1,46 @@
1+#ifndef BYTE_ARRAY_H
2+#define BYTE_ARRAY_H
3+#include <stdlib.h>
4+#include <string.h>
5+#include <errno.h>
6+
7+#define BYTEARRAY_DEFAULT_SIZE 4
8+
9+#define BT_FIXED 1
10+#define BT_FREE_EL 2
11+#define BT_FREE_ARRAY 4
12+#define BT_FREE_STRUCT 8
13+
14+typedef enum {b_false, b_true} bool_t;
15+
16+typedef struct Bytearray
17+{
18+ char* items;
19+ size_t capacity;
20+ size_t length;
21+ size_t element_size;
22+ short flags;
23+} Bytearray;
24+
25+#define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size)
26+#define bytearray_with_capacity(capacity, element_size) new_bytearray_ext(capacity, element_size, NULL, NULL, BT_FREE_ARRAY | BT_FREE_STRUCT)
27+Bytearray* new_bytearray_ext(size_t capacity, size_t element_size, char* array_storage, Bytearray* struct_storage, short flags);
28+void delete_bytearray(Bytearray* bytearray);
29+void delete_bytearray_ext(Bytearray* bytearray, void(*rmv_el) (void*), void(*rmv_items) (void*), void(*rmv_struct) (void*));
30+
31+void* bytearray_at(const Bytearray* bytearray, size_t index);
32+#define bytearray_pop(bytearray) bytearray_pop_at(bytearray, bytearray->length-1)
33+void* bytearray_pop_at(Bytearray* bytearray, size_t index);
34+
35+#define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item)
36+bool_t bytearray_insert(Bytearray* bytearray, size_t index, const void* item);
37+
38+void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*));
39+
40+bool_t bytearray_adjust_size(Bytearray* bytearray, size_t size);
41+bool_t bytearray_shrink(Bytearray* bytearray);
42+size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*));
43+
44+
45+#endif /* BYTE_ARRAY_H */
46+
Minclude/cutils/cutils.h
@@ -4,5 +4,7 @@
44 #include <cutils/vector.h>
55 #include <cutils/dyn_string.h>
66 #include <cutils/misc.h>
7+#include <cutils/byte_array.h>
8+
79
810 #endif /* CUTILS_H */
Minclude/cutils/dyn_string.h
@@ -14,16 +14,16 @@ typedef struct String
1414 size_t length;
1515 } String;
1616
17-#define new_string() string_with_capacity(STRING_DEFAULT_SIZE);
17+#define new_string() string_with_capacity(STRING_DEFAULT_SIZE)
1818 String* string_with_capacity(size_t capacity);
1919 void delete_string(String* string);
2020
2121 char string_at(const String* string, size_t index);
22-#define string_pop(string) string_pop_at(string, string->length-1);
22+#define string_pop(string) string_pop_at(string, string->length-1)
2323 char string_pop_at(String* string, size_t index);
2424
2525 bool string_insert(String* string, size_t index, char character);
26-#define string_push(string, character) string_insert(string, string->length, character);
26+#define string_push(string, character) string_insert(string, string->length, character)
2727
2828 void string_remove(String* string, size_t index);
2929
Minclude/cutils/vector.h
@@ -14,16 +14,16 @@ typedef struct Vector
1414 size_t length;
1515 } Vector;
1616
17-#define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE);
17+#define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE)
1818 Vector* vector_with_capacity(size_t capacity);
1919 void delete_vector(Vector* vector, void(*rmv) (void*));
2020
2121 void* vector_at(const Vector* vector, size_t index);
22-#define vector_pop(vector) vector_pop_at(vector, vector->length-1);
22+#define vector_pop(vector) vector_pop_at(vector, vector->length-1)
2323 void* vector_pop_at(Vector* vector, size_t index);
2424
2525 bool vector_insert(Vector* vector, size_t index, void* item);
26-#define vector_push(vector, item) vector_insert(vector, vector->length, item);
26+#define vector_push(vector, item) vector_insert(vector, vector->length, item)
2727
2828 void vector_remove(Vector* vector, size_t index, void (*rmv)(void*));
2929
Asrc/byte_array.c
@@ -0,0 +1,181 @@
1+#include <cutils/byte_array.h>
2+
3+Bytearray* new_bytearray_ext(size_t capacity, size_t element_size, char* array_storage, Bytearray* struct_storage, short flags)
4+{
5+ Bytearray* bytearray;
6+
7+ if(struct_storage)
8+ {
9+ bytearray = struct_storage;
10+ } else {
11+ bytearray = malloc(sizeof(*bytearray));
12+ if(!bytearray)
13+ return NULL;
14+ }
15+
16+ if(array_storage)
17+ {
18+ bytearray->items = array_storage;
19+ } else {
20+ bytearray->items = malloc(sizeof(*bytearray->items)*capacity*element_size);
21+ if(!bytearray->items)
22+ {
23+ free(bytearray);
24+ return NULL;
25+ }
26+ }
27+ bytearray->length = 0;
28+ bytearray->capacity = capacity;
29+ bytearray->element_size = element_size;
30+ bytearray->flags = flags;
31+
32+ return bytearray;
33+}
34+
35+void delete_bytearray(Bytearray* bytearray)
36+{
37+ delete_bytearray_ext(bytearray,
38+ (bytearray->flags & BT_FREE_EL) ? free : NULL,
39+ (bytearray->flags & BT_FREE_ARRAY) ? free : NULL,
40+ (bytearray->flags & BT_FREE_STRUCT) ? free : NULL);
41+}
42+
43+
44+void delete_bytearray_ext(Bytearray* bytearray, void(*rmv_el) (void*), void(*rmv_items) (void*), void(*rmv_struct) (void*))
45+{
46+ if(rmv_el)
47+ {
48+ size_t i;
49+ for(i = 0; i < bytearray->length; i++)
50+ {
51+ rmv_el(&bytearray->items[i*bytearray->element_size]);
52+ }
53+ }
54+ if(rmv_items)
55+ rmv_items(bytearray->items);
56+ if(rmv_struct)
57+ rmv_struct(bytearray);
58+}
59+
60+void* bytearray_at(const Bytearray* bytearray, size_t index)
61+{
62+ if(index >= bytearray->length)
63+ return NULL;
64+ else
65+ return bytearray->items+(index*bytearray->element_size);
66+}
67+
68+void* bytearray_pop_at(Bytearray* bytearray, size_t index)
69+{
70+ void *tmp, *ret;
71+
72+ tmp = bytearray_at(bytearray, index);
73+ if(!tmp)
74+ {
75+ errno = 0;
76+ return NULL;
77+ }
78+
79+ ret = malloc(bytearray->element_size);
80+ if(!ret)
81+ {
82+ errno = ENOMEM;
83+ return NULL;
84+ }
85+
86+ memcpy(ret, tmp, bytearray->element_size);
87+ bytearray_remove(bytearray, index, NULL);
88+ return ret;
89+}
90+
91+bool_t bytearray_insert(Bytearray* bytearray, size_t index, const void* item)
92+{
93+ size_t length = bytearray->length;
94+ size_t size = bytearray->element_size;
95+
96+ if(index > length || !bytearray_adjust_size(bytearray, length+1))
97+ return b_false;
98+
99+ memmove(bytearray->items+index*size+1*size, bytearray->items+index*size, (length*size-index*size)*sizeof(*bytearray->items));
100+ memcpy(bytearray->items+index*size, item, bytearray->element_size);
101+ ++bytearray->length;
102+ return b_true;
103+}
104+
105+void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*))
106+{
107+ if(index < bytearray->length)
108+ {
109+ size_t length = bytearray->length;
110+ size_t elsize = bytearray->element_size;
111+ if(rmv)
112+ rmv(&bytearray->items[index*elsize]);
113+
114+ memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, (length*elsize-index*elsize-1*elsize)*sizeof(*bytearray->items));
115+ --bytearray->length;
116+ }
117+}
118+
119+bool_t bytearray_adjust_size(Bytearray* bytearray, size_t size)
120+{
121+ if(bytearray->flags & BT_FIXED)
122+ {
123+ if(bytearray->capacity < size)
124+ return b_false;
125+ else
126+ return b_true;
127+ }
128+
129+ while(bytearray->capacity < size)
130+ {
131+ size_t capacity = bytearray->capacity;
132+ size_t elsize = bytearray->element_size;
133+ char* tmp = bytearray->items;
134+ bytearray->items = realloc(bytearray->items, capacity*elsize*2*sizeof(*bytearray->items));
135+ if(!bytearray->items)
136+ {
137+ bytearray->items = tmp;
138+ return b_false;
139+ }
140+ bytearray->capacity *= 2;
141+ }
142+ return b_true;
143+}
144+
145+bool_t bytearray_shrink(Bytearray* bytearray)
146+{
147+ if(bytearray->flags & BT_FIXED)
148+ return b_false;
149+
150+ while(bytearray->capacity > bytearray->length*2)
151+ {
152+ size_t capacity = bytearray->capacity;
153+ size_t size = bytearray->element_size;
154+ char* tmp = bytearray->items;
155+ bytearray->items = realloc(bytearray->items, (capacity*size)/(2*sizeof(*bytearray->items)));
156+ if(!bytearray->items)
157+ {
158+ bytearray->items = tmp;
159+ return b_false;
160+ }
161+ bytearray->capacity /= 2;
162+ }
163+ return b_true;
164+}
165+
166+size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*))
167+{
168+ size_t* ret;
169+ size_t i;
170+
171+ for(i = 0; i < haystack->length; i++)
172+ {
173+ if(cmp(haystack->items+(i*haystack->element_size),needle) == 0)
174+ {
175+ ret = malloc(sizeof(*ret));
176+ *ret = i;
177+ return ret;
178+ }
179+ }
180+ return NULL;
181+}
Msrc/dyn_string.c
@@ -22,7 +22,7 @@ void string_remove(String* string, size_t index)
2222 if(index < string->length)
2323 {
2424 memmove(string->chars+index, string->chars+index+1, (string->length-index-1)*sizeof(*string->chars));
25- string->length--;
25+ --string->length;
2626 }
2727 }
2828
Msrc/meson.build
@@ -1,4 +1,4 @@
1-src = ['vector.c', 'dyn_string.c', 'misc.c']
1+src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c']
22 srctest = src + ['test.c']
33
44 cutils_lib = library('cutils', src, include_directories : inc, install: true)
@@ -6,4 +6,4 @@ cutils_lib = library('cutils', src, include_directories : inc, install: true)
66 cutils_dep = declare_dependency(link_with : cutils_lib, include_directories : inc)
77
88 e = executable('test_cutils', srctest, include_directories : inc, c_args: CFLAGS )
9-test('test functionality', e)
9+test('test functionality', e)
Msrc/test.c
@@ -18,97 +18,181 @@ static int cmp_str(const void* str1, const void* str2)
1818 static void test1(void)
1919 {
2020 size_t* find;
21- Vector* test;
21+ Vector* vector;
2222 struct test* my_struct;
2323
2424 my_struct = malloc(sizeof(*my_struct));
25- test = new_vector()
25+ vector = new_vector();
2626
2727 my_struct->a = 5;
2828 my_struct->b = 5;
29- vector_push(test, my_struct);
29+ vector_push(vector, my_struct);
3030
3131 my_struct = malloc(sizeof(*my_struct));
3232 my_struct->a = 6;
3333 my_struct->b = 6;
34- vector_push(test, my_struct);
34+ vector_push(vector, my_struct);
3535
3636 my_struct = malloc(sizeof(*my_struct));
3737 my_struct->a = 7;
3838 my_struct->b = 7;
39- vector_push(test, my_struct);
40- assert(test->length == 3);
39+ vector_push(vector, my_struct);
40+ assert(vector->length == 3);
4141
42- vector_remove(test, 0,free);
43- assert(test->length == 2);
42+ vector_remove(vector, 0,free);
43+ assert(vector->length == 2);
4444
4545 my_struct = malloc(sizeof(*my_struct));
4646 my_struct->a = 8;
4747 my_struct->b = 8;
48- vector_insert(test, 2, my_struct);
49- assert(test->length == 3);
48+ vector_insert(vector, 2, my_struct);
49+ assert(vector->length == 3);
5050
5151 my_struct = malloc(sizeof(*my_struct));
5252 my_struct->a = 8;
5353 my_struct->b = 8;
5454
55- find = vector_find(test, my_struct, cmp_str);
55+ find = vector_find(vector, my_struct, cmp_str);
5656
5757 assert(*find == 2);
5858 free(find);
5959
6060 free(my_struct);
61- my_struct = vector_pop(test);
61+ my_struct = vector_pop(vector);
6262 assert(my_struct->a == 8 && my_struct->b == 8);
6363 free(my_struct);
6464
65- delete_vector(test,free);
65+ delete_vector(vector, free);
6666 }
6767
6868 static void test2(void)
6969 {
70- String* test;
71- String* test2;
70+ String* string;
71+ String* string2;
7272 char* cstring;
7373
74- test = new_string();
74+ string = new_string();
7575
76- string_push(test, 'a');
77- string_push(test, 'b');
78- string_push(test, 'c');
79- string_push(test, 'd');
80- assert(test->length == 4);
76+ string_push(string, 'a');
77+ string_push(string, 'b');
78+ string_push(string, 'c');
79+ string_push(string, 'd');
80+ assert(string->length == 4);
8181
82- cstring = to_cstring(test);
82+ cstring = to_cstring(string);
8383 assert(strcmp(cstring, "abcd") == 0);
8484 free(cstring);
8585
86- string_remove(test, 3);
87- cstring = to_cstring(test);
86+ string_remove(string, 3);
87+ cstring = to_cstring(string);
8888 assert(strcmp(cstring, "abc") == 0);
8989 free(cstring);
90- assert(test->length == 3);
90+ assert(string->length == 3);
9191
92- string_insert(test, 0,'a');
93- cstring = to_cstring(test);
92+ string_insert(string, 0,'a');
93+ cstring = to_cstring(string);
9494 assert(strcmp(cstring, "aabc") == 0);
9595 free(cstring);
9696
97- test2 = from_cstring("xyz");
97+ string2 = from_cstring("xyz");
9898
99- string_concat(test,test2);
100- cstring = to_cstring(test);
99+ string_concat(string,string2);
100+ cstring = to_cstring(string);
101101 assert(strcmp(cstring, "aabcxyz") == 0);
102102 free(cstring);
103103
104- delete_string(test2);
105- delete_string(test);
104+ delete_string(string2);
105+ delete_string(string);
106+}
107+
108+static void test3(void)
109+{
110+ Bytearray* bt;
111+ void* localarray;
112+ struct test my_struct;
113+ struct test* my_structptr;
114+ char* tmpchar;
115+
116+ /*test pushing and popping with default constructor and simple values*/
117+ bt = new_bytearray(1);
118+ bytearray_push(bt, "a");
119+ bytearray_push(bt, "b");
120+ bytearray_push(bt, "c");
121+ bytearray_push(bt, "d");
122+ bytearray_push(bt, "\0");
123+
124+ assert(strcmp(bt->items, "abcd") == 0);
125+
126+ tmpchar = bytearray_pop(bt);
127+ assert(*tmpchar == '\0');
128+ free(tmpchar);
129+
130+ tmpchar = bytearray_pop(bt);
131+ assert(*tmpchar == 'd');
132+ free(tmpchar);
133+
134+ tmpchar = bytearray_pop(bt);
135+ assert(*tmpchar == 'c');
136+ free(tmpchar);
137+
138+ tmpchar = bytearray_pop(bt);
139+ assert(*tmpchar == 'b');
140+ free(tmpchar);
141+
142+ tmpchar = bytearray_pop(bt);
143+ assert(*tmpchar == 'a');
144+ free(tmpchar);
145+
146+ tmpchar = bytearray_pop(bt);
147+ assert(tmpchar == NULL);
148+ free(tmpchar);
149+
150+ bytearray_push(bt, "a");
151+ tmpchar = bytearray_pop(bt);
152+ assert(*tmpchar == 'a');
153+ free(tmpchar);
154+
155+ delete_bytearray(bt);
156+
157+ /*test pushing and popping with self allocated array and fixed size*/
158+ localarray = malloc(3*sizeof(struct test));
159+ my_struct.a = 0;
160+ my_struct.b = 0;
161+
162+ bt = new_bytearray_ext(3, sizeof(struct test), localarray, NULL, BT_FREE_ARRAY | BT_FIXED | BT_FREE_STRUCT);
163+ bytearray_push(bt, &my_struct);
164+ my_struct.a = 1;
165+ my_struct.b = 1;
166+ bytearray_push(bt, &my_struct);
167+
168+ my_struct.a = 2;
169+ my_struct.b = 2;
170+ bytearray_push(bt, &my_struct);
171+
172+ my_struct.a = 3;
173+ my_struct.b = 3;
174+ bytearray_push(bt, &my_struct);
175+
176+ my_structptr = bytearray_pop(bt);
177+
178+ my_struct.a = 2;
179+ my_struct.b = 2;
180+ printf("%d\n", my_structptr->a);
181+ assert(my_structptr->a == my_struct.a);
182+ assert(my_structptr->b == my_struct.b);
183+ free(my_structptr);
184+
185+
186+
187+ delete_bytearray(bt);
188+
106189 }
107190
108191 int main(int argc, char** argv)
109192 {
110193 test1();
111194 test2();
195+ test3();
112196 sleep_ms(1000);
113197 return 0;
114198 }
Msrc/vector.c
@@ -45,7 +45,7 @@ void vector_remove(Vector* vector, size_t index, void (*rmv)(void*))
4545 if(rmv)
4646 rmv(vector->items[index]);
4747 memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items));
48- vector->length--;
48+ --vector->length;
4949 }
5050 }
5151
@@ -56,7 +56,7 @@ size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const
5656
5757 for(i = 0; i < haystack->length; i++)
5858 {
59- if(cmp ? cmp(haystack->items[i],needle) == 0 : haystack->items[i] == needle)
59+ if(cmp(haystack->items[i],needle) == 0)
6060 {
6161 ret = malloc(sizeof(*ret));
6262 *ret = i;
@@ -111,11 +111,13 @@ bool vector_shrink(Vector* vector)
111111
112112 void delete_vector(Vector* vector, void (*rmv)(void*))
113113 {
114- size_t i;
115- for(i = 0; i < vector->length; i++)
114+ if(rmv)
116115 {
117- if(rmv)
116+ size_t i;
117+ for(i = 0; i < vector->length; i++)
118+ {
118119 rmv(vector->items[i]);
120+ }
119121 }
120122 free(vector->items);
121123 free(vector);