#include #include #include #include #include "DynString.h" #include "log.h" static void DynString_reserve(DynString* dstr, const size_t new_capacity) { if (dstr->capacity >= new_capacity) { return; } errno = 0; dstr->data = (char*) realloc(dstr->data, sizeof(char) * new_capacity); if (errno != 0) { LOG_FATAL("Ran out of memory"); } dstr->capacity = new_capacity; } DynString DynString_alloc(const char* str, const size_t len) { DynString dstr = { .data = (char*) malloc(sizeof(char) * (len + 1)), .len = len, .capacity = len + 1 }; if (dstr.data == NULL) { LOG_FATAL("Ran out of memory"); } dstr.data = memcpy(dstr.data, str, len); dstr.data[len] = '\0'; return dstr; } void DynString_free(DynString* dstr) { if (dstr->data != NULL) { free(dstr->data); dstr->data = NULL; } dstr->len = 0; dstr->capacity = 0; } bool DynString_is_null(const DynString* dstr) { return dstr->data == NULL; } const char* DynString_c_str(const DynString* dstr) { return dstr->data; } bool DynString_equal(const DynString* s1, const DynString* s2) { if (s1->data == NULL || s2->data == NULL) { return false; } if (s1->len != s2->len) { return false; } for (size_t i = 0; i < s1->len; i++) { if (s1->data[i] != s2->data[i]) { return false; } } return true; } bool DynString_equal_c_str(const DynString* s1, const char* s2) { if (s1->data == NULL || s2 == NULL) { return false; } if (s1->len != strlen(s2)) { return false; } for (size_t i = 0; i < s1->len; i++) { if (s1->data[i] != s2[i]) { return false; } } return true; } bool DynString_equal_next_chars_c_str( const DynString* dstr, const char* str, const size_t str_len, size_t s ) { if (dstr->len < s || dstr->len < s + str_len) { return false; } const size_t e = s + str_len; for (size_t i = 0; s < e; s++, i++) { if (dstr->data[s] != str[i]) { return false; } } return true; } void DynString_concat_c_str( DynString* dstr, const char* str, const size_t str_len ) { const size_t new_len = dstr->len + str_len; if (new_len > dstr->capacity) { DynString_reserve(dstr, new_len + 1); } strncpy(dstr->data + dstr->len, str, str_len); dstr->data[new_len] = '\0'; dstr->len = new_len; } DynString DynString_alloc_concat_c_strs( const char* s1, const size_t s1_len, const char* s2, const size_t s2_len ) { DynString dstr = DynString_alloc(s1, s1_len); DynString_concat_c_str(&dstr, s2, s2_len); return dstr; } DynString* DynString_split( const DynString* dstr, const char* delim, size_t* ret_len ) { DynString* arr = (DynString*) malloc(0); if (arr == NULL) { LOG_FATAL("malloc failed"); } *ret_len = 0; DynString elem = DynString_alloc("", 0); size_t delim_len = strlen(delim); for (size_t i = 0; i < dstr->len; i++) { if (DynString_equal_next_chars_c_str(dstr, delim, delim_len, i)) { arr = realloc(arr, sizeof(DynString) * (*ret_len + 1)); if (arr == NULL) { LOG_FATAL("realloc failed"); } arr[*ret_len] = elem; *ret_len += 1; elem = DynString_alloc("", 0); i += delim_len - 1; } else { DynString_concat_c_str(&elem, dstr->data + i, 1); } } arr = realloc(arr, sizeof(DynString) * (*ret_len + 1)); if (arr == NULL) { LOG_FATAL("realloc failed"); } arr[*ret_len] = elem; *ret_len += 1; return arr; }