From b8df6783e3b859013fe5defe80a304372bff93eb Mon Sep 17 00:00:00 2001 From: rephorm Date: Fri, 16 Feb 2007 23:49:55 +0000 Subject: [PATCH] add ecore_strlcat for symmetry add ecore_strbuf, an auto-expanding string buffer for building long strings whose length isn't easily determinable beforehand. for now just supports append. SVN revision: 28379 --- legacy/ecore/src/lib/ecore/Ecore_Data.h | 11 ++ legacy/ecore/src/lib/ecore/Makefile.am | 1 + legacy/ecore/src/lib/ecore/ecore_str.c | 36 +++++++ legacy/ecore/src/lib/ecore/ecore_strbuf.c | 117 ++++++++++++++++++++++ 4 files changed, 165 insertions(+) create mode 100644 legacy/ecore/src/lib/ecore/ecore_strbuf.c diff --git a/legacy/ecore/src/lib/ecore/Ecore_Data.h b/legacy/ecore/src/lib/ecore/Ecore_Data.h index 88adfffc3a..1b8261e82f 100644 --- a/legacy/ecore/src/lib/ecore/Ecore_Data.h +++ b/legacy/ecore/src/lib/ecore/Ecore_Data.h @@ -60,6 +60,9 @@ extern "C" { typedef struct _ecore_list_node Ecore_List_Node; # define ECORE_LIST_NODE(node) ((Ecore_List_Node *)node) + + typedef struct _ecore_strbuf Ecore_Strbuf; +# define ECORE_STRBUF(buf) ((Ecore_Strbuf *)buf) struct _ecore_list_node { void *data; @@ -476,6 +479,14 @@ extern "C" { /* Add a function to free the data stored in nodes */ EAPI int ecore_tree_set_free_cb(Ecore_Tree * tree, Ecore_Free_Cb free_func); + +Ecore_Strbuf * ecore_strbuf_new(void); +Ecore_Strbuf * ecore_strbuf_new(void); +void ecore_strbuf_free(Ecore_Strbuf *buf); +void ecore_strbuf_append(Ecore_Strbuf *buf, const char *str); +void ecore_strbuf_append_char(Ecore_Strbuf *buf, char c); +const char * ecore_strbuf_string_get(Ecore_Strbuf *buf); + #ifdef __cplusplus } #endif diff --git a/legacy/ecore/src/lib/ecore/Makefile.am b/legacy/ecore/src/lib/ecore/Makefile.am index bae47f1a4f..34a0aa6184 100644 --- a/legacy/ecore/src/lib/ecore/Makefile.am +++ b/legacy/ecore/src/lib/ecore/Makefile.am @@ -25,6 +25,7 @@ ecore_plugin.c \ ecore_sheap.c \ ecore_signal.c \ ecore_str.c \ +ecore_strbuf.c \ ecore_strings.c \ ecore_time.c \ ecore_timer.c \ diff --git a/legacy/ecore/src/lib/ecore/ecore_str.c b/legacy/ecore/src/lib/ecore/ecore_str.c index 6c2e4679e4..092e6e48d9 100644 --- a/legacy/ecore/src/lib/ecore/ecore_str.c +++ b/legacy/ecore/src/lib/ecore/ecore_str.c @@ -60,6 +60,42 @@ ecore_strlcpy(char *dst, const char *src, size_t siz) #endif } +/* + * Appends src to string dst of size siz (unlike strncat, siz is the + * full size of dst, not space left). At most siz-1 characters + * will be copied. Always NUL terminates (unless siz <= strlen(dst)). + * Returns strlen(src) + MIN(siz, strlen(initial dst)). + * If retval >= siz, truncation occurred. + */ +size_t +strlcat(char *dst, const char *src, size_t siz) +{ + char *d = dst; + const char *s = src; + size_t n = siz; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (n-- != 0 && *d != '\0') + d++; + dlen = d - dst; + n = siz - dlen; + + if (n == 0) + return(dlen + strlen(s)); + while (*s != '\0') { + if (n != 1) { + *d++ = *s; + n--; + } + s++; + } + *d = '\0'; + + return(dlen + (s - src)); /* count does not include NUL */ +} + + int ecore_str_has_prefix(const char *str, const char *prefix) { diff --git a/legacy/ecore/src/lib/ecore/ecore_strbuf.c b/legacy/ecore/src/lib/ecore/ecore_strbuf.c new file mode 100644 index 0000000000..fb0d21b002 --- /dev/null +++ b/legacy/ecore/src/lib/ecore/ecore_strbuf.c @@ -0,0 +1,117 @@ +#include "ecore_private.h" +#include "Ecore.h" +#include "Ecore_Data.h" +#include "Ecore_Str.h" + +#define ECORE_STRBUF_INIT_SIZE 32 +#define ECORE_STRBUF_INIT_STEP 32 +#define ECORE_STRBUF_MAX_STEP 4096 + +struct _ecore_strbuf +{ + char *buf; + int len; + int size; + int step; +}; + +/** + * Create a new string buffer + */ +Ecore_Strbuf * +ecore_strbuf_new(void) +{ + Ecore_Strbuf *buf; + + buf = malloc(sizeof(Ecore_Strbuf)); + if (!buf) return NULL; + + buf->len = 0; + buf->size = ECORE_STRBUF_INIT_SIZE; + buf->step = ECORE_STRBUF_INIT_STEP; + + buf->buf = malloc(buf->size); + buf->buf[0] = '\0'; + + return buf; +} + +/** + * Free a string buffer + * @param buf the buffer to free + */ +void +ecore_strbuf_free(Ecore_Strbuf *buf) +{ + CHECK_PARAM_POINTER("buf", buf); + free(buf->buf); + free(buf); +} + +/** + * Append a string to a buffer, reallocating as necessary. + * @param buf the Ecore_Strbuf to append to + * @param str the string to append + */ +void +ecore_strbuf_append(Ecore_Strbuf *buf, const char *str) +{ + CHECK_PARAM_POINTER("buf", buf); + CHECK_PARAM_POINTER("str", str); + + int l; + int off = 0; + + l = ecore_strlcpy(buf->buf + buf->len, str, buf->size - buf->len); + + while (l > buf->size - buf->len) + { + /* we successfully appended this much */ + off += buf->size - buf->len - 1; + buf->len = buf->size - 1; + buf->size += buf->step; + if (buf->step < ECORE_STRBUF_MAX_STEP) + buf->step *= 2; + buf->buf = realloc(buf->buf, buf->size); + *(buf->buf + buf->len) = '\0'; + + l = ecore_strlcpy(buf->buf + buf->len, str + off, buf->size - buf->len); + } + buf->len += l; +} + + +/** + * Append a character to a string buffer, reallocating as necessary. + * @param buf the Ecore_Strbuf to append to + * @param c the char to append + */ +void +ecore_strbuf_append_char(Ecore_Strbuf *buf, char c) +{ + CHECK_PARAM_POINTER("buf", buf); + if (buf->len >= buf->size - 1) + { + buf->size += buf->step; + if (buf->step < ECORE_STRBUF_MAX_STEP) + buf->step *= 2; + buf->buf = realloc(buf->buf, buf->size); + } + + buf->buf[(buf->len)++] = c; + buf->buf[buf->len] = '\0'; +} + +/** + * Retrieve a pointer to the contents of a string buffer + * @param buf the buffer + * + * This pointer must not be modified, and will no longer be valid if + * the Ecore_Strbuf is modified. + */ +const char * +ecore_strbuf_string_get(Ecore_Strbuf *buf) +{ + CHECK_PARAM_POINTER_RETURN("buf", buf, NULL); + return buf->buf; +}