| #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 <cstdlib> |
| #include <iostream> |
| #include <vector> |
| #include <string_view> |
| #include <cstring> |
| #include "fast_float/fast_float.h" |
| #include <cstdint> |
| |
| /* |
| 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<int> const int_basic_test_expected{0, 10, -40, 1001, 9}; |
| std::vector<std::string_view> 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<unsigned> const unsigned_basic_test_expected{0, 10, 1001, 9}; |
| std::vector<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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<int> const int_base_2_test_expected{0, 1, 4, 2, -1}; |
| std::vector<std::string_view> 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<unsigned> const unsigned_base_2_test_expected{0, 1, 4, 2}; |
| std::vector<std::string_view> 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<std::string_view> 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<std::string_view> 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<int> const base_octal_test_expected{0, 1, 7, 8, 9}; |
| std::vector<std::string_view> 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<int> const base_hex_test_expected{0, 1, 15, 31, 0, 16}; |
| std::vector<std::string_view> 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<std::string_view> 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<std::string_view> 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<std::string_view> 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, |
| int(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<std::string_view> 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"}; |
| int 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<std::string_view> 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, |
| int(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<std::string_view> 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"}; |
| int 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<std::string_view> 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, |
| int(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<char> 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 <iostream> |
| #include <cstdlib> |
| |
| int main() { |
| std::cerr << "The test requires C++17." << std::endl; |
| return EXIT_SUCCESS; |
| } |
| #endif |