#ifndef __cplusplus #error fastfloat requires a C++ compiler #endif // We want to enable the tests only for C++17 and above. #ifndef FASTFLOAT_CPLUSPLUS #if defined(_MSVC_LANG) && !defined(__clang__) #define FASTFLOAT_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG) #else #define FASTFLOAT_CPLUSPLUS __cplusplus #endif #endif #if FASTFLOAT_CPLUSPLUS >= 201703L #include #include #include #include #include #include "fast_float/fast_float.h" #include /* all tests conducted are to check fast_float::from_chars functionality with int and unsigned test cases include: int basic tests - numbers only, numbers with strings behind, decimals, negative numbers unsigned basic tests - numbers only, numbers with strings behind, decimals int invalid tests - strings only, strings with numbers behind, space in front of number, plus sign in front of number unsigned invalid tests - strings only, strings with numbers behind, space in front of number, plus/minus sign in front of number int out of range tests - numbers exceeding int bit size for 8, 16, 32, and 64 bits unsigned out of range tests - numbers exceeding unsigned bit size 8, 16, 32, and 64 bits int pointer tests - points to first character that is not recognized as int unsigned pointer tests - points to first character that is not recognized as unsigned int/unsigned base 2 tests - numbers are converted from binary to decimal octal tests - numbers are converted from octal to decimal hex tests - numbers are converted from hex to decimal (Note: 0x and 0X are considered invalid) invalid base tests - any base not within 2-36 is invalid out of range base tests - numbers exceeding int/unsigned bit size after converted from base (Note: only 64 bit int and unsigned are tested) within range base tests - max/min numbers are still within int/unsigned bit size after converted from base (Note: only 64 bit int and unsigned are tested) leading zeros tests - ignores all zeroes in front of valid number after converted from base */ int main() { // int basic test std::vector const int_basic_test_expected{0, 10, -40, 1001, 9}; std::vector const int_basic_test{"0", "10 ", "-40", "1001 with text", "9.999"}; for (std::size_t i = 0; i < int_basic_test.size(); ++i) { auto const f = int_basic_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc()) { if (answer.ec == std::errc::invalid_argument) { std::cerr << "could not convert to int for input: \"" << f << "\" because of invalid argument" << std::endl; } else if (answer.ec == std::errc::result_out_of_range) { std::cerr << "could not convert to int for input: \"" << f << "\" because it's out of range" << std::endl; } else { std::cerr << "could not convert to int for input: \"" << f << "\" because of an unknown error" << std::endl; } return EXIT_FAILURE; } else if (result != int_basic_test_expected[i]) { std::cerr << "result \"" << f << "\" did not match with expected int: " << int_basic_test_expected[i] << std::endl; return EXIT_FAILURE; } } // unsigned basic test std::vector const unsigned_basic_test_expected{0, 10, 1001, 9}; std::vector const unsigned_basic_test{ "0", "10 ", "1001 with text", "9.999"}; for (std::size_t i = 0; i < unsigned_basic_test.size(); ++i) { auto const &f = unsigned_basic_test[i]; unsigned result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc()) { std::cerr << "could not convert to unsigned for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != unsigned_basic_test_expected[i]) { std::cerr << "result \"" << f << "\" did not match with expected unsigned: " << unsigned_basic_test_expected[i] << std::endl; return EXIT_FAILURE; } } // int invalid error test std::vector const int_invalid_argument_test{ "text", "text with 1002", "+50", " 50"}; for (std::size_t i = 0; i < int_invalid_argument_test.size(); ++i) { auto const &f = int_invalid_argument_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned invalid error test std::vector const unsigned_invalid_argument_test{ "text", "text with 1002", "+50", " 50", "-50"}; for (std::size_t i = 0; i < unsigned_invalid_argument_test.size(); ++i) { auto const &f = unsigned_invalid_argument_test[i]; unsigned result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int out of range error test #1 (8 bit) std::vector const int_out_of_range_test_1{ "2000000000000000000000", "128", "-129"}; for (std::size_t i = 0; i < int_out_of_range_test_1.size(); ++i) { auto const &f = int_out_of_range_test_1[i]; int8_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int out of range error test #2 (16 bit) std::vector const int_out_of_range_test_2{ "2000000000000000000000", "32768", "-32769"}; for (std::size_t i = 0; i < int_out_of_range_test_2.size(); ++i) { auto const &f = int_out_of_range_test_2[i]; int16_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int out of range error test #3 (32 bit) std::vector const int_out_of_range_test_3{ "2000000000000000000000", "2147483648", "-2147483649"}; for (std::size_t i = 0; i < int_out_of_range_test_3.size(); ++i) { auto const &f = int_out_of_range_test_3[i]; int32_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int out of range error test #4 (64 bit) std::vector const int_out_of_range_test_4{ "2000000000000000000000", "9223372036854775808", "-9223372036854775809"}; for (std::size_t i = 0; i < int_out_of_range_test_4.size(); ++i) { auto const &f = int_out_of_range_test_4[i]; int64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned out of range error test #1 (8 bit) std::vector const unsigned_out_of_range_test_1{ "2000000000000000000000", "256"}; for (std::size_t i = 0; i < unsigned_out_of_range_test_1.size(); ++i) { auto const &f = unsigned_out_of_range_test_1[i]; uint8_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned out of range error test #2 (16 bit) std::vector const unsigned_out_of_range_test_2{ "2000000000000000000000", "65536"}; for (std::size_t i = 0; i < unsigned_out_of_range_test_2.size(); ++i) { auto const &f = unsigned_out_of_range_test_2[i]; uint16_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned out of range error test #3 (32 bit) std::vector const unsigned_out_of_range_test_3{ "2000000000000000000000", "4294967296"}; for (std::size_t i = 0; i < unsigned_out_of_range_test_3.size(); ++i) { auto const &f = unsigned_out_of_range_test_3[i]; uint32_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned out of range error test #4 (64 bit) std::vector const unsigned_out_of_range_test_4{ "2000000000000000000000", "18446744073709551616"}; for (std::size_t i = 0; i < unsigned_out_of_range_test_4.size(); ++i) { auto const &f = unsigned_out_of_range_test_4[i]; uint64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int pointer test #1 (only numbers) std::vector const int_pointer_test_1{"0", "010", "-40"}; for (std::size_t i = 0; i < int_pointer_test_1.size(); ++i) { auto const &f = int_pointer_test_1[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (strcmp(answer.ptr, "") != 0) { std::cerr << "ptr of result " << f << " did not match with expected ptr: \"\"" << std::endl; return EXIT_FAILURE; } } // int pointer test #2 (string behind numbers) std::string_view const int_pointer_test_2 = "1001 with text"; auto const &f2 = int_pointer_test_2; int result2; auto answer2 = fast_float::from_chars(f2.data(), f2.data() + f2.size(), result2); if (strcmp(answer2.ptr, " with text") != 0) { std::cerr << "ptr of result " << f2 << " did not match with expected ptr: \"with text\"" << std::endl; return EXIT_FAILURE; } // int pointer test #3 (string with newline behind numbers) std::string_view const int_pointer_test_3 = "1001 with text\n"; auto const &f3 = int_pointer_test_3; int result3; auto answer3 = fast_float::from_chars(f3.data(), f3.data() + f3.size(), result3); if (strcmp(answer3.ptr, " with text\n") != 0) { std::cerr << "ptr of result " << f3 << " did not match with expected ptr: with text" << std::endl; return EXIT_FAILURE; } // int pointer test #4 (float) std::string_view const int_pointer_test_4 = "9.999"; auto const &f4 = int_pointer_test_4; int result4; auto answer4 = fast_float::from_chars(f4.data(), f4.data() + f4.size(), result4); if (strcmp(answer4.ptr, ".999") != 0) { std::cerr << "ptr of result " << f4 << " did not match with expected ptr: .999" << std::endl; return EXIT_FAILURE; } // int pointer test #5 (invalid int) std::string_view const int_pointer_test_5 = "+50"; auto const &f5 = int_pointer_test_5; int result5; auto answer5 = fast_float::from_chars(f5.data(), f5.data() + f5.size(), result5); if (strcmp(answer5.ptr, "+50") != 0) { std::cerr << "ptr of result " << f5 << " did not match with expected ptr: +50" << std::endl; return EXIT_FAILURE; } // unsigned pointer test #2 (string behind numbers) std::string_view const unsigned_pointer_test_1 = "1001 with text"; auto const &f6 = unsigned_pointer_test_1; unsigned result6; auto answer6 = fast_float::from_chars(f6.data(), f6.data() + f6.size(), result6); if (strcmp(answer6.ptr, " with text") != 0) { std::cerr << "ptr of result " << f6 << " did not match with expected ptr: with text" << std::endl; return EXIT_FAILURE; } // unsigned pointer test #2 (invalid unsigned) std::string_view const unsigned_pointer_test_2 = "-50"; auto const &f7 = unsigned_pointer_test_2; unsigned result7; auto answer7 = fast_float::from_chars(f7.data(), f7.data() + f7.size(), result7); if (strcmp(answer7.ptr, "-50") != 0) { std::cerr << "ptr of result " << f7 << " did not match with expected ptr: -50" << std::endl; return EXIT_FAILURE; } // int base 2 test std::vector const int_base_2_test_expected{0, 1, 4, 2, -1}; std::vector const int_base_2_test{"0", "1", "100", "010", "-1"}; for (std::size_t i = 0; i < int_base_2_test.size(); ++i) { auto const f = int_base_2_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != int_base_2_test_expected[i]) { std::cerr << "result " << f << " did not match with expected int: " << int_base_2_test_expected[i] << std::endl; return EXIT_FAILURE; } } // unsigned base 2 test std::vector const unsigned_base_2_test_expected{0, 1, 4, 2}; std::vector const unsigned_base_2_test{"0", "1", "100", "010"}; for (std::size_t i = 0; i < unsigned_base_2_test.size(); ++i) { auto const &f = unsigned_base_2_test[i]; unsigned result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2); if (answer.ec != std::errc()) { std::cerr << "could not convert to unsigned for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != unsigned_base_2_test_expected[i]) { std::cerr << "result " << f << " did not match with expected unsigned: " << unsigned_base_2_test_expected[i] << std::endl; return EXIT_FAILURE; } } // int invalid error base 2 test std::vector const int_invalid_argument_base_2_test{"2", "A", "-2"}; for (std::size_t i = 0; i < int_invalid_argument_base_2_test.size(); ++i) { auto const &f = int_invalid_argument_base_2_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned invalid error base 2 test std::vector const unsigned_invalid_argument_base_2_test{ "2", "A", "-1", "-2"}; for (std::size_t i = 0; i < unsigned_invalid_argument_base_2_test.size(); ++i) { auto const &f = unsigned_invalid_argument_base_2_test[i]; unsigned result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // octal test std::vector const base_octal_test_expected{0, 1, 7, 8, 9}; std::vector const base_octal_test{"0", "1", "07", "010", "0011"}; for (std::size_t i = 0; i < base_octal_test.size(); ++i) { auto const &f = base_octal_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 8); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != base_octal_test_expected[i]) { std::cerr << "result " << f << " did not match with expected int: " << base_octal_test_expected[i] << std::endl; return EXIT_FAILURE; } } // hex test std::vector const base_hex_test_expected{0, 1, 15, 31, 0, 16}; std::vector const base_hex_test{"0", "1", "F", "01f", "0x11", "10X11"}; for (std::size_t i = 0; i < base_hex_test.size(); ++i) { auto const &f = base_hex_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 16); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != base_hex_test_expected[i]) { std::cerr << "result " << f << " did not match with expected int: " << base_hex_test_expected[i] << std::endl; return EXIT_FAILURE; } } // invalid base test #1 (-1) std::vector const invalid_base_test_1{"0", "1", "-1", "F", "10Z"}; for (std::size_t i = 0; i < invalid_base_test_1.size(); ++i) { auto const &f = invalid_base_test_1[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 1); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // invalid base test #2 (37) std::vector const invalid_base_test_2{"0", "1", "F", "Z", "10Z"}; for (std::size_t i = 0; i < invalid_base_test_2.size(); ++i) { auto const &f = invalid_base_test_2[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 37); if (answer.ec != std::errc::invalid_argument) { std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // int out of range error base test (64 bit) std::vector const int_out_of_range_base_test{ "1000000000000000000000000000000000000000000000000000000000000000", "-1000000000000000000000000000000000000000000000000000000000000001", "2021110011022210012102010021220101220222", "-2021110011022210012102010021220101221000", "20000000000000000000000000000000", "-20000000000000000000000000000001", "1104332401304422434310311213", "-1104332401304422434310311214", "1540241003031030222122212", "-1540241003031030222122213", "22341010611245052052301", "-22341010611245052052302", "1000000000000000000000", "-1000000000000000000001", "67404283172107811828", "-67404283172107811830", "9223372036854775808", "-9223372036854775809", "1728002635214590698", "-1728002635214590699", "41A792678515120368", "-41A792678515120369", "10B269549075433C38", "-10B269549075433C39", "4340724C6C71DC7A8", "-4340724C6C71DC7A9", "160E2AD3246366808", "-160E2AD3246366809", "8000000000000000", "-8000000000000001", "33D3D8307B214009", "-33D3D8307B21400A", "16AGH595DF825FA8", "-16AGH595DF825FA9", "BA643DCI0FFEEHI", "-BA643DCI0FFEEI0", "5CBFJIA3FH26JA8", "-5CBFJIA3FH26JA9", "2HEICIIIE82DH98", "-2HEICIIIE82DH99", "1ADAIBB21DCKFA8", "-1ADAIBB21DCKFA9", "I6K448CF4192C3", "-I6K448CF4192C4", "ACD772JNC9L0L8", "-ACD772JNC9L0L9", "64IE1FOCNN5G78", "-64IE1FOCNN5G79", "3IGOECJBMCA688", "-3IGOECJBMCA689", "27C48L5B37OAOQ", "-27C48L5B37OAP0", "1BK39F3AH3DMQ8", "-1BK39F3AH3DMQ9", "Q1SE8F0M04ISC", "-Q1SE8F0M04ISD", "HAJPPBC1FC208", "-HAJPPBC1FC209", "BM03I95HIA438", "-BM03I95HIA439", "8000000000000", "-8000000000001", "5HG4CK9JD4U38", "-5HG4CK9JD4U39", "3TDTK1V8J6TPQ", "-3TDTK1V8J6TPR", "2PIJMIKEXRXP8", "-2PIJMIKEXRXP9", "1Y2P0IJ32E8E8", "-1Y2P0IJ32E8E9"}; for (std::size_t i = 0; i < int_out_of_range_base_test.size(); ++i) { auto const &f = int_out_of_range_base_test[i]; int64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, uint_fast8_t(2 + (i / 2))); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } } // unsigned out of range error base test (64 bit) std::vector const unsigned_out_of_range_base_test{ "10000000000000000000000000000000000000000000000000000000000000000", "11112220022122120101211020120210210211221", "100000000000000000000000000000000", "2214220303114400424121122431", "3520522010102100444244424", "45012021522523134134602", "2000000000000000000000", "145808576354216723757", "18446744073709551616", "335500516A429071285", "839365134A2A240714", "219505A9511A867B73", "8681049ADB03DB172", "2C1D56B648C6CD111", "10000000000000000", "67979G60F5428011", "2D3FGB0B9CG4BD2G", "141C8786H1CCAAGH", "B53BJH07BE4DJ0G", "5E8G4GGG7G56DIG", "2L4LF104353J8KG", "1DDH88H2782I516", "L12EE5FN0JI1IG", "C9C336O0MLB7EG", "7B7N2PCNIOKCGG", "4EO8HFAM6FLLMP", "2NC6J26L66RHOG", "1N3RSH11F098RO", "14L9LKMO30O40G", "ND075IB45K86G", "G000000000000", "B1W8P7J5Q9R6G", "7ORP63SH4DPHI", "5G24A25TWKWFG", "3W5E11264SGSG"}; uint_fast8_t base_unsigned = 2; for (std::size_t i = 0; i < unsigned_out_of_range_base_test.size(); ++i) { auto const &f = unsigned_out_of_range_base_test[i]; uint64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned); if (answer.ec != std::errc::result_out_of_range) { std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl; return EXIT_FAILURE; } ++base_unsigned; } // just within range base test (64 bit) std::vector const int_within_range_base_test{ "111111111111111111111111111111111111111111111111111111111111111", "-1000000000000000000000000000000000000000000000000000000000000000", "2021110011022210012102010021220101220221", "-2021110011022210012102010021220101220222", "13333333333333333333333333333333", "-20000000000000000000000000000000", "1104332401304422434310311212", "-1104332401304422434310311213", "1540241003031030222122211", "-1540241003031030222122212", "22341010611245052052300", "-22341010611245052052301", "777777777777777777777", "-1000000000000000000000", "67404283172107811827", "-67404283172107811828", "9223372036854775807", "-9223372036854775808", "1728002635214590697", "-1728002635214590698", "41A792678515120367", "-41A792678515120368", "10B269549075433C37", "-10B269549075433C38", "4340724C6C71DC7A7", "-4340724C6C71DC7A8", "160E2AD3246366807", "-160E2AD3246366808", "7FFFFFFFFFFFFFFF", "-8000000000000000", "33D3D8307B214008", "-33D3D8307B214009", "16AGH595DF825FA7", "-16AGH595DF825FA8", "BA643DCI0FFEEHH", "-BA643DCI0FFEEHI", "5CBFJIA3FH26JA7", "-5CBFJIA3FH26JA8", "2HEICIIIE82DH97", "-2HEICIIIE82DH98", "1ADAIBB21DCKFA7", "-1ADAIBB21DCKFA8", "I6K448CF4192C2", "-I6K448CF4192C3", "ACD772JNC9L0L7", "-ACD772JNC9L0L8", "64IE1FOCNN5G77", "-64IE1FOCNN5G78", "3IGOECJBMCA687", "-3IGOECJBMCA688", "27C48L5B37OAOP", "-27C48L5B37OAOQ", "1BK39F3AH3DMQ7", "-1BK39F3AH3DMQ8", "Q1SE8F0M04ISB", "-Q1SE8F0M04ISC", "HAJPPBC1FC207", "-HAJPPBC1FC208", "BM03I95HIA437", "-BM03I95HIA438", "7VVVVVVVVVVVV", "-8000000000000", "5HG4CK9JD4U37", "-5HG4CK9JD4U38", "3TDTK1V8J6TPP", "-3TDTK1V8J6TPQ", "2PIJMIKEXRXP7", "-2PIJMIKEXRXP8", "1Y2P0IJ32E8E7", "-1Y2P0IJ32E8E8"}; for (std::size_t i = 0; i < int_within_range_base_test.size(); ++i) { auto const &f = int_within_range_base_test[i]; int64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, uint_fast8_t(2 + (i / 2))); if (answer.ec != std::errc()) { std::cerr << "converting " << f << " to int failed (most likely out of range)" << std::endl; return EXIT_FAILURE; } } // unsigned within range base test (64 bit) std::vector const unsigned_within_range_base_test{ "1111111111111111111111111111111111111111111111111111111111111111", "11112220022122120101211020120210210211220", "33333333333333333333333333333333", "2214220303114400424121122430", "3520522010102100444244423", "45012021522523134134601", "1777777777777777777777", "145808576354216723756", "18446744073709551615", "335500516A429071284", "839365134A2A240713", "219505A9511A867B72", "8681049ADB03DB171", "2C1D56B648C6CD110", "FFFFFFFFFFFFFFFF", "67979G60F5428010", "2D3FGB0B9CG4BD2F", "141C8786H1CCAAGG", "B53BJH07BE4DJ0F", "5E8G4GGG7G56DIF", "2L4LF104353J8KF", "1DDH88H2782I515", "L12EE5FN0JI1IF", "C9C336O0MLB7EF", "7B7N2PCNIOKCGF", "4EO8HFAM6FLLMO", "2NC6J26L66RHOF", "1N3RSH11F098RN", "14L9LKMO30O40F", "ND075IB45K86F", "FVVVVVVVVVVVV", "B1W8P7J5Q9R6F", "7ORP63SH4DPHH", "5G24A25TWKWFF", "3W5E11264SGSF"}; uint_fast8_t base_unsigned2 = 2; for (std::size_t i = 0; i < unsigned_within_range_base_test.size(); ++i) { auto const &f = unsigned_within_range_base_test[i]; uint64_t result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned2); if (answer.ec != std::errc()) { std::cerr << "converting " << f << " to unsigned failed (most likely out of range)" << std::endl; return EXIT_FAILURE; } ++base_unsigned2; } // int leading zeros test std::vector const int_leading_zeros_test{ "000000000000000000000000000000000000000000000000000000000000000000000011" "11110111", "000000000000000000000000000000000000000000000000001101121", "000000000000000000000000000000000000000033313", "00000000000000000000000000000013030", "0000000000000000000000000000004411", "0000000000000000000000000000002650", "0000000000000000000000000000001767", "0000000000000000000000000000001347", "0000000000000000000000000000001015", "00000000000000000000843", "00000000000000000000707", "00000000000000000000601", "00000000000000000000527", "0000000000000000000047A", "000000000000000000003F7", "0000000000000000000038C", "00000000000000000000327", "000000000000000000002F8", "000000000000000000002AF", "00000000000000000000267", "00000000000000000000223", "000000000000000000001L3", "000000000000000000001I7", "000000000000000000001FF", "000000000000000000001D1", "000000000000000000001AG", "00000000000000000000187", "00000000000000000000160", "0000000000000000000013P", "0000000000000000000011N", "00000000000000000000VN", "00000000000000000000UP", "00000000000000000000TT", "00000000000000000000T0", "00000000000000000000S7"}; for (std::size_t i = 0; i < int_leading_zeros_test.size(); ++i) { auto const &f = int_leading_zeros_test[i]; int result; auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, uint_fast8_t(i + 2)); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl; return EXIT_FAILURE; } else if (result != 1015) { std::cerr << "result " << f << " did not match with expected int: " << 1015 << std::endl; return EXIT_FAILURE; } } // issue 235 { std::vector s = {'0'}; s.shrink_to_fit(); int foo; auto answer = fast_float::from_chars(s.data(), s.data() + s.size(), foo); if (answer.ec != std::errc()) { std::cerr << "could not convert to int for input: '0'" << std::endl; return EXIT_FAILURE; } else if (foo != 0) { std::cerr << "expected zero: " << foo << std::endl; return EXIT_FAILURE; } } // dont parse UTF-16 code units of emojis as int if low byte is ascii digit { const std::u16string emojis[] = { u"ℹ", u"ℹ️", u"☸", u"☸️", u"☹", u"☹️", u"✳", u"✳️", u"✴", u"✴️", u"⤴", u"⤴️", u"⤵", u"⤵️", u"〰", u"〰️", }; bool failed = false; auto array_size = sizeof(emojis) / sizeof(emojis[0]); for (size_t i = 0; i < array_size; i++) { auto e = emojis[i]; int foo; auto answer = fast_float::from_chars(e.data(), e.data() + e.size(), foo); if (answer.ec == std::errc()) { failed = true; std::cerr << "Incorrectly parsed emoji #" << i << " as integer " << foo << "." << std::endl; } } if (failed) { return EXIT_FAILURE; } } // dont parse UTF-32 code points of emojis as int if low byte is ascii digit { const std::u32string emojis[] = { U"ℹ", U"ℹ️", U"☸", U"☸️", U"☹", U"☹️", U"✳", U"✳️", U"✴", U"✴️", U"⤴", U"⤴️", U"⤵", U"⤵️", U"〰", U"〰️", U"🈲", U"🈳", U"🈴", U"🈵", U"🈶", U"🈷", U"🈷️", U"🈸", U"🈹", U"🌰", U"🌱", U"🌲", U"🌳", U"🌴", U"🌵", U"🌶", U"🌶️", U"🌷", U"🌸", U"🌹", U"🐰", U"🐱", U"🐲", U"🐳", U"🐴", U"🐵", U"🐶", U"🐷", U"🐸", U"🐹", U"🔰", U"🔱", U"🔲", U"🔳", U"🔴", U"🔵", U"🔶", U"🔷", U"🔸", U"🔹", U"😰", U"😱", U"😲", U"😳", U"😴", U"😵", U"😵‍💫", U"😶", U"😶‍🌫", U"😶‍🌫️", U"😷", U"😸", U"😹", U"🤰", U"🤰🏻", U"🤰🏼", U"🤰🏽", U"🤰🏾", U"🤰🏿", U"🤱", U"🤱🏻", U"🤱🏼", U"🤱🏽", U"🤱🏾", U"🤱🏿", U"🤲", U"🤲🏻", U"🤲🏼", U"🤲🏽", U"🤲🏾", U"🤲🏿", U"🤳", U"🤳🏻", U"🤳🏼", U"🤳🏽", U"🤳🏾", U"🤳🏿", U"🤴", U"🤴🏻", U"🤴🏼", U"🤴🏽", U"🤴🏾", U"🤴🏿", U"🤵", U"🤵‍♀", U"🤵‍♀️", U"🤵‍♂", U"🤵‍♂️", U"🤵🏻", U"🤵🏻‍♀", U"🤵🏻‍♀️", U"🤵🏻‍♂", U"🤵🏻‍♂️", U"🤵🏼", U"🤵🏼‍♀", U"🤵🏼‍♀️", U"🤵🏼‍♂", U"🤵🏼‍♂️", U"🤵🏽", U"🤵🏽‍♀", U"🤵🏽‍♀️", U"🤵🏽‍♂", U"🤵🏽‍♂️", U"🤵🏾", U"🤵🏾‍♀", U"🤵🏾‍♀️", U"🤵🏾‍♂", U"🤵🏾‍♂️", U"🤵🏿", U"🤵🏿‍♀", U"🤵🏿‍♀️", U"🤵🏿‍♂", U"🤵🏿‍♂️", U"🤶", U"🤶🏻", U"🤶🏼", U"🤶🏽", U"🤶🏾", U"🤶🏿", U"🤷", U"🤷‍♀", U"🤷‍♀️", U"🤷‍♂", U"🤷‍♂️", U"🤷🏻", U"🤷🏻‍♀", U"🤷🏻‍♀️", U"🤷🏻‍♂", U"🤷🏻‍♂️", U"🤷🏼", U"🤷🏼‍♀", U"🤷🏼‍♀️", U"🤷🏼‍♂", U"🤷🏼‍♂️", U"🤷🏽", U"🤷🏽‍♀", U"🤷🏽‍♀️", U"🤷🏽‍♂", U"🤷🏽‍♂️", U"🤷🏾", U"🤷🏾‍♀", U"🤷🏾‍♀️", U"🤷🏾‍♂", U"🤷🏾‍♂️", U"🤷🏿", U"🤷🏿‍♀", U"🤷🏿‍♀️", U"🤷🏿‍♂", U"🤷🏿‍♂️", U"🤸", U"🤸‍♀", U"🤸‍♀️", U"🤸‍♂", U"🤸‍♂️", U"🤸🏻", U"🤸🏻‍♀", U"🤸🏻‍♀️", U"🤸🏻‍♂", U"🤸🏻‍♂️", U"🤸🏼", U"🤸🏼‍♀", U"🤸🏼‍♀️", U"🤸🏼‍♂", U"🤸🏼‍♂️", U"🤸🏽", U"🤸🏽‍♀", U"🤸🏽‍♀️", U"🤸🏽‍♂", U"🤸🏽‍♂️", U"🤸🏾", U"🤸🏾‍♀", U"🤸🏾‍♀️", U"🤸🏾‍♂", U"🤸🏾‍♂️", U"🤸🏿", U"🤸🏿‍♀", U"🤸🏿‍♀️", U"🤸🏿‍♂", U"🤸🏿‍♂️", U"🤹", U"🤹‍♀", U"🤹‍♀️", U"🤹‍♂", U"🤹‍♂️", U"🤹🏻", U"🤹🏻‍♀", U"🤹🏻‍♀️", U"🤹🏻‍♂", U"🤹🏻‍♂️", U"🤹🏼", U"🤹🏼‍♀", U"🤹🏼‍♀️", U"🤹🏼‍♂", U"🤹🏼‍♂️", U"🤹🏽", U"🤹🏽‍♀", U"🤹🏽‍♀️", U"🤹🏽‍♂", U"🤹🏽‍♂️", U"🤹🏾", U"🤹🏾‍♀", U"🤹🏾‍♀️", U"🤹🏾‍♂", U"🤹🏾‍♂️", U"🤹🏿", U"🤹🏿‍♀", U"🤹🏿‍♀️", U"🤹🏿‍♂", U"🤹🏿‍♂️", }; bool failed = false; auto array_size = sizeof(emojis) / sizeof(emojis[0]); for (size_t i = 0; i < array_size; i++) { auto e = emojis[i]; int foo; auto answer = fast_float::from_chars(e.data(), e.data() + e.size(), foo); if (answer.ec == std::errc()) { failed = true; std::cerr << "Incorrectly parsed emoji #" << i << " as integer " << foo << "." << std::endl; } } if (failed) { return EXIT_FAILURE; } } return EXIT_SUCCESS; } #else #include #include int main() { std::cerr << "The test requires C++17." << std::endl; return EXIT_SUCCESS; } #endif