| 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); |
| 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 } |