Fri, 19 Jul 2013 14:17:12 +0200
completed documentation on sstr_t + sstrsplit overhaul + allocator version of sstrsplit
ucx/string.c | file | annotate | diff | comparison | revisions | |
ucx/string.h | file | annotate | diff | comparison | revisions |
--- a/ucx/string.c Wed Jul 17 20:03:01 2013 +0200 +++ b/ucx/string.c Fri Jul 19 14:17:12 2013 +0200 @@ -73,7 +73,7 @@ memcpy(ptr, c1.ptr, cplen); len -= cplen; ptr += cplen; - for (size_t i = 0 ; i < n-1 ; i++) { + for (size_t i = 1 ; i < n ; i++) { sstr_t str = va_arg (ap, sstr_t); cplen = str.length > len ? len : str.length; if(cplen <= 0) { @@ -120,7 +120,12 @@ } sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) { - if (d.length == 0) { + return sstrsplita(s, d, n, ucx_default_allocator()); +} + +sstr_t* sstrsplita(sstr_t s, sstr_t d, size_t *n, UcxAllocator *allocator) { + if (s.length == 0 || d.length == 0) { + *n = -1; return NULL; } @@ -129,11 +134,15 @@ *n = 1; /* special case: exact match - no processing needed */ - if (s.length == d.length && strncmp(s.ptr, d.ptr, s.length) == 0) { + if (sstrcmp(s, d) == 0) { *n = 0; return NULL; } sstr_t sv = sstrdup(s); + if (sv.length == 0) { + *n = -2; + return NULL; + } for (size_t i = 0 ; i < s.length ; i++) { if (sv.ptr[i] == d.ptr[0]) { @@ -156,19 +165,23 @@ } if ((*n) == nmax) break; } - result = (sstr_t*) malloc(sizeof(sstr_t) * (*n)); + result = (sstr_t*) allocator->malloc(sizeof(sstr_t) * (*n)); - char *pptr = sv.ptr; - for (size_t i = 0 ; i < *n ; i++) { - size_t l = strlen(pptr); - char* ptr = (char*) malloc(l + 1); - memcpy(ptr, pptr, l); - ptr[l] = 0; + if (result) { + char *pptr = sv.ptr; + for (size_t i = 0 ; i < *n ; i++) { + size_t l = strlen(pptr); + char* ptr = (char*) allocator->malloc(l + 1); + memcpy(ptr, pptr, l); + ptr[l] = 0; - result[i] = sstrn(ptr, l); - pptr += l + d.length; + result[i] = sstrn(ptr, l); + pptr += l + d.length; + } + } else { + *n = -2; } - + free(sv.ptr); return result;
--- a/ucx/string.h Wed Jul 17 20:03:01 2013 +0200 +++ b/ucx/string.h Fri Jul 19 14:17:12 2013 +0200 @@ -119,48 +119,157 @@ size_t sstrnlen(size_t count, sstr_t string, ...); -/* - * concatenates n strings - * - * n number of strings - * s new string with enough memory allocated - * ... strings +/** + * Concatenates strings. + * + * At least one string must be specified and there must be enough memory + * available referenced by the destination sstr_t.ptr for this function to + * successfully concatenate all specified strings. + * + * The sstr_t.length of the destination string specifies the capacity and + * should match the total memory available referenced by the destination + * sstr_t.ptr. This function <i>never</i> copies data beyond the capacity and + * does not modify any of the source strings. + * + * <b>Attention:</b> + * <ul> + * <li>Any content in the destination string will be overwritten</li> + * <li>The destination sstr_t.ptr is <b>NOT</b> + * <code>NULL</code>-terminated</li> + * <li>The destination sstr_t.length is set to the total length of the + * concatenated strings</li> + * <li><i>Hint:</i> get a <code>NULL</code>-terminated string by performing + * <code>mystring.ptr[mystring.length]='\0'</code> after calling this + * function</li> + * </ul> + * + * @param count the total number of strings to concatenate + * @param dest new sstr_t with capacity information and allocated memory + * @param src the first string + * @param ... all other strings + * @return the argument for <code>dest</code> is returned */ -sstr_t sstrncat(size_t n, sstr_t s, sstr_t c1, ...); +sstr_t sstrncat(size_t count, sstr_t dest, sstr_t src, ...); -/* - * +/** + * Returns a substring starting at the specified location. + * + * <b>Attention:</b> the new string references the same memory area as the + * input string and will <b>NOT</b> be <code>NULL</code>-terminated. + * Use sstrdup() to get a copy. + * + * @param string input string + * @param start start location of the substring + * @return a substring of <code>string</code> starting at <code>start</code> + * + * @see sstrsubsl() + * @see sstrchr() */ -sstr_t sstrsubs(sstr_t s, size_t start); +sstr_t sstrsubs(sstr_t string, size_t start); -/* - * +/** + * Returns a substring with a maximum length starting at the specified location. + * + * <b>Attention:</b> the new string references the same memory area as the + * input string and will <b>NOT</b> be <code>NULL</code>-terminated. + * Use sstrdup() to get a copy. + * + * @param string input string + * @param start start location of the substring + * @param length the maximum length of the substring + * @return a substring of <code>string</code> starting at <code>start</code> + * with a maximum length of <code>length</code> + * + * @see sstrsubs() + * @see sstrchr() */ -sstr_t sstrsubsl(sstr_t s, size_t start, size_t length); +sstr_t sstrsubsl(sstr_t string, size_t start, size_t length); -/* +/** + * Returns a substring starting at the location of the first occurrence of the + * specified character. + * + * If the string does not contain the character, an empty string is returned. * + * @param string the string where to locate the character + * @param chr the character to locate + * @return a substring starting at the least location of <code>chr</code> + * + * @see sstrsubs() */ -sstr_t sstrchr(sstr_t s, int c); +sstr_t sstrchr(sstr_t string, int chr); -/* - * splits s into n parts - * - * s the string to split - * d the delimiter string - * n the maximum size of the resulting list - * a size of 0 indicates an unbounded list size - * the actual size of the list will be stored here +/** + * Splits a string into parts by using a delimiter string. + * + * This function will return <code>NULL</code>, if one of the following happens: + * <ul> + * <li>the string length is zero</li> + * <li>the delimeter length is zero</li> + * <li>the string equals the delimeter</li> + * <li>memory allocation fails</li> + * </ul> + * + * The integer referenced by <code>count</code> is used as input and determines + * the maximum size of the resulting list, i.e. the maximum count of splits to + * perform + 1. + * + * The integer referenced by <code>count</code> is also used as output and is + * set to + * <ul> + * <li>-2, on memory allocation errors</li> + * <li>-1, if either the string or the delimiter is an empty string</li> + * <li>0, if the string equals the delimiter</li> + * <li>1, if the string does not contain the delimiter</li> + * <li>the count of list items, otherwise</li> + * </ul> + * + * If the string starts with the delimiter, the first item of the resulting + * list will be an empty string. + * + * If the string ends with the delimiter and the maximum list size is not + * exceeded, the last list item will be an empty string. + * + * <b>Attention:</b> All list items <b>AND</b> all sstr_t.ptr of the list + * items must be manually passed to <code>free()</code>. Use sstrsplita() with + * an allocator to managed memory, to avoid this. * - * Hint: use this value to avoid dynamic reallocation of the result list - * - * Returns a list of the split strings - * NOTE: this list needs to be freed manually after usage - * - * Returns NULL on error + * @param string the string to split + * @param delim the delimiter string + * @param count IN: the maximum size of the resulting list (0 for an + * unbounded list), OUT: the actual size of the list + * @return a list of the split strings as sstr_t array or + * <code>NULL</code> on error + * + * @see sstrsplita() */ -sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n); +sstr_t* sstrsplit(sstr_t string, sstr_t delim, size_t *count); + +/** + * Performing sstrsplit() using an UcxAllocator. + * + * <i>Read the description of sstrsplit() for details.</i> + * + * The memory for the sstr_t.ptr pointers of the list items and the memory for + * the sstr_t array itself are allocated by using the UcxAllocator.malloc() + * function. + * + * <b>Note:</b> the allocator is not used for memory that is freed within the + * same call of this function (locally scoped variables). + * + * @param string the string to split + * @param delim the delimiter string + * @param count IN: the maximum size of the resulting list (0 for an + * unbounded list), OUT: the actual size of the list + * @param allocator the UcxAllocator used for allocating memory + * @return a list of the split strings as sstr_t array or + * <code>NULL</code> on error + * + * @see sstrsplit() + */ +sstr_t* sstrsplita(sstr_t string, sstr_t delim, size_t *count, + UcxAllocator *allocator); /** * Compares two UCX strings with standard <code>memcmp()</code>. @@ -188,6 +297,7 @@ * * @param string the string to duplicate * @return a duplicate of the string + * @see sstrdupa() */ sstr_t sstrdup(sstr_t string); @@ -205,6 +315,7 @@ * @param allocator a valid instance of an UcxAllocator * @param string the string to duplicate * @return a duplicate of the string + * @see sstrdup() */ sstr_t sstrdupa(UcxAllocator *allocator, sstr_t string);