reimplementation of sstrsplit

Mon, 20 Feb 2017 16:57:09 +0100

author
Mike Becker <universe@uap-core.de>
date
Mon, 20 Feb 2017 16:57:09 +0100
changeset 233
bd58fdde142d
parent 232
5f2d650eade7
child 234
7a63b4986b5b

reimplementation of sstrsplit

test/string_tests.c file | annotate | diff | comparison | revisions
ucx/string.c file | annotate | diff | comparison | revisions
ucx/string.h file | annotate | diff | comparison | revisions
--- a/test/string_tests.c	Mon Feb 20 16:04:14 2017 +0100
+++ b/test/string_tests.c	Mon Feb 20 16:57:09 2017 +0100
@@ -299,7 +299,7 @@
     UCX_TEST_ASSERT(n == 3, "ewdeb, list length must be 3");
     UCX_TEST_ASSERT(strcmp(list[0].ptr, "a") == 0, "ewdeb, fst item corrupt");
     UCX_TEST_ASSERT(strcmp(list[1].ptr, "b") == 0, "ewdeb, snd item corrupt");
-    UCX_TEST_ASSERT(strcmp(list[2].ptr, "c") == 0, "ewdeb, trd item corrupt");
+    UCX_TEST_ASSERT(strcmp(list[2].ptr, "c,") == 0, "ewdeb, trd item corrupt");
     for(int i=0;i<n;i++) {
         free(list[i].ptr);
     }
--- a/ucx/string.c	Mon Feb 20 16:04:14 2017 +0100
+++ b/ucx/string.c	Mon Feb 20 16:57:09 2017 +0100
@@ -212,62 +212,58 @@
         } else /* no match possible */ {
             *n = 1;
             sstr_t *result = (sstr_t*) almalloc(allocator, sizeof(sstr_t));
-            result->ptr = (char*) almalloc(allocator, 1+s.length);
-            memcpy(result->ptr, s.ptr, s.length);
-            result->ptr[s.length] = '\0';
-            result->length = s.length;
+            *result = sstrdup_a(allocator, s);
             return result;
         }
     }
     
-    sstr_t* result;
     ssize_t nmax = *n;
-    *n = 1;
-    
-    sstr_t sv = sstrdup(s);
-    if (sv.length == 0) {
-        *n = -2;
-        return NULL;
-    }
-
-    for (size_t i = 0 ; i < s.length ; i++) {
-        sstr_t substr = sstrsubs(sv, i);
-        if (sstrprefix(substr, d)) {
-            (*n)++;
-            for (size_t j = 0 ; j < d.length ; j++) {
-                sv.ptr[i+j] = 0;
-            }
-            i += d.length - 1; // -1, because the loop will do a i++
-        }
-        if ((*n) == nmax) break;
-    }
-    result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n));
+    sstr_t* result = (sstr_t*) almalloc(allocator, sizeof(sstr_t));
 
     if (result) {
-        char *pptr = sv.ptr;
-        for (ssize_t i = 0 ; i < *n ; i++) {
-            size_t l = strlen(pptr);
-            char* ptr = (char*) almalloc(allocator, l + 1);
-            if (ptr) {
-                memcpy(ptr, pptr, l);
-                ptr[l] = '\0';
+        sstr_t curpos = s;
+        ssize_t j = 1;
+        while (1) {
+            sstr_t match = sstrstr(curpos, d);
+            if (match.length > 0) {
+                /* is this our last try? */
+                if (nmax == 0 || j < nmax) {
+                    /* copy the current string to the array */
+                    sstr_t item = sstrn(curpos.ptr, match.ptr - curpos.ptr);
+                    result[j-1] = sstrdup_a(allocator, item);
+                    size_t processed = item.length + d.length;
+                    curpos.ptr += processed;
+                    curpos.length -= processed;
 
-                result[i] = sstrn(ptr, l);
-                pptr += l + d.length;
+                    /* allocate memory for the next string */
+                    j++;
+                    sstr_t* reallocated = (sstr_t*)
+                            alrealloc(allocator, result, j*sizeof(sstr_t));
+                    if (reallocated) {
+                        result = reallocated;
+                    } else {
+                        for (ssize_t i = 0 ; i < j-1 ; i++) {
+                            alfree(allocator, result[i].ptr);
+                        }
+                        alfree(allocator, result);
+                        *n = -2;
+                        return NULL;
+                    }
+                } else {
+                    /* nmax reached, copy the _full_ remaining string */
+                    result[j-1] = sstrdup_a(allocator, curpos);
+                    break;
+                }
             } else {
-                for (ssize_t j = i-1 ; j >= 0 ; j--) {
-                    alfree(allocator, result[j].ptr);
-                }
-                alfree(allocator, result);
-                *n = -2;
+                /* no more matches, copy last string */
+                result[j-1] = sstrdup_a(allocator, curpos);
                 break;
             }
         }
+        *n = j;
     } else {
         *n = -2;
     }
-    
-    free(sv.ptr);
 
     return result;
 }
--- a/ucx/string.h	Mon Feb 20 16:04:14 2017 +0100
+++ b/ucx/string.h	Mon Feb 20 16:57:09 2017 +0100
@@ -260,6 +260,9 @@
  * 
  * If the string ends with the delimiter and the maximum list size is not
  * exceeded, the last array item will be an empty string.
+ * In case the list size would be exceeded, the last array item will be the
+ * remaining string after the last split, <i>including</i> the terminating
+ * delimiter.
  * 
  * <b>Attention:</b> The array pointer <b>AND</b> all sstr_t.ptr of the array
  * items must be manually passed to <code>free()</code>. Use sstrsplit_a() with

mercurial