mirror of
https://github.com/fastfloat/fast_float.git
synced 2025-12-06 16:56:57 +08:00
Merge pull request #237 from fastfloat/release610_candidate
preparing version 6.1.0
This commit is contained in:
commit
8378916ed8
@ -1,6 +1,8 @@
|
|||||||
cmake_minimum_required(VERSION 3.9)
|
cmake_minimum_required(VERSION 3.9)
|
||||||
|
|
||||||
project(fast_float VERSION 6.0.0 LANGUAGES CXX)
|
project(fast_float VERSION 6.0.0 LANGUAGES CXX)
|
||||||
|
set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat")
|
||||||
|
set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD})
|
||||||
option(FASTFLOAT_TEST "Enable tests" OFF)
|
option(FASTFLOAT_TEST "Enable tests" OFF)
|
||||||
if(FASTFLOAT_TEST)
|
if(FASTFLOAT_TEST)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
|||||||
12
README.md
12
README.md
@ -165,6 +165,16 @@ constexpr double constexptest() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## C++23: Fixed width floating-point types
|
||||||
|
|
||||||
|
The library also supports fixed-width floating-point types such as `std::float32_t` and `std::float64_t`. E.g., you can write:
|
||||||
|
|
||||||
|
```C++
|
||||||
|
std::float32_t result;
|
||||||
|
auto answer = fast_float::from_chars(f.data(), f.data() + f.size(), result);
|
||||||
|
``````
|
||||||
|
|
||||||
|
|
||||||
## Non-ASCII Inputs
|
## Non-ASCII Inputs
|
||||||
|
|
||||||
We also support UTF-16 and UTF-32 inputs, as well as ASCII/UTF-8, as in the following example:
|
We also support UTF-16 and UTF-32 inputs, as well as ASCII/UTF-8, as in the following example:
|
||||||
@ -371,7 +381,7 @@ the command line help.
|
|||||||
|
|
||||||
You may directly download automatically generated single-header files:
|
You may directly download automatically generated single-header files:
|
||||||
|
|
||||||
https://github.com/fastfloat/fast_float/releases/download/v6.0.0/fast_float.h
|
https://github.com/fastfloat/fast_float/releases/download/v6.1.0/fast_float.h
|
||||||
|
|
||||||
## RFC 7159
|
## RFC 7159
|
||||||
|
|
||||||
|
|||||||
@ -529,8 +529,8 @@ from_chars_result_t<UC> parse_int_string(UC const* p, UC const* pend, T& value,
|
|||||||
// this weird workaround is required because:
|
// this weird workaround is required because:
|
||||||
// - converting unsigned to signed when its value is greater than signed max is UB pre-C++23.
|
// - converting unsigned to signed when its value is greater than signed max is UB pre-C++23.
|
||||||
// - reinterpret_casting (~i + 1) would work, but it is not constexpr
|
// - reinterpret_casting (~i + 1) would work, but it is not constexpr
|
||||||
// this is always optimized into a neg instruction.
|
// this is always optimized into a neg instruction (note: T is an integer type)
|
||||||
value = T(-std::numeric_limits<T>::max() - T(i - std::numeric_limits<T>::max()));
|
value = T(-std::numeric_limits<T>::max() - T(i - uint64_t(std::numeric_limits<T>::max())));
|
||||||
#ifdef FASTFLOAT_VISUAL_STUDIO
|
#ifdef FASTFLOAT_VISUAL_STUDIO
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -7,7 +7,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#ifdef __has_include
|
||||||
|
#if __has_include(<stdfloat>)
|
||||||
|
#include <stdfloat>
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
#include "constexpr_feature_detect.h"
|
#include "constexpr_feature_detect.h"
|
||||||
|
|
||||||
namespace fast_float {
|
namespace fast_float {
|
||||||
@ -188,7 +192,14 @@ fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
fastfloat_really_inline constexpr bool is_supported_float_type() {
|
fastfloat_really_inline constexpr bool is_supported_float_type() {
|
||||||
return std::is_same<T, float>::value || std::is_same<T, double>::value;
|
return std::is_same<T, float>::value || std::is_same<T, double>::value
|
||||||
|
#if __STDCPP_FLOAT32_T__
|
||||||
|
|| std::is_same<T, std::float32_t>::value
|
||||||
|
#endif
|
||||||
|
#if __STDCPP_FLOAT64_T__
|
||||||
|
|| std::is_same<T, std::float64_t>::value
|
||||||
|
#endif
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename UC>
|
template <typename UC>
|
||||||
|
|||||||
@ -10,11 +10,6 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
#ifdef __has_include
|
|
||||||
#if __has_include(<stdfloat>)
|
|
||||||
#include <stdfloat>
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
namespace fast_float {
|
namespace fast_float {
|
||||||
|
|
||||||
|
|
||||||
@ -186,6 +181,7 @@ struct from_chars_caller<std::float64_t>
|
|||||||
|
|
||||||
|
|
||||||
template<typename T, typename UC, typename>
|
template<typename T, typename UC, typename>
|
||||||
|
FASTFLOAT_CONSTEXPR20
|
||||||
from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
|
from_chars_result_t<UC> from_chars(UC const * first, UC const * last,
|
||||||
T &value, chars_format fmt /*= chars_format::general*/) noexcept {
|
T &value, chars_format fmt /*= chars_format::general*/) noexcept {
|
||||||
return from_chars_caller<T>::call(first, last, value, parse_options_t<UC>(fmt));
|
return from_chars_caller<T>::call(first, last, value, parse_options_t<UC>(fmt));
|
||||||
@ -196,7 +192,7 @@ FASTFLOAT_CONSTEXPR20
|
|||||||
from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
from_chars_result_t<UC> from_chars_advanced(UC const * first, UC const * last,
|
||||||
T &value, parse_options_t<UC> options) noexcept {
|
T &value, parse_options_t<UC> options) noexcept {
|
||||||
|
|
||||||
static_assert (is_supported_float_type<T>(), "only float and double are supported");
|
static_assert (is_supported_float_type<T>(), "only some floating-point types are supported");
|
||||||
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;
|
||||||
|
|||||||
@ -84,11 +84,14 @@ fast_float_add_cpp_test(fast_int)
|
|||||||
target_compile_features(fast_int PRIVATE cxx_std_17)
|
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)
|
||||||
|
if(CMAKE_CXX_STANDARD GREATER_EQUAL 23)
|
||||||
option(FASTFLOAT_FIXEDWIDTH_TESTS "Require fixed width test for C++23 (build will fail if the compiler won't support it)" OFF)
|
option(FASTFLOAT_FIXEDWIDTH_TESTS "Require fixed width test for C++23 (build will fail if the compiler won't support it)" ON)
|
||||||
|
else()
|
||||||
|
option(FASTFLOAT_FIXEDWIDTH_TESTS "Require fixed width test for C++23 (build will fail if the compiler won't support it)" OFF)
|
||||||
|
endif()
|
||||||
if (FASTFLOAT_FIXEDWIDTH_TESTS)
|
if (FASTFLOAT_FIXEDWIDTH_TESTS)
|
||||||
fast_float_add_cpp_test(fixedwidthtest)
|
fast_float_add_cpp_test(fixedwidthtest)
|
||||||
target_compile_features(fixedwidthtest PRIVATE cxx_std_23)
|
target_compile_features(fixedwidthtest PUBLIC cxx_std_23)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF)
|
option(FASTFLOAT_EXHAUSTIVE "Exhaustive tests" OFF)
|
||||||
|
|||||||
@ -23,11 +23,6 @@
|
|||||||
#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:
|
||||||
@ -54,24 +49,24 @@ int main() {
|
|||||||
const std::vector<std::string_view> 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: " << quoted(f) << " because of invalid arguement" << std::endl;
|
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) {
|
else if (answer.ec == std::errc::result_out_of_range) {
|
||||||
std::cerr << "could not convert to int for input: " << quoted(f) << " because it's out of range" << std::endl;
|
std::cerr << "could not convert to int for input: \"" << f << "\" because it's out of range" << std::endl;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cerr << "could not convert to int for input: " << quoted(f) << " because of an unknown error" << std::endl;
|
std::cerr << "could not convert to int for input: \"" << 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 " << quoted(f) << " did not match with expected int: " << int_basic_test_expected[i] << std::endl;
|
std::cerr << "result \"" << f << "\" did not match with expected int: " << int_basic_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,11 +80,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to unsigned for input: \"" << 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 " << quoted(f) << " did not match with expected unsigned: " << unsigned_basic_test_expected[i] << std::endl;
|
std::cerr << "result \"" << f << "\" did not match with expected unsigned: " << unsigned_basic_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +97,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,7 +110,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,7 +123,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +136,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -154,7 +149,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,7 +162,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,7 +175,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,7 +188,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,7 +201,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -219,7 +214,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -232,11 +227,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: \"" << 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 " << quoted(f) << " did not match with expected ptr: " << quoted("") << std::endl;
|
std::cerr << "ptr of result " << f << " did not match with expected ptr: \"\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,7 +243,7 @@ int main() {
|
|||||||
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 " << quoted(f2) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << f2 << " did not match with expected ptr: \"with text\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,7 +254,7 @@ int main() {
|
|||||||
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 " << quoted(f3) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << f3 << " did not match with expected ptr: with text" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -270,7 +265,7 @@ int main() {
|
|||||||
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 " << quoted(f4) << " did not match with expected ptr: " << quoted(".999") << std::endl;
|
std::cerr << "ptr of result " << f4 << " did not match with expected ptr: .999" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +276,7 @@ int main() {
|
|||||||
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 " << quoted(f5) << " did not match with expected ptr: " << quoted("+50") << std::endl;
|
std::cerr << "ptr of result " << f5 << " did not match with expected ptr: +50" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +287,7 @@ int main() {
|
|||||||
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 " << quoted(f6) << " did not match with expected ptr: " << quoted(" with text") << std::endl;
|
std::cerr << "ptr of result " << f6 << " did not match with expected ptr: with text" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +298,7 @@ int main() {
|
|||||||
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 " << quoted(f7) << " did not match with expected ptr: " << quoted("-50") << std::endl;
|
std::cerr << "ptr of result " << f7 << " did not match with expected ptr: -50" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,15 +307,15 @@ int main() {
|
|||||||
const std::vector<std::string_view> 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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: \"" << 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 " << quoted(f) << " did not match with expected int: " << int_base_2_test_expected[i] << std::endl;
|
std::cerr << "result " << f << " did not match with expected int: " << int_base_2_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -334,11 +329,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to unsigned for input: \"" << 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 " << quoted(f) << " did not match with expected unsigned: " << unsigned_base_2_test_expected[i] << std::endl;
|
std::cerr << "result " << f << " did not match with expected unsigned: " << unsigned_base_2_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -351,7 +346,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -364,7 +359,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,11 +373,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: \"" << 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 " << quoted(f) << " did not match with expected int: " << base_octal_test_expected[i] << std::endl;
|
std::cerr << "result " << f << " did not match with expected int: " << base_octal_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,11 +391,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: \"" << 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 " << quoted(f) << " did not match with expected int: " << base_hex_test_expected[i] << std::endl;
|
std::cerr << "result " << f << " did not match with expected int: " << base_hex_test_expected[i] << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -413,7 +408,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -426,7 +421,7 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "expected error should be 'invalid_argument' for: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,7 +503,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -555,7 +550,7 @@ int main() {
|
|||||||
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': " << quoted(f) << std::endl;
|
std::cerr << "expected error for should be 'result_out_of_range': \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
++base_unsigned;
|
++base_unsigned;
|
||||||
@ -638,7 +633,7 @@ int main() {
|
|||||||
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 " << quoted(f) << " to int failed (most likely out of range)" << std::endl;
|
std::cerr << "converting " << f << " to int failed (most likely out of range)" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -685,7 +680,7 @@ int main() {
|
|||||||
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 " << quoted(f) << " to unsigned failed (most likely out of range)" << std::endl;
|
std::cerr << "converting " << f << " to unsigned failed (most likely out of range)" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
++base_unsigned2;
|
++base_unsigned2;
|
||||||
@ -733,11 +728,11 @@ int main() {
|
|||||||
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: " << quoted(f) << std::endl;
|
std::cerr << "could not convert to int for input: \"" << f << "\"" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
else if (result != 1015) {
|
else if (result != 1015) {
|
||||||
std::cerr << "result " << quoted(f) << " did not match with expected int: " << 1015 << std::endl;
|
std::cerr << "result " << f << " did not match with expected int: " << 1015 << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,46 +1,58 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iomanip>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "fast_float/fast_float.h"
|
#include "fast_float/fast_float.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <stdfloat>
|
#include <stdfloat>
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
|
||||||
// Write some testcases for the parsing of floating point numbers in the float32_t type.
|
// 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.
|
// We use the from_chars function defined in this library.
|
||||||
|
#if __STDCPP_FLOAT32_T__
|
||||||
const std::vector<std::float32_t> float32_test_expected{123.456f, -78.9f, 0.0001f, 3.40282e+038f};
|
const std::vector<std::float32_t> float32_test_expected{123.456f, -78.9f, 0.0001f, 3.40282e+038f};
|
||||||
const std::vector<std::string> float32_test{"123.456", "-78.9", "0.0001", "3.40282e+038"};
|
const std::vector<std::string_view> float32_test{"123.456", "-78.9", "0.0001", "3.40282e+038"};
|
||||||
|
std::cout << "runing float32 test" << std::endl;
|
||||||
for (std::size_t i = 0; i < float32_test.size(); ++i) {
|
for (std::size_t i = 0; i < float32_test.size(); ++i) {
|
||||||
const auto& f = float32_test[i];
|
const auto& f = float32_test[i];
|
||||||
std::float32_t result;
|
std::float32_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 != float32_test_expected[i]) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "Test failed for input: " << std::quoted(f) << std::endl;
|
std::cerr << "Failed to parse: \"" << f << "\"" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if(result != float32_test_expected[i]) {
|
||||||
|
std::cerr << "Test failed for input: \"" << f << "\" expected " << float32_test_expected[i] << " got " << result << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
std::cout << "No std::float32_t type available." << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __STDCPP_FLOAT64_T__
|
||||||
// Test cases for std::float64_t
|
// Test cases for std::float64_t
|
||||||
const std::vector<std::float64_t> float64_test_expected{1.23e4, -5.67e-8, 1.7976931348623157e+308, -1.7976931348623157e+308};
|
const std::vector<std::float64_t> float64_test_expected{1.23e4, -5.67e-8, 1.7976931348623157e+308, -1.7976931348623157e+308};
|
||||||
const std::vector<std::string> float64_test{"1.23e4", "-5.67e-8", "1.7976931348623157e+308", "-1.7976931348623157e+308"};
|
const std::vector<std::string_view> float64_test{"1.23e4", "-5.67e-8", "1.7976931348623157e+308", "-1.7976931348623157e+308"};
|
||||||
|
std::cout << "runing float64 test" << std::endl;
|
||||||
for (std::size_t i = 0; i < float64_test.size(); ++i) {
|
for (std::size_t i = 0; i < float64_test.size(); ++i) {
|
||||||
const auto& f = float64_test[i];
|
const auto& f = float64_test[i];
|
||||||
std::float64_t result;
|
std::float64_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 != float64_test_expected[i]) {
|
if (answer.ec != std::errc()) {
|
||||||
std::cerr << "Test failed for input: " << std::quoted(f) << std::endl;
|
std::cerr << "Failed to parse: \"" << f << "\"" << std::endl;
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
if(result != float64_test_expected[i]) {
|
||||||
|
std::cerr << "Test failed for input: \"" << f << "\" expected " << float64_test_expected[i] << " got " << result << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
std::cout << "No std::float64_t type available." << std::endl;
|
||||||
|
#endif
|
||||||
std::cout << "All tests passed successfully." << std::endl;
|
std::cout << "All tests passed successfully." << std::endl;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,6 @@ project(test_install VERSION 0.1.0 LANGUAGES CXX)
|
|||||||
|
|
||||||
set(FASTFLOAT_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for fastfloat")
|
set(FASTFLOAT_CXX_STANDARD 17 CACHE STRING "the C++ standard to use for fastfloat")
|
||||||
set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD})
|
set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD})
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
if(MSVC_VERSION GREATER 1910)
|
if(MSVC_VERSION GREATER 1910)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -permissive-")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -permissive-")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user