src/string.c

changeset 1132
b7fea9b2874c
parent 1127
1fd31909a3f8
child 1134
60edcd57d54c
equal deleted inserted replaced
1131:644f77f903b1 1132:b7fea9b2874c
28 #define CX_STR_IMPLEMENTATION 28 #define CX_STR_IMPLEMENTATION
29 #include "cx/string.h" 29 #include "cx/string.h"
30 30
31 #include <string.h> 31 #include <string.h>
32 #include <stdarg.h> 32 #include <stdarg.h>
33 #include <ctype.h>
34 #include <assert.h> 33 #include <assert.h>
35 #include <errno.h> 34 #include <errno.h>
36 #include <limits.h> 35 #include <limits.h>
37 #include <float.h> 36 #include <float.h>
38 37
527 memcpy(result.ptr, string.ptr, string.length); 526 memcpy(result.ptr, string.ptr, string.length);
528 result.ptr[string.length] = '\0'; 527 result.ptr[string.length] = '\0';
529 return result; 528 return result;
530 } 529 }
531 530
531 static bool str_isspace(char c) {
532 // TODO: remove once UCX has public API for this
533 return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v' || c == '\f';
534 }
535
532 cxstring cx_strtrim(cxstring string) { 536 cxstring cx_strtrim(cxstring string) {
533 cxstring result = string; 537 cxstring result = string;
534 // TODO: optimize by comparing multiple bytes at once 538 // TODO: optimize by comparing multiple bytes at once
535 while (result.length > 0 && isspace(*result.ptr)) { 539 while (result.length > 0 && str_isspace(*result.ptr)) {
536 result.ptr++; 540 result.ptr++;
537 result.length--; 541 result.length--;
538 } 542 }
539 while (result.length > 0 && isspace(result.ptr[result.length - 1])) { 543 while (result.length > 0 && str_isspace(result.ptr[result.length - 1])) {
540 result.length--; 544 result.length--;
541 } 545 }
542 return result; 546 return result;
543 } 547 }
544 548
590 #endif 594 #endif
591 } 595 }
592 596
593 void cx_strlower(cxmutstr string) { 597 void cx_strlower(cxmutstr string) {
594 for (size_t i = 0; i < string.length; i++) { 598 for (size_t i = 0; i < string.length; i++) {
595 string.ptr[i] = (char) tolower(string.ptr[i]); 599 if ((unsigned int) (string.ptr[i] - 'A') < 26u) {
600 string.ptr[i] += 'a' - 'A';
601 }
596 } 602 }
597 } 603 }
598 604
599 void cx_strupper(cxmutstr string) { 605 void cx_strupper(cxmutstr string) {
600 for (size_t i = 0; i < string.length; i++) { 606 for (size_t i = 0; i < string.length; i++) {
601 string.ptr[i] = (char) toupper(string.ptr[i]); 607 if ((unsigned int) (string.ptr[i] - 'a') < 26u) {
608 string.ptr[i] += 'A' - 'a';
609 }
602 } 610 }
603 } 611 }
604 612
605 #ifndef CX_STRREPLACE_INDEX_BUFFER_SIZE 613 #ifndef CX_STRREPLACE_INDEX_BUFFER_SIZE
606 #define CX_STRREPLACE_INDEX_BUFFER_SIZE 64 614 #define CX_STRREPLACE_INDEX_BUFFER_SIZE 64
1053 } 1061 }
1054 *output = (float) d; 1062 *output = (float) d;
1055 return 0; 1063 return 0;
1056 } 1064 }
1057 1065
1066 static bool str_isdigit(char c) {
1067 // TODO: remove once UCX has public API for this
1068 return c >= '0' && c <= '9';
1069 }
1070
1058 int cx_strtod_lc(cxstring str, double *output, char decsep, const char *groupsep) { 1071 int cx_strtod_lc(cxstring str, double *output, char decsep, const char *groupsep) {
1059 // TODO: overflow check 1072 // TODO: overflow check
1060 // TODO: increase precision 1073 // TODO: increase precision
1061 1074
1062 // trim and check 1075 // trim and check
1086 } 1099 }
1087 1100
1088 // parse all digits until we find the decsep 1101 // parse all digits until we find the decsep
1089 size_t pos = 0; 1102 size_t pos = 0;
1090 do { 1103 do {
1091 if (isdigit(str.ptr[pos])) { 1104 if (str_isdigit(str.ptr[pos])) {
1092 result = result * 10 + (str.ptr[pos] - '0'); 1105 result = result * 10 + (str.ptr[pos] - '0');
1093 } else if (strchr(groupsep, str.ptr[pos]) == NULL) { 1106 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
1094 break; 1107 break;
1095 } 1108 }
1096 } while (++pos < str.length); 1109 } while (++pos < str.length);
1115 } 1128 }
1116 } 1129 }
1117 // parse everything until exponent or end 1130 // parse everything until exponent or end
1118 double factor = 1.; 1131 double factor = 1.;
1119 do { 1132 do {
1120 if (isdigit(str.ptr[pos])) { 1133 if (str_isdigit(str.ptr[pos])) {
1121 factor *= 0.1; 1134 factor *= 0.1;
1122 result = result + factor * (str.ptr[pos] - '0'); 1135 result = result + factor * (str.ptr[pos] - '0');
1123 } else if (strchr(groupsep, str.ptr[pos]) == NULL) { 1136 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
1124 break; 1137 break;
1125 } 1138 }
1156 } 1169 }
1157 1170
1158 // parse the exponent 1171 // parse the exponent
1159 unsigned int exp = 0; 1172 unsigned int exp = 0;
1160 do { 1173 do {
1161 if (isdigit(str.ptr[pos])) { 1174 if (str_isdigit(str.ptr[pos])) {
1162 exp = 10 * exp + (str.ptr[pos] - '0'); 1175 exp = 10 * exp + (str.ptr[pos] - '0');
1163 } else if (strchr(groupsep, str.ptr[pos]) == NULL) { 1176 } else if (strchr(groupsep, str.ptr[pos]) == NULL) {
1164 errno = EINVAL; 1177 errno = EINVAL;
1165 return -1; 1178 return -1;
1166 } 1179 }

mercurial