#include #include #include #include #include "scufcont/scufcont.h" #include "scufcont/DString.h" ScufContResult SCDString_alloc(SCDString *const dstr, const char *str, const size_t len) { dstr->data = (char *) malloc(sizeof(char) * (len + 1)); dstr->len = len; dstr->capacity = len + 1; if (dstr->data == NULL) { return SCUFCONT_OUT_OF_MEMORY; } dstr->data = memcpy(dstr->data, str, len); dstr->data[len] = '\0'; return SCUFCONT_SUCCESS; } ScufContResult SCDString_reserve(SCDString *const dstr, const size_t new_capacity) { if (dstr->capacity < new_capacity) { errno = 0; dstr->data = (char *) realloc(dstr->data, sizeof(char) * new_capacity); if (errno != 0) { return SCUFCONT_OUT_OF_MEMORY; } dstr->capacity = new_capacity; } return SCUFCONT_SUCCESS; } void SCDString_free(SCDString *const dstr) { if (dstr->data != NULL) { free(dstr->data); dstr->data = NULL; } dstr->len = 0; dstr->capacity = 0; } bool SCDString_equal(const SCDString *const s1, const SCDString *const 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 SCDString_equal_c_str(const SCDString *const 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 SCDString_equal_next_chars_c_str( const SCDString *const 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; } ScufContResult SCDString_concat_c_str( SCDString *const dstr, const char *str, const size_t str_len ) { const size_t new_len = dstr->len + str_len; if (new_len > dstr->capacity) { ScufContResult res = SCDString_reserve(dstr, new_len + 1); if (res != SCUFCONT_SUCCESS) { return res; } } strncpy(dstr->data + dstr->len, str, str_len); dstr->data[new_len] = '\0'; dstr->len = new_len; return SCUFCONT_SUCCESS; } ScufContResult SCDString_alloc_concat_c_strs( SCDString *const dstr, const char *s1, const size_t s1_len, const char *s2, const size_t s2_len ) { ScufContResult res = SCDString_alloc(dstr, s1, s1_len); if (res != SCUFCONT_SUCCESS) { return res; } res = SCDString_concat_c_str(dstr, s2, s2_len); if (res != SCUFCONT_SUCCESS) { return res; } return SCUFCONT_SUCCESS; } ScufContResult SCDString_split( const SCDString *const dstr, const char *delim, SCDString **const split_arr, size_t *arr_len ) { ScufContResult ret = SCUFCONT_SUCCESS; *arr_len = 0; SCDString elem; ScufContResult res = SCDString_alloc(&elem, "", 0); if (res != SCUFCONT_SUCCESS) { return res; } const size_t delim_len = strlen(delim); for (size_t i = 0; i < dstr->len; i++) { if (SCDString_equal_next_chars_c_str(dstr, delim, delim_len, i)) { *arr_len += 1; *split_arr = realloc(*split_arr, sizeof(SCDString) * (*arr_len)); if (split_arr == NULL) { ret = SCUFCONT_OUT_OF_MEMORY; break; } (*split_arr)[(*arr_len) - 1] = elem; res = SCDString_alloc(&elem, "", 0); if (res != SCUFCONT_SUCCESS) { ret = res; break; } i += delim_len - 1; } else { SCDString_concat_c_str(&elem, dstr->data + i, 1); } } if (ret == SCUFCONT_SUCCESS) { *split_arr = realloc(*split_arr, sizeof(SCDString) * (*arr_len + 1)); if (split_arr != NULL) { (*split_arr)[*arr_len] = elem; *arr_len += 1; return ret; } ret = SCUFCONT_OUT_OF_MEMORY; } for (size_t i = 0; i < *arr_len; i++) { SCDString_free((*split_arr) + i); } free(*split_arr); *split_arr = NULL; SCDString_free(&elem); return ret; } void SCDString_split_arr_free(SCDString **const arr, const size_t arr_len) { for (size_t i = 0; i < arr_len; i++) { SCDString_free((*arr) + i); } free(*arr); *arr = NULL; }