| 218 |
218 |
| 219 cxstring cx_strchr( |
219 cxstring cx_strchr( |
| 220 cxstring string, |
220 cxstring string, |
| 221 int chr |
221 int chr |
| 222 ) { |
222 ) { |
| 223 chr = 0xFF & chr; |
223 char *ret = memchr(string.ptr, 0xFF & chr, string.length); |
| 224 // TODO: improve by comparing multiple bytes at once |
224 if (ret == NULL) return (cxstring) {NULL, 0}; |
| 225 for (size_t i = 0; i < string.length; i++) { |
225 return (cxstring) {ret, string.length - (ret - string.ptr)}; |
| 226 if (string.ptr[i] == chr) { |
|
| 227 return cx_strsubs(string, i); |
|
| 228 } |
|
| 229 } |
|
| 230 return (cxstring) {NULL, 0}; |
|
| 231 } |
226 } |
| 232 |
227 |
| 233 cxmutstr cx_strchr_m( |
228 cxmutstr cx_strchr_m( |
| 234 cxmutstr string, |
229 cxmutstr string, |
| 235 int chr |
230 int chr |
| 691 } while (searchstr.length > 0 && found < replmax); |
686 } while (searchstr.length > 0 && found < replmax); |
| 692 |
687 |
| 693 // Allocate result string |
688 // Allocate result string |
| 694 cxmutstr result; |
689 cxmutstr result; |
| 695 { |
690 { |
| 696 ssize_t adjlen = (ssize_t) replacement.length - (ssize_t) pattern.length; |
691 long long adjlen = (long long) replacement.length - (long long) pattern.length; |
| 697 size_t rcount = 0; |
692 size_t rcount = 0; |
| 698 curbuf = &ibuf; |
693 curbuf = &ibuf; |
| 699 do { |
694 do { |
| 700 rcount += curbuf->len; |
695 rcount += curbuf->len; |
| 701 curbuf = curbuf->next; |
696 curbuf = curbuf->next; |
| 845 int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep) { |
840 int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep) { |
| 846 // strategy: parse as unsigned, check range, negate if required |
841 // strategy: parse as unsigned, check range, negate if required |
| 847 bool neg = false; |
842 bool neg = false; |
| 848 size_t start_unsigned = 0; |
843 size_t start_unsigned = 0; |
| 849 |
844 |
| 850 // trim already, to search for a sign character |
845 // emptiness check |
| 851 str = cx_strtrim(str); |
|
| 852 if (str.length == 0) { |
846 if (str.length == 0) { |
| 853 errno = EINVAL; |
847 errno = EINVAL; |
| 854 return -1; |
848 return -1; |
| 855 } |
849 } |
| 856 |
850 |
| 901 } |
895 } |
| 902 |
896 |
| 903 int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep) { |
897 int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep) { |
| 904 assert(sizeof(long long) == sizeof(int64_t)); // should be true on all platforms |
898 assert(sizeof(long long) == sizeof(int64_t)); // should be true on all platforms |
| 905 return cx_strtoll_lc(str, (long long*) output, base, groupsep); |
899 return cx_strtoll_lc(str, (long long*) output, base, groupsep); |
| 906 } |
|
| 907 |
|
| 908 int cx_strtoz_lc_(cxstring str, ssize_t *output, int base, const char *groupsep) { |
|
| 909 #if SSIZE_MAX == INT32_MAX |
|
| 910 return cx_strtoi32_lc_(str, (int32_t*) output, base, groupsep); |
|
| 911 #elif SSIZE_MAX == INT64_MAX |
|
| 912 return cx_strtoll_lc_(str, (long long*) output, base, groupsep); |
|
| 913 #else |
|
| 914 #error "unsupported ssize_t size" |
|
| 915 #endif |
|
| 916 } |
900 } |
| 917 |
901 |
| 918 #define cx_strtoX_unsigned_impl(rtype, rmax) \ |
902 #define cx_strtoX_unsigned_impl(rtype, rmax) \ |
| 919 uint64_t result; \ |
903 uint64_t result; \ |
| 920 if (cx_strtou64_lc(str, &result, base, groupsep)) { \ |
904 if (cx_strtou64_lc(str, &result, base, groupsep)) { \ |
| 939 cx_strtoX_unsigned_impl(unsigned long, ULONG_MAX); |
923 cx_strtoX_unsigned_impl(unsigned long, ULONG_MAX); |
| 940 } |
924 } |
| 941 |
925 |
| 942 int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep) { |
926 int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep) { |
| 943 // some sanity checks |
927 // some sanity checks |
| 944 str = cx_strtrim(str); |
|
| 945 if (str.length == 0) { |
928 if (str.length == 0) { |
| 946 errno = EINVAL; |
929 errno = EINVAL; |
| 947 return -1; |
930 return -1; |
| 948 } |
931 } |
| 949 if (!(base == 2 || base == 8 || base == 10 || base == 16)) { |
932 if (!(base == 2 || base == 8 || base == 10 || base == 16)) { |
| 1034 int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep) { |
1017 int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep) { |
| 1035 assert(sizeof(unsigned long long) == sizeof(uint64_t)); // should be true on all platforms |
1018 assert(sizeof(unsigned long long) == sizeof(uint64_t)); // should be true on all platforms |
| 1036 return cx_strtoull_lc(str, (unsigned long long*) output, base, groupsep); |
1019 return cx_strtoull_lc(str, (unsigned long long*) output, base, groupsep); |
| 1037 } |
1020 } |
| 1038 |
1021 |
| 1039 int cx_strtouz_lc_(cxstring str, size_t *output, int base, const char *groupsep) { |
1022 int cx_strtoz_lc_(cxstring str, size_t *output, int base, const char *groupsep) { |
| 1040 #if SIZE_MAX == UINT32_MAX |
1023 #if SIZE_MAX == UINT32_MAX |
| 1041 return cx_strtou32_lc_(str, (uint32_t*) output, base, groupsep); |
1024 return cx_strtou32_lc_(str, (uint32_t*) output, base, groupsep); |
| 1042 #elif SIZE_MAX == UINT64_MAX |
1025 #elif SIZE_MAX == UINT64_MAX |
| 1043 return cx_strtoull_lc_(str, (unsigned long long *) output, base, groupsep); |
1026 return cx_strtoull_lc_(str, (unsigned long long *) output, base, groupsep); |
| 1044 #else |
1027 #else |
| 1068 |
1051 |
| 1069 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep) { |
1052 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep) { |
| 1070 // TODO: overflow check |
1053 // TODO: overflow check |
| 1071 // TODO: increase precision |
1054 // TODO: increase precision |
| 1072 |
1055 |
| 1073 // trim and check |
1056 // emptiness check |
| 1074 str = cx_strtrim(str); |
|
| 1075 if (str.length == 0) { |
1057 if (str.length == 0) { |
| 1076 errno = EINVAL; |
1058 errno = EINVAL; |
| 1077 return -1; |
1059 return -1; |
| 1078 } |
1060 } |
| 1079 |
1061 |