src/string.c

changeset 1134
60edcd57d54c
parent 1132
b7fea9b2874c
equal deleted inserted replaced
1133:0aecb9fda851 1134:60edcd57d54c
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 #define CX_STR_IMPLEMENTATION
29 #include "cx/string.h" 28 #include "cx/string.h"
30 29
31 #include <string.h> 30 #include <string.h>
32 #include <stdarg.h> 31 #include <stdarg.h>
33 #include <assert.h> 32 #include <assert.h>
509 const cxstring *left = s1; 508 const cxstring *left = s1;
510 const cxstring *right = s2; 509 const cxstring *right = s2;
511 return cx_strcasecmp(*left, *right); 510 return cx_strcasecmp(*left, *right);
512 } 511 }
513 512
514 cxmutstr cx_strdup_a( 513 cxmutstr cx_strdup_a_(
515 const CxAllocator *allocator, 514 const CxAllocator *allocator,
516 cxstring string 515 cxstring string
517 ) { 516 ) {
518 cxmutstr result = { 517 cxmutstr result = {
519 cxMalloc(allocator, string.length + 1), 518 cxMalloc(allocator, string.length + 1),
741 cx_strrepl_free_ibuf(firstbuf); 740 cx_strrepl_free_ibuf(firstbuf);
742 741
743 return result; 742 return result;
744 } 743 }
745 744
746 CxStrtokCtx cx_strtok( 745 CxStrtokCtx cx_strtok_(
747 cxstring str, 746 cxstring str,
748 cxstring delim, 747 cxstring delim,
749 size_t limit 748 size_t limit
750 ) { 749 ) {
751 CxStrtokCtx ctx; 750 CxStrtokCtx ctx;
830 return -1; \ 829 return -1; \
831 } \ 830 } \
832 *output = (rtype) result; \ 831 *output = (rtype) result; \
833 return 0 832 return 0
834 833
835 int cx_strtos_lc(cxstring str, short *output, int base, const char *groupsep) { 834 int cx_strtos_lc_(cxstring str, short *output, int base, const char *groupsep) {
836 cx_strtoX_signed_impl(short, SHRT_MIN, SHRT_MAX); 835 cx_strtoX_signed_impl(short, SHRT_MIN, SHRT_MAX);
837 } 836 }
838 837
839 int cx_strtoi_lc(cxstring str, int *output, int base, const char *groupsep) { 838 int cx_strtoi_lc_(cxstring str, int *output, int base, const char *groupsep) {
840 cx_strtoX_signed_impl(int, INT_MIN, INT_MAX); 839 cx_strtoX_signed_impl(int, INT_MIN, INT_MAX);
841 } 840 }
842 841
843 int cx_strtol_lc(cxstring str, long *output, int base, const char *groupsep) { 842 int cx_strtol_lc_(cxstring str, long *output, int base, const char *groupsep) {
844 cx_strtoX_signed_impl(long, LONG_MIN, LONG_MAX); 843 cx_strtoX_signed_impl(long, LONG_MIN, LONG_MAX);
845 } 844 }
846 845
847 int cx_strtoll_lc(cxstring str, long long *output, int base, const char *groupsep) { 846 int cx_strtoll_lc_(cxstring str, long long *output, int base, const char *groupsep) {
848 // strategy: parse as unsigned, check range, negate if required 847 // strategy: parse as unsigned, check range, negate if required
849 bool neg = false; 848 bool neg = false;
850 size_t start_unsigned = 0; 849 size_t start_unsigned = 0;
851 850
852 // trim already, to search for a sign character 851 // trim already, to search for a sign character
888 *output = (long long) v; 887 *output = (long long) v;
889 return 0; 888 return 0;
890 } 889 }
891 } 890 }
892 891
893 int cx_strtoi8_lc(cxstring str, int8_t *output, int base, const char *groupsep) { 892 int cx_strtoi8_lc_(cxstring str, int8_t *output, int base, const char *groupsep) {
894 cx_strtoX_signed_impl(int8_t, INT8_MIN, INT8_MAX); 893 cx_strtoX_signed_impl(int8_t, INT8_MIN, INT8_MAX);
895 } 894 }
896 895
897 int cx_strtoi16_lc(cxstring str, int16_t *output, int base, const char *groupsep) { 896 int cx_strtoi16_lc_(cxstring str, int16_t *output, int base, const char *groupsep) {
898 cx_strtoX_signed_impl(int16_t, INT16_MIN, INT16_MAX); 897 cx_strtoX_signed_impl(int16_t, INT16_MIN, INT16_MAX);
899 } 898 }
900 899
901 int cx_strtoi32_lc(cxstring str, int32_t *output, int base, const char *groupsep) { 900 int cx_strtoi32_lc_(cxstring str, int32_t *output, int base, const char *groupsep) {
902 cx_strtoX_signed_impl(int32_t, INT32_MIN, INT32_MAX); 901 cx_strtoX_signed_impl(int32_t, INT32_MIN, INT32_MAX);
903 } 902 }
904 903
905 int cx_strtoi64_lc(cxstring str, int64_t *output, int base, const char *groupsep) { 904 int cx_strtoi64_lc_(cxstring str, int64_t *output, int base, const char *groupsep) {
906 assert(sizeof(long long) == sizeof(int64_t)); // should be true on all platforms 905 assert(sizeof(long long) == sizeof(int64_t)); // should be true on all platforms
907 return cx_strtoll_lc(str, (long long*) output, base, groupsep); 906 return cx_strtoll_lc(str, (long long*) output, base, groupsep);
908 } 907 }
909 908
910 int cx_strtoz_lc(cxstring str, ssize_t *output, int base, const char *groupsep) { 909 int cx_strtoz_lc_(cxstring str, ssize_t *output, int base, const char *groupsep) {
911 #if SSIZE_MAX == INT32_MAX 910 #if SSIZE_MAX == INT32_MAX
912 return cx_strtoi32_lc(str, (int32_t*) output, base, groupsep); 911 return cx_strtoi32_lc_(str, (int32_t*) output, base, groupsep);
913 #elif SSIZE_MAX == INT64_MAX 912 #elif SSIZE_MAX == INT64_MAX
914 return cx_strtoll_lc(str, (long long*) output, base, groupsep); 913 return cx_strtoll_lc_(str, (long long*) output, base, groupsep);
915 #else 914 #else
916 #error "unsupported ssize_t size" 915 #error "unsupported ssize_t size"
917 #endif 916 #endif
918 } 917 }
919 918
927 return -1; \ 926 return -1; \
928 } \ 927 } \
929 *output = (rtype) result; \ 928 *output = (rtype) result; \
930 return 0 929 return 0
931 930
932 int cx_strtous_lc(cxstring str, unsigned short *output, int base, const char *groupsep) { 931 int cx_strtous_lc_(cxstring str, unsigned short *output, int base, const char *groupsep) {
933 cx_strtoX_unsigned_impl(unsigned short, USHRT_MAX); 932 cx_strtoX_unsigned_impl(unsigned short, USHRT_MAX);
934 } 933 }
935 934
936 int cx_strtou_lc(cxstring str, unsigned int *output, int base, const char *groupsep) { 935 int cx_strtou_lc_(cxstring str, unsigned int *output, int base, const char *groupsep) {
937 cx_strtoX_unsigned_impl(unsigned int, UINT_MAX); 936 cx_strtoX_unsigned_impl(unsigned int, UINT_MAX);
938 } 937 }
939 938
940 int cx_strtoul_lc(cxstring str, unsigned long *output, int base, const char *groupsep) { 939 int cx_strtoul_lc_(cxstring str, unsigned long *output, int base, const char *groupsep) {
941 cx_strtoX_unsigned_impl(unsigned long, ULONG_MAX); 940 cx_strtoX_unsigned_impl(unsigned long, ULONG_MAX);
942 } 941 }
943 942
944 int cx_strtoull_lc(cxstring str, unsigned long long *output, int base, const char *groupsep) { 943 int cx_strtoull_lc_(cxstring str, unsigned long long *output, int base, const char *groupsep) {
945 // some sanity checks 944 // some sanity checks
946 str = cx_strtrim(str); 945 str = cx_strtrim(str);
947 if (str.length == 0) { 946 if (str.length == 0) {
948 errno = EINVAL; 947 errno = EINVAL;
949 return -1; 948 return -1;
1019 1018
1020 *output = result; 1019 *output = result;
1021 return 0; 1020 return 0;
1022 } 1021 }
1023 1022
1024 int cx_strtou8_lc(cxstring str, uint8_t *output, int base, const char *groupsep) { 1023 int cx_strtou8_lc_(cxstring str, uint8_t *output, int base, const char *groupsep) {
1025 cx_strtoX_unsigned_impl(uint8_t, UINT8_MAX); 1024 cx_strtoX_unsigned_impl(uint8_t, UINT8_MAX);
1026 } 1025 }
1027 1026
1028 int cx_strtou16_lc(cxstring str, uint16_t *output, int base, const char *groupsep) { 1027 int cx_strtou16_lc_(cxstring str, uint16_t *output, int base, const char *groupsep) {
1029 cx_strtoX_unsigned_impl(uint16_t, UINT16_MAX); 1028 cx_strtoX_unsigned_impl(uint16_t, UINT16_MAX);
1030 } 1029 }
1031 1030
1032 int cx_strtou32_lc(cxstring str, uint32_t *output, int base, const char *groupsep) { 1031 int cx_strtou32_lc_(cxstring str, uint32_t *output, int base, const char *groupsep) {
1033 cx_strtoX_unsigned_impl(uint32_t, UINT32_MAX); 1032 cx_strtoX_unsigned_impl(uint32_t, UINT32_MAX);
1034 } 1033 }
1035 1034
1036 int cx_strtou64_lc(cxstring str, uint64_t *output, int base, const char *groupsep) { 1035 int cx_strtou64_lc_(cxstring str, uint64_t *output, int base, const char *groupsep) {
1037 assert(sizeof(unsigned long long) == sizeof(uint64_t)); // should be true on all platforms 1036 assert(sizeof(unsigned long long) == sizeof(uint64_t)); // should be true on all platforms
1038 return cx_strtoull_lc(str, (unsigned long long*) output, base, groupsep); 1037 return cx_strtoull_lc(str, (unsigned long long*) output, base, groupsep);
1039 } 1038 }
1040 1039
1041 int cx_strtouz_lc(cxstring str, size_t *output, int base, const char *groupsep) { 1040 int cx_strtouz_lc_(cxstring str, size_t *output, int base, const char *groupsep) {
1042 #if SIZE_MAX == UINT32_MAX 1041 #if SIZE_MAX == UINT32_MAX
1043 return cx_strtou32_lc(str, (uint32_t*) output, base, groupsep); 1042 return cx_strtou32_lc_(str, (uint32_t*) output, base, groupsep);
1044 #elif SIZE_MAX == UINT64_MAX 1043 #elif SIZE_MAX == UINT64_MAX
1045 return cx_strtoull_lc(str, (unsigned long long *) output, base, groupsep); 1044 return cx_strtoull_lc_(str, (unsigned long long *) output, base, groupsep);
1046 #else 1045 #else
1047 #error "unsupported size_t size" 1046 #error "unsupported size_t size"
1048 #endif 1047 #endif
1049 } 1048 }
1050 1049
1051 int cx_strtof_lc(cxstring str, float *output, char decsep, const char *groupsep) { 1050 int cx_strtof_lc_(cxstring str, float *output, char decsep, const char *groupsep) {
1052 // use string to double and add a range check 1051 // use string to double and add a range check
1053 double d; 1052 double d;
1054 int ret = cx_strtod_lc(str, &d, decsep, groupsep); 1053 int ret = cx_strtod_lc_(str, &d, decsep, groupsep);
1055 if (ret != 0) return ret; 1054 if (ret != 0) return ret;
1056 // note: FLT_MIN is the smallest POSITIVE number that can be represented 1055 // note: FLT_MIN is the smallest POSITIVE number that can be represented
1057 double test = d < 0 ? -d : d; 1056 double test = d < 0 ? -d : d;
1058 if (test < FLT_MIN || test > FLT_MAX) { 1057 if (test < FLT_MIN || test > FLT_MAX) {
1059 errno = ERANGE; 1058 errno = ERANGE;
1066 static bool str_isdigit(char c) { 1065 static bool str_isdigit(char c) {
1067 // TODO: remove once UCX has public API for this 1066 // TODO: remove once UCX has public API for this
1068 return c >= '0' && c <= '9'; 1067 return c >= '0' && c <= '9';
1069 } 1068 }
1070 1069
1071 int cx_strtod_lc(cxstring str, double *output, char decsep, const char *groupsep) { 1070 int cx_strtod_lc_(cxstring str, double *output, char decsep, const char *groupsep) {
1072 // TODO: overflow check 1071 // TODO: overflow check
1073 // TODO: increase precision 1072 // TODO: increase precision
1074 1073
1075 // trim and check 1074 // trim and check
1076 str = cx_strtrim(str); 1075 str = cx_strtrim(str);

mercurial