diff --git a/include/sexpr/cstring.h b/include/sexpr/cstring.h index 79e7458..3a921b1 100644 --- a/include/sexpr/cstring.h +++ b/include/sexpr/cstring.h @@ -78,14 +78,14 @@ extern "C" { * Set the growth size. Values less than one are ignored. */ void sgrowsize(size_t s); - + /** * Allocate a new CSTRING of the given size. * A NULL return value indicates that something went wrong and that * sexp_errno should be checked for the cause. */ CSTRING *snew(size_t s); - + /** * Concatenate the second argument to the CSTRING passed in the first. * The second argument must be a pointer to a null terminated string. @@ -96,7 +96,18 @@ extern "C" { * leak if an error condition occurs. */ CSTRING *sadd(CSTRING *s, char *a); - + + /** + * Concatenate the len bytes of the second argument to the CSTRING + * passed in the first. + * A NULL return value indicates that something went wrong and that + * sexp_errno should be checked for the cause. The contents of s are + * left alone. As such, the caller should check the pointer returned + * before overwriting the value of s, as this may result in a memory + * leak if an error condition occurs. + */ + CSTRING *snadd(CSTRING *s, char *a, size_t len); + /** * Append a character to the end of the CSTRING. * A NULL return value indicates that something went wrong and that @@ -106,7 +117,7 @@ extern "C" { * leak if an error condition occurs. */ CSTRING *saddch(CSTRING *s, char a); - + /** * Trim the allocated memory to precisely the string length plus one char * to hold the null terminator diff --git a/lib/cstring.c b/lib/cstring.c index 62a72be..18a4995 100644 --- a/lib/cstring.c +++ b/lib/cstring.c @@ -86,7 +86,18 @@ CSTRING *snew(size_t s) { return cs; } -CSTRING *sadd(CSTRING *s, char *a) { +CSTRING *sadd(CSTRING *s, char *a) +{ + size_t len = strlen(a); + + if(!s) return NULL; + if(!a || !len) return s; + + return snadd(s, a, len); +} + +CSTRING *snadd(CSTRING *s, char *a, size_t len) +{ size_t alen; char *newbase; @@ -100,7 +111,7 @@ CSTRING *sadd(CSTRING *s, char *a) { return s; } - alen = strlen(a); + alen = len; if (s->curlen + alen >= s->len) { #ifdef __cplusplus @@ -112,12 +123,12 @@ CSTRING *sadd(CSTRING *s, char *a) { s->len+cstring_growsize+alen, s->len); #endif - + /* do NOT destroy s anymore. if realloc fails, the original data is still valid, so just report the error to sexp_errno and return NULL. */ if (newbase == NULL) { - sexp_errno = SEXP_ERR_MEMORY; + sexp_errno = SEXP_ERR_MEMORY; return NULL; } @@ -125,9 +136,10 @@ CSTRING *sadd(CSTRING *s, char *a) { s->base = newbase; } - memcpy(&s->base[s->curlen],a,alen); + memcpy(&s->base[s->curlen], a, alen); s->curlen += alen; s->base[s->curlen] = 0; + return s; }