API Documentation
Loading...
Searching...
No Matches
NumberParser.hpp
Go to the documentation of this file.
1/**--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: NumberParser
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/BaseValues.h>
34#include <NDEVR/Angle.h>
35#include <cmath>
36namespace NDEVR
37{
38 const fltp08 fast_atof_table[20] = {
39 0.0,
40 0.1,
41 0.01,
42 0.001,
43 0.0001,
44 0.00001,
45 0.000001,
46 0.0000001,
47 0.00000001,
48 0.000000001,
49 0.0000000001,
50 0.00000000001,
51 0.000000000001,
52 0.0000000000001,
53 0.00000000000001,
54 0.000000000000001,
55 0.0000000000000001,
56 0.00000000000000001,
57 0.000000000000000001,
58 0.0000000000000000001,
59 };
60
61 template<class t_type>
62 constexpr uint04 maxDigits();
63
64 template<> constexpr uint04 maxDigits<uint01>() { return 3; }
65 template<> constexpr uint04 maxDigits<sint01>() { return 3; }
66
67 template<> constexpr uint04 maxDigits<uint02>() { return 5; }
68 template<> constexpr uint04 maxDigits<sint02>() { return 5; }
69
70 template<> constexpr uint04 maxDigits<uint04>() { return 10; }
71 template<> constexpr uint04 maxDigits<sint04>() { return 10; }
72
73 template<> constexpr uint04 maxDigits<sint08>() { return 19; }
74 template<> constexpr uint04 maxDigits<uint08>() { return 20; }
75
77 {
78 public:
79 template<class t_type>
80 static t_type _parse(const char* in, const char** out, t_type NaN_Value, bool check_overflow);
81
82 template<class t_type>
83 static t_type parse(const char* in, const char** out = nullptr, t_type NaN_Value = Constant<t_type>::NaN, bool check_overflow = true)
84 {
85 return _parse<t_type>(in, out, NaN_Value, check_overflow);
86 }
87 template<class t_type>
88 static constexpr t_type parseUInt(const char* in, const char** out, t_type NaN_Value, bool check_overflow)
89 {
90 if (*in < '0' || *in > '9')
91 {
92 if (out) *out = in;
93 return NaN_Value;
94 }
95 t_type value = 0;
96 for (uint04 i = 0; i < maxDigits<t_type>() - 1; i++)
97 {
98 if (*in < '0' || *in > '9')
99 {
100 check_overflow = false;
101 break;
102 }
103 value = (value * 10) + cast<t_type>(*in - '0');
104 ++in;
105 }
106 if (check_overflow)
107 {
108 if (*in >= '0' && *in <= '9')//read in last digit
109 {
110 t_type new_value = (value * 10) + (*in - '0');
111 ++in;
112 if (new_value < value)
113 {
114 value = NaN_Value;
115 }
116 else
117 {
118 value = new_value;
119 if (*in > '0' && *in < '9')
120 value = NaN_Value;
121 }
122 }
123 }
124 if (out)
125 *out = in;
126 return value;
127 }
128 // Number of relevant decimals for floating-point parsing.
129 template <class t_int_type, typename t_type>
130 static t_type parseFloat(const char* c, const char** out_s, t_type NaN_Value, bool check_overflow)
131 {
132 if (c == nullptr)
133 {
134 if (out_s)
135 *out_s = c;
136 return NaN_Value;
137 }
138 bool inv = (*c == '-');
139 if (inv || *c == '+')
140 ++c;
141 t_int_type value = 0;
142 if(*c != '.')
143 value = parse<t_int_type>(c, &c, Constant<t_int_type>::NaN, check_overflow);
144 if (isNaN(value))
145 {
146 if (out_s)
147 *out_s = c;
148 return NaN_Value;
149 }
150 t_type float_value = cast<t_type>(value);
151 if (*c == '.')
152 {
153 ++c;
154 const char* c_old = c;
156 if (!isNaN(value))
157 {
158 fltp08 pl = cast<fltp08>(value);
159 uint04 size = cast<uint04>(c - c_old);
160 pl *= fast_atof_table[size];
161 float_value += cast<t_type>(pl);
162 while (*c >= '0' && *c <= '9')//read in leftover
163 c++;
164 }
165 }
166 if (*c == 'e' || *c == 'E')
167 {
168 ++c;
169 float_value *= cast<t_type>(std::pow(cast<t_type>(10.0), parse<sint02>(c, &c, Constant<sint02>::NaN, check_overflow)));
170 }
171 if(out_s)
172 *out_s = c;
173 if (inv)
174 float_value = -float_value;
175 return float_value;
176 }
177
178
179
180
181
182 template<>
183 static inline uint01 _parse(const char* in, const char** out, uint01 NaN_Value, bool check_overflow)
184 {
185 if (*in == '+') in++;
186 return parseUInt(in, out, NaN_Value, check_overflow);
187 }
188 template<>
189 static inline uint02 _parse(const char* in, const char** out, uint02 NaN_Value, bool check_overflow)
190 {
191 if (*in == '+') in++;
192 return parseUInt(in, out, NaN_Value, check_overflow);
193 }
194 template<>
195 static inline uint04 _parse(const char* in, const char** out, uint04 NaN_Value, bool check_overflow)
196 {
197 if (*in == '+') in++;
198 return parseUInt(in, out, NaN_Value, check_overflow);
199 }
200 template<>
201 static inline uint08 _parse(const char* in, const char** out, uint08 NaN_Value, bool check_overflow)
202 {
203 if (*in == '+') in++;
204 return parseUInt(in, out, NaN_Value, check_overflow);
205 }
206 template<>
207 static inline sint01 _parse(const char* in, const char** out, sint01 NaN_Value, bool check_overflow)
208 {
209 bool inv = (*in == '-');
210 if (inv || *in == '+')
211 ++in;
212 sint01 value = parseUInt<sint01>(in, out, Constant<sint01>::NaN, check_overflow);
213 if (isNaN(value))
214 return NaN_Value;
215 return inv ? -value : value;
216 }
217 template<>
218 static inline sint02 _parse(const char* in, const char** out, sint02 NaN_Value, bool check_overflow)
219 {
220 bool inv = (*in == '-');
221 if (inv || *in == '+')
222 ++in;
223 sint02 value = parseUInt<sint02>(in, out, Constant<sint02>::NaN, check_overflow);
224 if (isNaN(value))
225 return NaN_Value;
226 return inv ? -value : value;
227 }
228
229 template<>
230 static inline sint04 _parse(const char* in, const char** out, sint04 NaN_Value, bool check_overflow)
231 {
232 bool inv = (*in == '-');
233 if (inv || *in == '+')
234 ++in;
235 sint04 value = parseUInt<sint04>(in, out, Constant<sint04>::NaN, check_overflow);
236 if (isNaN(value))
237 return NaN_Value;
238 return inv ? -value : value;
239 }
240
241 template<>
242 static inline sint08 _parse(const char* in, const char** out, sint08 NaN_Value, bool check_overflow)
243 {
244 bool inv = (*in == '-');
245 if (inv || *in == '+')
246 ++in;
247 sint08 value = parseUInt<sint08>(in, out, Constant<sint08>::NaN, check_overflow);
248 if (isNaN(value))
249 return NaN_Value;
250 if (inv)
251 value = -value;
252 return value;
253 }
254
255 // ------------------------------------------------------------------------------------
256 // The same but more human.
257 template<>
258 static inline fltp04 _parse(const char* in, const char** out, fltp04 NaN_Value, bool check_overflow)
259 {
260 return parseFloat<uint04, fltp04>(in, out, NaN_Value, check_overflow);
261 }
262
263 template<>
264 static inline fltp08 _parse(const char* in, const char** out, fltp08 NaN_Value, bool check_overflow)
265 {
266 return parseFloat<uint08, fltp08>(in, out, NaN_Value, check_overflow);
267 }
268 // ------------------------------------------------------------------------------------
269 // Convert a string in octal format to a number
270 // ------------------------------------------------------------------------------------
271 static inline uint04 parseOctal(const char* in, const char** out = nullptr)
272 {
273 uint04 value = 0;
274 for (;;)
275 {
276 if (*in < '0' || *in > '7')
277 break;
278 value = (value << 3) + (*in - '0');
279 ++in;
280 }
281 if (out)*out = in;
282 return value;
283 }
284
285 // ------------------------------------------------------------------------------------
286 // Convert a string in hex format to a number
287 // ------------------------------------------------------------------------------------
288 static inline uint04 parseHex(const char* in, const char** out = nullptr)
289 {
290 uint04 value = 0;
291 for (;;)
292 {
293 if (*in >= '0' && *in <= '9')
294 value = (value << 4u) + (*in - '0');
295 else if (*in >= 'A' && *in <= 'F')
296 value = (value << 4u) + (*in - 'A') + 10;
297 else if (*in >= 'a' && *in <= 'f')
298 value = (value << 4u) + (*in - 'a') + 10;
299 else
300 break;
301 ++in;
302 }
303 if (out)*out = in;
304 return value;
305 }
306
307 // ------------------------------------------------------------------------------------
308 // Convert just one hex digit
309 // Return value is null if the input character is not a hex digit.
310 // ------------------------------------------------------------------------------------
311 template<class t_char_type>
312 static inline uint04 HexDigitToDecimal(t_char_type in)
313 {
315 if (in >= '0' && in <= '9')
316 out = in - '0';
317 else if (in >= 'a' && in <= 'f')
318 out = 10u + in - 'a';
319 else if (in >= 'A' && in <= 'F')
320 out = 10u + in - 'A';
321 return out;
322 }
323
324 // ------------------------------------------------------------------------------------
325 // Convert a hex-encoded octet (2 characters, i.e. df or 1a).
326 // ------------------------------------------------------------------------------------
327 template<class t_char_type>
328 static inline uint01 HexOctetToDecimal(const t_char_type* in)
329 {
330 return (cast<uint01>(HexDigitToDecimal(in[0])) << 4) + cast<uint01>(HexDigitToDecimal(in[1]));
331 }
332
333 // ------------------------------------------------------------------------------------
334 // Parse a C++-like integer literal - hex and oct prefixes.
335 // 0xNNNN - hex
336 // 0NNN - oct
337 // NNN - dec
338 // ------------------------------------------------------------------------------------
339 template<class t_char_type>
340 static uint04 strtoul_cppstyle(const t_char_type* in, const t_char_type** out = nullptr)
341 {
342 if ('0' == in[0])
343 {
344 return 'x' == in[1] ? strtoul16(in + 2, out) : strtoul8(in + 1, out);
345 }
346 return strtoul10(in, out);
347 }
348 template<>
349 static inline Angle<sint04> _parse(const char* in, const char** out, Angle<sint04> NaN_Value, bool check_overflow)
350 {
351 return Angle<sint04>(NumberParser::_parse<sint04>(in, out, NaN_Value.internal<false>(), check_overflow));
352 }
353 template<>
354 static inline Angle<fltp08> _parse(const char* in, const char** out, Angle<fltp08> NaN_Value, bool check_overflow)
355 {
356 return Angle<fltp08>(NumberParser::_parse<fltp08>(in, out, NaN_Value.internal<false>(), check_overflow));
357 }
358 template<>
359 static inline Angle<fltp04> _parse(const char* in, const char** out, Angle<fltp04> NaN_Value, bool check_overflow)
360 {
361 return Angle<fltp04>(NumberParser::_parse<fltp04>(in, out, NaN_Value.internal<false>(), check_overflow));
362 }
363 };
364};//End namespace NDEVR
Stores an angle in an optimized format.
Definition StringStream.h:352
constexpr t_type internal() const
Definition Angle.h:313
Definition NumberParser.hpp:77
static sint02 _parse(const char *in, const char **out, sint02 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:218
static fltp08 _parse(const char *in, const char **out, fltp08 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:264
static t_type parse(const char *in, const char **out=nullptr, t_type NaN_Value=Constant< t_type >::NaN, bool check_overflow=true)
Definition NumberParser.hpp:83
static sint01 _parse(const char *in, const char **out, sint01 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:207
static uint01 _parse(const char *in, const char **out, uint01 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:183
static Angle< fltp04 > _parse(const char *in, const char **out, Angle< fltp04 > NaN_Value, bool check_overflow)
Definition NumberParser.hpp:359
static uint04 _parse(const char *in, const char **out, uint04 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:195
static Angle< sint04 > _parse(const char *in, const char **out, Angle< sint04 > NaN_Value, bool check_overflow)
Definition NumberParser.hpp:349
static uint02 _parse(const char *in, const char **out, uint02 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:189
static uint08 _parse(const char *in, const char **out, uint08 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:201
static sint08 _parse(const char *in, const char **out, sint08 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:242
static uint04 strtoul_cppstyle(const t_char_type *in, const t_char_type **out=nullptr)
Definition NumberParser.hpp:340
static t_type parseFloat(const char *c, const char **out_s, t_type NaN_Value, bool check_overflow)
Definition NumberParser.hpp:130
static sint04 _parse(const char *in, const char **out, sint04 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:230
static uint01 HexOctetToDecimal(const t_char_type *in)
Definition NumberParser.hpp:328
static uint04 HexDigitToDecimal(t_char_type in)
Definition NumberParser.hpp:312
static uint04 parseHex(const char *in, const char **out=nullptr)
Definition NumberParser.hpp:288
static t_type _parse(const char *in, const char **out, t_type NaN_Value, bool check_overflow)
static uint04 parseOctal(const char *in, const char **out=nullptr)
Definition NumberParser.hpp:271
static constexpr t_type parseUInt(const char *in, const char **out, t_type NaN_Value, bool check_overflow)
Definition NumberParser.hpp:88
static fltp04 _parse(const char *in, const char **out, fltp04 NaN_Value, bool check_overflow)
Definition NumberParser.hpp:258
static Angle< fltp08 > _parse(const char *in, const char **out, Angle< fltp08 > NaN_Value, bool check_overflow)
Definition NumberParser.hpp:354
Definition ACIColor.h:37
int32_t sint04
-Defines an alias representing a 4 byte, signed integer. -Can represent exact integer values -2147483...
Definition BaseValues.hpp:76
int64_t sint08
-Defines an alias representing an 8 byte, signed integer -Can represent exact integer values -9223372...
Definition BaseValues.hpp:86
float fltp04
Defines an alias representing a 4 byte floating-point number.
Definition BaseValues.hpp:157
uint8_t uint01
-Defines an alias representing a 1 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:98
int8_t sint01
-Defines an alias representing a 1 byte, signed integer. -Can represent exact integer values -127 thr...
Definition BaseValues.hpp:56
constexpr uint04 maxDigits< uint04 >()
Definition NumberParser.hpp:70
constexpr uint04 maxDigits< sint04 >()
Definition NumberParser.hpp:71
constexpr uint04 maxDigits< uint02 >()
Definition NumberParser.hpp:67
constexpr uint04 maxDigits< sint02 >()
Definition NumberParser.hpp:68
constexpr uint04 maxDigits< sint08 >()
Definition NumberParser.hpp:73
int16_t sint02
-Defines an alias representing a 2 byte, signed integer. -Can represent exact integer values -32767 t...
Definition BaseValues.hpp:66
constexpr uint04 maxDigits< uint08 >()
Definition NumberParser.hpp:74
uint64_t uint08
-Defines an alias representing an 8 byte, unsigned integer -Can represent exact integer values 0 thro...
Definition BaseValues.hpp:132
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:120
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:514
constexpr uint04 maxDigits< uint01 >()
Definition NumberParser.hpp:64
uint16_t uint02
-Defines an alias representing a 2 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:109
constexpr bool isNaN(const t_type &value)
Query if 'value' is valid or invalid.
Definition BaseFunctions.hpp:200
constexpr uint04 maxDigits()
const fltp08 fast_atof_table[20]
Definition NumberParser.hpp:38
constexpr uint04 maxDigits< sint01 >()
Definition NumberParser.hpp:65
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:181
Definition BaseValues.hpp:272