[libcxx-commits] [libcxx] [libc++] Refactor the <charconv> tests (PR #227611)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Sep 30 01:59:51 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/227611
None
>From f1139eca1f84570d5a6683b505c78c9e6ac5c737 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 30 Sep 2026 10:59:21 +0200
Subject: [PATCH] [libc++] Refactor the <charconv> tests
---
.../floating_point.pass.cpp | 1862 ++++++++---------
.../integral.bool.verify.cpp | 32 -
.../charconv.from.chars/integral.pass.cpp | 28 +-
.../integral.roundtrip.pass.cpp | 142 +-
.../integral.bool.verify.cpp | 32 -
.../charconv.to.chars/integral.pass.cpp | 599 ++++--
libcxx/test/support/charconv_test_helpers.h | 271 +--
7 files changed, 1409 insertions(+), 1557 deletions(-)
delete mode 100644 libcxx/test/std/utilities/charconv/charconv.from.chars/integral.bool.verify.cpp
delete mode 100644 libcxx/test/std/utilities/charconv/charconv.to.chars/integral.bool.verify.cpp
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
index a02c7ac466f04..fa223785d758d 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/floating_point.pass.cpp
@@ -17,6 +17,7 @@
// double& value, chars_format fmt = chars_format::general)
#include <array>
+#include <cassert>
#include <charconv>
#include <cmath>
#include <cstring>
@@ -24,8 +25,8 @@
#include <stdexcept>
#include <system_error>
-#include "charconv_test_helpers.h"
#include "test_macros.h"
+#include "type_algorithms.h"
template <class F>
void test_infinity(std::chars_format fmt) {
@@ -326,1193 +327,1183 @@ void test_fmt_independent(std::chars_format fmt) {
}
template <class F>
-struct test_basics {
- void operator()() {
- for (auto fmt : {std::chars_format::scientific,
- std::chars_format::fixed,
- /*std::chars_format::hex,*/ std::chars_format::general})
- test_fmt_independent<F>(fmt);
- }
-};
+void test_basics() {
+ for (auto fmt : {std::chars_format::scientific,
+ std::chars_format::fixed,
+ /*std::chars_format::hex,*/ std::chars_format::general})
+ test_fmt_independent<F>(fmt);
+}
template <class F>
-struct test_fixed {
- void operator()() {
- std::from_chars_result r;
- F x = 0.25;
+void test_fixed() {
+ std::from_chars_result r;
+ F x = 0.25;
- // *** Failures
+ // *** Failures
- { // Starts with invalid character
- std::array s = {' ', '1'};
- for (auto c : "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
- s[0] = c;
- r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::fixed);
+ { // Starts with invalid character
+ std::array s = {' ', '1'};
+ for (auto c : "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+ s[0] = c;
+ r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::fixed);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s.data());
- assert(x == F(0.25));
- }
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s.data());
+ assert(x == F(0.25));
}
+ }
- // *** Success
+ // *** Success
- { // number followed by non-numeric values
- const char* s = "001x";
+ { // number followed by non-numeric values
+ const char* s = "001x";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.0));
- }
- { // no leading digit
- const char* s = ".5";
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.0));
+ }
+ { // no leading digit
+ const char* s = ".5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 2);
+ assert(x == F(0.5));
+ }
+ { // negative sign and no leading digit
+ const char* s = "-.5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(-0.5));
+ }
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 2);
- assert(x == F(0.5));
- }
- { // negative sign and no leading digit
- const char* s = "-.5";
+ { // double decimal point
+ const char* s = "1.25.78";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(-0.5));
- }
+ // This number is halfway between two float values.
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
+ }
+ { // exponent no sign
+ const char* s = "1.5e10";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // exponent capitalized no sign
+ const char* s = "1.5E10";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // exponent + sign
+ const char* s = "1.5e+10";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // exponent - sign
+ const char* s = "1.5e-10";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // Exponent no number
+ const char* s = "1.5e";
- { // double decimal point
- const char* s = "1.25.78";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // Exponent sign no number
+ {
+ const char* s = "1.5e+";
- // This number is halfway between two float values.
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // exponent no sign
- const char* s = "1.5e10";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ {
+ const char* s = "1.5e-";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // exponent capitalized no sign
- const char* s = "1.5E10";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ }
+ { // Exponent with whitespace
+ {
+ const char* s = "1.5e +1";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // exponent + sign
- const char* s = "1.5e+10";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ {
+ const char* s = "1.5e+ 1";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // exponent - sign
- const char* s = "1.5e-10";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ {
+ const char* s = "1.5e -1";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // Exponent no number
- const char* s = "1.5e";
+ {
+ const char* s = "1.5e- 1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // Exponent sign no number
- {
- const char* s = "1.5e+";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e-";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- }
- { // Exponent with whitespace
- {
- const char* s = "1.5e +1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e+ 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e -1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e- 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- }
- { // double exponent
- const char* s = "1.25e0e12";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ }
+ { // double exponent
+ const char* s = "1.25e0e12";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
+ }
+ { // Exponent double sign
+ {
+ const char* s = "1.25e++12";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 4);
assert(x == F(1.25));
}
- { // Exponent double sign
- {
- const char* s = "1.25e++12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e+-12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e-+12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e--12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- }
- { // exponent hex prefix
- const char* s = "1.25e0x12";
+ {
+ const char* s = "1.25e+-12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + 4);
assert(x == F(1.25));
}
- { // This number is halfway between two float values.
- const char* s = "20040229";
+ {
+ const char* s = "1.25e-+12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 8);
- assert(x == F(20040229));
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
}
- { // Shifting mantissa exponent and no exponent
- const char* s = "123.456";
+ {
+ const char* s = "1.25e--12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.23456e2));
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
}
- { // Shifting mantissa exponent and an exponent
- const char* s = "123.456e3";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ }
+ { // exponent hex prefix
+ const char* s = "1.25e0x12";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
+ }
+ { // This number is halfway between two float values.
+ const char* s = "20040229";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 8);
+ assert(x == F(20040229));
+ }
+ { // Shifting mantissa exponent and no exponent
+ const char* s = "123.456";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.23456e2));
+ }
+ { // Shifting mantissa exponent and an exponent
+ const char* s = "123.456e3";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(123.456));
+ }
+ { // Mantissa overflow
+ {
+ const char* s = "0.111111111111111111111111111111111111111111";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(123.456));
- }
- { // Mantissa overflow
- {
- const char* s = "0.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(0.111111111111111111111111111111111111111111));
- }
- {
- const char* s = "111111111111.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(111111111111.111111111111111111111111111111111111111111));
- }
- }
- { // Negative value
- const char* s = "-0.25";
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(0.111111111111111111111111111111111111111111));
+ }
+ {
+ const char* s = "111111111111.111111111111111111111111111111111111111111";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
assert(r.ec == std::errc{});
assert(r.ptr == s + std::strlen(s));
- assert(x == F(-0.25));
+ assert(x == F(111111111111.111111111111111111111111111111111111111111));
}
}
-};
+ { // Negative value
+ const char* s = "-0.25";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::fixed);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(-0.25));
+ }
+}
template <class F>
-struct test_scientific {
- void operator()() {
- std::from_chars_result r;
- F x = 0.25;
+void test_scientific() {
+ std::from_chars_result r;
+ F x = 0.25;
- // *** Failures
+ // *** Failures
- { // Starts with invalid character
- std::array s = {' ', '1', 'e', '0'};
- for (auto c : "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
- s[0] = c;
- r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::scientific);
+ { // Starts with invalid character
+ std::array s = {' ', '1', 'e', '0'};
+ for (auto c : "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+ s[0] = c;
+ r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s.data());
- assert(x == F(0.25));
- }
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s.data());
+ assert(x == F(0.25));
}
- { // No exponent
- const char* s = "1.23";
- r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+ }
+ { // No exponent
+ const char* s = "1.23";
+ r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
+ }
+ { // Exponent no number
+ const char* s = "1.23e";
+ r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
+ }
+ { // Exponent sign no number
+ {
+ const char* s = "1.5e+";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
assert(r.ec == std::errc::invalid_argument);
assert(r.ptr == s);
assert(x == F(0.25));
}
- { // Exponent no number
- const char* s = "1.23e";
- r = std::from_chars(s, s + strlen(s), x, std::chars_format::scientific);
+ {
+ const char* s = "1.5e-";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
assert(r.ec == std::errc::invalid_argument);
assert(r.ptr == s);
assert(x == F(0.25));
}
- { // Exponent sign no number
- {
- const char* s = "1.5e+";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.5e-";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- }
- { // Exponent with whitespace
- {
- const char* s = "1.5e +1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.5e+ 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.5e -1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.5e- 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- }
- { // exponent double sign
- {
- const char* s = "1.25e++12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.25e+-12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.25e-+12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- {
- const char* s = "1.25e--12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s);
- assert(x == F(0.25));
- }
- }
-
- // *** Success
-
- { // number followed by non-numeric values
- const char* s = "001e0x";
-
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 5);
- assert(x == F(1.0));
- }
-
- { // double decimal point
- const char* s = "1.25e0.78";
+ }
+ { // Exponent with whitespace
+ {
+ const char* s = "1.5e +1";
- // This number is halfway between two float values.
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.25));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
-
- { // exponent no sign
- const char* s = "1.5e10";
+ {
+ const char* s = "1.5e+ 1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.5e10));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // exponent capitalized no sign
- const char* s = "1.5E10";
+ {
+ const char* s = "1.5e -1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.5e10));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // exponent + sign
- const char* s = "1.5e+10";
+ {
+ const char* s = "1.5e- 1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.5e10));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // exponent - sign
- const char* s = "1.5e-10";
+ }
+ { // exponent double sign
+ {
+ const char* s = "1.25e++12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.5e-10));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // exponent hex prefix -> e0
- const char* s = "1.25e0x12";
+ {
+ const char* s = "1.25e+-12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.25));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // double exponent
- const char* s = "1.25e0e12";
+ {
+ const char* s = "1.25e-+12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.25));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // This number is halfway between two float values.
- const char* s = "20040229e0";
+ {
+ const char* s = "1.25e--12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 10);
- assert(x == F(20040229));
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s);
+ assert(x == F(0.25));
}
- { // Shifting mantissa exponent and an exponent
- const char* s = "123.456e3";
+ }
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 9);
- assert(x == F(1.23456e5));
- }
- { // Mantissa overflow
- {
- const char* s = "0.111111111111111111111111111111111111111111e0";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(0.111111111111111111111111111111111111111111));
- }
- {
- const char* s = "111111111111.111111111111111111111111111111111111111111e0";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(111111111111.111111111111111111111111111111111111111111));
- }
- }
- { // Negative value
- const char* s = "-0.25e0";
+ // *** Success
+
+ { // number followed by non-numeric values
+ const char* s = "001e0x";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 5);
+ assert(x == F(1.0));
+ }
+
+ { // double decimal point
+ const char* s = "1.25e0.78";
+
+ // This number is halfway between two float values.
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.25));
+ }
+
+ { // exponent no sign
+ const char* s = "1.5e10";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.5e10));
+ }
+ { // exponent capitalized no sign
+ const char* s = "1.5E10";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.5e10));
+ }
+ { // exponent + sign
+ const char* s = "1.5e+10";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.5e10));
+ }
+ { // exponent - sign
+ const char* s = "1.5e-10";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.5e-10));
+ }
+ { // exponent hex prefix -> e0
+ const char* s = "1.25e0x12";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.25));
+ }
+ { // double exponent
+ const char* s = "1.25e0e12";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.25));
+ }
+ { // This number is halfway between two float values.
+ const char* s = "20040229e0";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 10);
+ assert(x == F(20040229));
+ }
+ { // Shifting mantissa exponent and an exponent
+ const char* s = "123.456e3";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 9);
+ assert(x == F(1.23456e5));
+ }
+ { // Mantissa overflow
+ {
+ const char* s = "0.111111111111111111111111111111111111111111e0";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
assert(r.ec == std::errc{});
assert(r.ptr == s + std::strlen(s));
- assert(x == F(-0.25));
+ assert(x == F(0.111111111111111111111111111111111111111111));
}
- { // value is too big -> +inf
- const char* s = "1e9999999999999999999999999999999999999999";
+ {
+ const char* s = "111111111111.111111111111111111111111111111111111111111e0";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == std::numeric_limits<F>::infinity());
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(111111111111.111111111111111111111111111111111111111111));
}
- { // negative value is too big -> -inf
- const char* s = "-1e9999999999999999999999999999999999999999";
+ }
+ { // Negative value
+ const char* s = "-0.25e0";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == -std::numeric_limits<F>::infinity());
- }
- { // value is too small -> 0
- const char* s = "1e-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(-0.25));
+ }
+ { // value is too big -> +inf
+ const char* s = "1e9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(0.0));
- }
- { // negative value is too small -> -0
- const char* s = "-1e-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == std::numeric_limits<F>::infinity());
+ }
+ { // negative value is too big -> -inf
+ const char* s = "-1e9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(-0.0));
- }
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == -std::numeric_limits<F>::infinity());
}
-};
+ { // value is too small -> 0
+ const char* s = "1e-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(0.0));
+ }
+ { // negative value is too small -> -0
+ const char* s = "-1e-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::scientific);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(-0.0));
+ }
+}
template <class F>
-struct test_general {
- void operator()() {
- std::from_chars_result r;
- F x = 0.25;
+void test_general() {
+ std::from_chars_result r;
+ F x = 0.25;
- // *** Failures
+ // *** Failures
- { // Starts with invalid character
- std::array s = {' ', '1'};
- for (auto c : "abcdefghijklmnopqrstuvwxyz"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
- s[0] = c;
- r = std::from_chars(s.data(), s.data() + s.size(), x);
+ { // Starts with invalid character
+ std::array s = {' ', '1'};
+ for (auto c : "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+ s[0] = c;
+ r = std::from_chars(s.data(), s.data() + s.size(), x);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s.data());
- assert(x == F(0.25));
- }
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s.data());
+ assert(x == F(0.25));
}
+ }
- // *** Success
+ // *** Success
- { // number followed by non-numeric values
- const char* s = "001x";
+ { // number followed by non-numeric values
+ const char* s = "001x";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.0));
- }
- { // no leading digit
- const char* s = ".5e0";
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.0));
+ }
+ { // no leading digit
+ const char* s = ".5e0";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(0.5));
+ }
+ { // negative sign and no leading digit
+ const char* s = "-.5e0";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 5);
+ assert(x == F(-0.5));
+ }
+ { // no leading digit
+ const char* s = ".5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 2);
+ assert(x == F(0.5));
+ }
+ { // negative sign and no leading digit
+ const char* s = "-.5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(-0.5));
+ }
+ { // double decimal point
+ const char* s = "1.25.78";
+
+ // This number is halfway between two float values.
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
+ }
+ { // exponent no sign
+ const char* s = "1.5e10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0.5));
- }
- { // negative sign and no leading digit
- const char* s = "-.5e0";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.5e10));
+ }
+ { // exponent capitalized no sign
+ const char* s = "1.5E10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 5);
- assert(x == F(-0.5));
- }
- { // no leading digit
- const char* s = ".5";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.5e10));
+ }
+ { // exponent + sign
+ const char* s = "1.5e+10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 2);
- assert(x == F(0.5));
- }
- { // negative sign and no leading digit
- const char* s = "-.5";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.5e10));
+ }
+ { // exponent - sign
+ const char* s = "1.5e-10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(-0.5));
- }
- { // double decimal point
- const char* s = "1.25.78";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.5e-10));
+ }
+ { // Exponent no number
+ const char* s = "1.5e";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
+ }
+ { // Exponent sign no number
+ {
+ const char* s = "1.5e+";
- // This number is halfway between two float values.
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // exponent no sign
- const char* s = "1.5e10";
+ {
+ const char* s = "1.5e-";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.5e10));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // exponent capitalized no sign
- const char* s = "1.5E10";
+ }
+ { // Exponent with whitespace
+ {
+ const char* s = "1.5e +1";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(1.5e10));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // exponent + sign
- const char* s = "1.5e+10";
+ {
+ const char* s = "1.5e+ 1";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.5e10));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // exponent - sign
- const char* s = "1.5e-10";
+ {
+ const char* s = "1.5e -1";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.5e-10));
+ assert(r.ptr == s + 3);
+ assert(x == F(1.5));
}
- { // Exponent no number
- const char* s = "1.5e";
+ {
+ const char* s = "1.5e- 1";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(1.5));
}
- { // Exponent sign no number
- {
- const char* s = "1.5e+";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e-";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- }
- { // Exponent with whitespace
- {
- const char* s = "1.5e +1";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e+ 1";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e -1";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- {
- const char* s = "1.5e- 1";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.5));
- }
- }
- { // exponent double sign
- {
- const char* s = "1.25e++12";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e+-12";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e-+12";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- {
- const char* s = "1.25e--12";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(1.25));
- }
- }
- { // exponent hex prefix -> e0
- const char* s = "1.25e0x12";
+ }
+ { // exponent double sign
+ {
+ const char* s = "1.25e++12";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
+ assert(r.ptr == s + 4);
assert(x == F(1.25));
}
- { // double exponent
- const char* s = "1.25e0e12";
+ {
+ const char* s = "1.25e+-12";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
+ assert(r.ptr == s + 4);
assert(x == F(1.25));
}
- { // This number is halfway between two float values.
- const char* s = "20040229";
+ {
+ const char* s = "1.25e-+12";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 8);
- assert(x == F(20040229));
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
}
- { // Shifting mantissa exponent and no exponent
- const char* s = "123.456";
+ {
+ const char* s = "1.25e--12";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(1.23456e2));
+ assert(r.ptr == s + 4);
+ assert(x == F(1.25));
}
- { // Shifting mantissa exponent and an exponent
- const char* s = "123.456e3";
+ }
+ { // exponent hex prefix -> e0
+ const char* s = "1.25e0x12";
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 9);
- assert(x == F(1.23456e5));
- }
- { // Mantissa overflow
- {
- const char* s = "0.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(0.111111111111111111111111111111111111111111));
- }
- {
- const char* s = "111111111111.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(111111111111.111111111111111111111111111111111111111111));
- }
- }
- { // Negative value
- const char* s = "-0.25";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.25));
+ }
+ { // double exponent
+ const char* s = "1.25e0e12";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(1.25));
+ }
+ { // This number is halfway between two float values.
+ const char* s = "20040229";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 8);
+ assert(x == F(20040229));
+ }
+ { // Shifting mantissa exponent and no exponent
+ const char* s = "123.456";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(1.23456e2));
+ }
+ { // Shifting mantissa exponent and an exponent
+ const char* s = "123.456e3";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 9);
+ assert(x == F(1.23456e5));
+ }
+ { // Mantissa overflow
+ {
+ const char* s = "0.111111111111111111111111111111111111111111";
r = std::from_chars(s, s + std::strlen(s), x);
assert(r.ec == std::errc{});
assert(r.ptr == s + std::strlen(s));
- assert(x == F(-0.25));
+ assert(x == F(0.111111111111111111111111111111111111111111));
}
- { // value is too big -> +inf
- const char* s = "1e9999999999999999999999999999999999999999";
+ {
+ const char* s = "111111111111.111111111111111111111111111111111111111111";
r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == std::numeric_limits<F>::infinity());
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(111111111111.111111111111111111111111111111111111111111));
}
- { // negative value is too big -> -inf
- const char* s = "-1e9999999999999999999999999999999999999999";
+ }
+ { // Negative value
+ const char* s = "-0.25";
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == -std::numeric_limits<F>::infinity());
- }
- { // value is too small -> 0
- const char* s = "1e-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(-0.25));
+ }
+ { // value is too big -> +inf
+ const char* s = "1e9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(0.0));
- }
- { // negative value is too small -> -0
- const char* s = "-1e-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == std::numeric_limits<F>::infinity());
+ }
+ { // negative value is too big -> -inf
+ const char* s = "-1e9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(-0.0));
- }
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == -std::numeric_limits<F>::infinity());
}
-};
+ { // value is too small -> 0
+ const char* s = "1e-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(0.0));
+ }
+ { // negative value is too small -> -0
+ const char* s = "-1e-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(-0.0));
+ }
+}
template <class F>
-struct test_hex {
- void operator()() {
- std::from_chars_result r;
- F x = 0.25;
+void test_hex() {
+ std::from_chars_result r;
+ F x = 0.25;
- // *** Failures
+ // *** Failures
- { // Starts with invalid character
- std::array s = {' ', '1', 'e', '0'};
- for (auto c : "ghijklmnopqrstuvwxyz"
- "GHIJKLMNOPQRSTUVWXYZ"
- "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
- s[0] = c;
- r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::hex);
+ { // Starts with invalid character
+ std::array s = {' ', '1', 'e', '0'};
+ for (auto c : "ghijklmnopqrstuvwxyz"
+ "GHIJKLMNOPQRSTUVWXYZ"
+ "`~!@#$%^&*()_=[]{}\\|;:'\",/<>? \t\v\r\n") {
+ s[0] = c;
+ r = std::from_chars(s.data(), s.data() + s.size(), x, std::chars_format::hex);
- assert(r.ec == std::errc::invalid_argument);
- assert(r.ptr == s.data());
- assert(x == F(0.25));
- }
+ assert(r.ec == std::errc::invalid_argument);
+ assert(r.ptr == s.data());
+ assert(x == F(0.25));
}
+ }
- // *** Success
+ // *** Success
- { // number followed by non-numeric values
- const char* s = "001x";
+ { // number followed by non-numeric values
+ const char* s = "001x";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(1.0));
- }
- { // no leading digit
- const char* s = ".5p0";
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(1.0));
+ }
+ { // no leading digit
+ const char* s = ".5p0";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(0x0.5p0));
+ }
+ { // negative sign and no leading digit
+ const char* s = "-.5p0";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 5);
+ assert(x == F(-0x0.5p0));
+ }
+ { // no leading digit
+ const char* s = ".5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 2);
+ assert(x == F(0x0.5p0));
+ }
+ { // negative sign and no leading digit
+ const char* s = "-.5";
+
+ // the expected form of the subject sequence is a nonempty sequence of
+ // decimal digits optionally containing a decimal-point character, then
+ // an optional exponent part as defined in 6.4.4.3, excluding any digit
+ // separators (6.4.4.2); (C23 7.24.1.5)
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(-0x0.5p0));
+ }
+ { // double decimal point
+ const char* s = "1.25.78";
+
+ // This number is halfway between two float values.
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 4);
+ assert(x == F(0x1.25p0));
+ }
+ { // exponent no sign
+ const char* s = "1.5p10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x0.5p0));
- }
- { // negative sign and no leading digit
- const char* s = "-.5p0";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(0x1.5p10));
+ }
+ { // exponent capitalized no sign
+ const char* s = "1.5P10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 5);
- assert(x == F(-0x0.5p0));
- }
- { // no leading digit
- const char* s = ".5";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(0x1.5p10));
+ }
+ { // exponent + sign
+ const char* s = "1.5p+10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 2);
- assert(x == F(0x0.5p0));
- }
- { // negative sign and no leading digit
- const char* s = "-.5";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(0x1.5p10));
+ }
+ { // exponent - sign
+ const char* s = "1.5p-10";
- // the expected form of the subject sequence is a nonempty sequence of
- // decimal digits optionally containing a decimal-point character, then
- // an optional exponent part as defined in 6.4.4.3, excluding any digit
- // separators (6.4.4.2); (C23 7.24.1.5)
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(-0x0.5p0));
- }
- { // double decimal point
- const char* s = "1.25.78";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(0x1.5p-10));
+ }
+ { // Exponent no number
+ const char* s = "1.5p";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
+ }
+ { // Exponent sign no number
+ {
+ const char* s = "1.5p+";
- // This number is halfway between two float values.
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x1.25p0));
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
}
- { // exponent no sign
- const char* s = "1.5p10";
+ {
+ const char* s = "1.5p-";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(0x1.5p10));
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
}
- { // exponent capitalized no sign
- const char* s = "1.5P10";
+ }
+ { // Exponent with whitespace
+ {
+ const char* s = "1.5p +1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
- assert(x == F(0x1.5p10));
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
}
- { // exponent + sign
- const char* s = "1.5p+10";
+ {
+ const char* s = "1.5p+ 1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(0x1.5p10));
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
}
- { // exponent - sign
- const char* s = "1.5p-10";
+ {
+ const char* s = "1.5p -1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(0x1.5p-10));
+ assert(r.ptr == s + 3);
+ assert(x == F(0x1.5p0));
}
- { // Exponent no number
- const char* s = "1.5p";
+ {
+ const char* s = "1.5p- 1";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
assert(r.ptr == s + 3);
assert(x == F(0x1.5p0));
}
- { // Exponent sign no number
- {
- const char* s = "1.5p+";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- {
- const char* s = "1.5p-";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- }
- { // Exponent with whitespace
- {
- const char* s = "1.5p +1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- {
- const char* s = "1.5p+ 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- {
- const char* s = "1.5p -1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- {
- const char* s = "1.5p- 1";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 3);
- assert(x == F(0x1.5p0));
- }
- }
- { // Exponent double sign
- {
- const char* s = "1.25p++12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x1.25p0));
- }
- {
- const char* s = "1.25p+-12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x1.25p0));
- }
- {
- const char* s = "1.25p-+12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x1.25p0));
- }
- {
- const char* s = "1.25p--12";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 4);
- assert(x == F(0x1.25p0));
- }
- }
- { // exponent hex prefix -> p0
- const char* s = "1.25p0x12";
+ }
+ { // Exponent double sign
+ {
+ const char* s = "1.25p++12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
+ assert(r.ptr == s + 4);
assert(x == F(0x1.25p0));
}
- { // double exponent
- const char* s = "1.25p0p12";
+ {
+ const char* s = "1.25p+-12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 6);
+ assert(r.ptr == s + 4);
assert(x == F(0x1.25p0));
}
- { // This number is halfway between two float values.
- const char* s = "131CA25";
+ {
+ const char* s = "1.25p-+12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(0x131CA25p0));
+ assert(r.ptr == s + 4);
+ assert(x == F(0x1.25p0));
}
- { // Shifting mantissa exponent and no exponent
- const char* s = "123.456";
+ {
+ const char* s = "1.25p--12";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
- assert(r.ptr == s + 7);
- assert(x == F(0x123.456p0));
+ assert(r.ptr == s + 4);
+ assert(x == F(0x1.25p0));
}
- { // Shifting mantissa exponent and an exponent
- const char* s = "123.456p3";
+ }
+ { // exponent hex prefix -> p0
+ const char* s = "1.25p0x12";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + 9);
- assert(x == F(0x123.456p3));
- }
- { // Mantissa overflow
- {
- const char* s = "0.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(0x0.111111111111111111111111111111111111111111p0));
- }
- {
- const char* s = "111111111111.111111111111111111111111111111111111111111";
-
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc{});
- assert(r.ptr == s + std::strlen(s));
- assert(x == F(0x111111111111.111111111111111111111111111111111111111111p0));
- }
- }
- { // Negative value
- const char* s = "-0.25";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(0x1.25p0));
+ }
+ { // double exponent
+ const char* s = "1.25p0p12";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 6);
+ assert(x == F(0x1.25p0));
+ }
+ { // This number is halfway between two float values.
+ const char* s = "131CA25";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(0x131CA25p0));
+ }
+ { // Shifting mantissa exponent and no exponent
+ const char* s = "123.456";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 7);
+ assert(x == F(0x123.456p0));
+ }
+ { // Shifting mantissa exponent and an exponent
+ const char* s = "123.456p3";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + 9);
+ assert(x == F(0x123.456p3));
+ }
+ { // Mantissa overflow
+ {
+ const char* s = "0.111111111111111111111111111111111111111111";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
assert(r.ec == std::errc{});
assert(r.ptr == s + std::strlen(s));
- assert(x == F(-0x0.25p0));
+ assert(x == F(0x0.111111111111111111111111111111111111111111p0));
}
- { // value is too big -> +inf
- const char* s = "1p9999999999999999999999999999999999999999";
+ {
+ const char* s = "111111111111.111111111111111111111111111111111111111111";
r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == std::numeric_limits<F>::infinity());
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(0x111111111111.111111111111111111111111111111111111111111p0));
}
- { // negative value is too big -> -inf
- const char* s = "-1p9999999999999999999999999999999999999999";
+ }
+ { // Negative value
+ const char* s = "-0.25";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == -std::numeric_limits<F>::infinity());
- }
- { // value is too small -> 0
- const char* s = "1p-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc{});
+ assert(r.ptr == s + std::strlen(s));
+ assert(x == F(-0x0.25p0));
+ }
+ { // value is too big -> +inf
+ const char* s = "1p9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(0.0));
- }
- { // negative value is too small -> -0
- const char* s = "-1p-9999999999999999999999999999999999999999";
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == std::numeric_limits<F>::infinity());
+ }
+ { // negative value is too big -> -inf
+ const char* s = "-1p9999999999999999999999999999999999999999";
- r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
- assert(r.ec == std::errc::result_out_of_range);
- assert(r.ptr == s + strlen(s));
- assert(x == F(-0.0));
- }
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == -std::numeric_limits<F>::infinity());
}
-};
+ { // value is too small -> 0
+ const char* s = "1p-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(0.0));
+ }
+ { // negative value is too small -> -0
+ const char* s = "-1p-9999999999999999999999999999999999999999";
+
+ r = std::from_chars(s, s + std::strlen(s), x, std::chars_format::hex);
+ assert(r.ec == std::errc::result_out_of_range);
+ assert(r.ptr == s + strlen(s));
+ assert(x == F(-0.0));
+ }
+}
// The test
// test/std/utilities/charconv/charconv.msvc/test.cpp
@@ -1546,13 +1537,20 @@ void test_random_errors() {
}
}
-int main(int, char**) {
- run<test_basics>(all_floats);
- run<test_scientific>(all_floats);
- run<test_fixed>(all_floats);
- run<test_general>(all_floats);
+struct Test {
+ template <class FloatT>
+ void operator()() {
+ test_basics<FloatT>();
+ test_scientific<FloatT>();
+ test_fixed<FloatT>();
+ test_general<FloatT>();
+ test_hex<FloatT>();
+ }
+};
- run<test_hex>(all_floats);
+int main(int, char**) {
+ //TODO: Make this floating_point_types
+ types::for_each(types::type_list<float, double>{}, Test());
test_random_errors();
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.bool.verify.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.bool.verify.cpp
deleted file mode 100644
index 5fa62a4683350..0000000000000
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.bool.verify.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14
-
-// <charconv>
-
-// In
-//
-// from_chars_result from_chars(const char* first, const char* last,
-// Integral& value, int base = 10)
-//
-// Integral cannot be bool.
-
-#include <charconv>
-
-int main(int, char**)
-{
- using std::from_chars;
- char buf[] = "01001";
- bool lv;
-
- from_chars(buf, buf + sizeof(buf), lv); // expected-error {{call to deleted function}}
- from_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}}
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
index 4708da4c38b9b..1e0aaebb1006e 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp
@@ -13,15 +13,31 @@
// constexpr from_chars_result from_chars(const char* first, const char* last,
// Integral& value, int base = 10)
+#include <cassert>
#include <charconv>
#include <system_error>
-#include "test_macros.h"
#include "charconv_test_helpers.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+template <class, class... Args>
+constexpr bool has_from_chars_impl = false;
+
+template <class... Args>
+constexpr bool has_from_chars_impl<decltype((void)std::from_chars(std::declval<Args>()...)), Args...> = true;
+
+template <class... Args>
+constexpr bool has_from_chars = has_from_chars_impl<void, Args...>;
+
+static_assert(has_from_chars<char*, char*, int&>);
+static_assert(has_from_chars<char*, char*, int&, int>);
+static_assert(!has_from_chars<char*, char*, bool&>);
+static_assert(!has_from_chars<char*, char*, bool&, int>);
-template <typename T>
struct test_basics
{
+ template <typename T>
TEST_CONSTEXPR_CXX23 void operator()()
{
std::from_chars_result r;
@@ -83,9 +99,9 @@ struct test_basics
}
};
-template <typename T>
struct test_signed
{
+ template <typename T>
TEST_CONSTEXPR_CXX23 void operator()()
{
std::from_chars_result r;
@@ -139,10 +155,10 @@ struct test_signed
TEST_CONSTEXPR_CXX23 bool test()
{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+ types::for_each(types::integer_types{}, test_basics{});
+ types::for_each(types::signed_integer_types{}, test_signed{});
- return true;
+ return true;
}
int main(int, char**) {
diff --git a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
index b1f2c77b34f8a..eaf353da16bc6 100644
--- a/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.roundtrip.pass.cpp
@@ -21,75 +21,101 @@
#include "test_macros.h"
#include "charconv_test_helpers.h"
-template <typename T>
-struct test_basics : roundtrip_test_base<T>
-{
- using roundtrip_test_base<T>::test;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(0);
- test(42);
- test(32768);
- test(0, 10);
- test(42, 10);
- test(32768, 10);
- test(0xf, 16);
- test(0xdeadbeaf, 16);
- test(0755, 8);
-
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
-
- test(1, b);
- test(-1, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
- test((xl::max)() / 2, b);
- }
+template <class X, class T, class... Ts>
+TEST_CONSTEXPR_CXX23 void test_roundtrip(T v, Ts... args) {
+ std::from_chars_result r2;
+ std::to_chars_result r;
+ X x = 0xc;
+ char buf[150];
+
+ if (fits_in<X>(v)) {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+ assert(r2.ptr == r.ptr);
+ assert(x == X(v));
+ } else {
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+
+ r2 = std::from_chars(buf, r.ptr, x, args...);
+
+ TEST_DIAGNOSTIC_PUSH
+ TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
+
+ if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value) {
+ assert(x == 0xc);
+ assert(r2.ptr == buf);
+ assert(r2.ec == std::errc::invalid_argument);
+ } else {
+ assert(x == 0xc);
+ assert(r2.ptr == r.ptr);
+ assert(r2.ec == std::errc::result_out_of_range);
}
+
+ TEST_DIAGNOSTIC_POP
+ }
+}
+
+struct test_basics {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test_roundtrip<T>(0);
+ test_roundtrip<T>(42);
+ test_roundtrip<T>(32768);
+ test_roundtrip<T>(0, 10);
+ test_roundtrip<T>(42, 10);
+ test_roundtrip<T>(32768, 10);
+ test_roundtrip<T>(0xf, 16);
+ test_roundtrip<T>(0xdeadbeaf, 16);
+ test_roundtrip<T>(0755, 8);
+
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
+
+ test_roundtrip<T>(1, b);
+ test_roundtrip<T>(-1, b);
+ test_roundtrip<T>(xl::lowest(), b);
+ test_roundtrip<T>((xl::max)(), b);
+ test_roundtrip<T>((xl::max)() / 2, b);
+ }
+ }
};
-template <typename T>
-struct test_signed : roundtrip_test_base<T>
-{
- using roundtrip_test_base<T>::test;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(-1);
- test(-12);
- test(-1, 10);
- test(-12, 10);
- test(-21734634, 10);
- test(-2647, 2);
- test(-0xcc1, 16);
-
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
-
- test(0, b);
- test(xl::lowest(), b);
- test((xl::max)(), b);
- }
+struct test_signed {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test_roundtrip<T>(-1);
+ test_roundtrip<T>(-12);
+ test_roundtrip<T>(-1, 10);
+ test_roundtrip<T>(-12, 10);
+ test_roundtrip<T>(-21734634, 10);
+ test_roundtrip<T>(-2647, 2);
+ test_roundtrip<T>(-0xcc1, 16);
+
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
+
+ test_roundtrip<T>(0, b);
+ test_roundtrip<T>(xl::lowest(), b);
+ test_roundtrip<T>((xl::max)(), b);
}
+ }
};
-TEST_CONSTEXPR_CXX23 bool test()
-{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+TEST_CONSTEXPR_CXX23 bool test() {
+ types::for_each(types::integer_types{}, test_basics{});
+ types::for_each(types::signed_integer_types{}, test_signed{});
- return true;
+ return true;
}
int main(int, char**) {
- test();
+ test();
#if TEST_STD_VER > 20
- static_assert(test());
+ static_assert(test());
#endif
- return 0;
+ return 0;
}
diff --git a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.bool.verify.cpp b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.bool.verify.cpp
deleted file mode 100644
index 630799b6738a2..0000000000000
--- a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.bool.verify.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14
-
-// <charconv>
-
-// In
-//
-// to_chars_result to_chars(char* first, char* last, Integral value,
-// int base = 10)
-//
-// Integral cannot be bool.
-
-#include <charconv>
-
-int main(int, char**)
-{
- using std::to_chars;
- char buf[10];
- bool lv = true;
-
- to_chars(buf, buf + sizeof(buf), false); // expected-error {{call to deleted function}}
- to_chars(buf, buf + sizeof(buf), lv, 16); // expected-error {{call to deleted function}}
-
- return 0;
-}
diff --git a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
index e89b340bdfcbe..2dcefd66396d6 100644
--- a/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
+++ b/libcxx/test/std/utilities/charconv/charconv.to.chars/integral.pass.cpp
@@ -17,12 +17,161 @@
// constexpr to_chars_result to_chars(char* first, char* last, Integral value,
// int base = 10)
+#include <algorithm>
+#include <cassert>
#include <charconv>
#include <cstdint>
+#include <cstdlib>
+#include <numeric>
#include <system_error>
-#include "test_macros.h"
#include "charconv_test_helpers.h"
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+template <class, class... Args>
+constexpr bool has_to_chars_impl = false;
+
+template <class... Args>
+constexpr bool has_to_chars_impl<decltype((void)std::to_chars(std::declval<Args>()...)), Args...> = true;
+
+template <class... Args>
+constexpr bool has_to_chars = has_to_chars_impl<void, Args...>;
+
+static_assert(has_to_chars<char*, char*, int&>);
+static_assert(has_to_chars<char*, char*, int&, int>);
+static_assert(!has_to_chars<char*, char*, bool&>);
+static_assert(!has_to_chars<char*, char*, bool&, int>);
+
+template <class X, class T, std::size_t N, class... Ts>
+TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args) {
+ std::to_chars_result r;
+ char buf[150];
+
+ constexpr std::size_t len = N - 1;
+ static_assert(len > 0, "expected output won't be empty");
+
+ if (!fits_in<X>(v))
+ return;
+
+ r = std::to_chars(buf, buf + len - 1, X(v), args...);
+ assert(r.ptr == buf + len - 1);
+ assert(r.ec == std::errc::value_too_large);
+
+ r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
+ assert(r.ptr == buf + len);
+ assert(r.ec == std::errc{});
+ assert(std::equal(buf, buf + len, expect));
+}
+
+TEST_CONSTEXPR_CXX23 long long fromchars_impl(char const* p, char const* ep, int base, std::true_type) {
+ char* last;
+ long long r;
+ if (TEST_IS_CONSTANT_EVALUATED)
+ last = const_cast<char*>(std::from_chars(p, ep, r, base).ptr);
+ else
+ r = strtoll(p, &last, base);
+ assert(last == ep);
+
+ return r;
+}
+
+TEST_CONSTEXPR_CXX23 unsigned long long fromchars_impl(char const* p, char const* ep, int base, std::false_type) {
+ char* last;
+ unsigned long long r;
+ if (TEST_IS_CONSTANT_EVALUATED)
+ last = const_cast<char*>(std::from_chars(p, ep, r, base).ptr);
+ else
+ r = strtoull(p, &last, base);
+ assert(last == ep);
+
+ return r;
+}
+#ifndef TEST_HAS_NO_INT128
+TEST_CONSTEXPR_CXX23 __int128_t fromchars128_impl(char const* p, char const* ep, int base, std::true_type) {
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ char* last;
+ __int128_t r = strtoll(p, &last, base);
+ if (errno != ERANGE) {
+ assert(last == ep);
+ return r;
+ }
+ }
+
+ // When the value doesn't fit in a long long use from_chars. This is
+ // not ideal since it does a round-trip test instead if using an
+ // external source.
+ __int128_t r;
+ std::from_chars_result s = std::from_chars(p, ep, r, base);
+ assert(s.ec == std::errc{});
+ assert(s.ptr == ep);
+
+ return r;
+}
+
+TEST_CONSTEXPR_CXX23 __uint128_t fromchars128_impl(char const* p, char const* ep, int base, std::false_type) {
+ if (!TEST_IS_CONSTANT_EVALUATED) {
+ char* last;
+ __uint128_t r = strtoull(p, &last, base);
+ if (errno != ERANGE) {
+ assert(last == ep);
+ return r;
+ }
+ }
+
+ __uint128_t r;
+ std::from_chars_result s = std::from_chars(p, ep, r, base);
+ assert(s.ec == std::errc{});
+ assert(s.ptr == ep);
+
+ return r;
+}
+
+template <class X>
+TEST_CONSTEXPR_CXX23 auto fromchars128_impl(char const* p, char const* ep, int base = 10)
+ -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>())) {
+ return fromchars128_impl(p, ep, base, std::is_signed<X>());
+}
+
+#endif
+
+template <class X>
+TEST_CONSTEXPR_CXX23 auto fromchars_impl(char const* p, char const* ep, int base = 10)
+ -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>())) {
+ return fromchars_impl(p, ep, base, std::is_signed<X>());
+}
+
+template <class X, class... Ts>
+TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args) {
+ std::to_chars_result r;
+ char buf[150];
+
+ // Poison the buffer for testing whether a successful std::to_chars
+ // doesn't modify data beyond r.ptr. Use unsigned values to avoid
+ // overflowing char when it's signed.
+ std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
+ r = std::to_chars(buf, buf + sizeof(buf), v, args...);
+ assert(r.ec == std::errc{});
+ for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
+ assert(static_cast<unsigned char>(buf[i]) == i + 1);
+ *r.ptr = '\0';
+
+#ifndef TEST_HAS_NO_INT128
+ if (sizeof(X) == sizeof(__int128_t)) {
+ auto a = fromchars128_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
+ } else
+#endif
+ {
+ auto a = fromchars_impl<X>(buf, r.ptr, args...);
+ assert(v == a);
+ }
+
+ auto ep = r.ptr - 1;
+ r = std::to_chars(buf, ep, v, args...);
+ assert(r.ptr == ep);
+ assert(r.ec == std::errc::value_too_large);
+}
#ifndef TEST_HAS_NO_INT128
TEST_CONSTEXPR_CXX23 __uint128_t make_u128(__uint128_t a, std::uint64_t b) {
@@ -51,261 +200,247 @@ TEST_CONSTEXPR_CXX23 __int128_t make_i128(__int128_t a, __int128_t b, std::int64
}
#endif
-template <typename T>
-struct test_basics : to_chars_test_base<T>
-{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(0, "0");
- test(42, "42");
- test(32768, "32768");
- test(0, "0", 10);
- test(42, "42", 10);
- test(32768, "32768", 10);
- test(0xf, "f", 16);
- test(0xdeadbeaf, "deadbeaf", 16);
- test(0755, "755", 8);
-
- // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test(1UL, "1");
- test(12UL, "12");
- test(123UL, "123");
- test(1234UL, "1234");
- test(12345UL, "12345");
- test(123456UL, "123456");
- test(1234567UL, "1234567");
- test(12345678UL, "12345678");
- test(123456789UL, "123456789");
- test(1234567890UL, "1234567890");
- test(12345678901UL, "12345678901");
- test(123456789012UL, "123456789012");
- test(1234567890123UL, "1234567890123");
- test(12345678901234UL, "12345678901234");
- test(123456789012345UL, "123456789012345");
- test(1234567890123456UL, "1234567890123456");
- test(12345678901234567UL, "12345678901234567");
- test(123456789012345678UL, "123456789012345678");
- test(1234567890123456789UL, "1234567890123456789");
- test(12345678901234567890UL, "12345678901234567890");
+struct test_basics {
+ template <typename T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(0, "0");
+ test<T>(42, "42");
+ test<T>(32768, "32768");
+ test<T>(0, "0", 10);
+ test<T>(42, "42", 10);
+ test<T>(32768, "32768", 10);
+ test<T>(0xf, "f", 16);
+ test<T>(0xdeadbeaf, "deadbeaf", 16);
+ test<T>(0755, "755", 8);
+
+ // Test each len till len of UINT64_MAX = 20 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(1UL, "1");
+ test<T>(12UL, "12");
+ test<T>(123UL, "123");
+ test<T>(1234UL, "1234");
+ test<T>(12345UL, "12345");
+ test<T>(123456UL, "123456");
+ test<T>(1234567UL, "1234567");
+ test<T>(12345678UL, "12345678");
+ test<T>(123456789UL, "123456789");
+ test<T>(1234567890UL, "1234567890");
+ test<T>(12345678901UL, "12345678901");
+ test<T>(123456789012UL, "123456789012");
+ test<T>(1234567890123UL, "1234567890123");
+ test<T>(12345678901234UL, "12345678901234");
+ test<T>(123456789012345UL, "123456789012345");
+ test<T>(1234567890123456UL, "1234567890123456");
+ test<T>(12345678901234567UL, "12345678901234567");
+ test<T>(123456789012345678UL, "123456789012345678");
+ test<T>(1234567890123456789UL, "1234567890123456789");
+ test<T>(12345678901234567890UL, "12345678901234567890");
#ifndef TEST_HAS_NO_INT128
- test(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
- test(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
- test(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
- test(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
- test(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
- test(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
- test(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
- test(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
- test(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
- test(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
- test(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
- test(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
- test(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
- test(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
- test(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
- test(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
- test(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
- test(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
- test(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
+ test<T>(make_u128(12UL, 3456789012345678901UL), "123456789012345678901");
+ test<T>(make_u128(123UL, 4567890123456789012UL), "1234567890123456789012");
+ test<T>(make_u128(1234UL, 5678901234567890123UL), "12345678901234567890123");
+ test<T>(make_u128(12345UL, 6789012345678901234UL), "123456789012345678901234");
+ test<T>(make_u128(123456UL, 7890123456789012345UL), "1234567890123456789012345");
+ test<T>(make_u128(1234567UL, 8901234567890123456UL), "12345678901234567890123456");
+ test<T>(make_u128(12345678UL, 9012345678901234567UL), "123456789012345678901234567");
+ test<T>(make_u128(123456789UL, 123456789012345678UL), "1234567890123456789012345678");
+ test<T>(make_u128(123UL, 4567890123456UL, 7890123456789UL), "12345678901234567890123456789");
+ test<T>(make_u128(1234UL, 5678901234567UL, 8901234567890UL), "123456789012345678901234567890");
+ test<T>(make_u128(12345UL, 6789012345678UL, 9012345678901UL), "1234567890123456789012345678901");
+ test<T>(make_u128(123456UL, 7890123456789UL, 123456789012UL), "12345678901234567890123456789012");
+ test<T>(make_u128(1234567UL, 8901234567890UL, 1234567890123UL), "123456789012345678901234567890123");
+ test<T>(make_u128(12345678UL, 9012345678901UL, 2345678901234UL), "1234567890123456789012345678901234");
+ test<T>(make_u128(123456789UL, 123456789012UL, 3456789012345UL), "12345678901234567890123456789012345");
+ test<T>(make_u128(1234567890UL, 1234567890123UL, 4567890123456UL), "123456789012345678901234567890123456");
+ test<T>(make_u128(12345678901UL, 2345678901234UL, 5678901234567UL), "1234567890123456789012345678901234567");
+ test<T>(make_u128(123456789012UL, 3456789012345UL, 6789012345678UL), "12345678901234567890123456789012345678");
+ test<T>(make_u128(1234567890123UL, 4567890123456UL, 7890123456789UL), "123456789012345678901234567890123456789");
#endif
- // Test special cases with zeros inside a value string representation,
- // to_chars algorithm processes them in a special way and should not
- // skip trailing zeros
- // Test driver automatically skips values not fitting into source type.
- test(0UL, "0");
- test(10UL, "10");
- test(100UL, "100");
- test(1000UL, "1000");
- test(10000UL, "10000");
- test(100000UL, "100000");
- test(1000000UL, "1000000");
- test(10000000UL, "10000000");
- test(100000000UL, "100000000");
- test(1000000000UL, "1000000000");
- test(10000000000UL, "10000000000");
- test(100000000000UL, "100000000000");
- test(1000000000000UL, "1000000000000");
- test(10000000000000UL, "10000000000000");
- test(100000000000000UL, "100000000000000");
- test(1000000000000000UL, "1000000000000000");
- test(10000000000000000UL, "10000000000000000");
- test(100000000000000000UL, "100000000000000000");
- test(1000000000000000000UL, "1000000000000000000");
- test(10000000000000000000UL, "10000000000000000000");
+ // Test special cases with zeros inside a value string representation,
+ // to_chars algorithm processes them in a special way and should not
+ // skip trailing zeros
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(0UL, "0");
+ test<T>(10UL, "10");
+ test<T>(100UL, "100");
+ test<T>(1000UL, "1000");
+ test<T>(10000UL, "10000");
+ test<T>(100000UL, "100000");
+ test<T>(1000000UL, "1000000");
+ test<T>(10000000UL, "10000000");
+ test<T>(100000000UL, "100000000");
+ test<T>(1000000000UL, "1000000000");
+ test<T>(10000000000UL, "10000000000");
+ test<T>(100000000000UL, "100000000000");
+ test<T>(1000000000000UL, "1000000000000");
+ test<T>(10000000000000UL, "10000000000000");
+ test<T>(100000000000000UL, "100000000000000");
+ test<T>(1000000000000000UL, "1000000000000000");
+ test<T>(10000000000000000UL, "10000000000000000");
+ test<T>(100000000000000000UL, "100000000000000000");
+ test<T>(1000000000000000000UL, "1000000000000000000");
+ test<T>(10000000000000000000UL, "10000000000000000000");
#ifndef TEST_HAS_NO_INT128
- test(make_u128(10UL, 0), "100000000000000000000");
- test(make_u128(100UL, 0), "1000000000000000000000");
- test(make_u128(1000UL, 0), "10000000000000000000000");
- test(make_u128(10000UL, 0), "100000000000000000000000");
- test(make_u128(100000UL, 0), "1000000000000000000000000");
- test(make_u128(1000000UL, 0), "10000000000000000000000000");
- test(make_u128(10000000UL, 0), "100000000000000000000000000");
- test(make_u128(100000000UL, 0), "1000000000000000000000000000");
- test(make_u128(100UL, 0, 0), "10000000000000000000000000000");
- test(make_u128(1000UL, 0, 0), "100000000000000000000000000000");
- test(make_u128(10000UL, 0, 0), "1000000000000000000000000000000");
- test(make_u128(100000UL, 0, 0), "10000000000000000000000000000000");
- test(make_u128(1000000UL, 0, 0), "100000000000000000000000000000000");
- test(make_u128(10000000UL, 0, 0), "1000000000000000000000000000000000");
- test(make_u128(100000000UL, 0, 0), "10000000000000000000000000000000000");
- test(make_u128(1000000000UL, 0, 0), "100000000000000000000000000000000000");
- test(make_u128(10000000000UL, 0, 0), "1000000000000000000000000000000000000");
- test(make_u128(100000000000UL, 0, 0), "10000000000000000000000000000000000000");
- test(make_u128(1000000000000UL, 0, 0), "100000000000000000000000000000000000000");
+ test<T>(make_u128(10UL, 0), "100000000000000000000");
+ test<T>(make_u128(100UL, 0), "1000000000000000000000");
+ test<T>(make_u128(1000UL, 0), "10000000000000000000000");
+ test<T>(make_u128(10000UL, 0), "100000000000000000000000");
+ test<T>(make_u128(100000UL, 0), "1000000000000000000000000");
+ test<T>(make_u128(1000000UL, 0), "10000000000000000000000000");
+ test<T>(make_u128(10000000UL, 0), "100000000000000000000000000");
+ test<T>(make_u128(100000000UL, 0), "1000000000000000000000000000");
+ test<T>(make_u128(100UL, 0, 0), "10000000000000000000000000000");
+ test<T>(make_u128(1000UL, 0, 0), "100000000000000000000000000000");
+ test<T>(make_u128(10000UL, 0, 0), "1000000000000000000000000000000");
+ test<T>(make_u128(100000UL, 0, 0), "10000000000000000000000000000000");
+ test<T>(make_u128(1000000UL, 0, 0), "100000000000000000000000000000000");
+ test<T>(make_u128(10000000UL, 0, 0), "1000000000000000000000000000000000");
+ test<T>(make_u128(100000000UL, 0, 0), "10000000000000000000000000000000000");
+ test<T>(make_u128(1000000000UL, 0, 0), "100000000000000000000000000000000000");
+ test<T>(make_u128(10000000000UL, 0, 0), "1000000000000000000000000000000000000");
+ test<T>(make_u128(100000000000UL, 0, 0), "10000000000000000000000000000000000000");
+ test<T>(make_u128(1000000000000UL, 0, 0), "100000000000000000000000000000000000000");
#endif
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
- test_value(1, b);
- test_value(xl::lowest(), b);
- test_value((xl::max)(), b);
- test_value((xl::max)() / 2, b);
- }
+ test_value(1, b);
+ test_value(xl::lowest(), b);
+ test_value((xl::max)(), b);
+ test_value((xl::max)() / 2, b);
}
+ }
};
-template <typename T>
-struct test_signed : to_chars_test_base<T>
-{
- using to_chars_test_base<T>::test;
- using to_chars_test_base<T>::test_value;
-
- TEST_CONSTEXPR_CXX23 void operator()()
- {
- test(-1, "-1");
- test(-12, "-12");
- test(-1, "-1", 10);
- test(-12, "-12", 10);
- test(-21734634, "-21734634", 10);
- test(-2647, "-101001010111", 2);
- test(-0xcc1, "-cc1", 16);
-
- // Test each len till len of INT64_MAX = 19 because to_chars algorithm
- // makes branches based on decimal digits count in the value string
- // representation.
- // Test driver automatically skips values not fitting into source type.
- test(-1L, "-1");
- test(-12L, "-12");
- test(-123L, "-123");
- test(-1234L, "-1234");
- test(-12345L, "-12345");
- test(-123456L, "-123456");
- test(-1234567L, "-1234567");
- test(-12345678L, "-12345678");
- test(-123456789L, "-123456789");
- test(-1234567890L, "-1234567890");
- test(-12345678901L, "-12345678901");
- test(-123456789012L, "-123456789012");
- test(-1234567890123L, "-1234567890123");
- test(-12345678901234L, "-12345678901234");
- test(-123456789012345L, "-123456789012345");
- test(-1234567890123456L, "-1234567890123456");
- test(-12345678901234567L, "-12345678901234567");
- test(-123456789012345678L, "-123456789012345678");
- test(-1234567890123456789L, "-1234567890123456789");
+struct test_signed {
+ template <class T>
+ TEST_CONSTEXPR_CXX23 void operator()() {
+ test<T>(-1, "-1");
+ test<T>(-12, "-12");
+ test<T>(-1, "-1", 10);
+ test<T>(-12, "-12", 10);
+ test<T>(-21734634, "-21734634", 10);
+ test<T>(-2647, "-101001010111", 2);
+ test<T>(-0xcc1, "-cc1", 16);
+
+ // Test each len till len of INT64_MAX = 19 because to_chars algorithm
+ // makes branches based on decimal digits count in the value string
+ // representation.
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(-1L, "-1");
+ test<T>(-12L, "-12");
+ test<T>(-123L, "-123");
+ test<T>(-1234L, "-1234");
+ test<T>(-12345L, "-12345");
+ test<T>(-123456L, "-123456");
+ test<T>(-1234567L, "-1234567");
+ test<T>(-12345678L, "-12345678");
+ test<T>(-123456789L, "-123456789");
+ test<T>(-1234567890L, "-1234567890");
+ test<T>(-12345678901L, "-12345678901");
+ test<T>(-123456789012L, "-123456789012");
+ test<T>(-1234567890123L, "-1234567890123");
+ test<T>(-12345678901234L, "-12345678901234");
+ test<T>(-123456789012345L, "-123456789012345");
+ test<T>(-1234567890123456L, "-1234567890123456");
+ test<T>(-12345678901234567L, "-12345678901234567");
+ test<T>(-123456789012345678L, "-123456789012345678");
+ test<T>(-1234567890123456789L, "-1234567890123456789");
#ifndef TEST_HAS_NO_INT128
- test(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
- test(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
- test(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
- test(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
- test(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
- test(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
- test(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
- test(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
- test(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
- test(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
- test(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
- test(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
- test(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
- test(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
- test(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
- test(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
- test(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
- test(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
- test(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
- test(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
- test(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
+ test<T>(make_i128(-1L, 2345678901234567890L), "-12345678901234567890");
+ test<T>(make_i128(-12L, 3456789012345678901L), "-123456789012345678901");
+ test<T>(make_i128(-123L, 4567890123456789012L), "-1234567890123456789012");
+ test<T>(make_i128(-1234L, 5678901234567890123L), "-12345678901234567890123");
+ test<T>(make_i128(-12345L, 6789012345678901234L), "-123456789012345678901234");
+ test<T>(make_i128(-123456L, 7890123456789012345L), "-1234567890123456789012345");
+ test<T>(make_i128(-1234567L, 8901234567890123456L), "-12345678901234567890123456");
+ test<T>(make_i128(-12345678L, 9012345678901234567L), "-123456789012345678901234567");
+ test<T>(make_i128(-123456789L, 123456789012345678L), "-1234567890123456789012345678");
+ test<T>(make_i128(-1234567890L, 1234567890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-123L, 4567890123456L, 7890123456789L), "-12345678901234567890123456789");
+ test<T>(make_i128(-1234L, 5678901234567L, 8901234567890L), "-123456789012345678901234567890");
+ test<T>(make_i128(-12345L, 6789012345678L, 9012345678901L), "-1234567890123456789012345678901");
+ test<T>(make_i128(-123456L, 7890123456789L, 123456789012L), "-12345678901234567890123456789012");
+ test<T>(make_i128(-1234567L, 8901234567890L, 1234567890123L), "-123456789012345678901234567890123");
+ test<T>(make_i128(-12345678L, 9012345678901L, 2345678901234L), "-1234567890123456789012345678901234");
+ test<T>(make_i128(-123456789L, 123456789012L, 3456789012345L), "-12345678901234567890123456789012345");
+ test<T>(make_i128(-1234567890L, 1234567890123L, 4567890123456L), "-123456789012345678901234567890123456");
+ test<T>(make_i128(-12345678901L, 2345678901234L, 5678901234567L), "-1234567890123456789012345678901234567");
+ test<T>(make_i128(-123456789012L, 3456789012345L, 6789012345678L), "-12345678901234567890123456789012345678");
+ test<T>(make_i128(-1234567890123L, 4567890123456L, 7890123456789L), "-123456789012345678901234567890123456789");
#endif
- // Test special cases with zeros inside a value string representation,
- // to_chars algorithm processes them in a special way and should not
- // skip trailing zeros
- // Test driver automatically skips values not fitting into source type.
- test(-10L, "-10");
- test(-100L, "-100");
- test(-1000L, "-1000");
- test(-10000L, "-10000");
- test(-100000L, "-100000");
- test(-1000000L, "-1000000");
- test(-10000000L, "-10000000");
- test(-100000000L, "-100000000");
- test(-1000000000L, "-1000000000");
- test(-10000000000L, "-10000000000");
- test(-100000000000L, "-100000000000");
- test(-1000000000000L, "-1000000000000");
- test(-10000000000000L, "-10000000000000");
- test(-100000000000000L, "-100000000000000");
- test(-1000000000000000L, "-1000000000000000");
- test(-10000000000000000L, "-10000000000000000");
- test(-100000000000000000L, "-100000000000000000");
- test(-1000000000000000000L, "-1000000000000000000");
+ // Test special cases with zeros inside a value string representation,
+ // to_chars algorithm processes them in a special way and should not
+ // skip trailing zeros
+ // Test driver automatically skips values not fitting into source type.
+ test<T>(-10L, "-10");
+ test<T>(-100L, "-100");
+ test<T>(-1000L, "-1000");
+ test<T>(-10000L, "-10000");
+ test<T>(-100000L, "-100000");
+ test<T>(-1000000L, "-1000000");
+ test<T>(-10000000L, "-10000000");
+ test<T>(-100000000L, "-100000000");
+ test<T>(-1000000000L, "-1000000000");
+ test<T>(-10000000000L, "-10000000000");
+ test<T>(-100000000000L, "-100000000000");
+ test<T>(-1000000000000L, "-1000000000000");
+ test<T>(-10000000000000L, "-10000000000000");
+ test<T>(-100000000000000L, "-100000000000000");
+ test<T>(-1000000000000000L, "-1000000000000000");
+ test<T>(-10000000000000000L, "-10000000000000000");
+ test<T>(-100000000000000000L, "-100000000000000000");
+ test<T>(-1000000000000000000L, "-1000000000000000000");
#ifndef TEST_HAS_NO_INT128
- test(make_i128(-1L, 0L), "-10000000000000000000");
- test(make_i128(-10L, 0L), "-100000000000000000000");
- test(make_i128(-100L, 0L), "-1000000000000000000000");
- test(make_i128(-1000L, 0L), "-10000000000000000000000");
- test(make_i128(-10000L, 0L), "-100000000000000000000000");
- test(make_i128(-100000L, 0L), "-1000000000000000000000000");
- test(make_i128(-1000000L, 0L), "-10000000000000000000000000");
- test(make_i128(-10000000L, 0L), "-100000000000000000000000000");
- test(make_i128(-100000000L, 0L), "-1000000000000000000000000000");
- test(make_i128(-1000000000L, 0L), "-10000000000000000000000000000");
- test(make_i128(-100L, 0L, 0L), "-10000000000000000000000000000");
- test(make_i128(-1000L, 0L, 0L), "-100000000000000000000000000000");
- test(make_i128(-10000L, 0L, 0L), "-1000000000000000000000000000000");
- test(make_i128(-100000L, 0L, 0L), "-10000000000000000000000000000000");
- test(make_i128(-1000000L, 0L, 0L), "-100000000000000000000000000000000");
- test(make_i128(-10000000L, 0L, 0L), "-1000000000000000000000000000000000");
- test(make_i128(-100000000L, 0L, 0L), "-10000000000000000000000000000000000");
- test(make_i128(-1000000000L, 0L, 0L), "-100000000000000000000000000000000000");
- test(make_i128(-10000000000L, 0L, 0L), "-1000000000000000000000000000000000000");
- test(make_i128(-100000000000L, 0L, 0L), "-10000000000000000000000000000000000000");
- test(make_i128(-1000000000000L, 0L, 0L), "-100000000000000000000000000000000000000");
+ test<T>(make_i128(-1L, 0L), "-10000000000000000000");
+ test<T>(make_i128(-10L, 0L), "-100000000000000000000");
+ test<T>(make_i128(-100L, 0L), "-1000000000000000000000");
+ test<T>(make_i128(-1000L, 0L), "-10000000000000000000000");
+ test<T>(make_i128(-10000L, 0L), "-100000000000000000000000");
+ test<T>(make_i128(-100000L, 0L), "-1000000000000000000000000");
+ test<T>(make_i128(-1000000L, 0L), "-10000000000000000000000000");
+ test<T>(make_i128(-10000000L, 0L), "-100000000000000000000000000");
+ test<T>(make_i128(-100000000L, 0L), "-1000000000000000000000000000");
+ test<T>(make_i128(-1000000000L, 0L), "-10000000000000000000000000000");
+ test<T>(make_i128(-100L, 0L, 0L), "-10000000000000000000000000000");
+ test<T>(make_i128(-1000L, 0L, 0L), "-100000000000000000000000000000");
+ test<T>(make_i128(-10000L, 0L, 0L), "-1000000000000000000000000000000");
+ test<T>(make_i128(-100000L, 0L, 0L), "-10000000000000000000000000000000");
+ test<T>(make_i128(-1000000L, 0L, 0L), "-100000000000000000000000000000000");
+ test<T>(make_i128(-10000000L, 0L, 0L), "-1000000000000000000000000000000000");
+ test<T>(make_i128(-100000000L, 0L, 0L), "-10000000000000000000000000000000000");
+ test<T>(make_i128(-1000000000L, 0L, 0L), "-100000000000000000000000000000000000");
+ test<T>(make_i128(-10000000000L, 0L, 0L), "-1000000000000000000000000000000000000");
+ test<T>(make_i128(-100000000000L, 0L, 0L), "-10000000000000000000000000000000000000");
+ test<T>(make_i128(-1000000000000L, 0L, 0L), "-100000000000000000000000000000000000000");
#endif
- for (int b = 2; b < 37; ++b)
- {
- using xl = std::numeric_limits<T>;
+ for (int b = 2; b < 37; ++b) {
+ using xl = std::numeric_limits<T>;
- test_value(0, b);
- test_value(xl::lowest(), b);
- test_value((xl::max)(), b);
- }
+ test_value(0, b);
+ test_value(xl::lowest(), b);
+ test_value((xl::max)(), b);
}
+ }
};
-TEST_CONSTEXPR_CXX23 bool test()
-{
- run<test_basics>(integrals);
- run<test_signed>(all_signed);
+TEST_CONSTEXPR_CXX23 bool test() {
+ types::for_each(types::integer_types{}, test_basics{});
+ types::for_each(types::signed_integer_types{}, test_signed{});
- return true;
+ return true;
}
-int main(int, char**)
-{
- test();
+int main(int, char**) {
+ test();
#if TEST_STD_VER > 20
- static_assert(test());
+ static_assert(test());
#endif
return 0;
diff --git a/libcxx/test/support/charconv_test_helpers.h b/libcxx/test/support/charconv_test_helpers.h
index fcae09478457b..51c579e7923ad 100644
--- a/libcxx/test/support/charconv_test_helpers.h
+++ b/libcxx/test/support/charconv_test_helpers.h
@@ -9,15 +9,8 @@
#ifndef SUPPORT_CHARCONV_TEST_HELPERS_H
#define SUPPORT_CHARCONV_TEST_HELPERS_H
-#include <algorithm>
-#include <cassert>
-#include <cerrno>
-#include <charconv>
#include <cstddef>
#include <limits>
-#include <numeric>
-#include <string.h>
-#include <stdlib.h>
#include <type_traits>
#include "test_macros.h"
@@ -26,47 +19,44 @@
#error This file requires C++11
#endif
-using std::false_type;
-using std::true_type;
-
template <typename To, typename From>
constexpr auto
-is_non_narrowing(From a) -> decltype(To{a}, true_type())
+is_non_narrowing(From a) -> decltype(To{a}, std::true_type())
{
return {};
}
template <typename To>
constexpr auto
-is_non_narrowing(...) -> false_type
+is_non_narrowing(...) -> std::false_type
{
return {};
}
template <typename X, typename T>
constexpr bool
-_fits_in(T, true_type /* non-narrowing*/, ...)
+_fits_in(T, std::true_type /* non-narrowing*/, ...)
{
return true;
}
template <typename X, typename T, typename xl = std::numeric_limits<X>>
constexpr bool
-_fits_in(T v, false_type, true_type /* T signed*/, true_type /* X signed */)
+_fits_in(T v, std::false_type, std::true_type /* T signed*/, std::true_type /* X signed */)
{
return xl::lowest() <= v && v <= (xl::max)();
}
template <typename X, typename T, typename xl = std::numeric_limits<X>>
constexpr bool
-_fits_in(T v, false_type, true_type /* T signed */, false_type /* X unsigned*/)
+_fits_in(T v, std::false_type, std::true_type /* T signed */, std::false_type /* X unsigned*/)
{
return 0 <= v && typename std::make_unsigned<T>::type(v) <= (xl::max)();
}
template <typename X, typename T, typename xl = std::numeric_limits<X>>
constexpr bool
-_fits_in(T v, false_type, false_type /* T unsigned */, ...)
+_fits_in(T v, std::false_type, std::false_type /* T unsigned */, ...)
{
return v <= typename std::make_unsigned<X>::type((xl::max)());
}
@@ -78,253 +68,4 @@ fits_in(T v)
return _fits_in<X>(v, is_non_narrowing<X>(v), std::is_signed<T>(), std::is_signed<X>());
}
-template <typename X>
-struct to_chars_test_base
-{
- template <typename T, std::size_t N, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, char const (&expect)[N], Ts... args)
- {
- std::to_chars_result r;
-
- constexpr std::size_t len = N - 1;
- static_assert(len > 0, "expected output won't be empty");
-
- if (!fits_in<X>(v))
- return;
-
- r = std::to_chars(buf, buf + len - 1, X(v), args...);
- assert(r.ptr == buf + len - 1);
- assert(r.ec == std::errc::value_too_large);
-
- r = std::to_chars(buf, buf + sizeof(buf), X(v), args...);
- assert(r.ptr == buf + len);
- assert(r.ec == std::errc{});
- assert(std::equal(buf, buf + len, expect));
- }
-
- template <typename... Ts>
- TEST_CONSTEXPR_CXX23 void test_value(X v, Ts... args)
- {
- std::to_chars_result r;
-
- // Poison the buffer for testing whether a successful std::to_chars
- // doesn't modify data beyond r.ptr. Use unsigned values to avoid
- // overflowing char when it's signed.
- std::iota(buf, buf + sizeof(buf), static_cast<unsigned char>(1));
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
- for (std::size_t i = r.ptr - buf; i < sizeof(buf); ++i)
- assert(static_cast<unsigned char>(buf[i]) == i + 1);
- *r.ptr = '\0';
-
-#ifndef TEST_HAS_NO_INT128
- if (sizeof(X) == sizeof(__int128_t)) {
- auto a = fromchars128_impl(buf, r.ptr, args...);
- assert(v == a);
- } else
-#endif
- {
- auto a = fromchars_impl(buf, r.ptr, args...);
- assert(v == a);
- }
-
- auto ep = r.ptr - 1;
- r = std::to_chars(buf, ep, v, args...);
- assert(r.ptr == ep);
- assert(r.ec == std::errc::value_too_large);
- }
-
-private:
- static TEST_CONSTEXPR_CXX23 long long fromchars_impl(char const* p, char const* ep, int base, true_type)
- {
- char* last;
- long long r;
- if (TEST_IS_CONSTANT_EVALUATED)
- last = const_cast<char*>(std::from_chars(p, ep, r, base).ptr);
- else
- r = strtoll(p, &last, base);
- assert(last == ep);
-
- return r;
- }
-
- static TEST_CONSTEXPR_CXX23 unsigned long long fromchars_impl(char const* p, char const* ep, int base, false_type)
- {
- char* last;
- unsigned long long r;
- if (TEST_IS_CONSTANT_EVALUATED)
- last = const_cast<char*>(std::from_chars(p, ep, r, base).ptr);
- else
- r = strtoull(p, &last, base);
- assert(last == ep);
-
- return r;
- }
-#ifndef TEST_HAS_NO_INT128
- static TEST_CONSTEXPR_CXX23 __int128_t fromchars128_impl(char const* p, char const* ep, int base, true_type)
- {
- if (!TEST_IS_CONSTANT_EVALUATED) {
- char* last;
- __int128_t r = strtoll(p, &last, base);
- if(errno != ERANGE) {
- assert(last == ep);
- return r;
- }
- }
-
- // When the value doesn't fit in a long long use from_chars. This is
- // not ideal since it does a round-trip test instead if using an
- // external source.
- __int128_t r;
- std::from_chars_result s = std::from_chars(p, ep, r, base);
- assert(s.ec == std::errc{});
- assert(s.ptr == ep);
-
- return r;
- }
-
- static TEST_CONSTEXPR_CXX23 __uint128_t fromchars128_impl(char const* p, char const* ep, int base, false_type)
- {
- if (!TEST_IS_CONSTANT_EVALUATED) {
- char* last;
- __uint128_t r = strtoull(p, &last, base);
- if(errno != ERANGE) {
- assert(last == ep);
- return r;
- }
- }
-
- __uint128_t r;
- std::from_chars_result s = std::from_chars(p, ep, r, base);
- assert(s.ec == std::errc{});
- assert(s.ptr == ep);
-
- return r;
- }
-
- static TEST_CONSTEXPR_CXX23 auto fromchars128_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars128_impl(p, ep, base, std::is_signed<X>()))
- {
- return fromchars128_impl(p, ep, base, std::is_signed<X>());
- }
-
-#endif
-
- static TEST_CONSTEXPR_CXX23 auto fromchars_impl(char const* p, char const* ep, int base = 10)
- -> decltype(fromchars_impl(p, ep, base, std::is_signed<X>()))
- {
- return fromchars_impl(p, ep, base, std::is_signed<X>());
- }
-
- char buf[150];
-};
-
-template <typename X>
-struct roundtrip_test_base
-{
- template <typename T, typename... Ts>
- TEST_CONSTEXPR_CXX23 void test(T v, Ts... args)
- {
- std::from_chars_result r2;
- std::to_chars_result r;
- X x = 0xc;
-
- if (fits_in<X>(v))
- {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
- assert(r2.ptr == r.ptr);
- assert(x == X(v));
- }
- else
- {
- r = std::to_chars(buf, buf + sizeof(buf), v, args...);
- assert(r.ec == std::errc{});
-
- r2 = std::from_chars(buf, r.ptr, x, args...);
-
- TEST_DIAGNOSTIC_PUSH
- TEST_MSVC_DIAGNOSTIC_IGNORED(4127) // conditional expression is constant
-
- if (std::is_signed<T>::value && v < 0 && std::is_unsigned<X>::value)
- {
- assert(x == 0xc);
- assert(r2.ptr == buf);
- assert(r2.ec == std::errc::invalid_argument);
- }
- else
- {
- assert(x == 0xc);
- assert(r2.ptr == r.ptr);
- assert(r2.ec == std::errc::result_out_of_range);
- }
-
- TEST_DIAGNOSTIC_POP
- }
- }
-
-private:
- char buf[150];
-};
-
-template <typename... T>
-struct type_list
-{
-};
-
-template <typename L1, typename L2>
-struct type_concat;
-
-template <typename... Xs, typename... Ys>
-struct type_concat<type_list<Xs...>, type_list<Ys...>>
-{
- using type = type_list<Xs..., Ys...>;
-};
-
-template <typename L1, typename L2>
-using concat_t = typename type_concat<L1, L2>::type;
-
-template <typename L1, typename L2>
-constexpr auto concat(L1, L2) -> concat_t<L1, L2>
-{
- return {};
-}
-
-auto all_signed = type_list<
- char,
- signed char,
- short,
- int,
- long,
- long long
-#ifndef TEST_HAS_NO_INT128
- ,
- __int128_t
-#endif
- >();
-auto all_unsigned = type_list<
- unsigned char,
- unsigned short,
- unsigned int,
- unsigned long,
- unsigned long long
-#ifndef TEST_HAS_NO_INT128
- ,
- __uint128_t
-#endif
- >();
-auto integrals = concat(all_signed, all_unsigned);
-
-auto all_floats = type_list< float, double >(); //TODO: Add long double
-
-template <template <typename> class Fn, typename... Ts>
-TEST_CONSTEXPR_CXX23 void
-run(type_list<Ts...>)
-{
- int ls[sizeof...(Ts)] = {(Fn<Ts>{}(), 0)...};
- (void)ls;
-}
-
#endif // SUPPORT_CHARCONV_TEST_HELPERS_H
More information about the libcxx-commits
mailing list