xref: /llvm-project/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp (revision a1e13a80d06c2d1764ab573df06a3b903f134703)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14
10 
11 // <charconv>
12 
13 // constexpr from_chars_result from_chars(const char* first, const char* last,
14 //                                        Integral& value, int base = 10)
15 
16 #include <charconv>
17 #include "test_macros.h"
18 #include "charconv_test_helpers.h"
19 
20 template <typename T>
21 struct test_basics
22 {
23     TEST_CONSTEXPR_CXX23 void operator()()
24     {
25         std::from_chars_result r;
26         T x;
27 
28         {
29             char s[] = "001x";
30 
31             // the expected form of the subject sequence is a sequence of
32             // letters and digits representing an integer with the radix
33             // specified by base (C11 7.22.1.4/3)
34             r = std::from_chars(s, s + sizeof(s), x);
35             assert(r.ec == std::errc{});
36             assert(r.ptr == s + 3);
37             assert(x == 1);
38         }
39 
40         {
41             // The string has more characters than valid in an 128-bit value.
42             char s[] = "0X7BAtSGHDkEIXZgQRfYChLpOzRnM ";
43 
44             // The letters from a (or A) through z (or Z) are ascribed the
45             // values 10 through 35; (C11 7.22.1.4/3)
46             r = std::from_chars(s, s + sizeof(s), x, 36);
47             assert(r.ec == std::errc::result_out_of_range);
48             // The member ptr of the return value points to the first character
49             // not matching the pattern
50             assert(r.ptr == s + sizeof(s) - 2);
51             assert(x == 1);
52 
53             // no "0x" or "0X" prefix shall appear if the value of base is 16
54             r = std::from_chars(s, s + sizeof(s), x, 16);
55             assert(r.ec == std::errc{});
56             assert(r.ptr == s + 1);
57             assert(x == 0);
58 
59             // only letters and digits whose ascribed values are less than that
60             // of base are permitted. (C11 7.22.1.4/3)
61             r = std::from_chars(s + 2, s + sizeof(s), x, 12);
62             // If the parsed value is not in the range representable by the type
63             // of value,
64             if (!fits_in<T>(1150))
65             {
66                 // value is unmodified and
67                 assert(x == 0);
68                 // the member ec of the return value is equal to
69                 // errc::result_out_of_range
70                 assert(r.ec == std::errc::result_out_of_range);
71             }
72             else
73             {
74                 // Otherwise, value is set to the parsed value,
75                 assert(x == 1150);
76                 // and the member ec is value-initialized.
77                 assert(r.ec == std::errc{});
78             }
79             assert(r.ptr == s + 5);
80         }
81     }
82 };
83 
84 template <typename T>
85 struct test_signed
86 {
87     TEST_CONSTEXPR_CXX23 void operator()()
88     {
89         std::from_chars_result r;
90         T x = 42;
91 
92         {
93             // If the pattern allows for an optional sign,
94             // but the string has no digit characters following the sign,
95             char s[] = "- 9+12";
96             r = std::from_chars(s, s + sizeof(s), x);
97             // value is unmodified,
98             assert(x == 42);
99             // no characters match the pattern.
100             assert(r.ptr == s);
101             assert(r.ec == std::errc::invalid_argument);
102         }
103 
104         {
105             char s[] = "9+12";
106             r = std::from_chars(s, s + sizeof(s), x);
107             assert(r.ec == std::errc{});
108             // The member ptr of the return value points to the first character
109             // not matching the pattern,
110             assert(r.ptr == s + 1);
111             assert(x == 9);
112         }
113 
114         {
115             char s[] = "12";
116             r = std::from_chars(s, s + 2, x);
117             assert(r.ec == std::errc{});
118             // or has the value last if all characters match.
119             assert(r.ptr == s + 2);
120             assert(x == 12);
121         }
122 
123         {
124             // '-' is the only sign that may appear
125             char s[] = "+30";
126             // If no characters match the pattern,
127             r = std::from_chars(s, s + sizeof(s), x);
128             // value is unmodified,
129             assert(x == 12);
130             // the member ptr of the return value is first and
131             assert(r.ptr == s);
132             // the member ec is equal to errc::invalid_argument.
133             assert(r.ec == std::errc::invalid_argument);
134         }
135     }
136 };
137 
138 TEST_CONSTEXPR_CXX23 bool test()
139 {
140     run<test_basics>(integrals);
141     run<test_signed>(all_signed);
142 
143     return true;
144 }
145 
146 int main(int, char**) {
147     test();
148 #if TEST_STD_VER > 20
149     static_assert(test());
150 #endif
151 
152     return 0;
153 }
154