#include #include #include #include "lsm.h" #include "lsm/str_internal.h" #define MIN(x, y) (((x) < (y)) ? (x) : (y)) lsm_error lsm_str_init(lsm_str **ptr, char *s) { lsm_str *str = calloc(1, sizeof(lsm_str)); if (str == NULL) { return lsm_error_failed_alloc; } lsm_str_overwrite(str, s); *ptr = str; return lsm_error_ok; } lsm_error lsm_str_init_zero(lsm_str **ptr) { lsm_str *str = calloc(1, sizeof(lsm_str)); if (str == NULL) { return lsm_error_failed_alloc; } *ptr = str; return lsm_error_ok; } lsm_error lsm_str_init_copy(lsm_str **ptr, const char *s) { lsm_str *str = calloc(1, sizeof(lsm_str)); if (str == NULL) { return lsm_error_failed_alloc; } lsm_str_overwrite_copy(str, s); *ptr = str; return lsm_error_ok; } lsm_error lsm_str_init_copy_n(lsm_str **ptr, const char *s, uint64_t len) { lsm_str *str = calloc(1, sizeof(lsm_str)); if (str == NULL) { return lsm_error_failed_alloc; } lsm_str_overwrite_copy_n(str, s, len); *ptr = str; return lsm_error_ok; } void lsm_str_overwrite(lsm_str *str, char *s) { str->len = strlen(s); if (str->len <= 8) { memcpy(str->data.val, s, str->len); free(s); } else { str->data.ptr = s; } } lsm_error lsm_str_overwrite_copy(lsm_str *str, const char *s) { return lsm_str_overwrite_copy_n(str, s, strlen(s)); } lsm_error lsm_str_overwrite_copy_n(lsm_str *str, const char *s, uint64_t len) { if (len <= 8) { memcpy(str->data.val, s, len); } else { char *buf = malloc(len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } memcpy(buf, s, len); str->data.ptr = buf; } str->len = len; return lsm_error_ok; } void lsm_str_zero(lsm_str *str) { if (str->len > 8) { free(str->data.ptr); } str->len = 0; } void lsm_str_free(lsm_str *str) { lsm_str_zero(str); free(str); } uint64_t lsm_str_len(const lsm_str *str) { return str->len; } const char *lsm_str_ptr(lsm_str *str) { if (str->len <= 8) { return str->data.val; } else { return str->data.ptr; } } char lsm_str_char(lsm_str *str, uint64_t index) { if (str->len <= 8) { return str->data.val[index]; } else { return str->data.ptr[index]; } } lsm_error lsm_str_substr(lsm_str *out, lsm_str *str, uint64_t start, uint64_t end) { // A substring that starts past the string's length will have length 0 uint64_t len = start < str->len ? end - start : 0; const char *str_ptr = lsm_str_ptr(str); if (len <= 8) { /* lsm_str_zero(out); */ memcpy(out->data.val, &str_ptr[start], len); } else { char *buf = malloc(len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } memcpy(buf, &str_ptr[start], len); /* lsm_str_zero(out); */ out->data.ptr = buf; } out->len = len; return lsm_error_ok; } uint64_t lsm_str_cmp(lsm_str *s1, uint64_t s1_offset, lsm_str *s2, uint64_t s2_offset) { uint64_t index = 0; uint64_t max_len = MIN(s1->len - s1_offset, s2->len - s2_offset); while ((index < max_len) && (lsm_str_char(s1, s1_offset + index) == lsm_str_char(s2, s2_offset + index))) { index++; } return index; } lsm_error lsm_str_truncate(lsm_str *s, uint64_t new_len) { if (new_len >= s->len) { return lsm_error_ok; } if (new_len <= 8) { char *s_buf = s->data.ptr; memcpy(s->data.val, lsm_str_ptr(s), new_len); if (s->len > 8) { free(s_buf); } } else { char *buf = malloc(new_len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } memcpy(buf, s->data.ptr, new_len); free(s->data.ptr); s->data.ptr = buf; } s->len = new_len; return lsm_error_ok; } lsm_error lsm_str_split(lsm_str *s, lsm_str *s2, uint64_t index) { lsm_error res = lsm_str_substr(s2, s, index, s->len); if (res != lsm_error_ok) { return res; } return lsm_str_truncate(s, index); } bool lsm_str_eq(lsm_str *s1, lsm_str *s2) { if (s1->len != s2->len) { return false; } return memcmp(lsm_str_ptr(s1), lsm_str_ptr(s2), s1->len) == 0; } lsm_error lsm_str_append(lsm_str *s, lsm_str *s2) { if (s2->len == 0) { return lsm_error_ok; } uint64_t new_len = s->len + s2->len; if (new_len <= 8) { memcpy(&s->data.val[s->len], s2->data.val, s2->len); } else { char *buf; if (s->len <= 8) { buf = malloc(new_len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } memcpy(buf, s->data.val, s->len); } else { buf = realloc(s->data.ptr, new_len * sizeof(char)); if (buf == NULL) { return lsm_error_failed_alloc; } } memcpy(&buf[s->len], lsm_str_ptr(s2), s2->len); s->data.ptr = buf; } s->len += s2->len; return lsm_error_ok; }