diff --git a/.github/workflows/ubuntu22-gcc13.yml b/.github/workflows/ubuntu22-gcc13.yml new file mode 100644 index 00000000..990a620c --- /dev/null +++ b/.github/workflows/ubuntu22-gcc13.yml @@ -0,0 +1,23 @@ +name: Ubuntu 22.04 CI (GCC 13) + +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 && + CXX=g++-13 CXXFLAGS=-Werror cmake -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure + - name: Use cmake CXX23 + run: | + mkdir build20 && + cd build20 && + CXX=g++-13 CXXFLAGS=-Werror cmake -DFASTFLOAT_CONSTEXPR_TESTS=ON -DFASTFLOAT_FIXEDWIDTH_TESTS=ON -DFASTFLOAT_CXX_STANDARD=23 -DFASTFLOAT_TEST=ON .. && + cmake --build . && + ctest --output-on-failure \ No newline at end of file diff --git a/CONTRIBUTORS b/CONTRIBUTORS index ef917434..da1e5d68 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -7,3 +7,4 @@ Fabio Pellacini Lénárd Szolnoki Jan Pharago Maya Warrier +Taha Khokhar diff --git a/include/fast_float/parse_number.h b/include/fast_float/parse_number.h index de70898b..e7ed8353 100644 --- a/include/fast_float/parse_number.h +++ b/include/fast_float/parse_number.h @@ -10,7 +10,11 @@ #include #include #include - +#ifdef __has_include + #if __has_include() + #include + #endif +#endif namespace fast_float { @@ -133,11 +137,58 @@ fastfloat_really_inline bool rounds_to_nearest() noexcept { } // namespace detail -template -FASTFLOAT_CONSTEXPR20 +template +struct from_chars_caller +{ + template + FASTFLOAT_CONSTEXPR20 + static from_chars_result_t call(UC const * first, UC const * last, + T &value, parse_options_t options) noexcept { + return from_chars_advanced(first, last, value, options); + } +}; + +#if __STDCPP_FLOAT32_T__ == 1 +template <> +struct from_chars_caller +{ + template + FASTFLOAT_CONSTEXPR20 + static from_chars_result_t call(UC const * first, UC const * last, + std::float32_t &value, parse_options_t options) noexcept{ + // if std::float32_t is defined, and we are in C++23 mode; macro set for float32; + // set value to float due to equivalence between float and float32_t + float val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +#if __STDCPP_FLOAT64_T__ == 1 +template <> +struct from_chars_caller +{ + template + FASTFLOAT_CONSTEXPR20 + static from_chars_result_t call(UC const * first, UC const * last, + std::float64_t &value, parse_options_t options) noexcept{ + // if std::float64_t is defined, and we are in C++23 mode; macro set for float64; + // set value as double due to equivalence between double and float64_t + double val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + + +template from_chars_result_t from_chars(UC const * first, UC const * last, T &value, chars_format fmt /*= chars_format::general*/) noexcept { - return from_chars_advanced(first, last, value, parse_options_t{fmt}); + return from_chars_caller::call(first, last, value, parse_options_t(fmt)); } template diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8083d5a6..b4734783 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -85,6 +85,12 @@ target_compile_features(fast_int PRIVATE cxx_std_17) fast_float_add_cpp_test(json_fmt) fast_float_add_cpp_test(fortran) +option(FASTFLOAT_FIXEDWIDTH_TESTS "Require fixed width test for C++23 (build will fail if the compiler won't support it)" OFF) +if (FASTFLOAT_FIXEDWIDTH_TESTS) + fast_float_add_cpp_test(fixedwidthtest) + target_compile_features(fixedwidthtest PRIVATE cxx_std_23) +endif() + option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF) if (FASTFLOAT_EXHAUSTIVE) diff --git a/tests/fixedwidthtest.cpp b/tests/fixedwidthtest.cpp new file mode 100644 index 00000000..b1660dd6 --- /dev/null +++ b/tests/fixedwidthtest.cpp @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include "fast_float/fast_float.h" +#include +#include + +int main() +{ + // Write some testcases for the parsing of floating point numbers in the float32_t type. + // We use the from_chars function defined in this library. + + const std::vector float32_test_expected{123.456f, -78.9f, 0.0001f, 3.40282e+038f}; + const std::vector float32_test{"123.456", "-78.9", "0.0001", "3.40282e+038"}; + + for (std::size_t i = 0; i < float32_test.size(); ++i) { + const auto& f = float32_test[i]; + std::float32_t result; + auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); + + if (answer.ec != std::errc() || result != float32_test_expected[i]) { + std::cerr << "Test failed for input: " << std::quoted(f) << std::endl; + return EXIT_FAILURE; + } + } + + // Test cases for std::float64_t + const std::vector float64_test_expected{1.23e4, -5.67e-8, 1.7976931348623157e+308, -1.7976931348623157e+308}; + const std::vector float64_test{"1.23e4", "-5.67e-8", "1.7976931348623157e+308", "-1.7976931348623157e+308"}; + + for (std::size_t i = 0; i < float64_test.size(); ++i) { + const auto& f = float64_test[i]; + std::float64_t result; + auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result); + + if (answer.ec != std::errc() || result != float64_test_expected[i]) { + std::cerr << "Test failed for input: " << std::quoted(f) << std::endl; + return EXIT_FAILURE; + } + } + + std::cout << "All tests passed successfully." << std::endl; + return EXIT_SUCCESS; + + return 0; +} \ No newline at end of file