utils changes + tests (not yet ok)
authorNiki Roo <niki@nikiroo.be>
Mon, 28 Feb 2022 08:08:58 +0000 (09:08 +0100)
committerNiki Roo <niki@nikiroo.be>
Mon, 28 Feb 2022 08:08:58 +0000 (09:08 +0100)
src/tests/utils/cstring.c
src/utils/cstring.c
src/utils/cstring.h
src/utils/utils.c
src/utils/utils.h

index 23e6bcb951512e87c90c4bedd1dbfbb99d8a9878..2df7764f7b6f05bd1caf9a24fad4f749164a9b0d 100644 (file)
@@ -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);
index 9413c4777bdc68709ef1b5498e8764dfef947050..c7f2548627345bca7f47e30f6e59406ac9a92e1a 100644 (file)
@@ -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)
index 60dc5b1d534ef4179925ed1eb47d61151c8a11c6..1ceb888201562baa0a7b349bba457794ff8c6552 100644 (file)
@@ -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 <tt>printf</tt> 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);
index 7770573d3af9864402af4dad90a9b716feac12ea..ab7ccb1faaf4054dc341ee7f29207627694324c6 100644 (file)
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #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;
+}
index d5104ab42b8fb417e1f4175de32e4c1f60431a3a..d23639352be24b05fb164a2e2bd07dc1aa270f78 100644 (file)
 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 <tt>strdup</tt> function (i.e., a <tt>strdup</tt> 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 <tt>strdup</tt> function (i.e., a <tt>strdup</tt> 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