moved remove and at functions to headers, improved remove_range functions, added string_strip + string_count, updated tests
Minclude/cutils/byte_array.h
| @@ -19,14 +19,32 @@ typedef struct Bytearray | |||
|---|---|---|---|
| 19 | 19 | Bytearray* bytearray_with_capacity(size_t capacity, size_t element_size); | |
| 20 | 20 | void delete_bytearray(Bytearray* bytearray, void(*rmv_el) (void*)); | |
| 21 | 21 | ||
| 22 | - | void* bytearray_at(const Bytearray* bytearray, size_t index); | |
| 22 | + | HEDLEY_INLINE | |
| 23 | + | static void* bytearray_at(const Bytearray* bytearray, size_t index) | |
| 24 | + | { | |
| 25 | + | return bytearray->items+(index*bytearray->element_size); | |
| 26 | + | } | |
| 23 | 27 | #define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, bytearray->length-1, retptr) | |
| 24 | 28 | void* bytearray_pop_at(Bytearray* bytearray, size_t index, void* retptr); | |
| 25 | 29 | ||
| 26 | 30 | #define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item) | |
| 27 | 31 | bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item); | |
| 28 | 32 | ||
| 29 | - | void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*)); | |
| 33 | + | HEDLEY_INLINE | |
| 34 | + | static void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*)) | |
| 35 | + | { | |
| 36 | + | if(index < bytearray->length) | |
| 37 | + | { | |
| 38 | + | size_t length = bytearray->length; | |
| 39 | + | size_t elsize = bytearray->element_size; | |
| 40 | + | if(rmv) | |
| 41 | + | rmv(&bytearray->items[index*elsize]); | |
| 42 | + | ||
| 43 | + | memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, length*elsize-index*elsize-1*elsize); | |
| 44 | + | bytearray->length--; | |
| 45 | + | } | |
| 46 | + | } | |
| 47 | + | void bytearray_remove_range(Bytearray* bytearray, size_t index, size_t length, void (*rmv)(void*)); | |
| 30 | 48 | ||
| 31 | 49 | bool bytearray_adjust_size(Bytearray* bytearray, size_t size); | |
| 32 | 50 | bool bytearray_shrink(Bytearray* bytearray); | |
Minclude/cutils/dyn_string.h
| @@ -18,21 +18,36 @@ typedef struct String | |||
|---|---|---|---|
| 18 | 18 | String* string_with_capacity(size_t capacity); | |
| 19 | 19 | void delete_string(String* string); | |
| 20 | 20 | ||
| 21 | - | char string_at(const String* string, size_t index); | |
| 21 | + | HEDLEY_INLINE | |
| 22 | + | static char string_at(const String* string, size_t index) | |
| 23 | + | { | |
| 24 | + | return string->chars[index]; | |
| 25 | + | } | |
| 26 | + | ||
| 22 | 27 | #define string_pop(string) string_pop_at(string, string->length-1) | |
| 23 | 28 | char string_pop_at(String* string, size_t index); | |
| 24 | 29 | ||
| 25 | 30 | bool string_insert(String* string, size_t index, char character); | |
| 26 | 31 | #define string_push(string, character) string_insert(string, string->length, character) | |
| 27 | 32 | ||
| 28 | - | void string_remove(String* string, size_t index); | |
| 33 | + | HEDLEY_INLINE | |
| 34 | + | static void string_remove(String* string, size_t index) | |
| 35 | + | { | |
| 36 | + | if(index < string->length) | |
| 37 | + | { | |
| 38 | + | memmove(string->chars+index, string->chars+index+1, (string->length-index-1)*sizeof(*string->chars)); | |
| 39 | + | string->length--; | |
| 40 | + | } | |
| 41 | + | } | |
| 29 | 42 | void string_remove_range(String* string, size_t index, size_t length); | |
| 43 | + | size_t string_strip(String* string, char character); | |
| 30 | 44 | ||
| 31 | 45 | bool string_adjust_size(String* string, size_t size); | |
| 32 | 46 | /* TODO: rework find functions to take extra argument of result count | |
| 33 | 47 | * and then find that many and return them in a vector/linked list */ | |
| 34 | 48 | bool string_find_char(const String* haystack, const char needle, size_t* pos); | |
| 35 | 49 | bool string_find_str(const String* haystack, const String* needle, size_t* pos); | |
| 50 | + | size_t string_count(const String* string, char character); | |
| 36 | 51 | ||
| 37 | 52 | bool string_concat(String* string, const String* other); | |
| 38 | 53 | ||
Minclude/cutils/vector.h
| @@ -18,14 +18,28 @@ typedef struct Vector | |||
|---|---|---|---|
| 18 | 18 | Vector* vector_with_capacity(size_t capacity); | |
| 19 | 19 | void delete_vector(Vector* vector, void(*rmv) (void*)); | |
| 20 | 20 | ||
| 21 | - | void* vector_at(const Vector* vector, size_t index); | |
| 21 | + | HEDLEY_INLINE | |
| 22 | + | static void* vector_at(const Vector* vector, size_t index) | |
| 23 | + | { | |
| 24 | + | return vector->items[index]; | |
| 25 | + | } | |
| 22 | 26 | #define vector_pop(vector) vector_pop_at(vector, vector->length-1) | |
| 23 | 27 | void* vector_pop_at(Vector* vector, size_t index); | |
| 24 | 28 | ||
| 25 | 29 | bool vector_insert(Vector* vector, size_t index, void* item); | |
| 26 | 30 | #define vector_push(vector, item) vector_insert(vector, vector->length, item) | |
| 27 | 31 | ||
| 28 | - | void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)); | |
| 32 | + | HEDLEY_INLINE | |
| 33 | + | static void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)) | |
| 34 | + | { | |
| 35 | + | if(index < vector->length) | |
| 36 | + | { | |
| 37 | + | if(rmv) | |
| 38 | + | rmv(vector->items[index]); | |
| 39 | + | memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items)); | |
| 40 | + | vector->length--; | |
| 41 | + | } | |
| 42 | + | } | |
| 29 | 43 | void vector_remove_range(Vector* vector, size_t index, size_t length, void (*rmv)(void*)); | |
| 30 | 44 | ||
| 31 | 45 | bool vector_adjust_size(Vector* vector, size_t size); | |
Msrc/byte_array.c
| @@ -38,14 +38,21 @@ void delete_bytearray(Bytearray* bytearray, void(*rmv_el) (void*)) | |||
|---|---|---|---|
| 38 | 38 | free(bytearray); | |
| 39 | 39 | } | |
| 40 | 40 | ||
| 41 | - | void* bytearray_at(const Bytearray* bytearray, size_t index) | |
| 41 | + | void bytearray_remove_range(Bytearray* bytearray, size_t index, size_t length, void (*rmv)(void*)) | |
| 42 | 42 | { | |
| 43 | - | if(index >= bytearray->length) | |
| 44 | - | return NULL; | |
| 45 | - | else | |
| 46 | - | return bytearray->items+(index*bytearray->element_size); | |
| 43 | + | size_t i; | |
| 44 | + | if(rmv) | |
| 45 | + | { | |
| 46 | + | for(i = index; i < length; i++) | |
| 47 | + | { | |
| 48 | + | rmv(bytearray_at(bytearray, i)); | |
| 49 | + | } | |
| 50 | + | } | |
| 51 | + | memmove(bytearray->items+index, bytearray->items+index+length, (bytearray->length-(index+length))*sizeof(*bytearray->items)); | |
| 52 | + | bytearray->length -= length; | |
| 47 | 53 | } | |
| 48 | 54 | ||
| 55 | + | ||
| 49 | 56 | void* bytearray_pop_at(Bytearray* bytearray, size_t index, void* retptr) | |
| 50 | 57 | { | |
| 51 | 58 | void *tmp; | |
| @@ -77,20 +84,6 @@ bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item) | |||
|---|---|---|---|
| 77 | 84 | return true; | |
| 78 | 85 | } | |
| 79 | 86 | ||
| 80 | - | void bytearray_remove(Bytearray* bytearray, size_t index, void (*rmv)(void*)) | |
| 81 | - | { | |
| 82 | - | if(index < bytearray->length) | |
| 83 | - | { | |
| 84 | - | size_t length = bytearray->length; | |
| 85 | - | size_t elsize = bytearray->element_size; | |
| 86 | - | if(rmv) | |
| 87 | - | rmv(&bytearray->items[index*elsize]); | |
| 88 | - | ||
| 89 | - | memmove(bytearray->items+index*elsize, bytearray->items+index*elsize+1*elsize, length*elsize-index*elsize-1*elsize); | |
| 90 | - | bytearray->length--; | |
| 91 | - | } | |
| 92 | - | } | |
| 93 | - | ||
| 94 | 87 | bool bytearray_adjust_size(Bytearray* bytearray, size_t size) | |
| 95 | 88 | { | |
| 96 | 89 | while(bytearray->capacity < size) | |
Msrc/dyn_string.c
| @@ -17,22 +17,37 @@ String* string_with_capacity(size_t capacity) | |||
|---|---|---|---|
| 17 | 17 | return string; | |
| 18 | 18 | } | |
| 19 | 19 | ||
| 20 | - | void string_remove(String* string, size_t index) | |
| 20 | + | void string_remove_range(String* string, size_t index, size_t length) | |
| 21 | 21 | { | |
| 22 | - | if(index < string->length) | |
| 23 | - | { | |
| 24 | - | memmove(string->chars+index, string->chars+index+1, (string->length-index-1)*sizeof(*string->chars)); | |
| 25 | - | string->length--; | |
| 26 | - | } | |
| 22 | + | memmove(string->chars+index, string->chars+index+length, (string->length-(index+length))); | |
| 23 | + | string->length -= length; | |
| 27 | 24 | } | |
| 28 | - | /* TODO: optimize */ | |
| 29 | - | void string_remove_range(String* string, size_t index, size_t length) | |
| 25 | + | ||
| 26 | + | size_t string_strip(String* string, char character) | |
| 30 | 27 | { | |
| 31 | - | size_t i; | |
| 32 | - | for(i = 0; i < length; i++) | |
| 28 | + | size_t i, last = 0, offset = 0; | |
| 29 | + | bool first = true; | |
| 30 | + | ||
| 31 | + | for(i = 0; i < string->length; i++) | |
| 33 | 32 | { | |
| 34 | - | string_remove(string, index+i); | |
| 33 | + | if(string_at(string,i) == character) | |
| 34 | + | { | |
| 35 | + | if(first) | |
| 36 | + | { | |
| 37 | + | first = false; | |
| 38 | + | } else { | |
| 39 | + | memmove(string->chars+last-offset, string->chars+last+1, i-last-1); | |
| 40 | + | offset++; | |
| 41 | + | } | |
| 42 | + | ||
| 43 | + | last = i; | |
| 44 | + | } | |
| 35 | 45 | } | |
| 46 | + | ||
| 47 | + | memmove(string->chars+last-offset, string->chars+last+1, string->length-last-1); | |
| 48 | + | ||
| 49 | + | string->length -= offset+(first ? 0 : 1); | |
| 50 | + | return offset; | |
| 36 | 51 | } | |
| 37 | 52 | ||
| 38 | 53 | bool string_insert(String* string, size_t index, char character) | |
| @@ -46,14 +61,6 @@ bool string_insert(String* string, size_t index, char character) | |||
|---|---|---|---|
| 46 | 61 | return true; | |
| 47 | 62 | } | |
| 48 | 63 | ||
| 49 | - | char string_at(const String* string, size_t index) | |
| 50 | - | { | |
| 51 | - | if(index >= string->length) | |
| 52 | - | return '\0'; | |
| 53 | - | else | |
| 54 | - | return string->chars[index]; | |
| 55 | - | } | |
| 56 | - | ||
| 57 | 64 | char string_pop_at(String* string, size_t index) | |
| 58 | 65 | { | |
| 59 | 66 | char tmp = string_at(string, index); | |
| @@ -110,6 +117,17 @@ bool string_find_str(const String* haystack, const String* needle, size_t* pos) | |||
|---|---|---|---|
| 110 | 117 | return false; | |
| 111 | 118 | } | |
| 112 | 119 | ||
| 120 | + | size_t string_count(const String* string, char character) | |
| 121 | + | { | |
| 122 | + | size_t i, ret = 0; | |
| 123 | + | for(i = 0; i < string->length; i++) | |
| 124 | + | { | |
| 125 | + | if(string_at(string, i) == character) | |
| 126 | + | ret++; | |
| 127 | + | } | |
| 128 | + | return ret; | |
| 129 | + | } | |
| 130 | + | ||
| 113 | 131 | bool string_adjust_size(String* string, size_t size) | |
| 114 | 132 | { | |
| 115 | 133 | while(string->capacity < size) | |
Msrc/test.c
| @@ -112,6 +112,19 @@ static void test_string(void) | |||
|---|---|---|---|
| 112 | 112 | ||
| 113 | 113 | delete_string(string2); | |
| 114 | 114 | delete_string(string); | |
| 115 | + | ||
| 116 | + | string = from_cstring("abcd"); | |
| 117 | + | assert(string->length == 4); | |
| 118 | + | string_remove_range(string, 0, string->length); | |
| 119 | + | assert(string->length == 0); | |
| 120 | + | delete_string(string); | |
| 121 | + | ||
| 122 | + | string = from_cstring("bba"); | |
| 123 | + | string_strip(string, 'a'); | |
| 124 | + | assert(string->length == 2); | |
| 125 | + | ||
| 126 | + | cstring = to_cstring_del(string); | |
| 127 | + | free(cstring); | |
| 115 | 128 | } | |
| 116 | 129 | ||
| 117 | 130 | static void test_bytearray(void) | |
| @@ -148,14 +161,18 @@ static void test_bytearray(void) | |||
|---|---|---|---|
| 148 | 161 | assert(*tmpchar == 'a'); | |
| 149 | 162 | free(tmpchar); | |
| 150 | 163 | ||
| 151 | - | tmpchar = bytearray_pop(bt, NULL); | |
| 152 | - | assert(tmpchar == NULL); | |
| 153 | - | ||
| 154 | 164 | bytearray_push(bt, "a"); | |
| 155 | 165 | tmpchar = bytearray_pop(bt, NULL); | |
| 156 | 166 | assert(*tmpchar == 'a'); | |
| 157 | 167 | free(tmpchar); | |
| 158 | 168 | ||
| 169 | + | bytearray_push(bt, "a"); | |
| 170 | + | bytearray_push(bt, "a"); | |
| 171 | + | bytearray_push(bt, "a"); | |
| 172 | + | assert(bt->length == 3); | |
| 173 | + | bytearray_remove_range(bt, 0, bt->length, NULL); | |
| 174 | + | assert(bt->length == 0); | |
| 175 | + | ||
| 159 | 176 | delete_bytearray(bt, NULL); | |
| 160 | 177 | } | |
| 161 | 178 | #if __STDC_VERSION__ >= 201112L | |
| @@ -242,6 +259,7 @@ static void test_ll(void) | |||
|---|---|---|---|
| 242 | 259 | ||
| 243 | 260 | ||
| 244 | 261 | ll_remove_range(ll, 0, ll->length-1, NULL); | |
| 262 | + | assert(ll->length == 1); | |
| 245 | 263 | ||
| 246 | 264 | delete_ll(ll, NULL); | |
| 247 | 265 | } | |
Msrc/vector.c
| @@ -17,14 +17,6 @@ Vector* vector_with_capacity(size_t capacity) | |||
|---|---|---|---|
| 17 | 17 | return vector; | |
| 18 | 18 | } | |
| 19 | 19 | ||
| 20 | - | void* vector_at(const Vector* vector, size_t index) | |
| 21 | - | { | |
| 22 | - | if(index >= vector->length) | |
| 23 | - | return NULL; | |
| 24 | - | else | |
| 25 | - | return vector->items[index]; | |
| 26 | - | } | |
| 27 | - | ||
| 28 | 20 | void* vector_pop_at(Vector* vector, size_t index) | |
| 29 | 21 | { | |
| 30 | 22 | void* tmp = vector_at(vector, index); | |
| @@ -37,25 +29,18 @@ void* vector_pop_at(Vector* vector, size_t index) | |||
|---|---|---|---|
| 37 | 29 | } | |
| 38 | 30 | } | |
| 39 | 31 | ||
| 40 | - | ||
| 41 | - | void vector_remove(Vector* vector, size_t index, void (*rmv)(void*)) | |
| 42 | - | { | |
| 43 | - | if(index < vector->length) | |
| 44 | - | { | |
| 45 | - | if(rmv) | |
| 46 | - | rmv(vector->items[index]); | |
| 47 | - | memmove(vector->items+index, vector->items+index+1, (vector->length-index-1)*sizeof(*vector->items)); | |
| 48 | - | vector->length--; | |
| 49 | - | } | |
| 50 | - | } | |
| 51 | - | /* TODO: optimize */ | |
| 52 | 32 | void vector_remove_range(Vector* vector, size_t index, size_t length, void (*rmv)(void*)) | |
| 53 | 33 | { | |
| 54 | 34 | size_t i; | |
| 55 | - | for(i = 0; i < length; i++) | |
| 35 | + | if(rmv) | |
| 56 | 36 | { | |
| 57 | - | vector_remove(vector, index+i, rmv); | |
| 37 | + | for(i = index; i < length; i++) | |
| 38 | + | { | |
| 39 | + | rmv(vector_at(vector, i)); | |
| 40 | + | } | |
| 58 | 41 | } | |
| 42 | + | memmove(vector->items+index, vector->items+index+length, (vector->length-(index+length))*sizeof(*vector->items)); | |
| 43 | + | vector->length -= length; | |
| 59 | 44 | } | |
| 60 | 45 | ||
| 61 | 46 | size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*)) | |