changed signature of delete_string() (for easier usage as rmv function)
added string_cmp_cstr() added string_split() + tests added casts to macros changed name of ntoh32() to nethost32() (because it works both ways) removed bounds check in insert functions fixed bugs in string_concat() and from_cstring_reuse()
Minclude/cutils/byte_array.h
| @@ -50,8 +50,8 @@ HEDLEY_NON_NULL(3) | |||
|---|---|---|---|
| 50 | 50 | size_t* bytearray_find(const Bytearray* haystack, const void* needle, int (*cmp)(const void*, const void*)); | |
| 51 | 51 | ||
| 52 | 52 | #define new_bytearray(element_size) bytearray_with_capacity(BYTEARRAY_DEFAULT_SIZE, element_size) | |
| 53 | - | #define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, bytearray->length-1, retptr) | |
| 54 | - | #define bytearray_push(bytearray, item) bytearray_insert(bytearray, bytearray->length, item) | |
| 53 | + | #define bytearray_pop(bytearray, retptr) bytearray_pop_at(bytearray, ((Vector*)vector)->length-1, retptr) | |
| 54 | + | #define bytearray_push(bytearray, item) bytearray_insert(bytearray, ((Vector*)vector)->length, item) | |
| 55 | 55 | ||
| 56 | 56 | #endif /* CUTILS_BYTE_ARRAY_H */ | |
| 57 | 57 | ||
Minclude/cutils/dyn_string.h
| @@ -6,6 +6,7 @@ | |||
|---|---|---|---|
| 6 | 6 | #include <stdlib.h> | |
| 7 | 7 | #include <string.h> | |
| 8 | 8 | #include <cutils/common.h> | |
| 9 | + | #include <cutils/vector.h> | |
| 9 | 10 | ||
| 10 | 11 | typedef struct String | |
| 11 | 12 | { | |
| @@ -16,7 +17,7 @@ typedef struct String | |||
|---|---|---|---|
| 16 | 17 | } String; | |
| 17 | 18 | ||
| 18 | 19 | String* string_with_capacity(size_t capacity, bool null_terminated); | |
| 19 | - | void delete_string(String* string); | |
| 20 | + | void delete_string(void* string); | |
| 20 | 21 | ||
| 21 | 22 | HEDLEY_INLINE | |
| 22 | 23 | static char string_at(const String* string, size_t index) | |
| @@ -49,10 +50,10 @@ static bool string_find_str(const String* haystack, const String* needle, size_t | |||
|---|---|---|---|
| 49 | 50 | return cutil_memmem(haystack->chars, haystack->length, needle->chars, needle->length, pos); | |
| 50 | 51 | } | |
| 51 | 52 | int string_cmp(const String* s1, const String* s2); | |
| 52 | - | ||
| 53 | + | int string_cmp_cstr(const String* s1, const char* s2); | |
| 53 | 54 | size_t string_count(const String* string, char character); | |
| 54 | - | ||
| 55 | 55 | bool string_concat(String* string, const String* other); | |
| 56 | + | Vector* string_split(const String* string, const char* set, bool null_terminated); | |
| 56 | 57 | ||
| 57 | 58 | String* from_cstring(const char* cstring, bool null_terminated); | |
| 58 | 59 | String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated); | |
| @@ -62,7 +63,7 @@ char* to_cstring_del(String* string); | |||
|---|---|---|---|
| 62 | 63 | void string_move(String* dest, String* src); | |
| 63 | 64 | ||
| 64 | 65 | #define new_string(null_terminated) string_with_capacity(STRING_DEFAULT_SIZE, null_terminated) | |
| 65 | - | #define string_pop(string) string_pop_at(string, string->length-1) | |
| 66 | - | #define string_push(string, character) string_insert(string, string->length, character) | |
| 66 | + | #define string_pop(string) string_pop_at(string, ((String*)string)->length-1) | |
| 67 | + | #define string_push(string, character) string_insert(string, ((String*)string)->length, character) | |
| 67 | 68 | ||
| 68 | 69 | #endif /* CUTILS_DYN_STRING_H */ | |
Minclude/cutils/misc.h
| @@ -31,7 +31,7 @@ typedef unsigned long long ullong; | |||
|---|---|---|---|
| 31 | 31 | ||
| 32 | 32 | #if __STDC_VERSION__ >= 199901L | |
| 33 | 33 | #ifdef UINT32_MAX | |
| 34 | - | uint32_t ntoh32(uint32_t const net); | |
| 34 | + | uint32_t nethost32(uint32_t const net); | |
| 35 | 35 | #endif | |
| 36 | 36 | HEDLEY_INLINE | |
| 37 | 37 | static void memqswap_stack(void* item1, void* item2, size_t length) | |
Minclude/cutils/vector.h
| @@ -46,7 +46,7 @@ HEDLEY_NON_NULL(3) | |||
|---|---|---|---|
| 46 | 46 | size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const void*, const void*)); | |
| 47 | 47 | ||
| 48 | 48 | #define new_vector() vector_with_capacity(VECTOR_DEFAULT_SIZE) | |
| 49 | - | #define vector_pop(vector) vector_pop_at(vector, vector->length-1) | |
| 50 | - | #define vector_push(vector, item) vector_insert(vector, vector->length, item) | |
| 49 | + | #define vector_pop(vector) vector_pop_at(vector, ((Vector*)vector)->length-1) | |
| 50 | + | #define vector_push(vector, item) vector_insert(vector, ((Vector*)vector)->length, item) | |
| 51 | 51 | ||
| 52 | 52 | #endif /* CUTILS_VECTOR_H */ | |
Msrc/byte_array.c
| @@ -75,7 +75,7 @@ bool bytearray_insert(Bytearray* bytearray, size_t index, const void* item) | |||
|---|---|---|---|
| 75 | 75 | size_t length = bytearray->length; | |
| 76 | 76 | size_t size = bytearray->element_size; | |
| 77 | 77 | ||
| 78 | - | if(index > length || !bytearray_grow(bytearray, 1)) | |
| 78 | + | if(!bytearray_grow(bytearray, 1)) | |
| 79 | 79 | return false; | |
| 80 | 80 | ||
| 81 | 81 | memmove(bytearray->items+index*size+1*size, bytearray->items+index*size, (length*size-index*size)*sizeof(*bytearray->items)); | |
Msrc/dyn_string.c
| @@ -55,7 +55,7 @@ size_t string_strip(String* string, char character) | |||
|---|---|---|---|
| 55 | 55 | ||
| 56 | 56 | bool string_insert(String* string, size_t index, char character) | |
| 57 | 57 | { | |
| 58 | - | if(index > string->length || !string_grow(string, 1)) | |
| 58 | + | if(!string_grow(string, 1)) | |
| 59 | 59 | return false; | |
| 60 | 60 | ||
| 61 | 61 | memmove(string->chars+index+1, string->chars+index, (string->length-index+(string->null_terminated?1:0))*sizeof(*string->chars)); | |
| @@ -75,11 +75,12 @@ bool string_concat(String* string, const String* other) | |||
|---|---|---|---|
| 75 | 75 | { | |
| 76 | 76 | if(other->length == 0) | |
| 77 | 77 | return true; | |
| 78 | - | if(!string_grow(string, other->length-1)) | |
| 78 | + | if(!string_grow(string, other->length)) | |
| 79 | 79 | return false; | |
| 80 | 80 | memcpy(string->chars+string->length,other->chars,other->length); | |
| 81 | 81 | string->length += other->length; | |
| 82 | - | string->chars[string->length] = '\0'; | |
| 82 | + | if(string->null_terminated) | |
| 83 | + | string->chars[string->length] = '\0'; | |
| 83 | 84 | return true; | |
| 84 | 85 | } | |
| 85 | 86 | ||
| @@ -104,6 +105,15 @@ int string_cmp(const String* s1, const String* s2) | |||
|---|---|---|---|
| 104 | 105 | return ret; | |
| 105 | 106 | } | |
| 106 | 107 | ||
| 108 | + | int string_cmp_cstr(const String* s1, const char* s2) | |
| 109 | + | { | |
| 110 | + | int ret = memcmp(s1->chars, s2, s1->length < strlen(s2) ? s1->length : strlen(s2)); | |
| 111 | + | if(ret == 0 && s1->length != strlen(s2)) | |
| 112 | + | return s1->length < strlen(s2) ? -1 : 1; | |
| 113 | + | else | |
| 114 | + | return ret; | |
| 115 | + | } | |
| 116 | + | ||
| 107 | 117 | ||
| 108 | 118 | size_t string_count(const String* string, char character) | |
| 109 | 119 | { | |
| @@ -116,6 +126,51 @@ size_t string_count(const String* string, char character) | |||
|---|---|---|---|
| 116 | 126 | return ret; | |
| 117 | 127 | } | |
| 118 | 128 | ||
| 129 | + | Vector* string_split(const String* string, const char* set, bool null_terminated) | |
| 130 | + | { | |
| 131 | + | #define CHECKRESULT(x) if(!x){delete_vector(ret, delete_string);return NULL;} | |
| 132 | + | size_t i, currentvec = 0, currentlen = 0; | |
| 133 | + | char c; | |
| 134 | + | const char* orig = set; | |
| 135 | + | String* tmp; | |
| 136 | + | Vector* ret = new_vector(); | |
| 137 | + | bool is_delimiter = true; | |
| 138 | + | ||
| 139 | + | if(!ret) | |
| 140 | + | return NULL; | |
| 141 | + | ||
| 142 | + | for(i = 0; i < string->length; i++) | |
| 143 | + | { | |
| 144 | + | for(c = *set++; c != '\0'; c = *set++) | |
| 145 | + | { | |
| 146 | + | if(string_at(string, i) == c) | |
| 147 | + | { | |
| 148 | + | is_delimiter = true; | |
| 149 | + | currentlen = 0; | |
| 150 | + | break; | |
| 151 | + | } else { | |
| 152 | + | is_delimiter = false; | |
| 153 | + | } | |
| 154 | + | } | |
| 155 | + | if(!is_delimiter) | |
| 156 | + | { | |
| 157 | + | if(currentlen == 0) | |
| 158 | + | { | |
| 159 | + | tmp = new_string(null_terminated); | |
| 160 | + | CHECKRESULT(tmp); | |
| 161 | + | CHECKRESULT(vector_push(ret, tmp)); | |
| 162 | + | currentvec++; | |
| 163 | + | } | |
| 164 | + | currentlen++; | |
| 165 | + | CHECKRESULT(string_push(vector_at(ret, currentvec-1), string_at(string, i))); | |
| 166 | + | } | |
| 167 | + | set = orig; | |
| 168 | + | } | |
| 169 | + | ||
| 170 | + | return ret; | |
| 171 | + | #undef CHECKRESULT | |
| 172 | + | } | |
| 173 | + | ||
| 119 | 174 | bool string_grow(String* string, size_t add) | |
| 120 | 175 | { | |
| 121 | 176 | if(string->length+add < string->length) | |
| @@ -143,9 +198,9 @@ bool string_adjust_size(String* string, size_t size) | |||
|---|---|---|---|
| 143 | 198 | } | |
| 144 | 199 | ||
| 145 | 200 | ||
| 146 | - | void delete_string(String* string) | |
| 201 | + | void delete_string(void* string) | |
| 147 | 202 | { | |
| 148 | - | free(string->chars); | |
| 203 | + | free(((String*)string)->chars); | |
| 149 | 204 | free(string); | |
| 150 | 205 | } | |
| 151 | 206 | ||
| @@ -178,6 +233,7 @@ String* from_cstring_reuse(char* cstring, size_t capacity, bool null_terminated) | |||
|---|---|---|---|
| 178 | 233 | string->chars = cstring; | |
| 179 | 234 | string->length = strlen(cstring); | |
| 180 | 235 | string->capacity = capacity; | |
| 236 | + | string->null_terminated = null_terminated; | |
| 181 | 237 | ||
| 182 | 238 | return string; | |
| 183 | 239 | } | |
Msrc/misc.c
| @@ -12,7 +12,7 @@ void sleep_ms(unsigned int milliseconds) | |||
|---|---|---|---|
| 12 | 12 | ||
| 13 | 13 | #if __STDC_VERSION__ >= 199901L | |
| 14 | 14 | #ifdef UINT32_MAX | |
| 15 | - | uint32_t ntoh32(uint32_t const net) | |
| 15 | + | uint32_t nethost32(uint32_t const net) | |
| 16 | 16 | { | |
| 17 | 17 | uint8_t data[4]; | |
| 18 | 18 | memcpy(&data, &net, sizeof(data)); | |
Msrc/test.c
| @@ -72,6 +72,7 @@ static void test_string(void) | |||
|---|---|---|---|
| 72 | 72 | char* cstring; | |
| 73 | 73 | size_t tmp; | |
| 74 | 74 | int truth; | |
| 75 | + | Vector* vec; | |
| 75 | 76 | ||
| 76 | 77 | for(truth = false; truth == false || truth == true; truth++) | |
| 77 | 78 | { | |
| @@ -160,6 +161,18 @@ static void test_string(void) | |||
|---|---|---|---|
| 160 | 161 | free(string); | |
| 161 | 162 | free(string2); | |
| 162 | 163 | ||
| 164 | + | string = from_cstring(" -hi1 hi2 hello3 ; hi4!-!hi5- ", false); | |
| 165 | + | vec = string_split(string, " ;-", true); | |
| 166 | + | assert(vec->length == 5); | |
| 167 | + | assert(string_cmp_cstr(vector_at(vec,0), "hi1") == 0); | |
| 168 | + | assert(string_cmp_cstr(vector_at(vec,1), "hi2") == 0); | |
| 169 | + | assert(string_cmp_cstr(vector_at(vec,2), "hello3") == 0); | |
| 170 | + | assert(string_cmp_cstr(vector_at(vec,3), "hi4!") == 0); | |
| 171 | + | assert(string_cmp_cstr(vector_at(vec,4), "!hi5") == 0); | |
| 172 | + | ||
| 173 | + | delete_string(string); | |
| 174 | + | delete_vector(vec, delete_string); | |
| 175 | + | ||
| 163 | 176 | } | |
| 164 | 177 | ||
| 165 | 178 | static void test_bytearray(void) | |
Msrc/vector.c
| @@ -61,7 +61,7 @@ size_t* vector_find(const Vector* haystack, const void* needle, int (*cmp)(const | |||
|---|---|---|---|
| 61 | 61 | ||
| 62 | 62 | bool vector_insert(Vector* vector, size_t index, void* item) | |
| 63 | 63 | { | |
| 64 | - | if(index > vector->length || !vector_grow(vector, 1)) | |
| 64 | + | if(!vector_grow(vector, 1)) | |
| 65 | 65 | return false; | |
| 66 | 66 | ||
| 67 | 67 | memmove(vector->items+index+1, vector->items+index, (vector->length-index)*sizeof(*vector->items)); | |