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 |