Wed, 17 Jul 2013 15:56:01 +0200
some fixes and some documentation
test/string_tests.c | file | annotate | diff | comparison | revisions | |
ucx/map.c | file | annotate | diff | comparison | revisions | |
ucx/mempool.c | file | annotate | diff | comparison | revisions | |
ucx/properties.c | file | annotate | diff | comparison | revisions | |
ucx/string.c | file | annotate | diff | comparison | revisions | |
ucx/string.h | file | annotate | diff | comparison | revisions | |
ucx/ucx.h | file | annotate | diff | comparison | revisions |
1.1 --- a/test/string_tests.c Wed Jul 17 12:32:03 2013 +0200 1.2 +++ b/test/string_tests.c Wed Jul 17 15:56:01 2013 +0200 1.3 @@ -41,9 +41,9 @@ 1.4 } 1.5 1.6 UCX_TEST_IMPLEMENT(test_sstr_len_cat) { 1.7 - sstr_t s1 = S("1234"); 1.8 - sstr_t s2 = S(".:.:."); 1.9 - sstr_t s3 = S("X"); 1.10 + sstr_t s1 = ST("1234"); 1.11 + sstr_t s2 = ST(".:.:."); 1.12 + sstr_t s3 = ST("X"); 1.13 1.14 size_t len = sstrnlen(3, s1, s2, s3); 1.15 sstr_t cat; 1.16 @@ -72,7 +72,7 @@ 1.17 UCX_TEST_IMPLEMENT(test_sstrsplit) { 1.18 1.19 const char *original = "this,is,a,csv,string"; 1.20 - sstr_t test = S("this,is,a,csv,string"); /* use copy of original here */ 1.21 + sstr_t test = ST("this,is,a,csv,string"); /* use copy of original here */ 1.22 size_t n; 1.23 sstr_t *list; 1.24 1.25 @@ -80,12 +80,12 @@ 1.26 1.27 /* Nullpointer check */ 1.28 n = 0; 1.29 - UCX_TEST_ASSERT(sstrsplit(test, ST(""), &n) == NULL, 1.30 + UCX_TEST_ASSERT(sstrsplit(test, S(""), &n) == NULL, 1.31 "empty delimiter must return NULL"); 1.32 1.33 /* no delimiter occurence (ndo) */ 1.34 n = 0; 1.35 - list = sstrsplit(test, ST("z"), &n); 1.36 + list = sstrsplit(test, S("z"), &n); 1.37 UCX_TEST_ASSERT(n == 1, "ndo, list length must be 1"); 1.38 UCX_TEST_ASSERT(strcmp(list[0].ptr, original) == 0, "ndo, " 1.39 "original string shall be returned as single list element"); 1.40 @@ -95,7 +95,7 @@ 1.41 1.42 /* partially matching delimiter (pmd) */ 1.43 n = 0; 1.44 - list = sstrsplit(test, ST("stringbuilder"), &n); 1.45 + list = sstrsplit(test, S("stringbuilder"), &n); 1.46 UCX_TEST_ASSERT(n == 1, "pmd, list length must be 1"); 1.47 UCX_TEST_ASSERT(strcmp(list[0].ptr, original) == 0, "pmd, " 1.48 "original string shall be returned as single list element"); 1.49 @@ -105,7 +105,7 @@ 1.50 1.51 /* matching single-char delimiter (mscd) */ 1.52 n = 0; 1.53 - list = sstrsplit(test, ST(","), &n); 1.54 + list = sstrsplit(test, S(","), &n); 1.55 UCX_TEST_ASSERT(n == 5, "mscd, list length must be 5"); 1.56 UCX_TEST_ASSERT(strcmp(list[0].ptr, "this") == 0, "mscd, item 0 mismatch"); 1.57 UCX_TEST_ASSERT(strcmp(list[1].ptr, "is") == 0, "mscd, item 1 mismatch"); 1.58 @@ -118,7 +118,7 @@ 1.59 1.60 /* matching multi-char delimiter (mmcd) */ 1.61 n = 0; 1.62 - list = sstrsplit(test, ST("is"), &n); 1.63 + list = sstrsplit(test, S("is"), &n); 1.64 UCX_TEST_ASSERT(n == 3, "mscd, list length must be 3"); 1.65 UCX_TEST_ASSERT(strcmp(list[0].ptr, "th") == 0, "mmcd, item 0 mismatch"); 1.66 UCX_TEST_ASSERT(strcmp(list[1].ptr, ",") == 0, "mmcd, item 1 mismatch"); 1.67 @@ -130,7 +130,7 @@ 1.68 1.69 /* bounded list using single-char delimiter (blsc) */ 1.70 n = 3; 1.71 - list = sstrsplit(test, ST(","), &n); 1.72 + list = sstrsplit(test, S(","), &n); 1.73 UCX_TEST_ASSERT(n == 3, "blsc, list length must be 3"); 1.74 UCX_TEST_ASSERT(strcmp(list[0].ptr, "this") == 0, "blsc, item 0 mismatch"); 1.75 UCX_TEST_ASSERT(strcmp(list[1].ptr, "is") == 0, "blsc, item 1 mismatch"); 1.76 @@ -142,7 +142,7 @@ 1.77 1.78 /* bounded list using multi-char delimiter (blmc) */ 1.79 n = 2; 1.80 - list = sstrsplit(test, ST("is"), &n); 1.81 + list = sstrsplit(test, S("is"), &n); 1.82 UCX_TEST_ASSERT(n == 2, "blmc, list length must be 2"); 1.83 UCX_TEST_ASSERT(strcmp(list[0].ptr, "th") == 0, "blmc, item 0 mismatch"); 1.84 UCX_TEST_ASSERT(strcmp(list[1].ptr, ",is,a,csv,string") == 0, 1.85 @@ -153,7 +153,7 @@ 1.86 1.87 /* start with delimiter (swd) */ 1.88 n = 0; 1.89 - list = sstrsplit(test, ST("this"), &n); 1.90 + list = sstrsplit(test, S("this"), &n); 1.91 UCX_TEST_ASSERT(n == 2, "swd, list length must be 2"); 1.92 UCX_TEST_ASSERT(list[0].length == 0, "swd, first item must be empty"); 1.93 UCX_TEST_ASSERT(strcmp(list[1].ptr, ",is,a,csv,string") == 0, 1.94 @@ -164,7 +164,7 @@ 1.95 1.96 /* end with delimiter (ewd) */ 1.97 n = 0; 1.98 - list = sstrsplit(test, ST("string"), &n); 1.99 + list = sstrsplit(test, S("string"), &n); 1.100 UCX_TEST_ASSERT(n == 2, "ewd, list length must be 2"); 1.101 UCX_TEST_ASSERT(strcmp(list[0].ptr, "this,is,a,csv,") == 0, 1.102 "swd, first item corrupt"); 1.103 @@ -175,14 +175,14 @@ 1.104 1.105 /* exact match (exm) */ 1.106 n = 0; 1.107 - list = sstrsplit(test, ST("this,is,a,csv,string"), &n); 1.108 + list = sstrsplit(test, S("this,is,a,csv,string"), &n); 1.109 UCX_TEST_ASSERT(n == 0, "exm, list length must be 0"); 1.110 UCX_TEST_ASSERT(list == NULL, "exm, list must be NULL"); 1.111 free(list); 1.112 1.113 /* substring (subs) */ 1.114 n = 0; 1.115 - list = sstrsplit(test, ST("this,is,a,csv,string,with,extension"), &n); 1.116 + list = sstrsplit(test, S("this,is,a,csv,string,with,extension"), &n); 1.117 UCX_TEST_ASSERT(n == 1, "subs, list length must be 1"); 1.118 UCX_TEST_ASSERT(strcmp(list[0].ptr, original) == 0, 1.119 "subs, single item must be the original string");
2.1 --- a/ucx/map.c Wed Jul 17 12:32:03 2013 +0200 2.2 +++ b/ucx/map.c Wed Jul 17 15:56:01 2013 +0200 2.3 @@ -64,7 +64,7 @@ 2.4 return map; 2.5 } 2.6 2.7 -void ucx_map_free_elmlist(UcxMap *map) { 2.8 +static void ucx_map_free_elmlist(UcxMap *map) { 2.9 for (size_t n = 0 ; n < map->size ; n++) { 2.10 UcxMapElement *elem = map->map[n]; 2.11 if (elem != NULL) {
3.1 --- a/ucx/mempool.c Wed Jul 17 12:32:03 2013 +0200 3.2 +++ b/ucx/mempool.c Wed Jul 17 15:56:01 2013 +0200 3.3 @@ -112,7 +112,7 @@ 3.4 return newm + sizeof(ucx_destructor); 3.5 } 3.6 } 3.7 - fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", 3.8 + fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", 3.9 (intptr_t)ptr, (intptr_t)pool); 3.10 exit(1); 3.11 } else { 3.12 @@ -136,7 +136,7 @@ 3.13 return; 3.14 } 3.15 } 3.16 - fprintf(stderr, "FATAL: 0x%08"PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", 3.17 + fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n", 3.18 (intptr_t)ptr, (intptr_t)pool); 3.19 exit(1); 3.20 }
4.1 --- a/ucx/properties.c Wed Jul 17 12:32:03 2013 +0200 4.2 +++ b/ucx/properties.c Wed Jul 17 15:56:01 2013 +0200 4.3 @@ -199,17 +199,11 @@ 4.4 sstr_t name; 4.5 sstr_t value; 4.6 while(ucx_properties_next(parser, &name, &value)) { 4.7 - name = sstrdup_alloc(map->allocator, name); 4.8 - if(!name.ptr) { 4.9 - return 1; 4.10 - } 4.11 - value = sstrdup_alloc(map->allocator, value); 4.12 + value = sstrdupa(map->allocator, value); 4.13 if(!value.ptr) { 4.14 - map->allocator->free(map->allocator->pool, value.ptr); 4.15 return 1; 4.16 } 4.17 if(ucx_map_sstr_put(map, name, value.ptr)) { 4.18 - map->allocator->free(map->allocator->pool, name.ptr); 4.19 map->allocator->free(map->allocator->pool, value.ptr); 4.20 return 1; 4.21 }
5.1 --- a/ucx/string.c Wed Jul 17 12:32:03 2013 +0200 5.2 +++ b/ucx/string.c Wed Jul 17 15:56:01 2013 +0200 5.3 @@ -33,17 +33,17 @@ 5.4 #include "string.h" 5.5 #include "allocator.h" 5.6 5.7 -sstr_t sstr(char *s) { 5.8 +sstr_t sstr(char *cstring) { 5.9 sstr_t string; 5.10 - string.ptr = s; 5.11 - string.length = strlen(s); 5.12 + string.ptr = cstring; 5.13 + string.length = strlen(cstring); 5.14 return string; 5.15 } 5.16 5.17 -sstr_t sstrn(char *s, size_t n) { 5.18 +sstr_t sstrn(char *cstring, size_t length) { 5.19 sstr_t string; 5.20 - string.ptr = s; 5.21 - string.length = n; 5.22 + string.ptr = cstring; 5.23 + string.length = length; 5.24 return string; 5.25 } 5.26 5.27 @@ -52,7 +52,7 @@ 5.28 size_t size = s.length; 5.29 va_start(ap, s); 5.30 5.31 - for (size_t i = 0 ; i < n-1 ; i++) { 5.32 + for (size_t i = 1 ; i < n ; i++) { 5.33 sstr_t str = va_arg(ap, sstr_t); 5.34 size += str.length; 5.35 } 5.36 @@ -175,25 +175,20 @@ 5.37 } 5.38 5.39 int sstrcmp(sstr_t s1, sstr_t s2) { 5.40 - return strncmp(s1.ptr, s2.ptr, s1.length>s2.length ? s2.length: s1.length); 5.41 + if (s1.length == s2.length) { 5.42 + return memcmp(s1.ptr, s2.ptr, s1.length); 5.43 + } else if (s1.length > s2.length) { 5.44 + return 1; 5.45 + } else { 5.46 + return -1; 5.47 + } 5.48 } 5.49 5.50 sstr_t sstrdup(sstr_t s) { 5.51 - sstr_t newstring; 5.52 - newstring.ptr = (char*) malloc(s.length + 1); 5.53 - if (newstring.ptr) { 5.54 - newstring.length = s.length; 5.55 - newstring.ptr[newstring.length] = 0; 5.56 - 5.57 - memcpy(newstring.ptr, s.ptr, s.length); 5.58 - } else { 5.59 - newstring.length = 0; 5.60 - } 5.61 - 5.62 - return newstring; 5.63 + return sstrdupa(ucx_default_allocator(), s); 5.64 } 5.65 5.66 -sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s) { 5.67 +sstr_t sstrdupa(UcxAllocator *allocator, sstr_t s) { 5.68 sstr_t newstring; 5.69 newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1); 5.70 if (newstring.ptr) {
6.1 --- a/ucx/string.h Wed Jul 17 12:32:03 2013 +0200 6.2 +++ b/ucx/string.h Wed Jul 17 15:56:01 2013 +0200 6.3 @@ -25,51 +25,98 @@ 6.4 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 6.5 * POSSIBILITY OF SUCH DAMAGE. 6.6 */ 6.7 +/** 6.8 + * Bounded string implementation. 6.9 + * 6.10 + * The UCX strings (<code>sstr_t</code>) provide an alternative to C strings. 6.11 + * The main difference to C strings is, that <code>sstr_t</code> does <b>not 6.12 + * need to be <code>NULL</code>-terminated</b>. Instead the length is stored 6.13 + * within the structure. 6.14 + * 6.15 + * When using <code>sstr_t</code>, developers must be full aware of what type 6.16 + * of string (<code>NULL</code>-terminated) or not) they are using, when 6.17 + * accessing the <code>char* ptr</code> directly. 6.18 + * 6.19 + * The UCX string module provides some common string functions, known from 6.20 + * standard libc, working with <code>sstr_t</code>. 6.21 + * 6.22 + * @file string.h 6.23 + * @author Mike Becker 6.24 + * @author Olaf Wintermann 6.25 + */ 6.26 6.27 -#ifndef _SSTRING_H 6.28 -#define _SSTRING_H 6.29 +#ifndef UCX_STRING_H 6.30 +#define UCX_STRING_H 6.31 6.32 #include "ucx.h" 6.33 #include "allocator.h" 6.34 #include <stddef.h> 6.35 6.36 -/* use macros for literals only */ 6.37 -#define S(s) { (char*)s, sizeof(s)-1 } 6.38 -#define ST(s) sstrn((char*)s, sizeof(s)-1) 6.39 +/** Shortcut for a <code>sstr_t struct</code> literal. */ 6.40 +#define ST(s) { (char*)s, sizeof(s)-1 } 6.41 +/** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */ 6.42 +#define S(s) sstrn((char*)s, sizeof(s)-1) 6.43 6.44 #ifdef __cplusplus 6.45 extern "C" { 6.46 #endif 6.47 6.48 -typedef struct sstring { 6.49 +/** 6.50 + * The UCX string structure. 6.51 + */ 6.52 +typedef struct { 6.53 + /** A reference to the string (<b>not necessarily <code>NULL</code> 6.54 + * -terminated</b>) */ 6.55 char *ptr; 6.56 + /** The length of the string */ 6.57 size_t length; 6.58 } sstr_t; 6.59 6.60 -/* 6.61 - * creates a new sstr_t from a null terminated string 6.62 +/** 6.63 + * Creates a new sstr_t based on a C string. 6.64 + * 6.65 + * The length is implicitly inferred by using a call to <code>strlen()</code>. 6.66 * 6.67 - * s null terminated string 6.68 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you 6.69 + * do want a copy, use sstrdup() on the return value of this function. 6.70 + * 6.71 + * @param cstring the C string to wrap 6.72 + * @return a new sstr_t containing the C string 6.73 + * 6.74 + * @see sstrn() 6.75 */ 6.76 -sstr_t sstr(char *s); 6.77 +sstr_t sstr(char *cstring); 6.78 6.79 -/* 6.80 - * creates a new sstr_t from a string and length 6.81 +/** 6.82 + * Creates a new sstr_t of the specified length based on a C string. 6.83 * 6.84 - * s string 6.85 - * n length of string 6.86 + * <b>Note:</b> the sstr_t will hold a <i>reference</i> to the C string. If you 6.87 + * do want a copy, use sstrdup() on the return value of this function. 6.88 + * 6.89 + * @param cstring the C string to wrap 6.90 + * @param length the length of the string 6.91 + * @return a new sstr_t containing the C string 6.92 + * 6.93 + * @see sstr() 6.94 + * @see S() 6.95 */ 6.96 -sstr_t sstrn(char *s, size_t n); 6.97 +sstr_t sstrn(char *cstring, size_t length); 6.98 6.99 6.100 -/* 6.101 - * gets the length of n sstr_t strings 6.102 +/** 6.103 + * Returns the cumulated length of all specified strings. 6.104 * 6.105 - * n number of strings 6.106 - * s string 6.107 - * ... strings 6.108 + * At least one string must be specified. 6.109 + * 6.110 + * <b>Attention:</b> if the count argument does not match the count of the 6.111 + * specified strings, the behavior is undefined. 6.112 + * 6.113 + * @param count the total number of specified strings (so at least 1) 6.114 + * @param string the first string 6.115 + * @param ... all other strings 6.116 + * @return the cumulated length of all strings 6.117 */ 6.118 -size_t sstrnlen(size_t n, sstr_t s, ...); 6.119 +size_t sstrnlen(size_t count, sstr_t string, ...); 6.120 6.121 6.122 /* 6.123 @@ -115,10 +162,32 @@ 6.124 */ 6.125 sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n); 6.126 6.127 +/** 6.128 + * Compares two UCX strings with standard <code>memcmp()</code>. 6.129 + * 6.130 + * At first it compares the sstr_t.length attribute of the two strings. The 6.131 + * <code>memcmp()</code> function is called, if and only if the lengths match. 6.132 + * 6.133 + * @param s1 the first string 6.134 + * @param s2 the second string 6.135 + * @return -1, if the length of s1 is less than the length of s2 or 1, if the 6.136 + * length of s1 is greater than the length of s2 or the result of 6.137 + * <code>memcmp()</code> otherwise (i.e. 0 if the strings match) 6.138 + */ 6.139 int sstrcmp(sstr_t s1, sstr_t s2); 6.140 6.141 -sstr_t sstrdup(sstr_t s); 6.142 -sstr_t sstrdup_alloc(UcxAllocator *allocator, sstr_t s); 6.143 +/** 6.144 + * Creates a duplicate of the specified string. 6.145 + * 6.146 + * The new sstr_t will contain a copy allocated by standard 6.147 + * <code>malloc()</code>. So developers <b>MUST</b> pass the sstr_t.ptr to 6.148 + * <code>free()</code>. 6.149 + * 6.150 + * @param string the string to duplicate 6.151 + * @return a duplicate of the argument 6.152 + */ 6.153 +sstr_t sstrdup(sstr_t string); 6.154 +sstr_t sstrdupa(UcxAllocator *allocator, sstr_t s); 6.155 6.156 sstr_t sstrtrim(sstr_t string); 6.157 6.158 @@ -126,4 +195,4 @@ 6.159 } 6.160 #endif 6.161 6.162 -#endif /* _SSTRING_H */ 6.163 +#endif /* UCX_STRING_H */
7.1 --- a/ucx/ucx.h Wed Jul 17 12:32:03 2013 +0200 7.2 +++ b/ucx/ucx.h Wed Jul 17 15:56:01 2013 +0200 7.3 @@ -51,7 +51,6 @@ 7.4 * 7.5 * The first argument is the type of the list and its elements (e.g. UcxList). 7.6 * The structure invariant of the list must be as follows: 7.7 - * 7.8 * <ul> 7.9 * <li>a first (non-<code>NULL</code>) element</li> 7.10 * <li>for each element a reference to the <code>next</code> element (the 7.11 @@ -107,7 +106,8 @@ 7.12 * source and destination. 7.13 * 7.14 * The arguments shall contain (in ascending order): a pointer to the source, 7.15 - * the length of one element, the element count, a pointer to the destination. 7.16 + * the length of one element, the element count and a pointer to the 7.17 + * destination. 7.18 */ 7.19 typedef size_t(*write_func)(const void*, size_t, size_t, void*); 7.20 7.21 @@ -119,8 +119,8 @@ 7.22 * source and destination. 7.23 * 7.24 * The arguments shall contain (in ascending order): a pointer to the 7.25 - * destination, the length of one element, the element count, a pointer to the 7.26 - * source. 7.27 + * destination, the length of one element, the element count and a pointer to 7.28 + * the source. 7.29 */ 7.30 typedef size_t(*read_func)(void*, size_t, size_t, void*); 7.31