|
55 | 55 | #include <locale> |
56 | 56 | #endif |
57 | 57 |
|
58 | | -// TODO: |
59 | | -// POCO version is fast but simplistic, hence less accurate, undef this for |
60 | | -// double-conversion library use in string => float/double conversions (T.B.D.) |
61 | | -// (double-conversion library is always used for float/double => string) |
62 | | -#define POCO_STR_TO_FLOAT_FAST |
63 | 58 |
|
64 | 59 | #define POCO_MAX_INT_STRING_LEN 65 |
65 | 60 | #define POCO_MAX_FLT_STRING_LEN 128 |
| 61 | +#define POCO_FLT_INF "inf" |
| 62 | +#define POCO_FLT_NAN "nan" |
| 63 | +#define POCO_FLT_EXP 'e' |
66 | 64 |
|
67 | 65 |
|
68 | 66 | namespace Poco { |
@@ -210,173 +208,6 @@ bool strToInt(const std::string& str, I& result, short base, char thSep = ',') |
210 | 208 | { |
211 | 209 | return strToInt(str.c_str(), result, base, thSep); |
212 | 210 | } |
213 | | - |
214 | | - |
215 | | -namespace Impl { |
216 | | - |
217 | | -static char DUMMY_EXP_UNDERFLOW; // dummy default val |
218 | | - |
219 | | -} |
220 | | - |
221 | | - |
222 | | -template <typename F> |
223 | | -bool strToFloat (const char* pStr, F& result, char& eu = Impl::DUMMY_EXP_UNDERFLOW, char decSep = '.', char thSep = ',') |
224 | | - /// Converts zero-terminated array to floating-point number; |
225 | | - /// Returns true if succesful. Exponent underflow (i.e. loss of precision due to exponent value) |
226 | | - /// is signalled in eu. Thousand separators are recognized for the locale |
227 | | - /// and silently skipped but not verified for correct positioning. |
228 | | - /// |
229 | | - /// If parsing was unsuccesful, the return value is false with |
230 | | - /// result and eu values undetermined. |
231 | | - /// This function will perform fast but significant rounding errors may occur after |
232 | | - /// the platform precision is exceeded. |
233 | | - /// For better precision conversion, use double-conversion wrappers (strToFloatDC and strToDoubleDC). |
234 | | -{ |
235 | | -#ifndef POCO_STR_TO_FLOAT_FAST |
236 | | - // TODO: for high-precision, use double-conversion here |
237 | | -#else |
238 | | - poco_assert (decSep != thSep); |
239 | | - |
240 | | - if (pStr == 0 || *pStr == '\0') return false; |
241 | | - |
242 | | - // parser states: |
243 | | - const char STATE_LEADING_SPACES = 0; |
244 | | - const char STATE_DIGITS_BEFORE_DEC_POINT = 1; |
245 | | - const char STATE_DIGITS_AFTER_DEC_POINT = 2; |
246 | | - const char STATE_EXP_CHAR = 3; |
247 | | - const char STATE_EXP_DIGITS = 4; |
248 | | - const char STATE_SUFFIX = 5; // 'f' suffix |
249 | | - |
250 | | - char numSign = 1, expSign = 1; |
251 | | - char state = STATE_LEADING_SPACES; |
252 | | - F mantissa = 0.0, exponent = 0.0, pow10 = 1.0; |
253 | | - |
254 | | - result = 0.0; |
255 | | - eu = 0; |
256 | | - for (; *pStr != '\0'; ++pStr) |
257 | | - { |
258 | | - switch (*pStr) |
259 | | - { |
260 | | - case '.': |
261 | | - if (decSep == '.') |
262 | | - { |
263 | | - if (state >= STATE_DIGITS_AFTER_DEC_POINT) return false; |
264 | | - state = STATE_DIGITS_AFTER_DEC_POINT; |
265 | | - break; |
266 | | - } |
267 | | - else if ((thSep == '.') && (state == STATE_DIGITS_BEFORE_DEC_POINT)) |
268 | | - break; |
269 | | - else |
270 | | - return false; |
271 | | - |
272 | | - case ',': |
273 | | - if (decSep == ',') |
274 | | - { |
275 | | - if (state >= STATE_DIGITS_AFTER_DEC_POINT) return false; |
276 | | - state = STATE_DIGITS_AFTER_DEC_POINT; |
277 | | - break; |
278 | | - } |
279 | | - else if ((thSep == ',') && (state == STATE_DIGITS_BEFORE_DEC_POINT)) |
280 | | - break; |
281 | | - else |
282 | | - return false; |
283 | | - |
284 | | - case ' ': // space (SPC) |
285 | | - if ((thSep == ' ') && (state == STATE_DIGITS_BEFORE_DEC_POINT)) break; |
286 | | - case '\t': // horizontal tab (TAB) |
287 | | - case '\n': // line feed (LF) |
288 | | - case '\v': // vertical tab (VT) |
289 | | - case '\f': // form feed (FF) |
290 | | - case '\r': // carriage return (CR) |
291 | | - if ((state >= STATE_DIGITS_AFTER_DEC_POINT) || (state >= STATE_EXP_DIGITS)) |
292 | | - break; |
293 | | - else if ((state > STATE_LEADING_SPACES) && (state < STATE_DIGITS_AFTER_DEC_POINT)) |
294 | | - return false; |
295 | | - break; |
296 | | - |
297 | | - case '-': |
298 | | - if (state == STATE_LEADING_SPACES) |
299 | | - numSign = -1; |
300 | | - else if (state == STATE_EXP_CHAR) // exponential char |
301 | | - expSign = -1; |
302 | | - else return false; |
303 | | - case '+': |
304 | | - break; |
305 | | - |
306 | | - case '0': |
307 | | - case '1': |
308 | | - case '2': |
309 | | - case '3': |
310 | | - case '4': |
311 | | - case '5': |
312 | | - case '6': |
313 | | - case '7': |
314 | | - case '8': |
315 | | - case '9': |
316 | | - if (state >= STATE_SUFFIX) return false; // constant suffix |
317 | | - if (state <= STATE_DIGITS_BEFORE_DEC_POINT) // integral part digits |
318 | | - { |
319 | | - result = result * 10 + (*pStr - '0'); |
320 | | - state = STATE_DIGITS_BEFORE_DEC_POINT; |
321 | | - } |
322 | | - else if (state <= STATE_DIGITS_AFTER_DEC_POINT) // fractional part digits |
323 | | - { |
324 | | - mantissa += F(*pStr - '0') / (pow10 *= 10.); |
325 | | - state = STATE_DIGITS_AFTER_DEC_POINT; |
326 | | - } |
327 | | - else if (state <= STATE_EXP_DIGITS) // exponent digits |
328 | | - { |
329 | | - exponent = exponent * 10. + (*pStr - '0'); |
330 | | - state = STATE_EXP_DIGITS; |
331 | | - } |
332 | | - else return false; |
333 | | - break; |
334 | | - |
335 | | - case 'E': |
336 | | - case 'e': |
337 | | - if (state > STATE_DIGITS_AFTER_DEC_POINT) return false; |
338 | | - state = STATE_EXP_CHAR; |
339 | | - break; |
340 | | - |
341 | | - case 'F': |
342 | | - case 'f': |
343 | | - state = STATE_SUFFIX; |
344 | | - break; |
345 | | - |
346 | | - default: |
347 | | - return false; |
348 | | - } |
349 | | - } |
350 | | - |
351 | | - if (exponent > std::numeric_limits<F>::max_exponent10) |
352 | | - { |
353 | | - eu = expSign; |
354 | | - exponent = std::numeric_limits<F>::max_exponent10; |
355 | | - } |
356 | | - |
357 | | - result += mantissa; |
358 | | - if (numSign != 1) result *= numSign; |
359 | | - if (exponent > 1.0) |
360 | | - { |
361 | | - F scale = std::pow(10., exponent); |
362 | | - result = (expSign < 0) ? (result / scale) : (result * scale); |
363 | | - } |
364 | | - |
365 | | - return (state != STATE_LEADING_SPACES) && // empty/zero-length string |
366 | | - !FPEnvironment::isInfinite(result) && |
367 | | - !FPEnvironment::isNaN(result); |
368 | | -#endif // POCO_STR_TO_FLOAT_FAST |
369 | | -} |
370 | | - |
371 | | - |
372 | | -template <typename F> |
373 | | -bool strToFloat (const std::string& s, F& result, char& eu = Impl::DUMMY_EXP_UNDERFLOW, char decSep = '.', char thSep = ',') |
374 | | - /// Converts string to floating-point number; |
375 | | - /// This is a wrapper function, for details see see the |
376 | | - /// bool strToFloat(const char*, F&, char&, char, char) implementation. |
377 | | -{ |
378 | | - return strToFloat(s.c_str(), result, eu, decSep, thSep); |
379 | | -} |
380 | 211 |
|
381 | 212 |
|
382 | 213 | // |
@@ -636,12 +467,10 @@ bool uIntToStr (T number, unsigned short base, std::string& result, bool prefix |
636 | 467 |
|
637 | 468 |
|
638 | 469 | // |
639 | | -// Functions using double-conversion library (http://code.google.com/p/double-conversion/). |
640 | | -// Library is the implementation of the Grisu algorithm as described in Florian Loitsch's paper: |
641 | | -// http://florian.loitsch.com/publications/dtoa-pldi2010.pdf |
| 470 | +// Wrappers for double-conversion library (http://code.google.com/p/double-conversion/). |
642 | 471 | // |
643 | | -// For a complete (and simpler) story on floating-point numbers rendering accuracy and performance, see: |
644 | | -// http://www.serpentine.com/blog/2011/06/29/here-be-dragons-advances-in-problems-you-didnt-even-know-you-had/ |
| 472 | +// Library is the implementation of the algorithm described in Florian Loitsch's paper: |
| 473 | +// http://florian.loitsch.com/publications/dtoa-pldi2010.pdf |
645 | 474 | // |
646 | 475 |
|
647 | 476 | Foundation_API void floatToStr(char* buffer, |
@@ -688,12 +517,31 @@ Foundation_API std::string& doubleToStr(std::string& str, |
688 | 517 | /// precision (total number of digits after the decimal point) and width (total length of formatted string). |
689 | 518 |
|
690 | 519 |
|
691 | | -Foundation_API float strToFloatDC(const char* str); |
692 | | - /// For testing and performance comparison purposes only. |
| 520 | +Foundation_API float strToFloat(const char* str); |
| 521 | + /// Converts the string of characters into single-precision floating point number. |
| 522 | + /// Function uses double_convesrion::DoubleToStringConverter to do the conversion. |
| 523 | + |
| 524 | + |
| 525 | +Foundation_API bool strToFloat(const std::string&, float& result, char decSep = '.', char thSep = ','); |
| 526 | + /// Converts the string of characters into single-precision floating point number. |
| 527 | + /// The conversion result is assigned to the result parameter. |
| 528 | + /// If decimal separator and/or thousand separator are different from defaults, they should be |
| 529 | + /// supplied to ensure proper conversion. |
| 530 | + /// |
| 531 | + /// Returns true if succesful, false otherwise. |
| 532 | + |
| 533 | + |
| 534 | +Foundation_API double strToDouble(const char* str); |
| 535 | + /// Converts the string of characters into double-precision floating point number. |
693 | 536 |
|
694 | 537 |
|
695 | | -Foundation_API double strToDoubleDC(const char* str); |
696 | | - /// For testing and performance comparison purposes only. |
| 538 | +Foundation_API bool strToDouble(const std::string& str, double& result, char decSep = '.', char thSep = ','); |
| 539 | + /// Converts the string of characters into double-precision floating point number. |
| 540 | + /// The conversion result is assigned to the result parameter. |
| 541 | + /// If decimal separator and/or thousand separator are different from defaults, they should be |
| 542 | + /// supplied to ensure proper conversion. |
| 543 | + /// |
| 544 | + /// Returns true if succesful, false otherwise. |
697 | 545 |
|
698 | 546 | // |
699 | 547 | // end double-conversion functions declarations |
|
0 commit comments