#include "config.h" #include #include #include #include #include #include #include #include #include "logerr.h" #include "math.h" #include "util.h" #include "string.h" struct String { const size_t length; const uint8_t *const bytes; }; int string_new_with( const char *const string, const size_t length, const struct String **const out ) { int rc = -1; const struct String *ret = NULL; const uint8_t *bytes = NULL; ret = malloc(sizeof(*ret)); if (ret == NULL) { logerr("malloc(): %s", strerror(errno)); goto out; } bytes = malloc(length + NULL_TERMINATOR); if (bytes == NULL) { logerr("malloc(): %s", strerror(errno)); goto out; } memcpy((void *)bytes, string, length); memcpy((void *)(bytes + length), "", NULL_TERMINATOR); memcpy((void *)ret, &(struct String) { .length = length, .bytes = bytes, }, sizeof(*ret)); *out = ret; rc = 0; out: if (rc) { if (bytes != NULL) { freeit((void *)&bytes); } if (ret != NULL) { freeit((void *)&ret); } } return rc; } int string_new(const char *const string, const struct String **const out) { return string_new_with(string, strlen(string), out); } void string_free(const struct String **const s) { free((void *)(*s)->bytes); free((void *)(*s)); *s = NULL; } const char * cstr(const struct String *s) { return (const char *)s->bytes; } enum Comparison string_compare(const struct String *const s1, const struct String *const s2) { if (s1->length < s2->length) { return Comparison_LT; } else if (s1->length > s2->length) { return Comparison_GT; } else { const int ret = strcmp((const char *)s1->bytes, (const char *)s2->bytes); if (ret < 0) { return Comparison_LT; } else if (ret > 0) { return Comparison_GT; } else { return Comparison_EQ; } } } bool string_equals(const struct String *const s1, const struct String *const s2) { return string_compare(s1, s2) == Comparison_EQ; } int string_append( const struct String *const s1, const struct String *const s2, const struct String **const out ) { int rc = -1; const struct String *ret = NULL; const uint8_t *bytes = NULL; size_t length; if (add_size(s1->length, s2->length, &length)) { logerr("add_size()"); goto out; } ret = malloc(sizeof(*ret)); if (ret == NULL) { logerr("malloc(): %s", strerror(errno)); goto out; } bytes = malloc(length + NULL_TERMINATOR); if (bytes == NULL) { logerr("malloc(): %s", strerror(errno)); goto out; } memcpy((void *)bytes, s1->bytes, s1->length); memcpy((void *)(bytes + s1->length), s2->bytes, s2->length); memcpy((void *)(bytes + length), "", NULL_TERMINATOR); memcpy((void *)ret, &(struct String) { .length = length, .bytes = bytes, }, sizeof(*ret)); *out = ret; rc = 0; out: if (rc) { if (bytes != NULL) { freeit((void *)&bytes); } if (ret != NULL) { freeit((void *)&ret); } } return rc; }