Skylicht Engine
Loading...
Searching...
No Matches
fast_atof.h
1// Copyright (C) 2002-2012 Nikolaus Gebhardt
2// This file is part of the "Irrlicht Engine" and the "irrXML" project.
3// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
4
5#ifndef __FAST_ATOF_H_INCLUDED__
6#define __FAST_ATOF_H_INCLUDED__
7
8#include "irrMath.h"
9#include "irrString.h"
10
11namespace irr
12{
13namespace core
14{
16 // TODO: This should probably also be used in irr::core::string, but
17 // the float-to-string code used there has to be rewritten first.
18 IRRLICHT_API extern irr::core::stringc LOCALE_DECIMAL_POINTS;
19
20// we write [17] here instead of [] to work around a swig bug
21const float fast_atof_table[17] = {
22 0.f,
23 0.1f,
24 0.01f,
25 0.001f,
26 0.0001f,
27 0.00001f,
28 0.000001f,
29 0.0000001f,
30 0.00000001f,
31 0.000000001f,
32 0.0000000001f,
33 0.00000000001f,
34 0.000000000001f,
35 0.0000000000001f,
36 0.00000000000001f,
37 0.000000000000001f,
38 0.0000000000000001f
39};
40
42
49inline u32 strtoul10(const char* in, const char** out=0)
50{
51 if (!in)
52 {
53 if (out)
54 *out = in;
55 return 0;
56 }
57
58 bool overflow=false;
59 u32 unsignedValue = 0;
60 while ( ( *in >= '0') && ( *in <= '9' ))
61 {
62 const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' );
63 if (tmp<unsignedValue)
64 {
65 unsignedValue=(u32)0xffffffff;
66 overflow=true;
67 }
68 if (!overflow)
69 unsignedValue = tmp;
70 ++in;
71 }
72
73 if (out)
74 *out = in;
75
76 return unsignedValue;
77}
78
80
89inline s32 strtol10(const char* in, const char** out=0)
90{
91 if (!in)
92 {
93 if (out)
94 *out = in;
95 return 0;
96 }
97
98 const bool negative = ('-' == *in);
99 if (negative || ('+' == *in))
100 ++in;
101
102 const u32 unsignedValue = strtoul10(in,out);
103 if (unsignedValue > (u32)INT_MAX)
104 {
105 if (negative)
106 return (s32)INT_MIN;
107 else
108 return (s32)INT_MAX;
109 }
110 else
111 {
112 if (negative)
113 return -((s32)unsignedValue);
114 else
115 return (s32)unsignedValue;
116 }
117}
118
120
125inline u32 ctoul16(char in)
126{
127 if (in >= '0' && in <= '9')
128 return in - '0';
129 else if (in >= 'a' && in <= 'f')
130 return 10u + in - 'a';
131 else if (in >= 'A' && in <= 'F')
132 return 10u + in - 'A';
133 else
134 return 0xffffffff;
135}
136
138
146inline u32 strtoul16(const char* in, const char** out=0)
147{
148 if (!in)
149 {
150 if (out)
151 *out = in;
152 return 0;
153 }
154
155 bool overflow=false;
156 u32 unsignedValue = 0;
157 while (true)
158 {
159 u32 tmp = 0;
160 if ((*in >= '0') && (*in <= '9'))
161 tmp = (unsignedValue << 4u) + (*in - '0');
162 else if ((*in >= 'A') && (*in <= 'F'))
163 tmp = (unsignedValue << 4u) + (*in - 'A') + 10;
164 else if ((*in >= 'a') && (*in <= 'f'))
165 tmp = (unsignedValue << 4u) + (*in - 'a') + 10;
166 else
167 break;
168 if (tmp<unsignedValue)
169 {
170 unsignedValue=(u32)INT_MAX;
171 overflow=true;
172 }
173 if (!overflow)
174 unsignedValue = tmp;
175 ++in;
176 }
177
178 if (out)
179 *out = in;
180
181 return unsignedValue;
182}
183
185
193inline u32 strtoul8(const char* in, const char** out=0)
194{
195 if (!in)
196 {
197 if (out)
198 *out = in;
199 return 0;
200 }
201
202 bool overflow=false;
203 u32 unsignedValue = 0;
204 while (true)
205 {
206 u32 tmp = 0;
207 if ((*in >= '0') && (*in <= '7'))
208 tmp = (unsignedValue << 3u) + (*in - '0');
209 else
210 break;
211 if (tmp<unsignedValue)
212 {
213 unsignedValue=(u32)INT_MAX;
214 overflow=true;
215 }
216 if (!overflow)
217 unsignedValue = tmp;
218 ++in;
219 }
220
221 if (out)
222 *out = in;
223
224 return unsignedValue;
225}
226
228
236inline u32 strtoul_prefix(const char* in, const char** out=0)
237{
238 if (!in)
239 {
240 if (out)
241 *out = in;
242 return 0;
243 }
244 if ('0'==in[0])
245 return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out));
246 return strtoul10(in,out);
247}
248
250
258inline f32 strtof10(const char* in, const char** out = 0)
259{
260 if (!in)
261 {
262 if (out)
263 *out = in;
264 return 0.f;
265 }
266
267 const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
268 u32 intValue = 0;
269
270 // Use integer arithmetic for as long as possible, for speed
271 // and precision.
272 while ( ( *in >= '0') && ( *in <= '9' ) )
273 {
274 // If it looks like we're going to overflow, bail out
275 // now and start using floating point.
276 if (intValue >= MAX_SAFE_U32_VALUE)
277 break;
278
279 intValue = (intValue * 10) + (*in - '0');
280 ++in;
281 }
282
283 f32 floatValue = (f32)intValue;
284
285 // If there are any digits left to parse, then we need to use
286 // floating point arithmetic from here.
287 while ( ( *in >= '0') && ( *in <= '9' ) )
288 {
289 floatValue = (floatValue * 10.f) + (f32)(*in - '0');
290 ++in;
291 if (floatValue > FLT_MAX) // Just give up.
292 break;
293 }
294
295 if (out)
296 *out = in;
297
298 return floatValue;
299}
300
302
309inline const char* fast_atof_move(const char* in, f32& result)
310{
311 // Please run the regression test when making any modifications to this function.
312
313 result = 0.f;
314 if (!in)
315 return 0;
316
317 const bool negative = ('-' == *in);
318 if (negative || ('+'==*in))
319 ++in;
320
321 f32 value = strtof10(in, &in);
322
323 if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
324 {
325 const char* afterDecimal = ++in;
326 const f32 decimal = strtof10(in, &afterDecimal);
327 value += decimal * fast_atof_table[afterDecimal - in];
328 in = afterDecimal;
329 }
330
331 if ('e' == *in || 'E' == *in)
332 {
333 ++in;
334 // Assume that the exponent is a whole number.
335 // strtol10() will deal with both + and - signs,
336 // but calculate as f32 to prevent overflow at FLT_MAX
337 value *= powf(10.f, (f32)strtol10(in, &in));
338 }
339
340 result = negative?-value:value;
341 return in;
342}
343
345
350inline float fast_atof(const char* floatAsString, const char** out=0)
351{
352 float ret;
353 if (out)
354 *out=fast_atof_move(floatAsString, ret);
355 else
356 fast_atof_move(floatAsString, ret);
357 return ret;
358}
359
360} // end namespace core
361} // end namespace irr
362
363#endif
364
Basic classes such as vectors, planes, arrays, lists, and so on can be found in this namespace.
Definition aabbox3d.h:15
u32 strtoul8(const char *in, const char **out=0)
Convert a simple string of base 8 digits into an unsigned 32 bit integer.
Definition fast_atof.h:193
f32 strtof10(const char *in, const char **out=0)
Converts a sequence of digits into a whole positive floating point value.
Definition fast_atof.h:258
const char * fast_atof_move(const char *in, f32 &result)
Provides a fast function for converting a string into a float.
Definition fast_atof.h:309
s32 strtol10(const char *in, const char **out=0)
Convert a simple string of base 10 digits into a signed 32 bit integer.
Definition fast_atof.h:89
u32 ctoul16(char in)
Convert a hex-encoded character to an unsigned integer.
Definition fast_atof.h:125
u32 strtoul16(const char *in, const char **out=0)
Convert a simple string of base 16 digits into an unsigned 32 bit integer.
Definition fast_atof.h:146
IRRLICHT_API irr::core::stringc LOCALE_DECIMAL_POINTS
Selection of characters which count as decimal point in fast_atof.
u32 strtoul_prefix(const char *in, const char **out=0)
Convert a C-style prefixed string (hex, oct, integer) into an unsigned 32 bit integer.
Definition fast_atof.h:236
string< c8 > stringc
Typedef for character strings.
Definition irrString.h:1373
u32 strtoul10(const char *in, const char **out=0)
Convert a simple string of base 10 digits into an unsigned 32 bit integer.
Definition fast_atof.h:49
float fast_atof(const char *floatAsString, const char **out=0)
Convert a string to a floating point number.
Definition fast_atof.h:350
Everything in the Irrlicht Engine can be found in this namespace.
Definition Skylicht.h:33
float f32
32 bit floating point variable.
Definition irrTypes.h:104
unsigned int u32
32 bit unsigned variable.
Definition irrTypes.h:58
signed int s32
32 bit signed variable.
Definition irrTypes.h:66