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 the float-to-string code
17  // used there has to be rewritten first.
19 
20 // we write [17] here instead of [] to work around a swig bug
21 const 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 
49 inline 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 
89 inline 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 
125 inline 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 
146 inline 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 
193 inline 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 
236 inline 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 
258 inline 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 
309 inline 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 
350 inline 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 
float fast_atof(const char *floatAsString, const char **out=0)
Convert a string to a floating point number.
Definition: fast_atof.h:350
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
float f32
32 bit floating point variable.
Definition: irrTypes.h:104
#define IRRLICHT_API
Set FPU settings.
Everything in the Irrlicht Engine can be found in this namespace.
Definition: aabbox3d.h:12
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
signed int s32
32 bit signed variable.
Definition: irrTypes.h:66
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
unsigned int u32
32 bit unsigned variable.
Definition: irrTypes.h:58
#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: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 float fast_atof_table[17]
Definition: fast_atof.h:21
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
u32 ctoul16(char in)
Convert a hex-encoded character to an unsigned integer.
Definition: fast_atof.h:125
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
IRRLICHT_API irr::core::stringc LOCALE_DECIMAL_POINTS
Selection of characters which count as decimal point in fast_atof.