diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/string.c | 149 | ||||
-rw-r--r-- | src/string.h | 22 |
2 files changed, 169 insertions, 2 deletions
diff --git a/src/string.c b/src/string.c index 6e1ba40..dce00f3 100644 --- a/src/string.c +++ b/src/string.c @@ -1,11 +1,156 @@ #include "config.h" +#include <assert.h> +#include <errno.h> #include <stddef.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "logerr.h" +#include "math.h" +#include "util.h" #include "string.h" + struct String { - char *bytes; - size_t length; + 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) { + free((void *)bytes); + ret = NULL; + } + if (ret != NULL) { + free((void *)ret); + ret = NULL; + } + } + 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_equal(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; + } + } +} + +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) { + free((void *)bytes); + bytes = NULL; + } + if (ret != NULL) { + free((void *)ret); + ret = NULL; + } + } + return rc; +} diff --git a/src/string.h b/src/string.h index 2a60e26..e945b40 100644 --- a/src/string.h +++ b/src/string.h @@ -1 +1,23 @@ struct String; + +enum Comparison { + Comparison_LT, + Comparison_EQ, + Comparison_GT, +}; + +int +string_new(const char *const string, const struct String **out); + +void +string_free(const struct String **const s); + +enum Comparison +string_equal(const struct String *const s1, const struct String *const s2); + +int +string_append( + const struct String *const s1, + const struct String *const s2, + const struct String **const out +); |