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)
if (s->length)
FAIL("empty cstring has a size of %zu", s->length);
+
END
START(addp)
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);
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) {
}
}
-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)
*
* 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);
#include <string.h>
#include "utils.h"
+#include "cstring.h"
char *utils_strdup(const char *source) {
size_t sz = strlen(source);
strcpy(new, source);
return new;
}
+
+cstring *utils_cstrdup(const cstring *source) {
+ cstring *clone = new_cstring();
+ cstring_add(clone, source->string);
+ return clone;
+}
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