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 @@
#ifndef BYTE_ARRAY_H
#define BYTE_ARRAY_H
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define BYTEARRAY_DEFAULT_SIZE 4
#define BT_FIXED 1
#define BT_FREE_EL 2
#define BT_FREE_ARRAY 4
#define BT_FREE_STRUCT 8
typedef enum {b_false, b_true} bool_t;
typedef struct Bytearray
{
char* items;
size_t capacity;
size_t length;
size_t element_size;
short flags;
} Bytearray;
#define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size)
#define bytearray_with_capacity(capacity, element_size) new_bytearray_ext(capacity, element_size, NULL, NULL, BT_FREE_ARRAY | BT_FREE_STRUCT)
Bytearray* new_bytearray_ext(size_t capacity, size_t element_size, char* array_storage, Bytearray* struct_storage, short flags);
void delete_bytearray(Bytearray* bytearray);
void delete_bytearray_ext(Bytearray* bytearray, void(*rmv_el) (void*), void(*rmv_items) (void*), void(*rmv_struct) (void*));
void* bytearray_at(const Bytearray* bytearray, size_t index);
#define bytearray_pop(bytearray) bytearray_pop_at(bytearray, bytearray->length-1)
void* bytearray_pop_at(Bytearray* bytearray, size_t index);
#define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item)
bool_t bytearray_insert(Bytearray* bytearray, size_t index, const void* item);
void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*));
bool_t bytearray_adjust_size(Bytearray* bytearray, size_t size);
bool_t bytearray_shrink(Bytearray* bytearray);
size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*));
#endif /* BYTE_ARRAY_H */
▾Minclude/cutils/cutils.h
@@ -4,5 +4,7 @@
#include <cutils/vector.h>
#include <cutils/dyn_string.h>
#include <cutils/misc.h>
#include <cutils/byte_array.h>
#endif /* CUTILS_H */
▾Minclude/cutils/dyn_string.h
@@ -14,16 +14,16 @@ typedef struct String
size_t length;
} String;
#define new_string() string_with_capacity(STRING_DEFAULT_SIZE);
#define new_string() string_with_capacity(STRING_DEFAULT_SIZE)
String* string_with_capacity(size_t capacity);
void delete_string(String* string);
char string_at(const String* string, size_t index);
#define string_pop(string) string_pop_at(string, string->length-1);
#define string_pop(string) string_pop_at(string, string->length-1)
char string_pop_at(String* string, size_t index);
bool string_insert(String* string, size_t index, char character);
#define string_push(string, character) string_insert(string, string->length, character);
#define string_push(string, character) string_insert(string, string->length, character)
void string_remove(String* string, size_t index);
▾Minclude/cutils/vector.h
@@ -14,16 +14,16 @@ typedef struct Vector
size_t length;
} Vector;
#define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE);
#define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE)
Vector* vector_with_capacity(size_t capacity);
void delete_vector(Vector* vector, void(*rmv) (void*));
void* vector_at(const Vector* vector, size_t index);
#define vector_pop(vector) vector_pop_at(vector, vector->length-1);
#define vector_pop(vector) vector_pop_at(vector, vector->length-1)
void* vector_pop_at(Vector* vector, size_t index);
bool vector_insert(Vector* vector, size_t index, void* item);
#define vector_push(vector, item) vector_insert(vector, vector->length, item);
#define vector_push(vector, item) vector_insert(vector, vector->length, item)
void vector_remove(Vector* vector, size_t index, void (*rmv)(void*));
▾Asrc/byte_array.c
@@ -0,0 +1,181 @@
#include <cutils/byte_array.h>
Bytearray* new_bytearray_ext(size_t capacity, size_t element_size, char* array_storage, Bytearray* struct_storage, short flags)
{
Bytearray* bytearray;
if(struct_storage)
{
bytearray = struct_storage;
} else {
bytearray = malloc(sizeof(*bytearray));
if(!bytearray)
return NULL;
}
if(array_storage)
{
bytearray->items = array_storage;
} else {
bytearray->items = malloc(sizeof(*bytearray->items)*capacity*element_size);
if(!bytearray->items)
{
free(bytearray);
return NULL;
}
}
bytearray->length = 0;
bytearray->capacity = capacity;
bytearray->element_size = element_size;
bytearray->flags = flags;
return bytearray;
}
void delete_bytearray(Bytearray* bytearray)
{
delete_bytearray_ext(bytearray,
(bytearray->flags & BT_FREE_EL) ? free : NULL,
(bytearray->flags & BT_FREE_ARRAY) ? free : NULL,
(bytearray->flags & BT_FREE_STRUCT) ? free : NULL);
}
void delete_bytearray_ext(Bytearray* bytearray, void(*rmv_el) (void*), void(*rmv_items) (void*), void(*rmv_struct) (void*))
{
if(rmv_el)
{
size_t i;
for(i = 0; i < bytearray->length; i++)
{
rmv_el(&bytearray->items[i*bytearray->element_size]);
}
}
if(rmv_items)
rmv_items(bytearray->items);
if(rmv_struct)
rmv_struct(bytearray);
}
void* bytearray_at(const Bytearray* bytearray, size_t index)
{
if(index >= bytearray->length)
return NULL;
else
return bytearray->items+(index*bytearray->element_size);
}
void* bytearray_pop_at(Bytearray* bytearray, size_t index)
{
void *tmp, *ret;
tmp = bytearray_at(bytearray, index);
if(!tmp)
{
errno = 0;
return NULL;
}
ret = malloc(bytearray->element_size);
if(!ret)
{
errno = ENOMEM;
return NULL;
}
memcpy(ret, tmp, bytearray->element_size);
bytearray_remove(bytearray, index, NULL);
return ret;
}
bool_t bytearray_insert(Bytearray* bytearray, size_t index, const void* item)
{
size_t length = bytearray->length;
size_t size = bytearray->element_size;
if(index > length || !bytearray_adjust_size(bytearray, length+1))
return b_false;
memmove(bytearray->items+index*size+1*size, bytearray->items+index*size, (length*size-index*size)*sizeof(*bytearray->items));
memcpy(bytearray->items+index*size, item, bytearray->element_size);
++bytearray->length;
return b_true;
}
void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*))
{
if(index < bytearray->length)
{
size_t length = bytearray->length;
size_t elsize = bytearray->element_size;
if(rmv)
rmv(&bytearray->items[index*elsize]);
memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, (length*elsize-index*elsize-1*elsize)*sizeof(*bytearray->items));
--bytearray->length;
}
}
bool_t bytearray_adjust_size(Bytearray* bytearray, size_t size)
{
if(bytearray->flags & BT_FIXED)
{
if(bytearray->capacity < size)
return b_false;
else
return b_true;
}
while(bytearray->capacity < size)
{
size_t capacity = bytearray->capacity;
size_t elsize = bytearray->element_size;
char* tmp = bytearray->items;
bytearray->items = realloc(bytearray->items, capacity*elsize*2*sizeof(*bytearray->items));
if(!bytearray->items)
{
bytearray->items = tmp;
return b_false;
}
bytearray->capacity *= 2;
}
return b_true;
}
bool_t bytearray_shrink(Bytearray* bytearray)
{
if(bytearray->flags & BT_FIXED)
return b_false;
while(bytearray->capacity > bytearray->length*2)
{
size_t capacity = bytearray->capacity;
size_t size = bytearray->element_size;
char* tmp = bytearray->items;
bytearray->items = realloc(bytearray->items, (capacity*size)/(2*sizeof(*bytearray->items)));
if(!bytearray->items)
{
bytearray->items = tmp;
return b_false;
}
bytearray->capacity /= 2;
}
return b_true;
}
size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*))
{
size_t* ret;
size_t i;
for(i = 0; i < haystack->length; i++)
{
if(cmp(haystack->items+(i*haystack->element_size),needle) == 0)
{
ret = malloc(sizeof(*ret));
*ret = i;
return ret;
}
}
return NULL;
}
▾Msrc/dyn_string.c
@@ -22,7 +22,7 @@ void string_remove(String* string, size_t index)
if(index < string->length)
{
memmove(string->chars+index, string->chars+index+1, (string->length-index-1)*sizeof(*string->chars));
string->length--;
--string->length;
}
}
▾Msrc/meson.build
@@ -1,4 +1,4 @@
src = ['vector.c', 'dyn_string.c', 'misc.c']
src = ['vector.c', 'dyn_string.c', 'misc.c', 'byte_array.c']
srctest = src + ['test.c']
cutils_lib = library('cutils', src, include_directories : inc, install: true)
@@ -6,4 +6,4 @@ cutils_lib = library('cutils', src, include_directories : inc, install: true)
cutils_dep = declare_dependency(link_with : cutils_lib, include_directories : inc)
e = executable('test_cutils', srctest, include_directories : inc, c_args: CFLAGS )
test('test functionality', e)
test('test functionality', e)
▾Msrc/test.c
@@ -18,97 +18,181 @@ static int cmp_str(const void* str1, const void* str2)
static void test1(void)
{
size_t* find;
Vector* test;
Vector* vector;
struct test* my_struct;
my_struct = malloc(sizeof(*my_struct));
test = new_vector()
vector = new_vector();
my_struct->a = 5;
my_struct->b = 5;
vector_push(test, my_struct);
vector_push(vector, my_struct);
my_struct = malloc(sizeof(*my_struct));
my_struct->a = 6;
my_struct->b = 6;
vector_push(test, my_struct);
vector_push(vector, my_struct);
my_struct = malloc(sizeof(*my_struct));
my_struct->a = 7;
my_struct->b = 7;
vector_push(test, my_struct);
assert(test->length == 3);
vector_push(vector, my_struct);
assert(vector->length == 3);
vector_remove(test, 0,free);
assert(test->length == 2);
vector_remove(vector, 0,free);
assert(vector->length == 2);
my_struct = malloc(sizeof(*my_struct));
my_struct->a = 8;
my_struct->b = 8;
vector_insert(test, 2, my_struct);
assert(test->length == 3);
vector_insert(vector, 2, my_struct);
assert(vector->length == 3);
my_struct = malloc(sizeof(*my_struct));
my_struct->a = 8;
my_struct->b = 8;
find = vector_find(test, my_struct, cmp_str);
find = vector_find(vector, my_struct, cmp_str);
assert(*find == 2);
free(find);
free(my_struct);
my_struct = vector_pop(test);
my_struct = vector_pop(vector);
assert(my_struct->a == 8 && my_struct->b == 8);
free(my_struct);
delete_vector(test,free);
delete_vector(vector, free);
}
static void test2(void)
{
String* test;
String* test2;
String* string;
String* string2;
char* cstring;
test = new_string();
string = new_string();
string_push(test, 'a');
string_push(test, 'b');
string_push(test, 'c');
string_push(test, 'd');
assert(test->length == 4);
string_push(string, 'a');
string_push(string, 'b');
string_push(string, 'c');
string_push(string, 'd');
assert(string->length == 4);
cstring = to_cstring(test);
cstring = to_cstring(string);
assert(strcmp(cstring, "abcd") == 0);
free(cstring);
string_remove(test, 3);
cstring = to_cstring(test);
string_remove(string, 3);
cstring = to_cstring(string);
assert(strcmp(cstring, "abc") == 0);
free(cstring);
assert(test->length == 3);
assert(string->length == 3);
string_insert(test, 0,'a');
cstring = to_cstring(test);
string_insert(string, 0,'a');
cstring = to_cstring(string);
assert(strcmp(cstring, "aabc") == 0);
free(cstring);
test2 = from_cstring("xyz");
string2 = from_cstring("xyz");
string_concat(test,test2);
cstring = to_cstring(test);
string_concat(string,string2);
cstring = to_cstring(string);
assert(strcmp(cstring, "aabcxyz") == 0);
free(cstring);
delete_string(test2);
delete_string(test);
delete_string(string2);
delete_string(string);
}
static void test3(void)
{
Bytearray* bt;
void* localarray;
struct test my_struct;
struct test* my_structptr;
char* tmpchar;
/*test pushing and popping with default constructor and simple values*/
bt = new_bytearray(1);
bytearray_push(bt, "a");
bytearray_push(bt, "b");
bytearray_push(bt, "c");
bytearray_push(bt, "d");
bytearray_push(bt, "\0");
assert(strcmp(bt->items, "abcd") == 0);
tmpchar = bytearray_pop(bt);
assert(*tmpchar == '\0');
free(tmpchar);
tmpchar = bytearray_pop(bt);
assert(*tmpchar == 'd');
free(tmpchar);
tmpchar = bytearray_pop(bt);
assert(*tmpchar == 'c');
free(tmpchar);
tmpchar = bytearray_pop(bt);
assert(*tmpchar == 'b');
free(tmpchar);
tmpchar = bytearray_pop(bt);
assert(*tmpchar == 'a');
free(tmpchar);
tmpchar = bytearray_pop(bt);
assert(tmpchar == NULL);
free(tmpchar);
bytearray_push(bt, "a");
tmpchar = bytearray_pop(bt);
assert(*tmpchar == 'a');
free(tmpchar);
delete_bytearray(bt);
/*test pushing and popping with self allocated array and fixed size*/
localarray = malloc(3*sizeof(struct test));
my_struct.a = 0;
my_struct.b = 0;
bt = new_bytearray_ext(3, sizeof(struct test), localarray, NULL, BT_FREE_ARRAY | BT_FIXED | BT_FREE_STRUCT);
bytearray_push(bt, &my_struct);
my_struct.a = 1;
my_struct.b = 1;
bytearray_push(bt, &my_struct);
my_struct.a = 2;
my_struct.b = 2;
bytearray_push(bt, &my_struct);
my_struct.a = 3;
my_struct.b = 3;
bytearray_push(bt, &my_struct);
my_structptr = bytearray_pop(bt);
my_struct.a = 2;
my_struct.b = 2;
printf("%d\n", my_structptr->a);
assert(my_structptr->a == my_struct.a);
assert(my_structptr->b == my_struct.b);
free(my_structptr);
delete_bytearray(bt);
}
int main(int argc, char** argv)
{
test1();
test2();
test3();
sleep_ms(1000);
return 0;
}
▾Msrc/vector.c
@@ -45,7 +45,7 @@ void vector_remove(Vector* vector, size_t index, void (*rmv)(void*))
if(rmv)
rmv(vector->items[index]);
memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items));
vector->length--;
--vector->length;
}
}
@@ -56,7 +56,7 @@ size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const
for(i = 0; i < haystack->length; i++)
{
if(cmp ? cmp(haystack->items[i],needle) == 0 : haystack->items[i] == needle)
if(cmp(haystack->items[i],needle) == 0)
{
ret = malloc(sizeof(*ret));
*ret = i;
@@ -111,11 +111,13 @@ bool vector_shrink(Vector* vector)
void delete_vector(Vector* vector, void (*rmv)(void*))
{
size_t i;
for(i = 0; i < vector->length; i++)
if(rmv)
{
if(rmv)
size_t i;
for(i = 0; i < vector->length; i++)
{
rmv(vector->items[i]);
}
}
free(vector->items);
free(vector);