// retoor #include "string.h" #include #include #include #include struct string_t { char *data; size_t length; size_t capacity; }; static const size_t DEFAULT_CAPACITY = 32; string_handle string_create(const char *str) { if (!str) return string_create_empty(); return string_create_n(str, strlen(str)); } string_handle string_create_empty(void) { struct string_t *s = calloc(1, sizeof(struct string_t)); if (!s) return NULL; s->data = malloc(DEFAULT_CAPACITY); if (!s->data) { free(s); return NULL; } s->data[0] = '\0'; s->length = 0; s->capacity = DEFAULT_CAPACITY; return s; } string_handle string_create_n(const char *str, size_t len) { if (!str) return string_create_empty(); if (len == 0) return string_create_empty(); struct string_t *s = malloc(sizeof(struct string_t)); if (!s) return NULL; s->capacity = len + 1; if (s->capacity < DEFAULT_CAPACITY) s->capacity = DEFAULT_CAPACITY; s->data = malloc(s->capacity); if (!s->data) { free(s); return NULL; } memcpy(s->data, str, len); s->data[len] = '\0'; s->length = len; return s; } string_handle string_format(const char *fmt, ...) { if (!fmt) return string_create_empty(); va_list args, args_copy; va_start(args, fmt); va_copy(args_copy, args); int len = vsnprintf(NULL, 0, fmt, args_copy); va_end(args_copy); if (len < 0) { va_end(args); return string_create_empty(); } struct string_t *s = malloc(sizeof(struct string_t)); if (!s) { va_end(args); return NULL; } s->capacity = (size_t)len + 1; s->data = malloc(s->capacity); if (!s->data) { free(s); va_end(args); return NULL; } vsnprintf(s->data, s->capacity, fmt, args); s->length = (size_t)len; va_end(args); return s; } string_handle string_clone(const char *str) { return string_create(str); } string_handle string_clone_handle(string_handle s) { if (!s) return NULL; return string_create_n(s->data, s->length); } string_handle string_concat(const char *a, const char *b) { if (!a) return string_create(b); if (!b) return string_create(a); size_t len_a = strlen(a); size_t len_b = strlen(b); struct string_t *s = malloc(sizeof(struct string_t)); if (!s) return NULL; s->length = len_a + len_b; s->capacity = s->length + 1; s->data = malloc(s->capacity); if (!s->data) { free(s); return NULL; } memcpy(s->data, a, len_a); memcpy(s->data + len_a, b, len_b); s->data[s->length] = '\0'; return s; } string_handle string_concat_handle(string_handle a, const char *b) { if (!a) return string_create(b); if (!b) return string_clone_handle(a); size_t len_b = strlen(b); size_t new_len = a->length + len_b; if (new_len + 1 > a->capacity) { size_t new_capacity = a->capacity * 2; while (new_capacity < new_len + 1) new_capacity *= 2; char *new_data = realloc(a->data, new_capacity); if (!new_data) return NULL; a->data = new_data; a->capacity = new_capacity; } memcpy(a->data + a->length, b, len_b); a->length = new_len; a->data[a->length] = '\0'; return a; } void string_append(string_handle s, const char *str) { if (!s || !str) return; string_append_n(s, str, strlen(str)); } void string_append_n(string_handle s, const char *str, size_t len) { if (!s || !str || len == 0) return; if (s->length + len + 1 > s->capacity) { size_t new_capacity = s->capacity; while (new_capacity < s->length + len + 1) new_capacity *= 2; char *new_data = realloc(s->data, new_capacity); if (!new_data) return; s->data = new_data; s->capacity = new_capacity; } memcpy(s->data + s->length, str, len); s->length += len; s->data[s->length] = '\0'; } void string_appendf(string_handle s, const char *fmt, ...) { if (!s || !fmt) return; va_list args; va_start(args, fmt); int len = vsnprintf(NULL, 0, fmt, args); va_end(args); if (len < 0) return; if (s->length + (size_t)len + 1 > s->capacity) { size_t new_capacity = s->capacity; while (new_capacity < s->length + (size_t)len + 1) new_capacity *= 2; char *new_data = realloc(s->data, new_capacity); if (!new_data) return; s->data = new_data; s->capacity = new_capacity; } va_start(args, fmt); vsnprintf(s->data + s->length, s->capacity - s->length, fmt, args); s->length += (size_t)len; va_end(args); } void string_append_handle(string_handle dest, string_handle src) { if (!dest || !src) return; string_append_n(dest, src->data, src->length); } size_t string_length(string_handle s) { return s ? s->length : 0; } size_t string_capacity(string_handle s) { return s ? s->capacity : 0; } const char *string_c_str(string_handle s) { return s ? s->data : ""; } char *string_release(string_handle s) { if (!s) return NULL; char *data = s->data; free(s); return data; } bool string_equals(string_handle a, string_handle b) { if (!a && !b) return true; if (!a || !b) return false; if (a->length != b->length) return false; return memcmp(a->data, b->data, a->length) == 0; } bool string_equals_c_str(string_handle s, const char *str) { if (!s && !str) return true; if (!s || !str) return false; return strcmp(s->data, str) == 0; } bool string_is_empty(string_handle s) { return !s || s->length == 0; } void string_clear(string_handle s) { if (!s) return; s->length = 0; if (s->data) s->data[0] = '\0'; } void string_destroy(string_handle s) { if (!s) return; if (s->data) free(s->data); free(s); }