254 lines
4.8 KiB
C
254 lines
4.8 KiB
C
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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;
|
|
}
|