ucx/string.c

changeset 22
112b85020dc9
parent 21
5ea41679e15d
--- a/ucx/string.c	Thu May 29 15:59:27 2025 +0200
+++ b/ucx/string.c	Wed Nov 12 18:37:58 2025 +0100
@@ -25,6 +25,10 @@
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGE.
  */
+#ifdef MEMRCHR_NEED_GNU
+#define _GNU_SOURCE
+#endif
+
 #include "cx/string.h"
 
 #include <string.h>
@@ -33,6 +37,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <float.h>
+#include <ctype.h>
 
 #ifdef _WIN32
 #define cx_strcasecmp_impl _strnicmp
@@ -42,7 +47,7 @@
 #endif
 
 cxmutstr cx_mutstr(char *cstring) {
-    return (cxmutstr) {cstring, strlen(cstring)};
+    return (cxmutstr) {cstring, cstring == NULL ? 0 : strlen(cstring)};
 }
 
 cxmutstr cx_mutstrn(
@@ -53,7 +58,7 @@
 }
 
 cxstring cx_str(const char *cstring) {
-    return (cxstring) {cstring, strlen(cstring)};
+    return (cxstring) {cstring, cstring == NULL ? 0 : strlen(cstring)};
 }
 
 cxstring cx_strn(
@@ -231,19 +236,24 @@
 }
 
 cxstring cx_strrchr(
-        cxstring string,
-        int chr
+    cxstring string,
+    int chr
 ) {
+#ifdef WITH_MEMRCHR
+    char *ret = memrchr(string.ptr, 0xFF & chr, string.length);
+    if (ret == NULL) return (cxstring) {NULL, 0};
+    return (cxstring) {ret, string.length - (ret - string.ptr)};
+#else
     chr = 0xFF & chr;
     size_t i = string.length;
     while (i > 0) {
         i--;
-        // TODO: improve by comparing multiple bytes at once
         if (string.ptr[i] == chr) {
             return cx_strsubs(string, i);
         }
     }
     return (cxstring) {NULL, 0};
+#endif
 }
 
 cxmutstr cx_strrchr_m(
@@ -451,7 +461,7 @@
                          delim, limit, (cxstring **) output);
 }
 
-int cx_strcmp(
+int cx_strcmp_(
         cxstring s1,
         cxstring s2
 ) {
@@ -468,7 +478,7 @@
     }
 }
 
-int cx_strcasecmp(
+int cx_strcasecmp_(
         cxstring s1,
         cxstring s2
 ) {
@@ -520,19 +530,13 @@
     return result;
 }
 
-static bool str_isspace(char c) {
-    // TODO: remove once UCX has public API for this
-    return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f';
-}
-
 cxstring cx_strtrim(cxstring string) {
     cxstring result = string;
-    // TODO: optimize by comparing multiple bytes at once
-    while (result.length > 0 && str_isspace(*result.ptr)) {
+    while (result.length > 0 && isspace((unsigned char)(result.ptr[0]))) {
         result.ptr++;
         result.length--;
     }
-    while (result.length > 0 && str_isspace(result.ptr[result.length - 1])) {
+    while (result.length > 0 && isspace((unsigned char)result.ptr[result.length - 1])) {
         result.length--;
     }
     return result;
@@ -543,7 +547,7 @@
     return (cxmutstr) {(char *) result.ptr, result.length};
 }
 
-bool cx_strprefix(
+bool cx_strprefix_(
         cxstring string,
         cxstring prefix
 ) {
@@ -551,7 +555,7 @@
     return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
 }
 
-bool cx_strsuffix(
+bool cx_strsuffix_(
         cxstring string,
         cxstring suffix
 ) {
@@ -560,7 +564,7 @@
                   suffix.ptr, suffix.length) == 0;
 }
 
-bool cx_strcaseprefix(
+bool cx_strcaseprefix_(
         cxstring string,
         cxstring prefix
 ) {
@@ -572,7 +576,7 @@
 #endif
 }
 
-bool cx_strcasesuffix(
+bool cx_strcasesuffix_(
         cxstring string,
         cxstring suffix
 ) {
@@ -957,11 +961,6 @@
     return 0;
 }
 
-static bool str_isdigit(char c) {
-    // TODO: remove once UCX has public API for this
-    return c >= '0' && c <= '9';
-}
-
 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep) {
     // TODO: overflow check
     // TODO: increase precision
@@ -994,7 +993,7 @@
     // parse all digits until we find the decsep
     size_t pos = 0;
     do {
-        if (str_isdigit(str.ptr[pos])) {
+        if (isdigit((unsigned char)str.ptr[pos])) {
             result = result * 10 + (str.ptr[pos] - '0');
         } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
             break;
@@ -1023,7 +1022,7 @@
         // parse everything until exponent or end
         double factor = 1.;
         do {
-            if (str_isdigit(str.ptr[pos])) {
+            if (isdigit((unsigned char)str.ptr[pos])) {
                 factor *= 0.1;
                 result = result + factor * (str.ptr[pos] - '0');
             } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
@@ -1064,7 +1063,7 @@
     // parse the exponent
     unsigned int exp = 0;
     do {
-        if (str_isdigit(str.ptr[pos])) {
+        if (isdigit((unsigned char)str.ptr[pos])) {
             exp = 10 * exp + (str.ptr[pos] - '0');
         } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
             errno = EINVAL;

mercurial