mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-07 01:06:48 +08:00
Merge pull request #236 from fastfloat/issue235
Verify and fix issue 235
This commit is contained in:
commit
a642af5235
16
.github/workflows/ubuntu22-sanitize.yml
vendored
Normal file
16
.github/workflows/ubuntu22-sanitize.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
name: Ubuntu 22.04 CI Sanitized (GCC 11)
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
ubuntu-build:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Use cmake
|
||||||
|
run: |
|
||||||
|
mkdir build &&
|
||||||
|
cd build &&
|
||||||
|
cmake -DFASTFLOAT_TEST=ON -D FASTFLOAT_SANITIZE=ON .. &&
|
||||||
|
cmake --build . &&
|
||||||
|
ctest --output-on-failure
|
||||||
@ -27,8 +27,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
|||||||
auto answer =
|
auto answer =
|
||||||
fast_float::from_chars(input_d.data(), input_d.data() + input_d.size(), result_d, format);
|
fast_float::from_chars(input_d.data(), input_d.data() + input_d.size(), result_d, format);
|
||||||
std::string input_f = fdp.ConsumeRandomLengthString(128);
|
std::string input_f = fdp.ConsumeRandomLengthString(128);
|
||||||
double result_f = 0.0;
|
float result_f = 0.0;
|
||||||
answer =
|
answer =
|
||||||
fast_float::from_chars(input_f.data(), input_f.data() + input_f.size(), result_f, format);
|
fast_float::from_chars(input_f.data(), input_f.data() + input_f.size(), result_f, format);
|
||||||
|
int result_i = 0;
|
||||||
|
std::string input_i = fdp.ConsumeRandomLengthString(128);
|
||||||
|
answer =
|
||||||
|
fast_float::from_chars(input_i.data(), input_i.data() + input_i.size(), result_i);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -442,8 +442,7 @@ parsed_number_string_t<UC> parse_number_string(UC const *p, UC const * pend, par
|
|||||||
|
|
||||||
template <typename T, typename UC>
|
template <typename T, typename UC>
|
||||||
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
fastfloat_really_inline FASTFLOAT_CONSTEXPR20
|
||||||
from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value, int base)
|
from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value, int base) {
|
||||||
{
|
|
||||||
from_chars_result_t<UC> answer;
|
from_chars_result_t<UC> answer;
|
||||||
|
|
||||||
UC const* const first = p;
|
UC const* const first = p;
|
||||||
@ -463,9 +462,11 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
|||||||
}
|
}
|
||||||
|
|
||||||
UC const* const start_num = p;
|
UC const* const start_num = p;
|
||||||
while (*p == UC('0')) {
|
|
||||||
|
while (p!= pend && *p == UC('0')) {
|
||||||
++p;
|
++p;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool has_leading_zeros = p > start_num;
|
const bool has_leading_zeros = p > start_num;
|
||||||
|
|
||||||
UC const* const start_digits = p;
|
UC const* const start_digits = p;
|
||||||
|
|||||||
@ -232,8 +232,7 @@ from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
|||||||
|
|
||||||
template <typename T, typename UC, typename>
|
template <typename T, typename UC, typename>
|
||||||
FASTFLOAT_CONSTEXPR20
|
FASTFLOAT_CONSTEXPR20
|
||||||
from_chars_result_t<UC> from_chars(UC const* first, UC const* last, T& value, int base) noexcept
|
from_chars_result_t<UC> from_chars(UC const* first, UC const* last, T& value, int base) noexcept {
|
||||||
{
|
|
||||||
static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
|
static_assert (is_supported_char_type<UC>(), "only char, wchar_t, char16_t and char32_t are supported");
|
||||||
|
|
||||||
from_chars_result_t<UC> answer;
|
from_chars_result_t<UC> answer;
|
||||||
|
|||||||
@ -10,7 +10,7 @@ option(FASTFLOAT_SUPPLEMENTAL_TESTS "Run supplemental tests" ON)
|
|||||||
if (NOT SYSTEM_DOCTEST)
|
if (NOT SYSTEM_DOCTEST)
|
||||||
FetchContent_Declare(doctest
|
FetchContent_Declare(doctest
|
||||||
GIT_REPOSITORY https://github.com/onqtam/doctest.git
|
GIT_REPOSITORY https://github.com/onqtam/doctest.git
|
||||||
GIT_TAG v2.4.10)
|
GIT_TAG v2.4.11)
|
||||||
endif()
|
endif()
|
||||||
if (FASTFLOAT_SUPPLEMENTAL_TESTS)
|
if (FASTFLOAT_SUPPLEMENTAL_TESTS)
|
||||||
FetchContent_Declare(supplemental_test_files
|
FetchContent_Declare(supplemental_test_files
|
||||||
@ -81,6 +81,7 @@ fast_float_add_cpp_test(long_test)
|
|||||||
fast_float_add_cpp_test(powersoffive_hardround)
|
fast_float_add_cpp_test(powersoffive_hardround)
|
||||||
fast_float_add_cpp_test(string_test)
|
fast_float_add_cpp_test(string_test)
|
||||||
fast_float_add_cpp_test(fast_int)
|
fast_float_add_cpp_test(fast_int)
|
||||||
|
target_compile_features(fast_int PRIVATE cxx_std_17)
|
||||||
fast_float_add_cpp_test(json_fmt)
|
fast_float_add_cpp_test(json_fmt)
|
||||||
fast_float_add_cpp_test(fortran)
|
fast_float_add_cpp_test(fortran)
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,33 @@
|
|||||||
|
#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 <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iomanip>
|
#include <string_view>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "fast_float/fast_float.h"
|
#include "fast_float/fast_float.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::string quoted(T& s) {
|
||||||
|
return "\""+std::string(s)+"\"";
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
all tests conducted are to check fast_float::from_chars functionality with int and unsigned
|
all tests conducted are to check fast_float::from_chars functionality with int and unsigned
|
||||||
test cases include:
|
test cases include:
|
||||||
@ -26,414 +48,391 @@ within range base tests - max/min numbers are still within int/unsigned bit size
|
|||||||
leading zeros tests - ignores all zeroes in front of valid number after converted from base
|
leading zeros tests - ignores all zeroes in front of valid number after converted from base
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
|
|
||||||
// int basic test
|
// int basic test
|
||||||
const std::vector<int> int_basic_test_expected { 0, 10, -40, 1001, 9 };
|
const std::vector<int> int_basic_test_expected { 0, 10, -40, 1001, 9 };
|
||||||
const std::vector<std::string> int_basic_test { "0", "10 ", "-40", "1001 with text", "9.999" };
|
const std::vector<std::string_view> int_basic_test { "0", "10 ", "-40", "1001 with text", "9.999" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_basic_test.size(); ++i)
|
for (std::size_t i = 0; i < int_basic_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_basic_test[i];
|
const auto& f = int_basic_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
|
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
if (answer.ec == std::errc::invalid_argument) {
|
if (answer.ec == std::errc::invalid_argument) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << " because of invalid arguement" << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << " because of invalid arguement" << std::endl;
|
||||||
}
|
}
|
||||||
else if (answer.ec == std::errc::result_out_of_range) {
|
else if (answer.ec == std::errc::result_out_of_range) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << " because it's out of range" << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << " because it's out of range" << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << " because of an unknown error" << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << " because of an unknown error" << std::endl;
|
||||||
}
|
}
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != int_basic_test_expected[i]) {
|
else if (result != int_basic_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected int: " << int_basic_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected int: " << int_basic_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned basic test
|
// unsigned basic test
|
||||||
const std::vector<unsigned> unsigned_basic_test_expected { 0, 10, 1001, 9 };
|
const std::vector<unsigned> unsigned_basic_test_expected { 0, 10, 1001, 9 };
|
||||||
const std::vector<std::string> unsigned_basic_test { "0", "10 ", "1001 with text", "9.999" };
|
const std::vector<std::string_view> unsigned_basic_test { "0", "10 ", "1001 with text", "9.999" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_basic_test.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_basic_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_basic_test[i];
|
const auto& f = unsigned_basic_test[i];
|
||||||
unsigned result;
|
unsigned result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to unsigned for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to unsigned for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != unsigned_basic_test_expected[i]) {
|
else if (result != unsigned_basic_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected unsigned: " << unsigned_basic_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected unsigned: " << unsigned_basic_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int invalid error test
|
// int invalid error test
|
||||||
const std::vector<std::string> int_invalid_argument_test{ "text", "text with 1002", "+50", " 50" };
|
const std::vector<std::string_view> int_invalid_argument_test{ "text", "text with 1002", "+50", " 50" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_invalid_argument_test.size(); ++i)
|
for (std::size_t i = 0; i < int_invalid_argument_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_invalid_argument_test[i];
|
const auto& f = int_invalid_argument_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned invalid error test
|
// unsigned invalid error test
|
||||||
const std::vector<std::string> unsigned_invalid_argument_test{ "text", "text with 1002", "+50", " 50", "-50" };
|
const std::vector<std::string_view> unsigned_invalid_argument_test{ "text", "text with 1002", "+50", " 50", "-50" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_invalid_argument_test.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_invalid_argument_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_invalid_argument_test[i];
|
const auto& f = unsigned_invalid_argument_test[i];
|
||||||
unsigned result;
|
unsigned result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int out of range error test #1 (8 bit)
|
// int out of range error test #1 (8 bit)
|
||||||
const std::vector<std::string> int_out_of_range_test_1{ "2000000000000000000000", "128", "-129"};
|
const std::vector<std::string_view> int_out_of_range_test_1{ "2000000000000000000000", "128", "-129"};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_out_of_range_test_1.size(); ++i)
|
for (std::size_t i = 0; i < int_out_of_range_test_1.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_out_of_range_test_1[i];
|
const auto& f = int_out_of_range_test_1[i];
|
||||||
int8_t result;
|
int8_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int out of range error test #2 (16 bit)
|
// int out of range error test #2 (16 bit)
|
||||||
const std::vector<std::string> int_out_of_range_test_2{ "2000000000000000000000", "32768", "-32769"};
|
const std::vector<std::string_view> int_out_of_range_test_2{ "2000000000000000000000", "32768", "-32769"};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_out_of_range_test_2.size(); ++i)
|
for (std::size_t i = 0; i < int_out_of_range_test_2.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_out_of_range_test_2[i];
|
const auto& f = int_out_of_range_test_2[i];
|
||||||
int16_t result;
|
int16_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int out of range error test #3 (32 bit)
|
// int out of range error test #3 (32 bit)
|
||||||
const std::vector<std::string> int_out_of_range_test_3{ "2000000000000000000000", "2147483648", "-2147483649"};
|
const std::vector<std::string_view> int_out_of_range_test_3{ "2000000000000000000000", "2147483648", "-2147483649"};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_out_of_range_test_3.size(); ++i)
|
for (std::size_t i = 0; i < int_out_of_range_test_3.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_out_of_range_test_3[i];
|
const auto& f = int_out_of_range_test_3[i];
|
||||||
int32_t result;
|
int32_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int out of range error test #4 (64 bit)
|
// int out of range error test #4 (64 bit)
|
||||||
const std::vector<std::string> int_out_of_range_test_4{ "2000000000000000000000", "9223372036854775808", "-9223372036854775809"};
|
const std::vector<std::string_view> int_out_of_range_test_4{ "2000000000000000000000", "9223372036854775808", "-9223372036854775809"};
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_out_of_range_test_4.size(); ++i)
|
for (std::size_t i = 0; i < int_out_of_range_test_4.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_out_of_range_test_4[i];
|
const auto& f = int_out_of_range_test_4[i];
|
||||||
int64_t result;
|
int64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned out of range error test #1 (8 bit)
|
// unsigned out of range error test #1 (8 bit)
|
||||||
const std::vector<std::string> unsigned_out_of_range_test_1{ "2000000000000000000000", "256" };
|
const std::vector<std::string_view> unsigned_out_of_range_test_1{ "2000000000000000000000", "256" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_out_of_range_test_1.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_out_of_range_test_1.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_out_of_range_test_1[i];
|
const auto& f = unsigned_out_of_range_test_1[i];
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned out of range error test #2 (16 bit)
|
// unsigned out of range error test #2 (16 bit)
|
||||||
const std::vector<std::string> unsigned_out_of_range_test_2{ "2000000000000000000000", "65536" };
|
const std::vector<std::string_view> unsigned_out_of_range_test_2{ "2000000000000000000000", "65536" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_out_of_range_test_2.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_out_of_range_test_2.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_out_of_range_test_2[i];
|
const auto& f = unsigned_out_of_range_test_2[i];
|
||||||
uint16_t result;
|
uint16_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned out of range error test #3 (32 bit)
|
// unsigned out of range error test #3 (32 bit)
|
||||||
const std::vector<std::string> unsigned_out_of_range_test_3{ "2000000000000000000000", "4294967296" };
|
const std::vector<std::string_view> unsigned_out_of_range_test_3{ "2000000000000000000000", "4294967296" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_out_of_range_test_3.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_out_of_range_test_3.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_out_of_range_test_3[i];
|
const auto& f = unsigned_out_of_range_test_3[i];
|
||||||
uint32_t result;
|
uint32_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned out of range error test #4 (64 bit)
|
// unsigned out of range error test #4 (64 bit)
|
||||||
const std::vector<std::string> unsigned_out_of_range_test_4{ "2000000000000000000000", "18446744073709551616" };
|
const std::vector<std::string_view> unsigned_out_of_range_test_4{ "2000000000000000000000", "18446744073709551616" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_out_of_range_test_4.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_out_of_range_test_4.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_out_of_range_test_4[i];
|
const auto& f = unsigned_out_of_range_test_4[i];
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int pointer test #1 (only numbers)
|
// int pointer test #1 (only numbers)
|
||||||
const std::vector<std::string> int_pointer_test_1 { "0", "010", "-40" };
|
const std::vector<std::string_view> int_pointer_test_1 { "0", "010", "-40" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_pointer_test_1.size(); ++i)
|
for (std::size_t i = 0; i < int_pointer_test_1.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_pointer_test_1[i];
|
const auto& f = int_pointer_test_1[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (strcmp(answer.ptr, "") != 0) {
|
else if (strcmp(answer.ptr, "") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f) << " did not match with expected ptr: " << std::quoted("") << std::endl;
|
std::cerr << "ptr of result " << quoted(f) << " did not match with expected ptr: " << quoted("") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int pointer test #2 (string behind numbers)
|
// int pointer test #2 (string behind numbers)
|
||||||
const std::string int_pointer_test_2 = "1001 with text";
|
const std::string_view int_pointer_test_2 = "1001 with text";
|
||||||
|
|
||||||
const auto& f2 = int_pointer_test_2;
|
const auto& f2 = int_pointer_test_2;
|
||||||
int result2;
|
int result2;
|
||||||
auto answer2 = fast_float::from_chars(f2.data(), f2.data() + f2.size(), result2);
|
auto answer2 = fast_float::from_chars(f2.data(), f2.data() + f2.size(), result2);
|
||||||
if (strcmp(answer2.ptr, " with text") != 0) {
|
if (strcmp(answer2.ptr, " with text") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f2) << " did not match with expected ptr: " << std::quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << quoted(f2) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int pointer test #3 (string with newline behind numbers)
|
// int pointer test #3 (string with newline behind numbers)
|
||||||
const std::string int_pointer_test_3 = "1001 with text\n";
|
const std::string_view int_pointer_test_3 = "1001 with text\n";
|
||||||
|
|
||||||
const auto& f3 = int_pointer_test_3;
|
const auto& f3 = int_pointer_test_3;
|
||||||
int result3;
|
int result3;
|
||||||
auto answer3 = fast_float::from_chars(f3.data(), f3.data() + f3.size(), result3);
|
auto answer3 = fast_float::from_chars(f3.data(), f3.data() + f3.size(), result3);
|
||||||
if (strcmp(answer3.ptr, " with text\n") != 0) {
|
if (strcmp(answer3.ptr, " with text\n") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f3) << " did not match with expected ptr: " << std::quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << quoted(f3) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int pointer test #4 (float)
|
// int pointer test #4 (float)
|
||||||
const std::string int_pointer_test_4 = "9.999";
|
const std::string_view int_pointer_test_4 = "9.999";
|
||||||
|
|
||||||
const auto& f4 = int_pointer_test_4;
|
const auto& f4 = int_pointer_test_4;
|
||||||
int result4;
|
int result4;
|
||||||
auto answer4 = fast_float::from_chars(f4.data(), f4.data() + f4.size(), result4);
|
auto answer4 = fast_float::from_chars(f4.data(), f4.data() + f4.size(), result4);
|
||||||
if (strcmp(answer4.ptr, ".999") != 0) {
|
if (strcmp(answer4.ptr, ".999") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f4) << " did not match with expected ptr: " << std::quoted(".999") << std::endl;
|
std::cerr << "ptr of result " << quoted(f4) << " did not match with expected ptr: " << quoted(".999") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int pointer test #5 (invalid int)
|
// int pointer test #5 (invalid int)
|
||||||
const std::string int_pointer_test_5 = "+50";
|
const std::string_view int_pointer_test_5 = "+50";
|
||||||
|
|
||||||
const auto& f5 = int_pointer_test_5;
|
const auto& f5 = int_pointer_test_5;
|
||||||
int result5;
|
int result5;
|
||||||
auto answer5 = fast_float::from_chars(f5.data(), f5.data() + f5.size(), result5);
|
auto answer5 = fast_float::from_chars(f5.data(), f5.data() + f5.size(), result5);
|
||||||
if (strcmp(answer5.ptr, "+50") != 0) {
|
if (strcmp(answer5.ptr, "+50") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f5) << " did not match with expected ptr: " << std::quoted("+50") << std::endl;
|
std::cerr << "ptr of result " << quoted(f5) << " did not match with expected ptr: " << quoted("+50") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned pointer test #2 (string behind numbers)
|
// unsigned pointer test #2 (string behind numbers)
|
||||||
const std::string unsigned_pointer_test_1 = "1001 with text";
|
const std::string_view unsigned_pointer_test_1 = "1001 with text";
|
||||||
|
|
||||||
const auto& f6 = unsigned_pointer_test_1;
|
const auto& f6 = unsigned_pointer_test_1;
|
||||||
unsigned result6;
|
unsigned result6;
|
||||||
auto answer6 = fast_float::from_chars(f6.data(), f6.data() + f6.size(), result6);
|
auto answer6 = fast_float::from_chars(f6.data(), f6.data() + f6.size(), result6);
|
||||||
if (strcmp(answer6.ptr, " with text") != 0) {
|
if (strcmp(answer6.ptr, " with text") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f6) << " did not match with expected ptr: " << std::quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << quoted(f6) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned pointer test #2 (invalid unsigned)
|
// unsigned pointer test #2 (invalid unsigned)
|
||||||
const std::string unsigned_pointer_test_2 = "-50";
|
const std::string_view unsigned_pointer_test_2 = "-50";
|
||||||
|
|
||||||
const auto& f7 = unsigned_pointer_test_2;
|
const auto& f7 = unsigned_pointer_test_2;
|
||||||
unsigned result7;
|
unsigned result7;
|
||||||
auto answer7 = fast_float::from_chars(f7.data(), f7.data() + f7.size(), result7);
|
auto answer7 = fast_float::from_chars(f7.data(), f7.data() + f7.size(), result7);
|
||||||
if (strcmp(answer7.ptr, "-50") != 0) {
|
if (strcmp(answer7.ptr, "-50") != 0) {
|
||||||
std::cerr << "ptr of result " << std::quoted(f7) << " did not match with expected ptr: " << std::quoted("-50") << std::endl;
|
std::cerr << "ptr of result " << quoted(f7) << " did not match with expected ptr: " << quoted("-50") << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int base 2 test
|
// int base 2 test
|
||||||
const std::vector<int> int_base_2_test_expected { 0, 1, 4, 2, -1 };
|
const std::vector<int> int_base_2_test_expected { 0, 1, 4, 2, -1 };
|
||||||
const std::vector<std::string> int_base_2_test { "0", "1", "100", "010", "-1" };
|
const std::vector<std::string_view> int_base_2_test { "0", "1", "100", "010", "-1" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_base_2_test.size(); ++i)
|
for (std::size_t i = 0; i < int_base_2_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_base_2_test[i];
|
const auto& f = int_base_2_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != int_base_2_test_expected[i]) {
|
else if (result != int_base_2_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected int: " << int_base_2_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected int: " << int_base_2_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned base 2 test
|
// unsigned base 2 test
|
||||||
const std::vector<unsigned> unsigned_base_2_test_expected { 0, 1, 4, 2 };
|
const std::vector<unsigned> unsigned_base_2_test_expected { 0, 1, 4, 2 };
|
||||||
const std::vector<std::string> unsigned_base_2_test { "0", "1", "100", "010" };
|
const std::vector<std::string_view> unsigned_base_2_test { "0", "1", "100", "010" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < unsigned_base_2_test.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_base_2_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_base_2_test[i];
|
const auto& f = unsigned_base_2_test[i];
|
||||||
unsigned result;
|
unsigned result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to unsigned for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to unsigned for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != unsigned_base_2_test_expected[i]) {
|
else if (result != unsigned_base_2_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected unsigned: " << unsigned_base_2_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected unsigned: " << unsigned_base_2_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int invalid error base 2 test
|
// int invalid error base 2 test
|
||||||
const std::vector<std::string> int_invalid_argument_base_2_test{ "2", "A", "-2" };
|
const std::vector<std::string_view> int_invalid_argument_base_2_test{ "2", "A", "-2" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_invalid_argument_base_2_test.size(); ++i)
|
for (std::size_t i = 0; i < int_invalid_argument_base_2_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_invalid_argument_base_2_test[i];
|
const auto& f = int_invalid_argument_base_2_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned invalid error base 2 test
|
// unsigned invalid error base 2 test
|
||||||
const std::vector<std::string> unsigned_invalid_argument_base_2_test{ "2", "A", "-1", "-2" };
|
const std::vector<std::string_view> 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)
|
for (std::size_t i = 0; i < unsigned_invalid_argument_base_2_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_invalid_argument_base_2_test[i];
|
const auto& f = unsigned_invalid_argument_base_2_test[i];
|
||||||
unsigned result;
|
unsigned result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 2);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// octal test
|
// octal test
|
||||||
const std::vector<int> base_octal_test_expected {0, 1, 7, 8, 9};
|
const std::vector<int> base_octal_test_expected {0, 1, 7, 8, 9};
|
||||||
const std::vector<std::string> base_octal_test { "0", "1", "07", "010", "0011" };
|
const std::vector<std::string_view> base_octal_test { "0", "1", "07", "010", "0011" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < base_octal_test.size(); ++i)
|
for (std::size_t i = 0; i < base_octal_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = base_octal_test[i];
|
const auto& f = base_octal_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 8);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 8);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != base_octal_test_expected[i]) {
|
else if (result != base_octal_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected int: " << base_octal_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected int: " << base_octal_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hex test
|
// hex test
|
||||||
const std::vector<int> base_hex_test_expected { 0, 1, 15, 31, 0, 16};
|
const std::vector<int> base_hex_test_expected { 0, 1, 15, 31, 0, 16};
|
||||||
const std::vector<std::string> base_hex_test { "0", "1", "F", "01f", "0x11", "10X11" };
|
const std::vector<std::string_view> base_hex_test { "0", "1", "F", "01f", "0x11", "10X11" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < base_hex_test.size(); ++i)
|
for (std::size_t i = 0; i < base_hex_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = base_hex_test[i];
|
const auto& f = base_hex_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 16);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 16);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != base_hex_test_expected[i]) {
|
else if (result != base_hex_test_expected[i]) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected int: " << base_hex_test_expected[i] << std::endl;
|
std::cerr << "result " << quoted(f) << " did not match with expected int: " << base_hex_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalid base test #1 (-1)
|
// invalid base test #1 (-1)
|
||||||
const std::vector<std::string> invalid_base_test_1 { "0", "1", "-1", "F", "10Z" };
|
const std::vector<std::string_view> invalid_base_test_1 { "0", "1", "-1", "F", "10Z" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < invalid_base_test_1.size(); ++i)
|
for (std::size_t i = 0; i < invalid_base_test_1.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = invalid_base_test_1[i];
|
const auto& f = invalid_base_test_1[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, -1);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, -1);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// invalid base test #2 (37)
|
// invalid base test #2 (37)
|
||||||
const std::vector<std::string> invalid_base_test_2 { "0", "1", "F", "Z", "10Z" };
|
const std::vector<std::string_view> invalid_base_test_2 { "0", "1", "F", "Z", "10Z" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < invalid_base_test_2.size(); ++i)
|
for (std::size_t i = 0; i < invalid_base_test_2.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = invalid_base_test_2[i];
|
const auto& f = invalid_base_test_2[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 37);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, 37);
|
||||||
if (answer.ec != std::errc::invalid_argument) {
|
if (answer.ec != std::errc::invalid_argument) {
|
||||||
std::cerr << "expected error should be 'invalid_argument' for: " << std::quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// int out of range error base test (64 bit)
|
// int out of range error base test (64 bit)
|
||||||
const std::vector<std::string> int_out_of_range_base_test { "1000000000000000000000000000000000000000000000000000000000000000",
|
const std::vector<std::string_view> int_out_of_range_base_test { "1000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"-1000000000000000000000000000000000000000000000000000000000000001",
|
"-1000000000000000000000000000000000000000000000000000000000000001",
|
||||||
"2021110011022210012102010021220101220222",
|
"2021110011022210012102010021220101220222",
|
||||||
"-2021110011022210012102010021220101221000",
|
"-2021110011022210012102010021220101221000",
|
||||||
@ -504,19 +503,18 @@ int main()
|
|||||||
"1Y2P0IJ32E8E8",
|
"1Y2P0IJ32E8E8",
|
||||||
"-1Y2P0IJ32E8E9" };
|
"-1Y2P0IJ32E8E9" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_out_of_range_base_test.size(); ++i)
|
for (std::size_t i = 0; i < int_out_of_range_base_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_out_of_range_base_test[i];
|
const auto& f = int_out_of_range_base_test[i];
|
||||||
int64_t result;
|
int64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, int(2 + (i / 2)));
|
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) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned out of range error base test (64 bit)
|
// unsigned out of range error base test (64 bit)
|
||||||
const std::vector<std::string> unsigned_out_of_range_base_test { "10000000000000000000000000000000000000000000000000000000000000000",
|
const std::vector<std::string_view> unsigned_out_of_range_base_test { "10000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"11112220022122120101211020120210210211221",
|
"11112220022122120101211020120210210211221",
|
||||||
"100000000000000000000000000000000",
|
"100000000000000000000000000000000",
|
||||||
"2214220303114400424121122431",
|
"2214220303114400424121122431",
|
||||||
@ -552,20 +550,19 @@ int main()
|
|||||||
"5G24A25TWKWFG",
|
"5G24A25TWKWFG",
|
||||||
"3W5E11264SGSG" };
|
"3W5E11264SGSG" };
|
||||||
int base_unsigned = 2;
|
int base_unsigned = 2;
|
||||||
for (std::size_t i = 0; i < unsigned_out_of_range_base_test.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_out_of_range_base_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_out_of_range_base_test[i];
|
const auto& f = unsigned_out_of_range_base_test[i];
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned);
|
||||||
if (answer.ec != std::errc::result_out_of_range) {
|
if (answer.ec != std::errc::result_out_of_range) {
|
||||||
std::cerr << "expected error for should be 'result_out_of_range': " << std::quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
++base_unsigned;
|
++base_unsigned;
|
||||||
}
|
}
|
||||||
|
|
||||||
// just within range base test (64 bit)
|
// just within range base test (64 bit)
|
||||||
const std::vector<std::string> int_within_range_base_test { "111111111111111111111111111111111111111111111111111111111111111",
|
const std::vector<std::string_view> int_within_range_base_test { "111111111111111111111111111111111111111111111111111111111111111",
|
||||||
"-1000000000000000000000000000000000000000000000000000000000000000",
|
"-1000000000000000000000000000000000000000000000000000000000000000",
|
||||||
"2021110011022210012102010021220101220221",
|
"2021110011022210012102010021220101220221",
|
||||||
"-2021110011022210012102010021220101220222",
|
"-2021110011022210012102010021220101220222",
|
||||||
@ -636,19 +633,18 @@ int main()
|
|||||||
"1Y2P0IJ32E8E7",
|
"1Y2P0IJ32E8E7",
|
||||||
"-1Y2P0IJ32E8E8" };
|
"-1Y2P0IJ32E8E8" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_within_range_base_test.size(); ++i)
|
for (std::size_t i = 0; i < int_within_range_base_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_within_range_base_test[i];
|
const auto& f = int_within_range_base_test[i];
|
||||||
int64_t result;
|
int64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, int(2 + (i / 2)));
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, int(2 + (i / 2)));
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "converting " << std::quoted(f) << " to int failed (most likely out of range)" << std::endl;
|
std::cerr << "converting " << quoted(f) << " to int failed (most likely out of range)" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsigned within range base test (64 bit)
|
// unsigned within range base test (64 bit)
|
||||||
const std::vector<std::string> unsigned_within_range_base_test { "1111111111111111111111111111111111111111111111111111111111111111",
|
const std::vector<std::string_view> unsigned_within_range_base_test { "1111111111111111111111111111111111111111111111111111111111111111",
|
||||||
"11112220022122120101211020120210210211220",
|
"11112220022122120101211020120210210211220",
|
||||||
"33333333333333333333333333333333",
|
"33333333333333333333333333333333",
|
||||||
"2214220303114400424121122430",
|
"2214220303114400424121122430",
|
||||||
@ -684,20 +680,19 @@ int main()
|
|||||||
"5G24A25TWKWFF",
|
"5G24A25TWKWFF",
|
||||||
"3W5E11264SGSF" };
|
"3W5E11264SGSF" };
|
||||||
int base_unsigned2 = 2;
|
int base_unsigned2 = 2;
|
||||||
for (std::size_t i = 0; i < unsigned_within_range_base_test.size(); ++i)
|
for (std::size_t i = 0; i < unsigned_within_range_base_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = unsigned_within_range_base_test[i];
|
const auto& f = unsigned_within_range_base_test[i];
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned2);
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, base_unsigned2);
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "converting " << std::quoted(f) << " to unsigned failed (most likely out of range)" << std::endl;
|
std::cerr << "converting " << quoted(f) << " to unsigned failed (most likely out of range)" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
++base_unsigned2;
|
++base_unsigned2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// int leading zeros test
|
// int leading zeros test
|
||||||
const std::vector<std::string> int_leading_zeros_test { "00000000000000000000000000000000000000000000000000000000000000000000001111110111",
|
const std::vector<std::string_view> int_leading_zeros_test { "00000000000000000000000000000000000000000000000000000000000000000000001111110111",
|
||||||
"000000000000000000000000000000000000000000000000001101121",
|
"000000000000000000000000000000000000000000000000001101121",
|
||||||
"000000000000000000000000000000000000000033313",
|
"000000000000000000000000000000000000000033313",
|
||||||
"00000000000000000000000000000013030",
|
"00000000000000000000000000000013030",
|
||||||
@ -733,20 +728,43 @@ int main()
|
|||||||
"00000000000000000000T0",
|
"00000000000000000000T0",
|
||||||
"00000000000000000000S7" };
|
"00000000000000000000S7" };
|
||||||
|
|
||||||
for (std::size_t i = 0; i < int_leading_zeros_test.size(); ++i)
|
for (std::size_t i = 0; i < int_leading_zeros_test.size(); ++i) {
|
||||||
{
|
|
||||||
const auto& f = int_leading_zeros_test[i];
|
const auto& f = int_leading_zeros_test[i];
|
||||||
int result;
|
int result;
|
||||||
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, int(i + 2));
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result, int(i + 2));
|
||||||
if (answer.ec != std::errc()) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "could not convert to int for input: " << std::quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: " << quoted(f) << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != 1015) {
|
else if (result != 1015) {
|
||||||
std::cerr << "result " << std::quoted(f) << " did not match with expected int: " << 1015 << std::endl;
|
std::cerr << "result " << quoted(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;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
std::cerr << "The test requires C++17." << std::endl;
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Loading…
x
Reference in New Issue
Block a user