xref: /llvm-project/libcxx/test/std/utilities/charconv/charconv.from.chars/integral.pass.cpp (revision 63ebd3bd24d414737e5404923dcd1b8dbdb8ee46)
1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // UNSUPPORTED: c++98, c++03, c++11
11 // <charconv>
12 
13 // from_chars_result from_chars(const char* first, const char* last,
14 //                              Integral& value, int base = 10)
15 
16 #include "charconv_test_helpers.h"
17 
18 template <typename T>
19 struct test_basics : roundtrip_test_base<T>
20 {
21     using roundtrip_test_base<T>::test;
22 
23     void operator()()
24     {
25         test(0);
26         test(42);
27         test(32768);
28         test(0, 10);
29         test(42, 10);
30         test(32768, 10);
31         test(0xf, 16);
32         test(0xdeadbeaf, 16);
33         test(0755, 8);
34 
35         for (int b = 2; b < 37; ++b)
36         {
37             using xl = std::numeric_limits<T>;
38 
39             test(1, b);
40             test(-1, b);
41             test(xl::lowest(), b);
42             test((xl::max)(), b);
43             test((xl::max)() / 2, b);
44         }
45 
46         using std::from_chars;
47         std::from_chars_result r;
48         T x;
49 
50         {
51             char s[] = "001x";
52 
53             // the expected form of the subject sequence is a sequence of
54             // letters and digits representing an integer with the radix
55             // specified by base (C11 7.22.1.4/3)
56             r = from_chars(s, s + sizeof(s), x);
57             assert(r.ec == std::errc{});
58             assert(r.ptr == s + 3);
59             assert(x == 1);
60         }
61 
62         {
63             char s[] = "0X7BAtSGHDkEIXZg ";
64 
65             // The letters from a (or A) through z (or Z) are ascribed the
66             // values 10 through 35; (C11 7.22.1.4/3)
67             r = from_chars(s, s + sizeof(s), x, 36);
68             assert(r.ec == std::errc::result_out_of_range);
69             // The member ptr of the return value points to the first character
70             // not matching the pattern
71             assert(r.ptr == s + sizeof(s) - 2);
72             assert(x == 1);
73 
74             // no "0x" or "0X" prefix shall appear if the value of base is 16
75             r = from_chars(s, s + sizeof(s), x, 16);
76             assert(r.ec == std::errc{});
77             assert(r.ptr == s + 1);
78             assert(x == 0);
79 
80             // only letters and digits whose ascribed values are less than that
81             // of base are permitted. (C11 7.22.1.4/3)
82             r = from_chars(s + 2, s + sizeof(s), x, 12);
83             // If the parsed value is not in the range representable by the type
84             // of value,
85             if (!fits_in<T>(1150))
86             {
87                 // value is unmodified and
88                 assert(x == 0);
89                 // the member ec of the return value is equal to
90                 // errc::result_out_of_range
91                 assert(r.ec == std::errc::result_out_of_range);
92             }
93             else
94             {
95                 // Otherwise, value is set to the parsed value,
96                 assert(x == 1150);
97                 // and the member ec is value-initialized.
98                 assert(r.ec == std::errc{});
99             }
100             assert(r.ptr == s + 5);
101         }
102     }
103 };
104 
105 template <typename T>
106 struct test_signed : roundtrip_test_base<T>
107 {
108     using roundtrip_test_base<T>::test;
109 
110     void operator()()
111     {
112         test(-1);
113         test(-12);
114         test(-1, 10);
115         test(-12, 10);
116         test(-21734634, 10);
117         test(-2647, 2);
118         test(-0xcc1, 16);
119 
120         for (int b = 2; b < 37; ++b)
121         {
122             using xl = std::numeric_limits<T>;
123 
124             test(0, b);
125             test(xl::lowest(), b);
126             test((xl::max)(), b);
127         }
128 
129         using std::from_chars;
130         std::from_chars_result r;
131         T x;
132 
133         {
134             // If the pattern allows for an optional sign,
135             // but the string has no digit characters following the sign,
136             char s[] = "- 9+12";
137             r = from_chars(s, s + sizeof(s), x);
138             // no characters match the pattern.
139             assert(r.ptr == s);
140             assert(r.ec == std::errc::invalid_argument);
141         }
142 
143         {
144             char s[] = "9+12";
145             r = from_chars(s, s + sizeof(s), x);
146             assert(r.ec == std::errc{});
147             // The member ptr of the return value points to the first character
148             // not matching the pattern,
149             assert(r.ptr == s + 1);
150             assert(x == 9);
151         }
152 
153         {
154             char s[] = "12";
155             r = from_chars(s, s + 2, x);
156             assert(r.ec == std::errc{});
157             // or has the value last if all characters match.
158             assert(r.ptr == s + 2);
159             assert(x == 12);
160         }
161 
162         {
163             // '-' is the only sign that may appear
164             char s[] = "+30";
165             // If no characters match the pattern,
166             r = from_chars(s, s + sizeof(s), x);
167             // value is unmodified,
168             assert(x == 12);
169             // the member ptr of the return value is first and
170             assert(r.ptr == s);
171             // the member ec is equal to errc::invalid_argument.
172             assert(r.ec == std::errc::invalid_argument);
173         }
174     }
175 };
176 
177 int
178 main()
179 {
180     run<test_basics>(integrals);
181     run<test_signed>(all_signed);
182 }
183