Irrlicht 3D Engine
fast_atof.h
Go to the documentation of this file.
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 
11 namespace irr
12 {
13 namespace 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.
19 
20 #define IRR_ATOF_TABLE_SIZE 17
21 // we write [IRR_ATOF_TABLE_SIZE] here instead of [] to work around a swig bug
22 const float fast_atof_table[17] = {
23  0.f,
24  0.1f,
25  0.01f,
26  0.001f,
27  0.0001f,
28  0.00001f,
29  0.000001f,
30  0.0000001f,
31  0.00000001f,
32  0.000000001f,
33  0.0000000001f,
34  0.00000000001f,
35  0.000000000001f,
36  0.0000000000001f,
37  0.00000000000001f,
38  0.000000000000001f,
39  0.0000000000000001f
40 };
41 
43 
50 inline u32 strtoul10(const char* in, const char** out=0)
51 {
52  if (!in)
53  {
54  if (out)
55  *out = in;
56  return 0;
57  }
58 
59  bool overflow=false;
60  u32 unsignedValue = 0;
61  while ( ( *in >= '0') && ( *in <= '9' ))
62  {
63  const u32 tmp = ( unsignedValue * 10 ) + ( *in - '0' );
64  if (tmp<unsignedValue)
65  {
66  unsignedValue=(u32)0xffffffff;
67  overflow=true;
68  }
69  if (!overflow)
70  unsignedValue = tmp;
71  ++in;
72  }
73 
74  if (out)
75  *out = in;
76 
77  return unsignedValue;
78 }
79 
81 
90 inline s32 strtol10(const char* in, const char** out=0)
91 {
92  if (!in)
93  {
94  if (out)
95  *out = in;
96  return 0;
97  }
98 
99  const bool negative = ('-' == *in);
100  if (negative || ('+' == *in))
101  ++in;
102 
103  const u32 unsignedValue = strtoul10(in,out);
104  if (unsignedValue > (u32)INT_MAX)
105  {
106  if (negative)
107  return (s32)INT_MIN;
108  else
109  return (s32)INT_MAX;
110  }
111  else
112  {
113  if (negative)
114  return -((s32)unsignedValue);
115  else
116  return (s32)unsignedValue;
117  }
118 }
119 
121 
126 inline u32 ctoul16(char in)
127 {
128  if (in >= '0' && in <= '9')
129  return in - '0';
130  else if (in >= 'a' && in <= 'f')
131  return 10u + in - 'a';
132  else if (in >= 'A' && in <= 'F')
133  return 10u + in - 'A';
134  else
135  return 0xffffffff;
136 }
137 
139 
147 inline u32 strtoul16(const char* in, const char** out=0)
148 {
149  if (!in)
150  {
151  if (out)
152  *out = in;
153  return 0;
154  }
155 
156  bool overflow=false;
157  u32 unsignedValue = 0;
158  while (true)
159  {
160  u32 tmp = 0;
161  if ((*in >= '0') && (*in <= '9'))
162  tmp = (unsignedValue << 4u) + (*in - '0');
163  else if ((*in >= 'A') && (*in <= 'F'))
164  tmp = (unsignedValue << 4u) + (*in - 'A') + 10;
165  else if ((*in >= 'a') && (*in <= 'f'))
166  tmp = (unsignedValue << 4u) + (*in - 'a') + 10;
167  else
168  break;
169  if (tmp<unsignedValue)
170  {
171  unsignedValue=(u32)INT_MAX;
172  overflow=true;
173  }
174  if (!overflow)
175  unsignedValue = tmp;
176  ++in;
177  }
178 
179  if (out)
180  *out = in;
181 
182  return unsignedValue;
183 }
184 
186 
194 inline u32 strtoul8(const char* in, const char** out=0)
195 {
196  if (!in)
197  {
198  if (out)
199  *out = in;
200  return 0;
201  }
202 
203  bool overflow=false;
204  u32 unsignedValue = 0;
205  while (true)
206  {
207  u32 tmp = 0;
208  if ((*in >= '0') && (*in <= '7'))
209  tmp = (unsignedValue << 3u) + (*in - '0');
210  else
211  break;
212  if (tmp<unsignedValue)
213  {
214  unsignedValue=(u32)INT_MAX;
215  overflow=true;
216  }
217  if (!overflow)
218  unsignedValue = tmp;
219  ++in;
220  }
221 
222  if (out)
223  *out = in;
224 
225  return unsignedValue;
226 }
227 
229 
237 inline u32 strtoul_prefix(const char* in, const char** out=0)
238 {
239  if (!in)
240  {
241  if (out)
242  *out = in;
243  return 0;
244  }
245  if ('0'==in[0])
246  return ('x'==in[1] ? strtoul16(in+2,out) : strtoul8(in+1,out));
247  return strtoul10(in,out);
248 }
249 
251 
259 inline f32 strtof10(const char* in, const char** out = 0)
260 {
261  if (!in)
262  {
263  if (out)
264  *out = in;
265  return 0.f;
266  }
267 
268  const u32 MAX_SAFE_U32_VALUE = UINT_MAX / 10 - 10;
269  u32 intValue = 0;
270 
271  // Use integer arithmetic for as long as possible, for speed
272  // and precision.
273  while ( ( *in >= '0') && ( *in <= '9' ) )
274  {
275  // If it looks like we're going to overflow, bail out
276  // now and start using floating point.
277  if (intValue >= MAX_SAFE_U32_VALUE)
278  break;
279 
280  intValue = (intValue * 10) + (*in - '0');
281  ++in;
282  }
283 
284  f32 floatValue = (f32)intValue;
285 
286  // If there are any digits left to parse, then we need to use
287  // floating point arithmetic from here.
288  while ( ( *in >= '0') && ( *in <= '9' ) )
289  {
290  floatValue = (floatValue * 10.f) + (f32)(*in - '0');
291  ++in;
292  if (floatValue > FLT_MAX) // Just give up.
293  break;
294  }
295 
296  if (out)
297  *out = in;
298 
299  return floatValue;
300 }
301 
303 
310 inline const char* fast_atof_move(const char* in, f32& result)
311 {
312  // Please run the regression test when making any modifications to this function.
313 
314  result = 0.f;
315  if (!in)
316  return 0;
317 
318  const bool negative = ('-' == *in);
319  if (negative || ('+'==*in))
320  ++in;
321 
322  f32 value = strtof10(in, &in);
323 
324  if ( LOCALE_DECIMAL_POINTS.findFirst(*in) >= 0 )
325  {
326  const char* afterDecimal = ++in;
327  f32 decimal = strtof10(in, &afterDecimal);
328  size_t numDecimals = afterDecimal - in;
329  if (numDecimals < IRR_ATOF_TABLE_SIZE)
330  {
331  value += decimal * fast_atof_table[numDecimals];
332  }
333  else
334  {
335  value += decimal * (f32)pow(10.f, -(float)numDecimals);
336  }
337  in = afterDecimal;
338  }
339 
340  if ('e' == *in || 'E' == *in)
341  {
342  ++in;
343  // Assume that the exponent is a whole number.
344  // strtol10() will deal with both + and - signs,
345  // but calculate as f32 to prevent overflow at FLT_MAX
346  // Using pow with float cast instead of powf as otherwise accuracy decreases.
347  value *= (f32)pow(10.f, (f32)strtol10(in, &in));
348  }
349 
350  result = negative?-value:value;
351  return in;
352 }
353 
355 
360 inline float fast_atof(const char* floatAsString, const char** out=0)
361 {
362  float ret;
363  if (out)
364  *out=fast_atof_move(floatAsString, ret);
365  else
366  fast_atof_move(floatAsString, ret);
367  return ret;
368 }
369 
370 } // end namespace core
371 } // end namespace irr
372 
373 #endif
374 
float fast_atof(const char *floatAsString, const char **out=0)
Convert a string to a floating point number.
Definition: fast_atof.h:360
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:310
float f32
32 bit floating point variable.
Definition: irrTypes.h:108
#define IRRLICHT_API
Set FPU settings.
Everything in the Irrlicht Engine can be found in this namespace.
Definition: aabbox3d.h:12
#define IRR_ATOF_TABLE_SIZE
Definition: fast_atof.h:20
Very simple string class with some useful features.
Definition: irrString.h:37
s32 findFirst(T c) const
finds first occurrence of character in string
Definition: irrString.h:775
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:50
signed int s32
32 bit signed variable.
Definition: irrTypes.h:70
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:237
unsigned int u32
32 bit unsigned variable.
Definition: irrTypes.h:62
#define FLT_MAX
Definition: irrMath.h:31
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:194
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:259
const float fast_atof_table[17]
Definition: fast_atof.h:22
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:147
u32 ctoul16(char in)
Convert a hex-encoded character to an unsigned integer.
Definition: fast_atof.h:126
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:90
IRRLICHT_API irr::core::stringc LOCALE_DECIMAL_POINTS
Selection of characters which count as decimal point in fast_atof.