remove uses of ctype.h - temporarily fixes #577

Sat, 18 Jan 2025 13:30:51 +0100

author
Mike Becker <universe@uap-core.de>
date
Sat, 18 Jan 2025 13:30:51 +0100
changeset 1132
b7fea9b2874c
parent 1131
644f77f903b1
child 1133
0aecb9fda851

remove uses of ctype.h - temporarily fixes #577

we are in desperate need of a good solution that also supports Unicode, though

src/json.c file | annotate | diff | comparison | revisions
src/string.c file | annotate | diff | comparison | revisions
--- a/src/json.c	Fri Jan 17 17:55:21 2025 +0100
+++ b/src/json.c	Sat Jan 18 13:30:51 2025 +0100
@@ -29,7 +29,6 @@
 #include "cx/json.h"
 
 #include <string.h>
-#include <ctype.h>
 #include <assert.h>
 #include <stdio.h>
 #include <inttypes.h>
@@ -133,6 +132,16 @@
     }
 }
 
+static bool json_isdigit(char c) {
+    // TODO: remove once UCX has public API for this
+    return c >= '0' && c <= '9';
+}
+
+static bool json_isspace(char c) {
+    // TODO: remove once UCX has public API for this
+    return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f';
+}
+
 static int num_isexp(const char *content, size_t length, size_t pos) {
     if (pos >= length) {
         return 0;
@@ -141,7 +150,7 @@
     int ok = 0;
     for (size_t i = pos; i < length; i++) {
         char c = content[i];
-        if (isdigit(c)) {
+        if (json_isdigit(c)) {
             ok = 1;
         } else if (i == pos) {
             if (!(c == '+' || c == '-')) {
@@ -158,7 +167,7 @@
 static CxJsonTokenType token_numbertype(const char *content, size_t length) {
     if (length == 0) return CX_JSON_TOKEN_ERROR;
 
-    if (content[0] != '-' && !isdigit(content[0])) {
+    if (content[0] != '-' && !json_isdigit(content[0])) {
         return CX_JSON_TOKEN_ERROR;
     }
 
@@ -171,7 +180,7 @@
             type = CX_JSON_TOKEN_NUMBER;
         } else if (content[i] == 'e' || content[i] == 'E') {
             return num_isexp(content, length, i + 1) ? CX_JSON_TOKEN_NUMBER : CX_JSON_TOKEN_ERROR;
-        } else if (!isdigit(content[i])) {
+        } else if (!json_isdigit(content[i])) {
             return CX_JSON_TOKEN_ERROR; // char is not a digit, decimal separator or exponent sep
         }
     }
@@ -235,7 +244,7 @@
             return CX_JSON_TOKEN_STRING;
         }
         default: {
-            if (isspace(c)) {
+            if (json_isspace(c)) {
                 return CX_JSON_TOKEN_SPACE;
             }
         }
--- a/src/string.c	Fri Jan 17 17:55:21 2025 +0100
+++ b/src/string.c	Sat Jan 18 13:30:51 2025 +0100
@@ -30,7 +30,6 @@
 
 #include <string.h>
 #include <stdarg.h>
-#include <ctype.h>
 #include <assert.h>
 #include <errno.h>
 #include <limits.h>
@@ -529,14 +528,19 @@
     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 && isspace(*result.ptr)) {
+    while (result.length > 0 && str_isspace(*result.ptr)) {
         result.ptr++;
         result.length--;
     }
-    while (result.length > 0 && isspace(result.ptr[result.length - 1])) {
+    while (result.length > 0 && str_isspace(result.ptr[result.length - 1])) {
         result.length--;
     }
     return result;
@@ -592,13 +596,17 @@
 
 void cx_strlower(cxmutstr string) {
     for (size_t i = 0; i < string.length; i++) {
-        string.ptr[i] = (char) tolower(string.ptr[i]);
+        if ((unsigned int) (string.ptr[i] - 'A') < 26u) {
+            string.ptr[i] += 'a' - 'A';
+        }
     }
 }
 
 void cx_strupper(cxmutstr string) {
     for (size_t i = 0; i < string.length; i++) {
-        string.ptr[i] = (char) toupper(string.ptr[i]);
+        if ((unsigned int) (string.ptr[i] - 'a') < 26u) {
+            string.ptr[i] += 'A' - 'a';
+        }
     }
 }
 
@@ -1055,6 +1063,11 @@
     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
@@ -1088,7 +1101,7 @@
     // parse all digits until we find the decsep
     size_t pos = 0;
     do {
-        if (isdigit(str.ptr[pos])) {
+        if (str_isdigit(str.ptr[pos])) {
             result = result * 10 + (str.ptr[pos] - '0');
         } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
             break;
@@ -1117,7 +1130,7 @@
         // parse everything until exponent or end
         double factor = 1.;
         do {
-            if (isdigit(str.ptr[pos])) {
+            if (str_isdigit(str.ptr[pos])) {
                 factor *= 0.1;
                 result = result + factor * (str.ptr[pos] - '0');
             } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
@@ -1158,7 +1171,7 @@
     // parse the exponent
     unsigned int exp = 0;
     do {
-        if (isdigit(str.ptr[pos])) {
+        if (str_isdigit(str.ptr[pos])) {
             exp = 10 * exp + (str.ptr[pos] - '0');
         } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
             errno = EINVAL;

mercurial