1// Copyright 2023 Matt Borland
2// Distributed under the Boost Software License, Version 1.0.
3// https://www.boost.org/LICENSE_1_0.txt
4
5#include <boost/charconv/detail/parser.hpp>
6#include <boost/charconv/chars_format.hpp>
7#include <boost/core/lightweight_test.hpp>
8#include <system_error>
9#include <type_traits>
10#include <cstdint>
11#include <cstring>
12#include <cerrno>
13
14template <typename T>
15void test_integer()
16{
17 std::uint64_t significand {};
18 std::int64_t exponent {};
19 bool sign {};
20
21 const char* val1 = "12";
22 auto r1 = boost::charconv::detail::parser(first: val1, last: val1 + std::strlen(s: val1), sign, significand, exponent);
23 BOOST_TEST(r1.ec == std::errc());
24 BOOST_TEST_EQ(sign, false);
25 BOOST_TEST_EQ(significand, UINT64_C(12));
26 BOOST_TEST_EQ(exponent, 0);
27
28 significand = 0;
29 exponent = 0;
30 sign = false;
31
32 const char* val2 = "123456789";
33 auto r2 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent);
34 BOOST_TEST(r2.ec == std::errc());
35 BOOST_TEST_EQ(sign, false);
36 BOOST_TEST_EQ(exponent, 0);
37 BOOST_TEST_EQ(significand, UINT64_C(123456789));
38
39 auto r3 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent, fmt: boost::charconv::chars_format::scientific);
40 BOOST_TEST(r3.ec == std::errc::invalid_argument);
41}
42
43template <typename T>
44void test_scientifc()
45{
46 std::uint64_t significand {};
47 std::int64_t exponent {};
48 bool sign {};
49
50 const char* val1 = "-1e1";
51 auto r1 = boost::charconv::detail::parser(first: val1, last: val1 + std::strlen(s: val1), sign, significand, exponent);
52 BOOST_TEST(r1.ec == std::errc());
53 BOOST_TEST_EQ(sign, true);
54 BOOST_TEST_EQ(significand, UINT64_C(1));
55 BOOST_TEST_EQ(exponent, 1);
56
57 significand = 0;
58 exponent = 0;
59 sign = false;
60
61 const char* val2 = "123456789e10";
62 auto r2 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent);
63 BOOST_TEST(r2.ec == std::errc());
64 BOOST_TEST_EQ(sign, false);
65 BOOST_TEST_EQ(exponent, 10);
66 BOOST_TEST_EQ(significand, UINT64_C(123456789));
67
68 significand = 0;
69 exponent = 0;
70 sign = false;
71
72 const char* val3 = "1.23456789e+10";
73 auto r3 = boost::charconv::detail::parser(first: val3, last: val3 + std::strlen(s: val3), sign, significand, exponent);
74 BOOST_TEST(r3.ec == std::errc());
75 BOOST_TEST_EQ(sign, false);
76 BOOST_TEST_EQ(exponent, 2);
77 BOOST_TEST_EQ(significand, UINT64_C(123456789));
78
79 const char* val4 = "1.23456789e-10";
80 auto r4 = boost::charconv::detail::parser(first: val4, last: val4 + std::strlen(s: val4), sign, significand, exponent);
81 BOOST_TEST(r4.ec == std::errc());
82 BOOST_TEST_EQ(sign, false);
83 BOOST_TEST_EQ(exponent, -18);
84 BOOST_TEST_EQ(significand, UINT64_C(123456789));
85
86 auto r5 = boost::charconv::detail::parser(first: val4, last: val4 + std::strlen(s: val4), sign, significand, exponent, fmt: boost::charconv::chars_format::fixed);
87 BOOST_TEST(r5.ec == std::errc::invalid_argument);
88
89 const char* val6 = "987654321e10";
90 auto r6 = boost::charconv::detail::parser(first: val6, last: val6 + std::strlen(s: val6), sign, significand, exponent);
91 BOOST_TEST(r6.ec == std::errc());
92 BOOST_TEST_EQ(sign, false);
93 BOOST_TEST_EQ(exponent, 10);
94 BOOST_TEST_EQ(significand, UINT64_C(987654321));
95
96 const char* val7 = "1.23456789E+10";
97 auto r7 = boost::charconv::detail::parser(first: val7, last: val7 + std::strlen(s: val7), sign, significand, exponent);
98 BOOST_TEST(r7.ec == std::errc());
99 BOOST_TEST_EQ(sign, false);
100 BOOST_TEST_EQ(exponent, 2);
101 BOOST_TEST_EQ(significand, UINT64_C(123456789));
102
103}
104
105template <typename T>
106void test_hex_integer()
107{
108 std::uint64_t significand {};
109 std::int64_t exponent {};
110 bool sign {};
111
112 const char* val1 = "2a";
113 auto r1 = boost::charconv::detail::parser(first: val1, last: val1 + std::strlen(s: val1), sign, significand, exponent, fmt: boost::charconv::chars_format::hex);
114 BOOST_TEST(r1.ec == std::errc());
115 BOOST_TEST_EQ(sign, false);
116 BOOST_TEST_EQ(significand, UINT64_C(42));
117 BOOST_TEST_EQ(exponent, 0);
118
119 significand = 0;
120 exponent = 0;
121 sign = false;
122
123 const char* val2 = "-1a3b5c7d9";
124 auto r2 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent, fmt: boost::charconv::chars_format::hex);
125 BOOST_TEST(r2.ec == std::errc());
126 BOOST_TEST_EQ(sign, true);
127 BOOST_TEST_EQ(exponent, 0);
128 BOOST_TEST_EQ(significand, UINT64_C(7041566681));
129
130 auto r3 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent, fmt: boost::charconv::chars_format::scientific);
131 BOOST_TEST(r3.ec == std::errc::invalid_argument);
132}
133
134template <typename T>
135void test_hex_scientific()
136{
137 std::uint64_t significand {};
138 std::int64_t exponent {};
139 bool sign {};
140
141 const char* val1 = "2ap+5";
142 auto r1 = boost::charconv::detail::parser(first: val1, last: val1 + std::strlen(s: val1), sign, significand, exponent, fmt: boost::charconv::chars_format::hex);
143 BOOST_TEST(r1.ec == std::errc());
144 BOOST_TEST_EQ(sign, false);
145 BOOST_TEST_EQ(significand, UINT64_C(42));
146 BOOST_TEST_EQ(exponent, 5);
147
148 significand = 0;
149 exponent = 0;
150 sign = false;
151
152 const char* val2 = "-1.3a2bp-10";
153 auto r2 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent, fmt: boost::charconv::chars_format::hex);
154 BOOST_TEST(r2.ec == std::errc());
155 BOOST_TEST_EQ(sign, true);
156 BOOST_TEST_EQ(exponent, -14);
157 BOOST_TEST_EQ(significand, UINT64_C(80427));
158
159 auto r3 = boost::charconv::detail::parser(first: val2, last: val2 + std::strlen(s: val2), sign, significand, exponent, fmt: boost::charconv::chars_format::scientific);
160 BOOST_TEST(r3.ec == std::errc::invalid_argument);
161
162 const char* val4 = "-1.3A2BP-10";
163 auto r4 = boost::charconv::detail::parser(first: val4, last: val4 + std::strlen(s: val4), sign, significand, exponent, fmt: boost::charconv::chars_format::hex);
164 BOOST_TEST(r4.ec == std::errc());
165 BOOST_TEST_EQ(sign, true);
166 BOOST_TEST_EQ(exponent, -14);
167 BOOST_TEST_EQ(significand, UINT64_C(80427));
168}
169
170int main()
171{
172 test_integer<float>();
173 test_integer<double>();
174 test_integer<long double>();
175
176 test_scientifc<float>();
177 test_scientifc<double>();
178 test_scientifc<long double>();
179
180 test_hex_integer<float>();
181 test_hex_integer<double>();
182 test_hex_integer<long double>();
183
184 test_hex_scientific<float>();
185 test_hex_scientific<double>();
186 test_hex_scientific<long double>();
187
188 return boost::report_errors();
189}
190

source code of boost/libs/charconv/test/test_parser.cpp