#include #include #include #include #include "ucore/dstr.h" #include "ucore/utils.h" void uc_dstr_init(struct DStr *str) { str->len = 0; str->allocated = 0; str->str = NULL; } void uc_dstr_destroy(struct DStr *str) { #ifdef DEBUG if (str->str) { memset(str->str, 0xcc, str->allocated); } str->len = -1; str->allocated = -1; #endif free(str->str); } int uc_dstr_copy(struct DStr *dest, const struct DStr *src) { char *s; uc_dstr_init(dest); if (src->allocated == 0) { return 0; } s = uc_dstr_put(dest, src->len); if (s == NULL) { return -1; } //+1 to copy a potential nul terminator, uc_dstr_put //guarantees we have room for it. memcpy(s, src->str, UC_MIN(src->len + 1, src->allocated)); return 0; } size_t uc_dstr_available(const struct DStr *str) { return str->allocated - str->len; } int uc_dstr_ensure(struct DStr *str, size_t total) { if (str->allocated < total) { //allocate a minimum no. of bytes, and one //additional for the common case of nul terminating //the string size_t new_len = UC_MAX(7U, total) + 1; char *new_str = realloc(str->str, new_len); if (new_str == NULL) { return -1; } str->str = new_str; str->allocated = new_len; } return 0; } void uc_dstr_reset(struct DStr *str) { str->len = 0; #ifdef DEBUG if (str->str) { memset(str->str, 0xcc, str->allocated); } #endif } void uc_dstr_terminate(struct DStr *str) { uc_dstr_ensure(str, str->len + 1); str->str[str->len] = 0; } char *uc_dstr_str(struct DStr *str) { uc_dstr_terminate(str); return str->str; } char *uc_dstr_put(struct DStr *str, size_t len) { char *start; if (uc_dstr_ensure(str, str->len + len) != 0) { return NULL; } start = str->str + str->len; str->len += len; return start; } size_t uc_dstr_put_str_filter(struct DStr *str, const char *s, int (*is_x)(int c)) { size_t len = strlen(s); size_t i; size_t idx = 0; if (uc_dstr_ensure(str, str->len + len) != 0) { return 0; } for (i = 0; i < len; i++) { if (is_x(s[i])) { str->str[str->len + idx]= s[i]; idx++; } } str->len += idx; return idx; } int uc_dstr_put_str_sz(struct DStr *str, const char *s, size_t len) { char *start = uc_dstr_put(str, len); if (start == NULL) { return -1; } memcpy(start, s, len); return 0; } int uc_dstr_put_str(struct DStr *str, const char *s) { size_t len = strlen(s); return uc_dstr_put_str_sz(str, s ,len); } int uc_dstr_put_char(struct DStr *str, char c) { char *start = uc_dstr_put(str, 1); if (start == NULL) { return -1; } *start = c; return 0; } void uc_dstr_own(struct DStr *str, char *s) { size_t len = strlen(s); if (str->str) { free(str); } str->len = len; str->allocated = len + 1; str->str = s; } char *uc_dstr_steal(struct DStr *str) { char *s = str->str; uc_dstr_init(str); return s; } void uc_str_swap(struct DStr *a, struct DStr *b) { struct DStr tmp; tmp = *a; *a = *b; *b = tmp; } size_t uc_dstr_replace(struct DStr *str, char f, char r) { size_t i; size_t count = 0; if (str->len == 0) { return 0; } for (i = 0; i < str->len; i++) { if (str->str[i] == f) { str->str[i] = r; count++; } } return count; } void uc_dstr_trim(struct DStr *str) { size_t spaces; uc_dstr_terminate(str); //spaces at the start spaces = strspn(str->str, " \t\n\v\f\r"); if (spaces > 0) { memmove(str->str, str->str + spaces, str->len - spaces); str->len -= spaces; } //spaces at the end if (str->len > 0) { size_t idx = str->len - 1; do { if (strchr(" \t\n\v\f\r", str->str[idx]) == NULL) { break; } else { str->len--; idx--; } } while (idx != 0); } } int uc_dstr_sprintf(struct DStr *str, const char *fmt, ...) { va_list ap; int rc; va_start(ap, fmt); rc = uc_dstr_vsprintf(str, fmt, ap); va_end(ap); return rc; } int uc_dstr_vsprintf(struct DStr *str, const char *fmt, va_list ap_) { va_list ap; int rc; int available; int needed; rc = uc_dstr_ensure(str, str->len + 1); if (rc != 0) { return -1; } available = uc_dstr_available(str); va_copy(ap, ap_); needed = vsnprintf(str->str + str->len, available, fmt, ap); va_end(ap); if (needed <= 0) { return needed; } if (needed >= available) { rc = uc_dstr_ensure(str, str->len + needed); if (rc != 0) { return -1; } available = uc_dstr_available(str); va_copy(ap, ap_); needed = vsnprintf(str->str + str->len, available, fmt, ap); va_end(ap); } str->len += needed; return needed; }