Maipa's Standard Library Extension 1.5.6
mstd
Loading...
Searching...
No Matches
strtonum.hpp
1/*
2 * mstd - Maipa's Standard Library
3 *
4 * Licensed under the BSD 3-Clause License with Attribution Requirement.
5 * See the LICENSE file for details: https://github.com/MAIPA01/mstd/blob/main/LICENSE
6 *
7 * Copyright (c) 2025, Patryk Antosik (MAIPA01)
8 */
9
10#pragma once
11#ifndef _MSTD_STRTONUM_HPP
12 #define _MSTD_STRTONUM_HPP
13
14 #include <mstd/config.hpp>
15
17_MSTD_WARNING("this is only available for c++17 and greater!");
18 #else
19
20 #include <mstd/overflow_operations.hpp>
21 #include <mstd/string_types.hpp>
22
23namespace mstd {
24 // 0x0F...
26 template<mstd::integral N>
27 #else
28 template<class N, std::enable_if_t<std::is_integral_v<N>, bool> = true>
29 #endif
30 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strxtonum(const std::string_view hexStr, N& num) {
34
35 if (hexStr.size() <= 2) { return false; }
36
37 if (hexStr[0] != '0' || hexStr[1] != 'x') { return false; }
38 size_t i = 2;
39
40 using limits = std::numeric_limits<N>;
42
43 using UN = std::make_unsigned_t<N>;
44 UN unum = 0;
45 while (((hexStr[i] >= '0' && hexStr[i] <= '9') || (hexStr[i] >= 'A' && hexStr[i] <= 'F') ||
46 (hexStr[i] >= 'a' && hexStr[i] <= 'f')) &&
47 i - 2 < maxBitsNum) {
48 if (mul_overflow(unum, hex_divider, unum)) { return false; }
49
50 if (hexStr[i] >= '0' && hexStr[i] <= '9' && add_overflow(unum, hexStr[i] - '0', unum)) { return false; }
51
52 if (hexStr[i] >= 'A' && hexStr[i] <= 'F' && add_overflow(unum, (hexStr[i] - 'A') + a_decimal_rep, unum)) {
53 return false;
54 }
55
56 if (hexStr[i] >= 'a' && hexStr[i] <= 'f' && add_overflow(unum, (hexStr[i] - 'a') + a_decimal_rep, unum)) {
57 return false;
58 }
59
60 ++i;
61 if (i == hexStr.size()) {
62 num = static_cast<N>(unum);
63 return true;
64 }
65 }
66
67 return false;
68 }
69
70 // 0c07...
72 template<mstd::integral N>
73 #else
74 template<class N, std::enable_if_t<std::is_integral_v<N>, bool> = true>
75 #endif
76 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strctonum(const std::string_view octStr, N& num) {
78
79 if (octStr.size() <= 2) { return false; }
80
81 if (octStr[0] != '0' || octStr[1] != 'c') { return false; }
82 size_t i = 2;
83
84 using limits = std::numeric_limits<N>;
85 const uint32_t& maxOctalsNum = std::max((limits::digits + limits::is_signed) / 4, 1);
86
87 using UN = std::make_unsigned_t<N>;
88 UN unum = 0;
89 while (octStr[i] >= '0' && octStr[i] <= '7' && i - 2 < maxOctalsNum) {
90 if (mul_overflow(unum, oct_divider, unum)) { return false; }
91
92 if (add_overflow(unum, octStr[i] - '0', unum)) { return false; }
93
94 ++i;
95 if (i == octStr.size()) {
96 num = static_cast<N>(unum);
97 return true;
98 }
99 }
100
101 return false;
102 }
103
104 // 0b01...
106 template<mstd::integral N>
107 #else
108 template<class N, std::enable_if_t<std::is_integral_v<N>, bool> = true>
109 #endif
110 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strbtonum(const std::string_view binStr, N& num) {
111 if (binStr.size() <= 2) { return false; }
112
113 if (binStr[0] != '0' || binStr[1] != 'b') { return false; }
114 size_t i = 2;
115
116 using limits = std::numeric_limits<N>;
118
119 using UN = std::make_unsigned_t<N>;
120 UN unum = 0;
121 while (binStr[i] >= '0' && binStr[i] <= '1' && i - 2 < maxOctalsNum) {
122 if (mul_overflow(unum, 2u, unum)) { return false; }
123
124 if (add_overflow(unum, binStr[i] - '0', unum)) { return false; }
125
126 ++i;
127 if (i == binStr.size()) {
128 num = static_cast<N>(unum);
129 return true;
130 }
131 }
132
133 return false;
134 }
135
136 // ((+|-)* 12) | (0b00...) | (0c00...) | (0x00...)
138 template<mstd::signed_integral SN>
139 #else
140 template<class SN, std::enable_if_t<mstd::is_signed_integral_v<SN>, bool> = true>
141 #endif
142 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtonum(const std::string_view str, SN& num) {
144
145 if (str.empty()) { return false; }
146
147 if (str.size() > 2 && str[0] == '0') {
148 if (str[1] == 'b') { return strbtonum(str, num); }
149
150 if (str[1] == 'c') { return strctonum(str, num); }
151
152 if (str[1] == 'x') { return strxtonum(str, num); }
153 }
154
155 size_t i = 0;
156
157 SN sign = 1;
158 while (str[i] == '-' || str[i] == '+') {
159 if (str[i] == '-') { sign *= static_cast<SN>(-1); }
160
161 ++i;
162 if (i == str.size()) { return false; }
163 }
164
165 num = 0;
166 while (str[i] >= '0' && str[i] <= '9') {
167 if (mul_overflow(num, decimal_base, num)) { return false; }
168 if (add_overflow(num, sign * (str[i] - '0'), num)) { return false; }
169
170 ++i;
171 if (i == str.size()) { return true; }
172 }
173
174 return false;
175 }
176
177 // (+* 12) | (0b00...) | (0c00...) | (0x00...)
179 template<mstd::unsigned_integral UN>
180 #else
181 template<class UN, std::enable_if_t<mstd::is_unsigned_integral_v<UN>, bool> = true>
182 #endif
183 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtounum(const std::string_view str, UN& num) {
185
186 if (str.empty()) { return false; }
187
188 if (str.size() > 2 && str[0] == '0') {
189 if (str[1] == 'b') { return strbtonum(str, num); }
190
191 if (str[1] == 'c') { return strctonum(str, num); }
192
193 if (str[1] == 'x') { return strxtonum(str, num); }
194 }
195
196 size_t i = 0;
197 while (str[i] == '+') {
198 ++i;
199 if (i == str.size()) { return false; }
200 }
201
202 num = 0;
203 while (str[i] >= '0' && str[i] <= '9') {
204 if (mul_overflow(num, decimal_base, num)) { return false; }
205 if (add_overflow(num, str[i] - '0', num)) { return false; }
206
207 ++i;
208 if (i == str.size()) { return true; }
209 }
210
211 return false;
212 }
213
214 // ((+|-)* 12.22)
216 template<mstd::floating_point FP>
217 #else
218 template<class FP, std::enable_if_t<std::is_floating_point_v<FP>, bool> = true>
219 #endif
220 _MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtofp(const std::string_view str, FP& num) {
221 _MSTD_CONSTEXPR17 const double decimal_mul = 0.1;
223
224 if (str.empty()) { return false; }
225
226 size_t i = 0;
227
228 FP sign = 1;
229 while (str[i] == '-' || str[i] == '+') {
230 if (str[i] == '-') { sign *= static_cast<FP>(-1); }
231
232 ++i;
233 if (i == str.size()) { return false; }
234 }
235
236 num = 0;
237
238 while (str[i] >= '0' && str[i] <= '9') {
239 num *= decimal_base;
240 num += str[i] - '0';
241
242 ++i;
243 if (i == str.size()) {
244 num *= sign;
245 return true;
246 }
247 }
248
249 if (str[i] == '.') {
250 ++i;
251 if (i == str.size()) { return false; }
252
253 FP decimal = static_cast<FP>(decimal_mul);
254 while (str[i] >= '0' && str[i] <= '9') {
255 num += decimal * (str[i] - '0');
256 decimal *= static_cast<FP>(decimal_mul);
257
258 ++i;
259 if (i == str.size()) {
260 num *= sign;
261 return true;
262 }
263 }
264 }
265
266 return false;
267 }
268} // namespace mstd
269
270 #endif
271#endif
#define _MSTD_HAS_CXX17
Definition config.hpp:45
#define _MSTD_CONSTEXPR17
Definition config.hpp:76
#define _MSTD_HAS_CXX20
Definition config.hpp:52
#define _MSTD_INLINE17
Definition config.hpp:83
#define _MSTD_CONSTEXPR20
Definition config.hpp:84
Definition arithmetic_types.hpp:23
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtounum(const std::string_view str, UN &num)
Definition strtonum.hpp:183
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strxtonum(const std::string_view hexStr, N &num)
Definition strtonum.hpp:30
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strbtonum(const std::string_view binStr, N &num)
Definition strtonum.hpp:110
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strctonum(const std::string_view octStr, N &num)
Definition strtonum.hpp:76
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtofp(const std::string_view str, FP &num)
Definition strtonum.hpp:220
_MSTD_INLINE17 _MSTD_CONSTEXPR20 bool strtonum(const std::string_view str, SN &num)
Definition strtonum.hpp:142