1.1 --- a/src/string.c Wed Aug 31 23:12:05 2022 +0200 1.2 +++ b/src/string.c Sat Sep 03 14:56:07 2022 +0200 1.3 @@ -32,6 +32,13 @@ 1.4 #include <string.h> 1.5 #include <stdarg.h> 1.6 #include <stdint.h> 1.7 +#include <ctype.h> 1.8 + 1.9 +#ifndef _WIN32 1.10 + 1.11 +#include <strings.h> /* for strncasecmp() */ 1.12 + 1.13 +#endif /* _WIN32 */ 1.14 1.15 cxmutstr cx_mutstr(char *cstring) { 1.16 return (cxmutstr) {cstring, strlen(cstring)}; 1.17 @@ -336,3 +343,90 @@ 1.18 return cx_strsplit_a(allocator, cx_strcast(string), 1.19 delim, limit, (cxstring **) output); 1.20 } 1.21 + 1.22 +int cx_strcmp(cxstring s1, cxstring s2) { 1.23 + if (s1.length == s2.length) { 1.24 + return memcmp(s1.ptr, s2.ptr, s1.length); 1.25 + } else if (s1.length > s2.length) { 1.26 + return 1; 1.27 + } else { 1.28 + return -1; 1.29 + } 1.30 +} 1.31 + 1.32 +int cx_strcasecmp(cxstring s1, cxstring s2) { 1.33 + if (s1.length == s2.length) { 1.34 +#ifdef _WIN32 1.35 + return _strnicmp(s1.ptr, s2.ptr, s1.length); 1.36 +#else 1.37 + return strncasecmp(s1.ptr, s2.ptr, s1.length); 1.38 +#endif 1.39 + } else if (s1.length > s2.length) { 1.40 + return 1; 1.41 + } else { 1.42 + return -1; 1.43 + } 1.44 +} 1.45 + 1.46 +cxmutstr cx_strdup_a(CxAllocator *allocator, cxstring string) { 1.47 + cxmutstr result = { 1.48 + cxMalloc(allocator, string.length + 1), 1.49 + string.length 1.50 + }; 1.51 + if (result.ptr == NULL) { 1.52 + result.length = 0; 1.53 + return result; 1.54 + } 1.55 + memcpy(result.ptr, string.ptr, string.length); 1.56 + result.ptr[string.length] = '\0'; 1.57 + return result; 1.58 +} 1.59 + 1.60 +cxstring cx_strtrim(cxstring string) { 1.61 + cxstring result = string; 1.62 + // TODO: optimize by comparing multiple bytes at once 1.63 + while (result.length > 0 && isspace(*result.ptr)) { 1.64 + result.ptr++; 1.65 + result.length--; 1.66 + } 1.67 + while (result.length > 0 && isspace(result.ptr[result.length - 1])) { 1.68 + result.length--; 1.69 + } 1.70 + return result; 1.71 +} 1.72 + 1.73 +cxmutstr cx_strtrim_m(cxmutstr string) { 1.74 + cxstring result = cx_strtrim(cx_strcast(string)); 1.75 + return (cxmutstr) {(char *) result.ptr, result.length}; 1.76 +} 1.77 + 1.78 +bool cx_strprefix(cxstring string, cxstring prefix) { 1.79 + if (string.length < prefix.length) return false; 1.80 + return memcmp(string.ptr, prefix.ptr, prefix.length) == 0; 1.81 +} 1.82 + 1.83 +bool cx_strsuffix(cxstring string, cxstring suffix) { 1.84 + if (string.length < suffix.length) return false; 1.85 + return memcmp(string.ptr + string.length - suffix.length, 1.86 + suffix.ptr, suffix.length) == 0; 1.87 +} 1.88 + 1.89 +bool cx_casestrprefix(cxstring string, cxstring prefix) { 1.90 + if (string.length < prefix.length) return false; 1.91 +#ifdef _WIN32 1.92 + return _strnicmp(string.ptr, prefix.ptr, prefix.length) == 0; 1.93 +#else 1.94 + return strncasecmp(string.ptr, prefix.ptr, prefix.length) == 0; 1.95 +#endif 1.96 +} 1.97 + 1.98 +bool cx_casestrsuffix(cxstring string, cxstring suffix) { 1.99 + if (string.length < suffix.length) return false; 1.100 +#ifdef _WIN32 1.101 + return _strnicmp(string.ptr+string.length-suffix.length, 1.102 + suffix.ptr, suffix.length) == 0; 1.103 +#else 1.104 + return strncasecmp(string.ptr + string.length - suffix.length, 1.105 + suffix.ptr, suffix.length) == 0; 1.106 +#endif 1.107 +}