ucx/string.c

changeset 124
80609f9675f1
parent 0
1f419bd32da1
child 152
62921b370c60
--- a/ucx/string.c	Tue Feb 16 17:39:33 2016 +0100
+++ b/ucx/string.c	Mon May 23 12:28:32 2016 +0200
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2013 Olaf Wintermann. All rights reserved.
+ * Copyright 2015 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
@@ -29,6 +29,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "string.h"
 #include "allocator.h"
@@ -61,32 +62,71 @@
     return size;
 }
 
-sstr_t sstrncat(sstr_t s, size_t n, sstr_t c1, ...) {
-    va_list ap;
-    va_start(ap, c1);
-    s.ptr[0] = 0;
+static sstr_t sstrvcat_a(
+        UcxAllocator *a,
+        size_t count,
+        sstr_t s1,
+        sstr_t s2,
+        va_list ap) {
+    sstr_t str;
+    str.ptr = NULL;
+    str.length = 0;
+    if(count < 2) {
+        return str;
+    }
     
-    size_t len = s.length;
-    size_t cplen = c1.length > len ? len : c1.length;
-    char   *ptr = s.ptr;
+    sstr_t *strings = (sstr_t*) calloc(count, sizeof(sstr_t));
+    if(!strings) {
+        return str;
+    }
+    
+    // get all args and overall length
+    strings[0] = s1;
+    strings[1] = s2;
+    size_t strlen = s1.length + s2.length;
+    for (size_t i=2;i<count;i++) {
+        sstr_t s = va_arg (ap, sstr_t);
+        strings[i] = s;
+        strlen += s.length;
+    }
     
-    memcpy(ptr, c1.ptr, cplen);
-    len -= cplen;
-    ptr += cplen;
-    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) {
-            va_end(ap);
-            return s;
-        }
-        memcpy(ptr, str.ptr, cplen);
-        len -= cplen;
-        ptr += cplen;
+    // create new string
+    str.ptr = (char*) almalloc(a, strlen + 1);
+    str.length = strlen;
+    if(!str.ptr) {
+        free(strings);
+        str.length = 0;
+        return str;
+    }
+    
+    // concatenate strings
+    size_t pos = 0;
+    for (size_t i=0;i<count;i++) {
+        sstr_t s = strings[i];
+        memcpy(str.ptr + pos, s.ptr, s.length);
+        pos += s.length;
     }
+    
+    str.ptr[str.length] = '\0';
+    
+    free(strings);
+    
+    return str;
+}
+
+sstr_t sstrcat(size_t count, sstr_t s1, sstr_t s2, ...) {
+    va_list ap;
+    va_start(ap, s2);
+    sstr_t s = sstrvcat_a(ucx_default_allocator(), count, s1, s2, ap);
     va_end(ap);
-    s.length = ptr - s.ptr;
+    return s;
+}
 
+sstr_t sstrcat_a(UcxAllocator *a, size_t count, sstr_t s1, sstr_t s2, ...) {
+    va_list ap;
+    va_start(ap, s2);
+    sstr_t s = sstrvcat_a(a, count, s1, s2, ap);
+    va_end(ap);
     return s;
 }
 
@@ -97,13 +137,15 @@
 sstr_t sstrsubsl(sstr_t s, size_t start, size_t length) {
     sstr_t new_sstr;
     if (start >= s.length) {
-        return s;
+        new_sstr.ptr = NULL;
+        new_sstr.length = 0;
+    } else {
+        if (length > s.length-start) {
+            length = s.length-start;
+        }
+        new_sstr.ptr = &s.ptr[start];
+        new_sstr.length = length;
     }
-    if (length > s.length-start) {
-        length = s.length-start;
-    }
-    new_sstr.ptr = &s.ptr[start];
-    new_sstr.length = length;
     return new_sstr;
 }
 
@@ -133,18 +175,18 @@
     return n;
 }
 
-sstr_t* sstrsplit(sstr_t s, sstr_t d, size_t *n) {
+sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) {
     return sstrsplit_a(ucx_default_allocator(), s, d, n);
 }
 
-sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, size_t *n) {
+sstr_t* sstrsplit_a(UcxAllocator *allocator, sstr_t s, sstr_t d, ssize_t *n) {
     if (s.length == 0 || d.length == 0) {
         *n = -1;
         return NULL;
     }
 
     sstr_t* result;
-    size_t nmax = *n;
+    ssize_t nmax = *n;
     *n = 1;
 
     /* special case: exact match - no processing needed */
@@ -179,18 +221,27 @@
         }
         if ((*n) == nmax) break;
     }
-    result = (sstr_t*) allocator->malloc(allocator->pool, sizeof(sstr_t)*(*n));
+    result = (sstr_t*) almalloc(allocator, sizeof(sstr_t)*(*n));
 
     if (result) {
         char *pptr = sv.ptr;
-        for (size_t i = 0 ; i < *n ; i++) {
+        for (ssize_t i = 0 ; i < *n ; i++) {
             size_t l = strlen(pptr);
-            char* ptr = (char*) allocator->malloc(allocator->pool, l + 1);
-            memcpy(ptr, pptr, l);
-            ptr[l] = 0;
+            char* ptr = (char*) almalloc(allocator, l + 1);
+            if (ptr) {
+                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 {
+                for (ssize_t j = i-1 ; j >= 0 ; j--) {
+                    alfree(allocator, result[j].ptr);
+                }
+                alfree(allocator, result);
+                *n = -2;
+                break;
+            }
         }
     } else {
         *n = -2;
@@ -231,7 +282,7 @@
 
 sstr_t sstrdup_a(UcxAllocator *allocator, sstr_t s) {
     sstr_t newstring;
-    newstring.ptr = (char*)allocator->malloc(allocator->pool, s.length + 1);
+    newstring.ptr = (char*)almalloc(allocator, s.length + 1);
     if (newstring.ptr) {
         newstring.length = s.length;
         newstring.ptr[newstring.length] = 0;
@@ -246,38 +297,15 @@
 
 sstr_t sstrtrim(sstr_t string) {
     sstr_t newstr = string;
-    if (string.length == 0) {
-        return newstr;
-    }
     
-    size_t i;
-    for(i=0;i<string.length;i++) {
-        char c = string.ptr[i];
-        if(c > 32) {
-            break;
-        }
+    while (newstr.length > 0 && isspace(*newstr.ptr)) {
+        newstr.ptr++;
+        newstr.length--;
     }
-    newstr.ptr = &string.ptr[i];
-    newstr.length = string.length - i;
-    
-    if(newstr.length == 0) {
-        return newstr;
+    while (newstr.length > 0 && isspace(newstr.ptr[newstr.length-1])) {
+        newstr.length--;
     }
     
-    i = newstr.length - 1;
-    for(;;) {
-        char c = newstr.ptr[i];
-        if(c > 32) {
-            break;
-        }
-        if(i > 0) {
-            i--;
-        } else {
-            break;
-        }
-    }
-    newstr.length = i + 1;
-    
     return newstr;
 }
 
@@ -311,3 +339,35 @@
             suffix.ptr, suffix.length) == 0;
     }
 }
+
+sstr_t sstrlower(sstr_t string) {
+    sstr_t ret = sstrdup(string);
+    for (size_t i = 0; i < ret.length ; i++) {
+        ret.ptr[i] = tolower(ret.ptr[i]);
+    }
+    return ret;
+}
+
+sstr_t sstrlower_a(UcxAllocator *allocator, sstr_t string) {
+    sstr_t ret = sstrdup_a(allocator, string);
+    for (size_t i = 0; i < ret.length ; i++) {
+        ret.ptr[i] = tolower(ret.ptr[i]);
+    }
+    return ret;
+}
+
+sstr_t sstrupper(sstr_t string) {
+    sstr_t ret = sstrdup(string);
+    for (size_t i = 0; i < ret.length ; i++) {
+        ret.ptr[i] = toupper(ret.ptr[i]);
+    }
+    return ret;
+}
+
+sstr_t sstrupper_a(UcxAllocator *allocator, sstr_t string) {
+    sstr_t ret = sstrdup_a(allocator, string);
+    for (size_t i = 0; i < ret.length ; i++) {
+        ret.ptr[i] = toupper(ret.ptr[i]);
+    }
+    return ret;
+}

mercurial