From 065b99325dd069ba8ed2bff0c134e7fc32d01184 Mon Sep 17 00:00:00 2001 From: Niki Roo Date: Mon, 28 Feb 2022 09:08:58 +0100 Subject: [PATCH] utils changes + tests (not yet ok) --- src/tests/utils/cstring.c | 15 ++++ src/utils/cstring.c | 173 +++++++++++++++++++++----------------- src/utils/cstring.h | 93 ++++++++++++++------ src/utils/utils.c | 7 ++ src/utils/utils.h | 16 +++- 5 files changed, 199 insertions(+), 105 deletions(-) diff --git a/src/tests/utils/cstring.c b/src/tests/utils/cstring.c index 23e6bcb..2df7764 100644 --- a/src/tests/utils/cstring.c +++ b/src/tests/utils/cstring.c @@ -44,6 +44,19 @@ START(init) if (s->length) FAIL("empty cstring has a size of %zu", s->length); + + END + +START(add_car) + cstring_add_car(s, 'T'); + ASSERT_EQUALS_STR("Cannot add a single char", "T", s->string); + + cstring_add_car(s, 'e'); + cstring_add_car(s, 's'); + cstring_add_car(s, 't'); + cstring_add_car(s, 'y'); + ASSERT_EQUALS_STR("Cannot add multiple chars", "Testy", s->string); + END START(adds) @@ -114,6 +127,7 @@ START(clear) if (s->length) FAIL("empty cstring has a size of %zu", s->length); + END START(addp) @@ -240,6 +254,7 @@ Suite *test_cstring(const char title[]) { TCase *core = tcase_create("core"); tcase_add_checked_fixture(core, test_cstring_setup, test_cstring_teardown); tcase_add_test(core, init); + tcase_add_test(core, add_car); tcase_add_test(core, adds); tcase_add_test(core, clear); tcase_add_test(core, addp); diff --git a/src/utils/cstring.c b/src/utils/cstring.c index 9413c47..c7f2548 100644 --- a/src/utils/cstring.c +++ b/src/utils/cstring.c @@ -96,16 +96,103 @@ void free_cstring(cstring *string) { free(string); } -void cstring_grow(cstring *self, int min) { - cstring_grow_to(self, self->length + min); +int cstring_grow(cstring *self, int min_extra) { + size_t sz = self->priv->buffer_length; + size_t req = self->length + min_extra; + + if (req > sz) { + sz += BUFFER_SIZE; + if (req > sz) + sz = req; + + return cstring_grow_to(self, sz); + } + + return 1; } -void cstring_grow_to(cstring *self, int buffer) { - if (buffer > self->priv->buffer_length) { - self->priv->buffer_length = buffer; - self->string = (char *) realloc(self->string, - sizeof(char) * self->priv->buffer_length); +int cstring_grow_to(cstring *self, int min_buffer) { + void *mem; + if (min_buffer > self->priv->buffer_length) { + self->priv->buffer_length = min_buffer; + mem = realloc(self->string, sizeof(char) * self->priv->buffer_length); + + if (mem) + self->string = (char *) mem; + else + return 0; } + + return 1; +} + +int cstring_add_car(cstring *self, char source) { + char source2[2]; + + source2[0] = source; + source2[1] = '\0'; + + return cstring_add(self, source2); +} + +int cstring_add(cstring *self, const char source[]) { + return cstring_addf(self, source, 0); +} + +int cstring_addf(cstring *self, const char source[], size_t idx) { + // Note: negative 'n' is not promised by the .h file + return cstring_addfn(self, source, idx, -1); +} + +int cstring_addn(cstring *self, const char source[], size_t n) { + return cstring_addfn(self, source, 0, n); +} + +int cstring_addfn(cstring *self, const char source[], size_t idx, size_t n) { + size_t ss; + + ss = strlen(source); + if (source && ss > idx && idx >= 0) { + ss -= idx; + + // Note: negative 'n' is not promised by the .h file + if (n >= 0 && n < ss) + ss = n; + + if (ss) { + // "+1" for the added '\0' + if (!cstring_grow(self, ss + 1)) + return 0; + + memcpy(self->string + self->length, source + idx, ss); + self->string[ss] = '\0'; + self->length += ss + 1; + } + } + + return 1; +} + +int cstring_addp(cstring *self, const char *fmt, ...) { + va_list ap; + char empty = '\0'; + + va_start(ap, fmt); + int sz = vsnprintf(&empty, 0, fmt, ap); + va_end(ap); + + char *tmp = malloc((sz + 1) * sizeof(char)); + if (!tmp) + return 0; + + va_start(ap, fmt); + sz = vsnprintf(tmp, sz + 1, fmt, ap); + va_end(ap); + + int ok = cstring_add(self, tmp); + free(tmp); + + return ok; } char *cstring_convert(cstring *self) { @@ -403,78 +490,6 @@ void cstring_reverse(cstring *self) { } } -void cstring_add_car(cstring *self, char source) { - char source2[2]; - - source2[0] = source; - source2[1] = '\0'; - - cstring_add(self, source2); -} - -void cstring_addp(cstring *self, const char *fmt, ...) { - va_list ap; - char empty = '\0'; - - va_start(ap, fmt); - int sz = vsnprintf(&empty, 0, fmt, ap); - va_end(ap); - - char *tmp = malloc((sz + 1) * sizeof(char)); - cstring_grow(self, sz); - - va_start(ap, fmt); - sz = vsnprintf(tmp, sz + 1, fmt, ap); - va_end(ap); - - cstring_add(self, tmp); - - free(tmp); -} - -void cstring_add(cstring *self, const char source[]) { - cstring_addf(self, source, 0); -} - -void cstring_addf(cstring *self, const char source[], size_t indexi) { - size_t ss, ptr; - - if (source != NULL && strlen(source) > indexi) { - ss = strlen(source) - indexi; - while ((self->length + ss) >= (self->priv->buffer_length)) { - self->priv->buffer_length += BUFFER_SIZE; - } - self->string = (char *) realloc(self->string, - sizeof(char) * self->priv->buffer_length); - - for (ptr = self->length; ptr <= (self->length + ss); ptr++) { - self->string[ptr] = source[ptr - self->length + indexi]; - } - self->length += ss; - } -} - -void cstring_addn(cstring *self, const char source[], size_t n) { - cstring_addfn(self, source, 0, n); -} - -void cstring_addfn(cstring *self, const char source[], size_t indexi, size_t n) { - size_t i; - char *tmp; - - for (i = indexi; i < (n + indexi) && source[i] != '\0'; i++) - ; - if (source[i] == '\0') { - cstring_addf(self, source, indexi); - } else { - tmp = (char *) malloc(sizeof(char) * (n + 1)); - strncpy(tmp, source + indexi, n); - tmp[n] = '\0'; - cstring_add(self, tmp); - free(tmp); - } -} - void cstring_rtrim(cstring *self, char car) { for (size_t i = self->length - 1; i >= 0; i--) { if (self->string[i] != car) diff --git a/src/utils/cstring.h b/src/utils/cstring.h index 60dc5b1..1ceb888 100644 --- a/src/utils/cstring.h +++ b/src/utils/cstring.h @@ -56,68 +56,113 @@ cstring *new_cstring(); * * Free all the resources allocated for this cstring. * - * @param string the cstring to free, which MUST NOT be used again afterward + * @param self the cstring to free, which MUST NOT be used again afterward */ -void free_cstring(cstring *string); +void free_cstring(cstring *self); -//TODO: desc: will make sure it has enough space for MIN more chars -void cstring_grow(cstring *self, int min); +/** + * Grow the cstring to accommodate that many characters in addition to those + * already held, if needed. + * + * @param self the string to grow + * @param min the minimum number of extra characters it should be able to hold + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) + */ +int cstring_grow(cstring *self, int min_extra); -//TODO: desc: will make sure it has enough space BUFFER chars (including NULL) -void cstring_grow_to(cstring *self, int buffer); +/** + * Grow the cstring to accommodate that many characters in total, if needed. + * + * @param self the string to grow + * @param min the minimum number of characters it should be able to hold + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) + */ +int cstring_grow_to(cstring *self, int min_buffer); /** * Add a char at the end of the given cstring. * * @param self the cstring to work on * @param source the character to add + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) */ -void cstring_add_car(cstring *self, char source); +int cstring_add_car(cstring *self, char source); /** - * Add a string (a sequence of char that MUST end with '\0') at the end of the given cstring. + * Add a string (a sequence of char that MUST end with '\0') at the end of the + * given cstring. * - * @param self the cstring to work on + * @param self the string to work on * @param source the string to add + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) */ -void cstring_add(cstring *self, const char source[]); +int cstring_add(cstring *self, const char source[]); /** - * Add a string (a sequence of char that MUST end with '\0') at the end of the given cstring, starting from index. + * Add a string (a sequence of char that MUST end with '\0') at the end of the + * given cstring, starting from index. * * @param self the cstring to work on * @param source the string to add - * @param index the starting index at which to copy from the source + * @param idx the starting index at which to copy from the source + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) */ -void cstring_addf(cstring *self, const char source[], size_t index); +int cstring_addf(cstring *self, const char source[], size_t idx); /** - * Add a string (a sequence of char that MAY end with '\0') at the end of the given cstring, up to N chars long. + * Add a string (a sequence of char that MAY end with '\0') at the end of the + * given cstring, up to N chars long. * - * @param self the cstring to work on + * @param self the string to work on * @param source the string to add * @param n the maximum number of chars to add (excluding the NUL byte) + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) */ -void cstring_addn(cstring *self, const char source[], size_t n); +int cstring_addn(cstring *self, const char source[], size_t n); /** - * Add a string (a sequence of char that MAY end with '\0') at the end of the given cstring, starting from index, up to N chars long. + * Add a string (a sequence of char that MAY end with '\0') at the end of the + * given cstring, starting from index, up to N chars long. * - * @param self the cstring to work on + * @param self the string to work on * @param source the string to add - * @param index the starting index at which to copy from the source + * @param idx the starting index at which to copy from the source * @param n the maximum number of chars to add (excluding the NUL byte) + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) */ -void cstring_addfn(cstring *self, const char source[], size_t index, size_t n); +int cstring_addfn(cstring *self, const char source[], size_t idx, size_t n); -//TODO: desc + tests -void cstring_addp(cstring *self, const char *fmt, ...); +/** + * Add a string via the usual printf formatters. + * + * @param self the string to add to + * @param fmt the required format specifiers (@{see printf}) + * @param ... the printf-format parameters + * + * @return TRUE if success (FALSE means it was unable to grow due to memory + * pressure) + */ +int cstring_addp(cstring *self, const char *fmt, ...); /** - * Cut the cstring at the given size if it is greater. + * Cut the string at the given size if it is greater. * E.g.: it will have (at most) this many characters (without counting NUL) in it after. * - * @param self the cstring to work on + * @param self the string to work on * @param size the size to cut at (the maximum size of the cstring after this operation, NUL excepted) */ void cstring_cut_at(cstring *self, size_t size); diff --git a/src/utils/utils.c b/src/utils/utils.c index 7770573..ab7ccb1 100644 --- a/src/utils/utils.c +++ b/src/utils/utils.c @@ -20,6 +20,7 @@ #include #include "utils.h" +#include "cstring.h" char *utils_strdup(const char *source) { size_t sz = strlen(source); @@ -27,3 +28,9 @@ char *utils_strdup(const char *source) { strcpy(new, source); return new; } + +cstring *utils_cstrdup(const cstring *source) { + cstring *clone = new_cstring(); + cstring_add(clone, source->string); + return clone; +} diff --git a/src/utils/utils.h b/src/utils/utils.h index d5104ab..d236393 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -31,20 +31,32 @@ extern "C" { #endif +#include "cstring.h" #include "array.h" #include "desktop.h" #include "print.h" #include "timing.h" /** - * A C99-compatible strdup function. + * A C99-compatible strdup function (i.e., a strdup for + * CentOS 6). * * @param source the source string to copy * - * @return a new string (malloc'ed) which your are now respionsible of + * @return a new string (malloc'ed) which your are now responsible of */ char *utils_strdup(const char *source); +/** + * A C99-compatible strdup function (i.e., a strdup for + * CentOS 6). + * + * @param source the source string to copy + * + * @return a new string (malloc'ed) which your are now responsible of + */ +cstring *utils_cstrdup(const cstring *source); + #endif // UTILS_H #ifdef __cplusplus -- 2.27.0