added tests, simplified some functions, added functions
M.gitignore
| @@ -1,6 +1,9 @@ | |||
|---|---|---|---|
| 1 | 1 | # Prerequisites | |
| 2 | 2 | *.d | |
| 3 | 3 | ||
| 4 | + | #binaries | |
| 5 | + | test | |
| 6 | + | ||
| 4 | 7 | # Object files | |
| 5 | 8 | *.o | |
| 6 | 9 | *.ko | |
MMakefile
| @@ -1,3 +1,9 @@ | |||
|---|---|---|---|
| 1 | 1 | all: | |
| 2 | - | gcc -Og -g -march=native -shared -fPIC -fstrict-aliasing vector.c dyn_string.c -o cutils.so -flto \ | |
| 3 | - | -Wall -Wpedantic -Wnull-dereference -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wstrict-overflow=5 -Wunreachable-code -Wno-unused-parameter | |
| 2 | + | gcc -Og -g -march=native -shared -fPIC -fstrict-aliasing vector.c dyn_string.c -o libcutils.so -flto \ | |
| 3 | + | -Wall -Wpedantic -Wnull-dereference -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wstrict-overflow=5 -Wunreachable-code -Wno-unused-parameter \ | |
| 4 | + | -fsanitize=undefined | |
| 5 | + | ||
| 6 | + | test: | |
| 7 | + | gcc -Og -g -march=native -fPIC -fstrict-aliasing vector.c dyn_string.c test.c -o test -flto \ | |
| 8 | + | -Wall -Wpedantic -Wnull-dereference -Wshadow -Wconversion -Wstrict-prototypes -Wmissing-prototypes -Wcast-qual -Wstrict-overflow=5 -Wunreachable-code -Wno-unused-parameter \ | |
| 9 | + | -fsanitize=undefined | |
Mdyn_string.c
| @@ -1,28 +1,30 @@ | |||
|---|---|---|---|
| 1 | 1 | #include "dyn_string.h" | |
| 2 | 2 | ||
| 3 | 3 | String* new_string(void) | |
| 4 | + | { | |
| 5 | + | return string_with_capacity(STRING_DEFAULT_SIZE); | |
| 6 | + | } | |
| 7 | + | ||
| 8 | + | String* string_with_capacity(size_t capacity) | |
| 4 | 9 | { | |
| 5 | 10 | String* string = malloc(sizeof(*string)); | |
| 6 | 11 | if(!string) | |
| 7 | 12 | return NULL; | |
| 8 | - | string->chars = calloc(sizeof(*string->chars)*STRING_DEFAULT_SIZE,1); | |
| 13 | + | string->chars = calloc(capacity,sizeof(*string->chars)); | |
| 9 | 14 | if(!string->chars) | |
| 10 | 15 | { | |
| 11 | 16 | free(string); | |
| 12 | 17 | return NULL; | |
| 13 | 18 | } | |
| 14 | 19 | string->length = 0; | |
| 15 | - | string->capacity = STRING_DEFAULT_SIZE; | |
| 20 | + | string->capacity = capacity; | |
| 16 | 21 | ||
| 17 | 22 | return string; | |
| 18 | 23 | } | |
| 19 | 24 | ||
| 20 | 25 | bool string_append(String* string, char character) | |
| 21 | 26 | { | |
| 22 | - | if(!string_adjust_size(string, ++string->length)) | |
| 23 | - | return false; | |
| 24 | - | string->chars[string->length-1] = character; | |
| 25 | - | return true; | |
| 27 | + | return string_insert(string, string->length, character); | |
| 26 | 28 | } | |
| 27 | 29 | ||
| 28 | 30 | void string_remove(String* string, size_t index) | |
| @@ -36,7 +38,7 @@ void string_remove(String* string, size_t index) | |||
|---|---|---|---|
| 36 | 38 | ||
| 37 | 39 | bool string_insert(String* string, size_t index, char character) | |
| 38 | 40 | { | |
| 39 | - | if(!string_adjust_size(string, string->length)) | |
| 41 | + | if(index > string->length || !string_adjust_size(string, string->length)) | |
| 40 | 42 | return false; | |
| 41 | 43 | ||
| 42 | 44 | memmove(string->chars+index+1, string->chars+index, (string->length-index)*sizeof(*string->chars)); | |
| @@ -53,11 +55,12 @@ char string_at(const String* string, size_t index) | |||
|---|---|---|---|
| 53 | 55 | return string->chars[index]; | |
| 54 | 56 | } | |
| 55 | 57 | ||
| 56 | - | bool string_concat(String* string, String* other) | |
| 58 | + | bool string_concat(String* string, const String* other) | |
| 57 | 59 | { | |
| 58 | 60 | if(!string_adjust_size(string,string->length+other->length-1)) | |
| 59 | 61 | return false; | |
| 60 | 62 | memcpy(string->chars+string->length,other->chars,other->length); | |
| 63 | + | string->length += other->length; | |
| 61 | 64 | return true; | |
| 62 | 65 | } | |
| 63 | 66 | ||
| @@ -89,16 +92,36 @@ bool string_adjust_size(String* string, size_t size) | |||
|---|---|---|---|
| 89 | 92 | } | |
| 90 | 93 | string->capacity *= 2; | |
| 91 | 94 | } | |
| 92 | - | while(string->capacity > (size*2)) | |
| 95 | + | return true; | |
| 96 | + | } | |
| 97 | + | ||
| 98 | + | ||
| 99 | + | ||
| 100 | + | void delete_string(String* string) | |
| 101 | + | { | |
| 102 | + | free(string->chars); | |
| 103 | + | free(string); | |
| 104 | + | } | |
| 105 | + | ||
| 106 | + | String* from_cstring(const char* cstring) | |
| 107 | + | { | |
| 108 | + | String* string = string_with_capacity(strlen(cstring)); | |
| 109 | + | if(!string) | |
| 93 | 110 | { | |
| 94 | - | char* tmp = string->chars; | |
| 95 | - | string->chars = realloc(string->chars, string->capacity/2*(sizeof(*string->chars))); | |
| 96 | - | if(!string->chars) | |
| 97 | - | { | |
| 98 | - | string->chars = tmp; | |
| 99 | - | return false; | |
| 100 | - | } | |
| 101 | - | string->capacity /= 2; | |
| 111 | + | return NULL; | |
| 112 | + | } else { | |
| 113 | + | memcpy(string->chars, cstring, strlen(cstring)); | |
| 114 | + | string->length = strlen(cstring); | |
| 115 | + | return string; | |
| 102 | 116 | } | |
| 103 | - | return true; | |
| 117 | + | ||
| 118 | + | } | |
| 119 | + | ||
| 120 | + | char* to_cstring(const String* string) | |
| 121 | + | { | |
| 122 | + | char* cstring = malloc(string->length+1); | |
| 123 | + | memcpy(cstring, string->chars, string->length); | |
| 124 | + | cstring[string->length] = '\0'; | |
| 125 | + | ||
| 126 | + | return cstring; | |
| 104 | 127 | } | |
Mdyn_string.h
| @@ -14,13 +14,22 @@ typedef struct String | |||
|---|---|---|---|
| 14 | 14 | } String; | |
| 15 | 15 | ||
| 16 | 16 | String* new_string(void); | |
| 17 | + | String* string_with_capacity(size_t capacity); | |
| 18 | + | void delete_string(String* string); | |
| 19 | + | ||
| 17 | 20 | char string_at(const String* string, size_t index); | |
| 18 | - | bool string_append(String* string, char item); | |
| 21 | + | ||
| 22 | + | bool string_append(String* string, char character); | |
| 23 | + | bool string_insert(String* string, size_t index, char character); | |
| 24 | + | ||
| 19 | 25 | void string_remove(String* string, size_t index); | |
| 26 | + | ||
| 20 | 27 | bool string_adjust_size(String* string, size_t size); | |
| 21 | 28 | size_t* string_find_char(const String* haystack, const char needle); | |
| 22 | - | bool string_insert(String* string, size_t index, char character); | |
| 23 | - | bool string_concat(String* string, String* other); | |
| 29 | + | bool string_concat(String* string, const String* other); | |
| 30 | + | ||
| 31 | + | String* from_cstring(const char* cstring); | |
| 32 | + | char* to_cstring(const String* string); | |
| 24 | 33 | ||
| 25 | 34 | ||
| 26 | 35 | #endif //DYN_STRING_H | |
Atest.c
| @@ -0,0 +1,101 @@ | |||
|---|---|---|---|
| 1 | + | #include "cutils.h" | |
| 2 | + | #include <stdio.h> | |
| 3 | + | ||
| 4 | + | struct test | |
| 5 | + | { | |
| 6 | + | int a; | |
| 7 | + | int b; | |
| 8 | + | }; | |
| 9 | + | ||
| 10 | + | int cmp_str(const void* str1, const void* str2) | |
| 11 | + | { | |
| 12 | + | const struct test* str1_s = str1; | |
| 13 | + | const struct test* str2_s = str2; | |
| 14 | + | return !((str1_s->a == str2_s->a) && (str1_s->b == str2_s->b)); | |
| 15 | + | } | |
| 16 | + | ||
| 17 | + | void test1(void) | |
| 18 | + | { | |
| 19 | + | Vector* test = new_vector(); | |
| 20 | + | ||
| 21 | + | struct test* my_struct = malloc(sizeof(*my_struct)); | |
| 22 | + | my_struct->a = 5; | |
| 23 | + | my_struct->b = 5; | |
| 24 | + | vector_push(test, my_struct); | |
| 25 | + | ||
| 26 | + | my_struct = malloc(sizeof(*my_struct)); | |
| 27 | + | my_struct->a = 6; | |
| 28 | + | my_struct->b = 6; | |
| 29 | + | vector_push(test, my_struct); | |
| 30 | + | ||
| 31 | + | my_struct = malloc(sizeof(*my_struct)); | |
| 32 | + | my_struct->a = 7; | |
| 33 | + | my_struct->b = 7; | |
| 34 | + | vector_push(test, my_struct); | |
| 35 | + | printf("%ld\n", test->length); | |
| 36 | + | ||
| 37 | + | vector_remove(test, 0,free); | |
| 38 | + | printf("%ld\n", test->length); | |
| 39 | + | ||
| 40 | + | my_struct = malloc(sizeof(*my_struct)); | |
| 41 | + | my_struct->a = 8; | |
| 42 | + | my_struct->b = 8; | |
| 43 | + | vector_insert(test, 2, my_struct); | |
| 44 | + | printf("%ld\n", test->length); | |
| 45 | + | ||
| 46 | + | my_struct = malloc(sizeof(*my_struct)); | |
| 47 | + | my_struct->a = 8; | |
| 48 | + | my_struct->b = 8; | |
| 49 | + | ||
| 50 | + | size_t* find = vector_find(test, my_struct, cmp_str); | |
| 51 | + | printf("pos: %lu\n", *find); | |
| 52 | + | free(find); | |
| 53 | + | ||
| 54 | + | free(my_struct); | |
| 55 | + | my_struct = vector_pop(test); | |
| 56 | + | printf("struct a: %d, b: %d\n", my_struct->a, my_struct->b); | |
| 57 | + | free(my_struct); | |
| 58 | + | ||
| 59 | + | delete_vector(test,free); | |
| 60 | + | } | |
| 61 | + | ||
| 62 | + | void test2(void) | |
| 63 | + | { | |
| 64 | + | String* test = new_string(); | |
| 65 | + | string_append(test, 'a'); | |
| 66 | + | string_append(test, 'b'); | |
| 67 | + | string_append(test, 'c'); | |
| 68 | + | string_append(test, 'd'); | |
| 69 | + | printf("%ld\n", test->length); | |
| 70 | + | ||
| 71 | + | char* cstring = to_cstring(test); | |
| 72 | + | printf("%s\n", cstring); | |
| 73 | + | free(cstring); | |
| 74 | + | ||
| 75 | + | string_remove(test, 3); | |
| 76 | + | cstring = to_cstring(test); | |
| 77 | + | printf("%s\n", cstring); | |
| 78 | + | free(cstring); | |
| 79 | + | printf("%ld\n", test->length); | |
| 80 | + | ||
| 81 | + | string_insert(test, 0,'a'); | |
| 82 | + | cstring = to_cstring(test); | |
| 83 | + | printf("%s\n", cstring); | |
| 84 | + | free(cstring); | |
| 85 | + | ||
| 86 | + | String* test2 = from_cstring("xyz"); | |
| 87 | + | ||
| 88 | + | string_concat(test,test2); | |
| 89 | + | cstring = to_cstring(test); | |
| 90 | + | printf("%s\n", cstring); | |
| 91 | + | free(cstring); | |
| 92 | + | ||
| 93 | + | delete_string(test2); | |
| 94 | + | delete_string(test); | |
| 95 | + | } | |
| 96 | + | ||
| 97 | + | int main(int argc, char** argv) | |
| 98 | + | { | |
| 99 | + | test1(); | |
| 100 | + | test2(); | |
| 101 | + | } | |
Mvector.c
| @@ -1,18 +1,23 @@ | |||
|---|---|---|---|
| 1 | 1 | #include "vector.h" | |
| 2 | 2 | ||
| 3 | 3 | Vector* new_vector(void) | |
| 4 | + | { | |
| 5 | + | return vector_with_capacity(VECTOR_DEFAULT_SIZE); | |
| 6 | + | } | |
| 7 | + | ||
| 8 | + | Vector* vector_with_capacity(size_t capacity) | |
| 4 | 9 | { | |
| 5 | 10 | Vector* vector = malloc(sizeof(*vector)); | |
| 6 | 11 | if(!vector) | |
| 7 | 12 | return NULL; | |
| 8 | - | vector->items = malloc(sizeof(*vector->items)*VECTOR_DEFAULT_SIZE); | |
| 13 | + | vector->items = malloc(sizeof(*vector->items)*capacity); | |
| 9 | 14 | if(!vector->items) | |
| 10 | 15 | { | |
| 11 | 16 | free(vector); | |
| 12 | 17 | return NULL; | |
| 13 | 18 | } | |
| 14 | 19 | vector->length = 0; | |
| 15 | - | vector->capacity = VECTOR_DEFAULT_SIZE; | |
| 20 | + | vector->capacity = capacity; | |
| 16 | 21 | ||
| 17 | 22 | return vector; | |
| 18 | 23 | } | |
| @@ -25,27 +30,30 @@ void* vector_at(const Vector* vector, size_t index) | |||
|---|---|---|---|
| 25 | 30 | return vector->items[index]; | |
| 26 | 31 | } | |
| 27 | 32 | ||
| 28 | - | void* vector_pop(Vector* vector, size_t index) | |
| 33 | + | void* vector_pop(Vector* vector) | |
| 29 | 34 | { | |
| 30 | - | if(index >= vector->length) | |
| 31 | - | return NULL; | |
| 32 | - | else | |
| 35 | + | return vector_pop_at(vector, vector->length-1); | |
| 36 | + | } | |
| 37 | + | ||
| 38 | + | void* vector_pop_at(Vector* vector, size_t index) | |
| 39 | + | { | |
| 40 | + | void* tmp = vector_at(vector, index); | |
| 41 | + | if(!tmp) | |
| 33 | 42 | { | |
| 34 | - | void* tmp = vector->items[index]; | |
| 35 | - | memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items)); | |
| 36 | - | vector->length--; | |
| 43 | + | return NULL; | |
| 44 | + | } else { | |
| 45 | + | vector_remove(vector, index, NULL); | |
| 37 | 46 | return tmp; | |
| 38 | 47 | } | |
| 39 | 48 | } | |
| 40 | 49 | ||
| 50 | + | ||
| 41 | 51 | void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)) | |
| 42 | 52 | { | |
| 43 | 53 | if(index < vector->length) | |
| 44 | 54 | { | |
| 45 | 55 | if(rmv) | |
| 46 | 56 | rmv(vector->items[index]); | |
| 47 | - | else | |
| 48 | - | free(vector->items[index]); | |
| 49 | 57 | memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items)); | |
| 50 | 58 | vector->length--; | |
| 51 | 59 | } | |
| @@ -53,18 +61,15 @@ void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)) | |||
|---|---|---|---|
| 53 | 61 | ||
| 54 | 62 | bool vector_push(Vector* vector, void* item) | |
| 55 | 63 | { | |
| 56 | - | if(!vector_adjust_size(vector, ++vector->length)) | |
| 57 | - | return false; | |
| 58 | - | vector->items[vector->length-1] = item; | |
| 59 | - | return true; | |
| 64 | + | return vector_insert(vector, vector->length, item); | |
| 60 | 65 | } | |
| 61 | 66 | ||
| 62 | - | size_t* vector_find(const Vector* haystack, const void* needle, bool (*cmp)(const void*, const void*)) | |
| 67 | + | size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*)) | |
| 63 | 68 | { | |
| 64 | 69 | size_t* ret; | |
| 65 | 70 | for(size_t i = 0; i < haystack->length; i++) | |
| 66 | 71 | { | |
| 67 | - | if(cmp ? cmp(haystack->items[i],needle) : haystack->items[i] == needle) | |
| 72 | + | if(cmp ? cmp(haystack->items[i],needle) == 0 : haystack->items[i] == needle) | |
| 68 | 73 | { | |
| 69 | 74 | ret = malloc(sizeof(*ret)); | |
| 70 | 75 | *ret = i; | |
| @@ -76,12 +81,12 @@ size_t* vector_find(const Vector* haystack, const void* needle, bool (*cmp)(cons | |||
|---|---|---|---|
| 76 | 81 | ||
| 77 | 82 | bool vector_insert(Vector* vector, size_t index, void* item) | |
| 78 | 83 | { | |
| 79 | - | if(!vector_adjust_size(vector, vector->length)) | |
| 84 | + | if(index > vector->length || !vector_adjust_size(vector, vector->length+1)) | |
| 80 | 85 | return false; | |
| 81 | 86 | ||
| 82 | 87 | memmove(vector->items+index+1, vector->items+index, (vector->length-index)*sizeof(*vector->items)); | |
| 83 | 88 | vector->items[index] = item; | |
| 84 | - | vector->length++; | |
| 89 | + | ++vector->length; | |
| 85 | 90 | return true; | |
| 86 | 91 | } | |
| 87 | 92 | ||
| @@ -90,7 +95,7 @@ bool vector_adjust_size(Vector* vector, size_t size) | |||
|---|---|---|---|
| 90 | 95 | while(vector->capacity < size) | |
| 91 | 96 | { | |
| 92 | 97 | void** tmp = vector->items; | |
| 93 | - | vector->items = realloc(vector->items, vector->capacity*2*(sizeof(*vector->items))); | |
| 98 | + | vector->items = realloc(vector->items, vector->capacity*2*sizeof(*vector->items)); | |
| 94 | 99 | if(!vector->items) | |
| 95 | 100 | { | |
| 96 | 101 | vector->items = tmp; | |
| @@ -98,10 +103,15 @@ bool vector_adjust_size(Vector* vector, size_t size) | |||
|---|---|---|---|
| 98 | 103 | } | |
| 99 | 104 | vector->capacity *= 2; | |
| 100 | 105 | } | |
| 101 | - | while(vector->capacity > (size*2)) | |
| 106 | + | return true; | |
| 107 | + | } | |
| 108 | + | ||
| 109 | + | bool vector_shrink(Vector* vector) | |
| 110 | + | { | |
| 111 | + | while(vector->capacity > (vector->length*2)) | |
| 102 | 112 | { | |
| 103 | 113 | void** tmp = vector->items; | |
| 104 | - | vector->items = realloc(vector->items, vector->capacity/2*(sizeof(*vector->items))); | |
| 114 | + | vector->items = realloc(vector->items, vector->capacity/2*sizeof(*vector->items)); | |
| 105 | 115 | if(!vector->items) | |
| 106 | 116 | { | |
| 107 | 117 | vector->items = tmp; | |
| @@ -118,8 +128,7 @@ void delete_vector(Vector* vector, void (*rmv)(void*)) | |||
|---|---|---|---|
| 118 | 128 | { | |
| 119 | 129 | if(rmv) | |
| 120 | 130 | rmv(vector->items[i]); | |
| 121 | - | else | |
| 122 | - | free(vector->items[i]); | |
| 123 | 131 | } | |
| 132 | + | free(vector->items); | |
| 124 | 133 | free(vector); | |
| 125 | 134 | } | |
Mvector.h
| @@ -14,14 +14,21 @@ typedef struct Vector | |||
|---|---|---|---|
| 14 | 14 | } Vector; | |
| 15 | 15 | ||
| 16 | 16 | Vector* new_vector(void); | |
| 17 | + | Vector* vector_with_capacity(size_t capacity); | |
| 18 | + | void delete_vector(Vector* vector, void(*rmv) (void*)); | |
| 19 | + | ||
| 17 | 20 | void* vector_at(const Vector* vector, size_t index); | |
| 18 | - | void* vector_pop(Vector* vector, size_t index); | |
| 21 | + | void* vector_pop(Vector* vector); | |
| 22 | + | void* vector_pop_at(Vector* vector, size_t index); | |
| 23 | + | ||
| 24 | + | bool vector_insert(Vector* vector, size_t index, void* item); | |
| 19 | 25 | bool vector_push(Vector* vector, void* item); | |
| 20 | 26 | void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)); | |
| 21 | - | void delete_vector(Vector* vector, void(*rmv) (void*)); | |
| 27 | + | ||
| 22 | 28 | bool vector_adjust_size(Vector* vector, size_t size); | |
| 23 | - | size_t* vector_find(const Vector* haystack, const void* needle, bool (*cmp)(const void*, const void*)); | |
| 24 | - | bool vector_insert(Vector* vector, size_t index, void* item); | |
| 29 | + | bool vector_shrink(Vector* vector); | |
| 30 | + | size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*)); | |
| 31 | + | ||
| 25 | 32 | ||
| 26 | 33 | ||
| 27 | 34 | #endif //VECTOR_H | |