1 /*
2  * Copyright (C) 2004-2007 by Marc Boris Duerner
3  * Copyright (C) 2004-2007 by Stepan Beal
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * As a special exception, you may use this file as part of a free
11  * software library without restriction. Specifically, if other files
12  * instantiate templates or use macros or inline functions from this
13  * file, or you compile this file and link it with other files to
14  * produce an executable, this file does not by itself cause the
15  * resulting executable to be covered by the GNU General Public
16  * License. This exception does not however invalidate any other
17  * reasons why the executable file might be covered by the GNU Library
18  * General Public License.
19  *
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  *
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
28  */
29 
30 #ifndef CXXTOOLS_CONVERT_H
31 #define CXXTOOLS_CONVERT_H
32 
33 #include <cxxtools/api.h>
34 #include <cxxtools/config.h>
35 #include <cxxtools/string.h>
36 #include <cxxtools/stringstream.h>
37 #include <cxxtools/conversionerror.h>
38 #include <cxxtools/typetraits.h>
39 #include <sstream>
40 #include <string>
41 #include <typeinfo>
42 #include <limits>
43 #include <iterator>
44 #include <cctype>
45 #include <cmath>
46 
47 #include <cxxtools/config.h>
48 
49 namespace cxxtools
50 {
51 
52 //
53 // Conversions to cxxtools::String
54 //
55 
convert(String & s,const String & str)56 inline void convert(String& s, const String& str)
57 {
58     s = str;
59 }
60 
61 CXXTOOLS_API void convert(String& s, const std::string& value);
62 
63 CXXTOOLS_API void convert(String& s, bool value);
64 
65 CXXTOOLS_API void convert(String& s, char value);
66 CXXTOOLS_API void convert(String& s, wchar_t value);
67 CXXTOOLS_API void convert(String& s, Char value);
68 CXXTOOLS_API void convert(String& s, unsigned char value);
69 CXXTOOLS_API void convert(String& s, signed char value);
70 
71 CXXTOOLS_API void convert(String& s, short value);
72 CXXTOOLS_API void convert(String& s, unsigned short value);
73 CXXTOOLS_API void convert(String& s, int value);
74 CXXTOOLS_API void convert(String& s, unsigned int value);
75 CXXTOOLS_API void convert(String& s, long value);
76 CXXTOOLS_API void convert(String& s, unsigned long value);
77 
78 CXXTOOLS_API void convert(String& s, float value);
79 CXXTOOLS_API void convert(String& s, double value);
80 CXXTOOLS_API void convert(String& s, long double value);
81 
82 template <typename T>
convert(String & s,const T & value)83 inline void convert(String& s, const T& value)
84 {
85     OStringStream os;
86     os << value;
87     s = os.str();
88 }
89 
90 //
91 // Conversions from cxxtools::String
92 //
93 
94 CXXTOOLS_API void convert(bool& n, const String& str);
95 
96 CXXTOOLS_API void convert(char& n, const String& str);
97 CXXTOOLS_API void convert(wchar_t& n, const String& str);
98 CXXTOOLS_API void convert(Char& n, const String& str);
99 CXXTOOLS_API void convert(unsigned char& n, const String& str);
100 CXXTOOLS_API void convert(signed char& n, const String& str);
101 
102 CXXTOOLS_API void convert(short& n, const String& str);
103 CXXTOOLS_API void convert(unsigned short& n, const String& str);
104 CXXTOOLS_API void convert(int& n, const String& str);
105 CXXTOOLS_API void convert(unsigned int& n, const String& str);
106 CXXTOOLS_API void convert(long& n, const String& str);
107 CXXTOOLS_API void convert(unsigned long& n, const String& str);
108 #ifdef HAVE_LONG_LONG
109 CXXTOOLS_API void convert(long long& n, const String& str);
110 #endif
111 #ifdef HAVE_UNSIGNED_LONG_LONG
112 CXXTOOLS_API void convert(unsigned long long& n, const String& str);
113 #endif
114 
115 CXXTOOLS_API void convert(float& n, const String& str);
116 CXXTOOLS_API void convert(double& n, const String& str);
117 CXXTOOLS_API void convert(long double& n, const String& str);
118 
119 template <typename T>
convert(T & t,const String & str)120 inline void convert(T& t, const String& str)
121 {
122     IStringStream is(str);
123     Char ch;
124     is >> t;
125     if (is.fail() || !(is >> ch).eof())
126         ConversionError::doThrow(typeid(T).name(), "String");
127 }
128 
129 //
130 // Conversions to std::string
131 //
132 
convert(std::string & s,const std::string & str)133 inline void convert(std::string& s, const std::string& str)
134 {
135     s = str;
136 }
137 
138 CXXTOOLS_API void convert(std::string& s, const String& str);
139 
140 CXXTOOLS_API void convert(std::string& s, bool value);
141 
142 CXXTOOLS_API void convert(std::string& s, char value);
143 CXXTOOLS_API void convert(std::string& s, signed char value);
144 CXXTOOLS_API void convert(std::string& s, unsigned char value);
145 
146 CXXTOOLS_API void convert(std::string& s, short value);
147 CXXTOOLS_API void convert(std::string& s, unsigned short value);
148 CXXTOOLS_API void convert(std::string& s, int value);
149 CXXTOOLS_API void convert(std::string& s, unsigned int value);
150 CXXTOOLS_API void convert(std::string& s, long value);
151 CXXTOOLS_API void convert(std::string& s, unsigned long value);
152 
153 CXXTOOLS_API void convert(std::string& s, float value);
154 CXXTOOLS_API void convert(std::string& s, double value);
155 CXXTOOLS_API void convert(std::string& s, long double value);
156 
157 template <typename T>
convert(std::string & s,const T & value)158 inline void convert(std::string& s, const T& value)
159 {
160     std::ostringstream os;
161     os << value;
162     s = os.str();
163 }
164 
165 //
166 // Conversions from std::string
167 //
168 
169 CXXTOOLS_API void convert(bool& n, const std::string& str);
170 
171 CXXTOOLS_API void convert(char& n, const std::string& str);
172 CXXTOOLS_API void convert(signed char& n, const std::string& str);
173 CXXTOOLS_API void convert(unsigned char& n, const std::string& str);
174 
175 CXXTOOLS_API void convert(short& n, const std::string& str);
176 CXXTOOLS_API void convert(unsigned short& n, const std::string& str);
177 CXXTOOLS_API void convert(int& n, const std::string& str);
178 CXXTOOLS_API void convert(unsigned int& n, const std::string& str);
179 CXXTOOLS_API void convert(long& n, const std::string& str);
180 CXXTOOLS_API void convert(unsigned long& n, const std::string& str);
181 #ifdef HAVE_LONG_LONG
182 CXXTOOLS_API void convert(long long& n, const std::string& str);
183 #endif
184 #ifdef HAVE_UNSIGNED_LONG_LONG
185 CXXTOOLS_API void convert(unsigned long long& n, const std::string& str);
186 #endif
187 
188 CXXTOOLS_API void convert(float& n, const std::string& str);
189 CXXTOOLS_API void convert(double& n, const std::string& str);
190 CXXTOOLS_API void convert(long double& n, const std::string& str);
191 
192 template <typename T>
convert(T & t,const std::string & str)193 inline void convert(T& t, const std::string& str)
194 {
195     std::istringstream is(str);
196     char ch;
197     is >> t;
198     if (is.fail() || !(is >> ch).eof())
199         ConversionError::doThrow(typeid(T).name(), "string");
200 }
201 
202 //
203 // Conversions from const char* (null-terminated)
204 //
205 
206 CXXTOOLS_API void convert(bool& n, const char* str);
207 
208 CXXTOOLS_API void convert(char& n, const char* str);
209 CXXTOOLS_API void convert(signed char& n, const char* str);
210 CXXTOOLS_API void convert(unsigned char& n, const char* str);
211 
212 CXXTOOLS_API void convert(short& n, const char* str);
213 CXXTOOLS_API void convert(unsigned short& n, const char* str);
214 CXXTOOLS_API void convert(int& n, const char* str);
215 CXXTOOLS_API void convert(unsigned int& n, const char* str);
216 CXXTOOLS_API void convert(long& n, const char* str);
217 CXXTOOLS_API void convert(unsigned long& n, const char* str);
218 #ifdef HAVE_LONG_LONG
219 CXXTOOLS_API void convert(long long& n, const char* str);
220 #endif
221 #ifdef HAVE_UNSIGNED_LONG_LONG
222 CXXTOOLS_API void convert(unsigned long long& n, const char* str);
223 #endif
224 
225 CXXTOOLS_API void convert(float& n, const char* str);
226 CXXTOOLS_API void convert(double& n, const char* str);
227 CXXTOOLS_API void convert(long double& n, const char* str);
228 
229 
230 //
231 // Generic stream-based conversions
232 //
233 
234 template<typename T, typename S>
convert(T & to,const S & from)235 void convert(T& to, const S& from)
236 {
237     StringStream ss;
238     if( !(ss << from && ss >> to) )
239         throw ConversionError("conversion between streamable types failed");
240 }
241 
242 
243 template<typename T, typename S>
244 struct Convert
245 {
operatorConvert246     T operator()(const S& from) const
247     {
248         T value = T();
249         convert(value, from);
250         return value;
251     }
252 };
253 
254 
255 template<typename T, typename S>
convert(const S & from)256 T convert(const S& from)
257 {
258     T value = T();
259     convert(value, from);
260     return value;
261 }
262 
263 //
264 // number formatting
265 //
266 
267 /** @brief Formats an integer in a given format format.
268  */
269 template <typename OutIterT, typename T, typename FormatT>
270 inline OutIterT putInt(OutIterT it, T i, const FormatT& fmt);
271 
272 /** @brief Formats an integer in a decimal format.
273  */
274 template <typename OutIterT, typename T>
275 inline OutIterT putInt(OutIterT it, T i);
276 
277 /** @brief Formats a floating point value in a given format.
278  */
279 template <typename OutIterT, typename T, typename FormatT>
280 OutIterT putFloat(OutIterT it, T d, const FormatT& fmt, int precision);
281 
282 /** @brief Formats a floating point value in default format.
283  */
284 template <typename OutIterT, typename T>
285 OutIterT putFloat(OutIterT it, T d);
286 
287 //
288 // number parsing
289 //
290 
291 /** @brief Parses an integer value in a given format.
292  */
293 template <typename InIterT, typename T, typename FormatT>
294 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt);
295 
296 /** @brief Parses an integer value in decimal format.
297  */
298 template <typename InIterT, typename T>
299 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n);
300 
301 /** @brief Parses a floating point value in a given format.
302  */
303 template <typename InIterT, typename T, typename FormatT>
304 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt);
305 
306 /** @brief Parses a floating point value.
307  */
308 template <typename InIterT, typename T>
309 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n);
310 
311 
312 template <typename CharType>
313 struct NumberFormat
314 {
315     typedef CharType CharT;
316 
plusNumberFormat317     static CharT plus()
318     { return CharT('+'); }
319 
minusNumberFormat320     static CharT minus()
321     { return CharT('-'); }
322 };
323 
324 
325 template <typename CharType>
326 struct DecimalFormat : public NumberFormat<CharType>
327 {
328     typedef CharType CharT;
329 
330     static const unsigned base = 10;
331 
toCharDecimalFormat332     static CharT toChar(unsigned char n)
333     {
334         return CharT(static_cast<char>('0' + n));
335     }
336 
337     /** @brief Converts a character to a digit.
338 
339         Returns a number equal or less than the base on success or a number
340         greater than base on failure.
341     */
toDigitDecimalFormat342     static unsigned char toDigit(CharT ch)
343     {
344         int cc = std::char_traits<CharT>::to_int_type(ch) - 48;
345         // let negatives overrun
346         return static_cast<unsigned>(cc);
347 
348     }
349 };
350 
351 
352 template <typename CharType>
353 struct OctalFormat : public NumberFormat<CharType>
354 {
355     typedef CharType CharT;
356 
357     static const unsigned base = 8;
358 
toCharOctalFormat359     static CharT toChar(unsigned char n)
360     {
361         return CharT(static_cast<char>('0' + n));
362     }
363 
364     /** @brief Converts a character to a digit.
365 
366         Returns a number equal or less than the base on success or a number
367         greater than base on failure.
368 
369     */
toDigitOctalFormat370     static unsigned char toDigit(CharT ch)
371     {
372         int cc = std::char_traits<CharT>::to_int_type(ch) - 48;
373         // let negatives overrun
374         return static_cast<unsigned>(cc);
375     }
376 };
377 
378 
379 template <typename CharType>
380 struct HexFormat : public NumberFormat<CharType>
381 {
382     typedef CharType CharT;
383 
384     static const unsigned base = 16;
385 
toCharHexFormat386     static CharT toChar(unsigned char n)
387     {
388         n &= 0x1F; // prevent overrun
389         static const char* digtab = "0123456789abcdef";
390         return digtab[n];
391     }
392 
393     /** @brief Converts a character to a digit.
394 
395         Returns a number equal or less than the base on success or a number
396         greater than base on failure.
397     */
toDigitHexFormat398     static unsigned char toDigit(CharT ch)
399     {
400         static const unsigned char chartab[64] =
401         {
402             0, 1, 2, 3, 4, 5, 6, 7, 8, 9,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
403             0xFF,10,11,12,13,14,15,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
404             0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
405             0xFF,10,11,12,13,14,15,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
406         };
407 
408         int cc = ch - 48;
409         // let negatives overrun
410         unsigned uc = static_cast<unsigned>(cc);
411 
412         if(uc > 64)
413             return 0xFF;
414 
415         unsigned char idx = static_cast<unsigned char>(uc);
416         return chartab[ idx ];
417     }
418 };
419 
420 
421 template <typename CharType>
422 struct BinaryFormat : public NumberFormat<CharType>
423 {
424     typedef CharType CharT;
425 
426     static const unsigned base = 2;
427 
toCharBinaryFormat428     static CharT toChar(unsigned char n)
429     {
430         return CharT(static_cast<char>('0' + n));
431     }
432 
433     /** @brief Converts a character to a digit.
434 
435         Returns a number equal or less than the base on success or a number
436         greater than base on failure.
437 
438     */
toDigitBinaryFormat439     static unsigned char toDigit(CharT ch)
440     {
441         int cc = std::char_traits<CharT>::to_int_type(ch) - 48;
442         // let negatives overrun
443         return static_cast<unsigned>(cc);
444 
445     }
446 };
447 
448 
449 template <typename CharType>
450 struct FloatFormat : public DecimalFormat<CharType>
451 {
452     typedef CharType CharT;
453 
pointFloatFormat454     static CharT point()
455     { return CharT('.'); }
456 
eFloatFormat457     static CharT e()
458     { return CharT('e'); }
459 
EFloatFormat460     static CharT E()
461     { return CharT('E'); }
462 
nanFloatFormat463     static const CharT* nan()
464     {
465         static const CharT nanstr[] = { CharT('n'), CharT('a'), CharT('n'), 0 };
466         return nanstr;
467     }
468 
infFloatFormat469     static const CharT* inf()
470     {
471         static const CharT nanstr[] = { CharT('i'), CharT('n'), CharT('f'), 0 };
472         return nanstr;
473     }
474 };
475 
476 //! @internal @brief Returns the absolute value of \a i
formatAbs(char i,bool & isNeg)477 inline unsigned char formatAbs(char i, bool& isNeg)
478 {
479     isNeg = i < 0;
480     unsigned char u = isNeg ? -i : static_cast<unsigned char>(i);
481     return u;
482 }
483 
484 //! @internal @brief Returns the absolute value of \a i
formatAbs(unsigned char i,bool & isNeg)485 inline unsigned char formatAbs(unsigned char i, bool& isNeg)
486 {
487     isNeg = false;
488     return i;
489 }
490 
491 //! @internal @brief Returns the absolute value of \a i
formatAbs(short i,bool & isNeg)492 inline unsigned short formatAbs(short i, bool& isNeg)
493 {
494     isNeg = i < 0;
495     unsigned short u = isNeg ? -i : static_cast<unsigned short>(i);
496     return u;
497 }
498 
499 //! @internal @brief Returns the absolute value of \a i
formatAbs(unsigned short i,bool & isNeg)500 inline unsigned short formatAbs(unsigned short i, bool& isNeg)
501 {
502     isNeg = false;
503     return i;
504 }
505 
506 //! @internal @brief Returns the absolute value of \a i
formatAbs(int i,bool & isNeg)507 inline unsigned int formatAbs(int i, bool& isNeg)
508 {
509     isNeg = i < 0;
510     unsigned int u = isNeg ? -i : static_cast<unsigned int>(i);
511     return u;
512 }
513 
514 //! @internal @brief Returns the absolute value of \a i
formatAbs(unsigned int i,bool & isNeg)515 inline unsigned int formatAbs(unsigned int i, bool& isNeg)
516 {
517     isNeg = false;
518     return i;
519 }
520 
521 //! @internal @brief Returns the absolute value of \a i
formatAbs(long i,bool & isNeg)522 inline unsigned long formatAbs(long i, bool& isNeg)
523 {
524     isNeg = i < 0;
525     unsigned long u = isNeg ? -i : static_cast<unsigned long>(i);
526     return u;
527 }
528 
529 //! @internal @brief Returns the absolute value of \a i
formatAbs(unsigned long i,bool & isNeg)530 inline unsigned long formatAbs(unsigned long i, bool& isNeg)
531 {
532     isNeg = false;
533     return i;
534 }
535 
536 #ifdef HAVE_LONG_LONG
537 //! @internal @brief Returns the absolute value of \a i
formatAbs(long long i,bool & isNeg)538 inline unsigned long long formatAbs(long long i, bool& isNeg)
539 {
540     isNeg = i < 0;
541     unsigned long long u = isNeg ? -i : static_cast<unsigned long long>(i);
542     return u;
543 }
544 #endif
545 
546 #ifdef HAVE_UNSIGNEDLONG_LONG
547 //! @internal @brief Returns the absolute value of \a i
formatAbs(unsigned long long i,bool & isNeg)548 inline unsigned long long formatAbs(unsigned long long i, bool& isNeg)
549 {
550     isNeg = false;
551     return i;
552 }
553 #endif
554 
555 /** @brief Formats an integer in a given format.
556  */
557 template <typename CharT, typename T, typename FormatT>
formatInt(CharT * buf,std::size_t buflen,T si,const FormatT & fmt)558 inline CharT* formatInt(CharT* buf, std::size_t buflen, T si, const FormatT& fmt)
559 {
560     typedef typename IntTraits<T>::Unsigned UnsignedInt;
561 
562     CharT* end = buf + buflen;
563     CharT* cur = end;
564 
565     const unsigned base = fmt.base;
566 
567     bool isNeg = false;
568     UnsignedInt u = formatAbs(si, isNeg);
569 
570     do
571     {
572         T lsd = u % base;
573         u /= base;
574         --cur;
575         *cur = fmt.toChar( unsigned(lsd) );
576     }
577     while(u != 0 && cur != buf);
578 
579     if(cur == buf)
580         return buf;
581 
582     if(isNeg)
583     {
584         --cur;
585         *cur = fmt.minus();
586     }
587 
588     return cur;
589 }
590 
591 /** @brief Formats an integer in binary format.
592  */
593 template <typename CharT, typename T>
formatInt(CharT * buf,std::size_t buflen,T i,const BinaryFormat<CharT> & fmt)594 inline CharT* formatInt(CharT* buf, std::size_t buflen, T i, const BinaryFormat<CharT>& fmt)
595 {
596     CharT* end = buf + buflen;
597     CharT* cur = end;
598     T mask = 1;
599 
600     do
601     {
602         --cur;
603         *cur = fmt.toChar( unsigned(i & mask));
604         i = i >> 1;
605     }
606     while(i != 0 && cur != buf);
607 
608     if(cur == buf)
609         return buf;
610 
611     return cur;
612 }
613 
614 
615 template <typename OutIterT, typename T, typename FormatT>
putInt(OutIterT it,T i,const FormatT & fmt)616 inline OutIterT putInt(OutIterT it, T i, const FormatT& fmt)
617 {
618     // large enough even for binary and a sign
619     const std::size_t buflen = (sizeof(T) * 8) + 1;
620     typename FormatT::CharT buf[buflen];
621     typename FormatT::CharT* p = formatInt(buf, buflen, i, fmt);
622 
623     typename FormatT::CharT* end = buf + buflen;
624     for(; p != end; ++p)
625         *it++ = *p;
626 
627     return it;
628 }
629 
630 
631 template <typename OutIterT, typename T>
putInt(OutIterT it,T i)632 inline OutIterT putInt(OutIterT it, T i)
633 {
634     DecimalFormat<char> fmt;
635     return putInt(it, i, fmt);
636 }
637 
638 
639 template <typename OutIterT, typename T, typename FormatT>
putFloat(OutIterT it,T d,const FormatT & fmt,int precision)640 inline OutIterT putFloat(OutIterT it, T d, const FormatT& fmt, int precision)
641 {
642     typedef typename FormatT::CharT CharT;
643 
644     // 1. Test for not-a-number with d != d
645     if( d != d )
646     {
647         for(const CharT* nanstr = fmt.nan(); *nanstr != 0; ++nanstr)
648         {
649             *it = *nanstr;
650             ++it;
651         }
652 
653         return it;
654     }
655 
656     // 2. check sign
657     if(d < 0.0)
658     {
659         *it = fmt.minus();
660         ++it;
661     }
662 
663     T num = std::fabs(d);
664 
665     // 3. Test for infinity
666     if( num == std::numeric_limits<T>::infinity() )
667     {
668         for(const CharT* infstr = fmt.inf(); *infstr != 0; ++infstr)
669         {
670             *it = *infstr;
671             ++it;
672         }
673 
674         return it;
675     }
676 
677     const int bufsize = std::numeric_limits<T>::digits10 + 1;
678 
679     if (precision > bufsize)
680         precision = bufsize;
681 
682     CharT fract[bufsize + 1];
683     fract[bufsize] = CharT('\0');
684 
685     int exp = static_cast<int>(std::floor(std::log10(num))) + 1;
686 
687     num *= std::pow(T(10.0), static_cast<int>(precision) - exp);
688     num += .5;
689 
690     bool notZero = false;
691     for (unsigned short d = precision; d > 0; --d)
692     {
693         T n = num / 10.0;
694         T fl = std::floor(n) * 10.0;
695         unsigned char v = static_cast<unsigned char>(num - fl);
696         notZero |= (v != 0);
697         fract[d - 1] = notZero ? fmt.toChar(v) : CharT('\0');
698         num = n;
699     }
700 
701     if (fract[0] == CharT('\0'))
702     {
703         *it = '0'; ++it;
704         return it;
705     }
706 
707     if (exp <= 0)
708     {
709         *it = '0'; ++it;
710         *it = '.'; ++it;
711 
712         while (exp < 0)
713         {
714             *it = '0'; ++it;
715             ++exp;
716         }
717 
718         for (int d = 0; fract[d]; ++d)
719         {
720             *it = fract[d]; ++it;
721         }
722     }
723     else
724     {
725         for (int d = 0; fract[d]; ++d)
726         {
727             if (exp-- == 0)
728             {
729                 *it = '.';
730                 ++it;
731             }
732             *it = fract[d]; ++it;
733         }
734 
735         while (exp-- > 0)
736         {
737             *it = '0'; ++it;
738         }
739     }
740 
741     return it;
742 }
743 
744 
745 template <typename OutIterT, typename T>
putFloat(OutIterT it,T d)746 inline OutIterT putFloat(OutIterT it, T d)
747 {
748     const int precision = std::numeric_limits<T>::digits10 + 1;
749     FloatFormat<char> fmt;
750     return putFloat(it, d, fmt, precision);
751 }
752 
753 
754 template <typename InIterT, typename FormatT>
getSign(InIterT it,InIterT end,bool & pos,const FormatT & fmt)755 InIterT getSign(InIterT it, InIterT end, bool& pos, const FormatT& fmt)
756 {
757     pos = true;
758 
759     // strip leading whitespace, parse sign
760     while (it != end && isspace(*it))
761         ++it;
762 
763     if(*it == fmt.minus())
764     {
765         pos = false;
766         ++it;
767     }
768     else if( *it == fmt.plus() )
769     {
770         ++it;
771     }
772 
773     return it;
774 }
775 
776 
777 template <typename InIterT, typename T, typename FormatT>
getInt(InIterT it,InIterT end,bool & ok,T & n,const FormatT & fmt)778 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt)
779 {
780     typedef typename IntTraits<T>::Unsigned UnsignedInt;
781     typedef typename IntTraits<T>::Signed SignedInt;
782 
783     n = 0;
784     ok = false;
785     UnsignedInt max = std::numeric_limits<T>::max();
786 
787     bool pos = false;
788     it = getSign(it, end, pos, fmt);
789 
790     if (it == end)
791         return it;
792 
793     bool isNeg = ! pos;
794     if( isNeg )
795     {
796         // return if minus sign was parsed for unsigned type
797         if( isNeg != std::numeric_limits<T>::is_signed)
798             return it;
799 
800         // abs(min) is max for negative signed types
801         SignedInt smin = std::numeric_limits<T>::min();
802         max = static_cast<UnsignedInt>(-smin);
803     }
804 
805     // parse number
806     UnsignedInt u = 0;
807     const UnsignedInt base = fmt.base;
808     unsigned char d = 0;
809     while(it != end)
810     {
811         d = fmt.toDigit(*it);
812 
813         if(d >= base)
814             break;
815 
816         if ( u != 0u && base > (max/u) )
817           return it;
818 
819         u *= base;
820 
821         if(d > max - u)
822             return it;
823 
824         u += d;
825         ++it;
826     }
827 
828     if( isNeg )
829         n = static_cast<T>(u * -1);
830     else
831         n = static_cast<T>(u);
832 
833     ok = true;
834     return it;
835 }
836 
837 
838 template <typename InIterT, typename T>
getInt(InIterT it,InIterT end,bool & ok,T & n)839 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n)
840 {
841     return getInt(it, end, ok, n, DecimalFormat<char>() );
842 }
843 
844 
845 template <typename InIterT, typename T, typename FormatT>
getFloat(InIterT it,InIterT end,bool & ok,T & n,const FormatT & fmt)846 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt)
847 {
848     typedef typename FormatT::CharT CharT;
849     CharT zero = fmt.toChar(0);
850     n = 0.0;
851     ok = false;
852 
853     bool pos = false;
854     it = getSign(it, end, pos, fmt);
855 
856     if (it == end)
857         return it;
858 
859     // NaN, -inf, +inf
860     bool done = false;
861     while(it != end)
862     {
863         switch(std::char_traits<CharT>::to_int_type(*it))
864         {
865             case 'n':
866             case 'N':
867                 if(++it == end)
868                     return it;
869 
870                 if(*it != CharT('a') && *it != CharT('A'))
871                     return it;
872 
873                 if(++it == end)
874                     return it;
875 
876                 if(*it != CharT('n') && *it != CharT('N'))
877                     return it;
878 
879                 // NaNQ, NaNS (seen on AIX/xlC)
880                 {
881                     InIterT nit = it;
882                     ++nit;
883                     if (*nit == CharT('q') || *nit == CharT('Q'))
884                     {
885                         n = std::numeric_limits<T>::quiet_NaN();
886                         ++it;
887                     }
888                     else if (*nit == CharT('s') || *nit == CharT('S'))
889                     {
890                         n = std::numeric_limits<T>::signaling_NaN();
891                         ++it;
892                     }
893                     else
894                     {
895                         n = std::numeric_limits<T>::quiet_NaN();
896                     }
897                 }
898 
899                 ok = true;
900                 return ++it;
901                 break;
902 
903             case 'i':
904             case 'I':
905                 if(++it == end)
906                     return it;
907 
908                 if(*it != CharT('n') && *it != CharT('N'))
909                     return it;
910 
911                 if(++it == end)
912                     return it;
913 
914                 if(*it != CharT('f') && *it != CharT('F'))
915                     return it;
916 
917                 if( ++it != end )
918                 {
919                     if(*it != CharT('i') && *it != CharT('I'))
920                         return it;
921 
922                     if(++it == end)
923                         return it;
924 
925                     if(*it != CharT('n') && *it != CharT('N'))
926                         return it;
927 
928                     if(++it == end)
929                         return it;
930 
931                     if(*it != CharT('i') && *it != CharT('I'))
932                         return it;
933 
934                     if(++it == end)
935                         return it;
936 
937                     if(*it != CharT('t') && *it != CharT('T'))
938                         return it;
939 
940                     if(++it == end)
941                         return it;
942 
943                     if(*it != CharT('y') && *it != CharT('Y'))
944                         return it;
945 
946                     ++it;
947                 }
948 
949                 n = std::numeric_limits<T>::infinity();
950                 if(!pos)
951                     n *= -1;
952 
953                 ok = true;
954                 return it;
955                 break;
956 
957             default:
958                 done = true;
959                 break;
960         }
961 
962         if(done)
963             break;
964 
965         ++it;
966     }
967 
968     // integral part
969     bool withFractional = false;
970     for( ; it != end; ++it)
971     {
972         if( *it == fmt.point() || *it == fmt.e() || *it == fmt.E() )
973         {
974             if( *it == fmt.point())
975             {
976                 withFractional = true;
977                 ++it;
978             }
979             break;
980         }
981 
982         unsigned digit = fmt.toDigit(*it);
983         if(digit >= fmt.base)
984             return it;
985 
986         n *= 10;
987         n += digit;
988     }
989 
990     // it is ok, if fraction is missing
991     if(it == end)
992     {
993         if( ! pos )
994             n *= -1;
995 
996         ok = true;
997         return it;
998     }
999 
1000     T base = 10.0;
1001     if( withFractional)
1002     {
1003         // fractional part, ignore 0 digits after dot
1004         unsigned short fractDigits = 0;
1005         size_t maxDigits = std::numeric_limits<unsigned short>::max() - std::numeric_limits<T>::digits10;
1006         while(it != end && *it == zero)
1007         {
1008             if( fractDigits > maxDigits )
1009                 return it;
1010 
1011             ++fractDigits;
1012             ++it;
1013         }
1014 
1015         // fractional part, parse like integer, skip insignificant digits
1016         unsigned short significants = 0;
1017         T fraction = 0.0;
1018         for( ; it != end; ++it)
1019         {
1020             unsigned digit = fmt.toDigit(*it);
1021             if(digit >= fmt.base)
1022                 break;
1023 
1024             if( significants <= std::numeric_limits<T>::digits10 )
1025             {
1026                 fraction *= 10;
1027                 fraction += digit;
1028 
1029                 ++fractDigits;
1030                 ++significants;
1031             }
1032         }
1033 
1034 
1035         // fractional part, scale down
1036         fraction /= std::pow(base, T(fractDigits));
1037         n += fraction;
1038     }
1039 
1040     // exponent [e|E][+|-][0-9]*
1041     if(it != end && (*it == fmt.e() || *it == fmt.E()) )
1042     {
1043         if(++it == end)
1044             return it;
1045 
1046         long exp = 0;
1047         it = getInt(it, end, ok, exp, fmt);
1048         if( ! ok )
1049             return it;
1050 
1051         n *= std::pow(base, T(exp));
1052     }
1053 
1054     if( ! pos )
1055         n *= -1;
1056 
1057     ok = true;
1058     return it;
1059 }
1060 
1061 
1062 template <typename InIterT, typename T>
getFloat(InIterT it,InIterT end,bool & ok,T & n)1063 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n)
1064 {
1065     return getFloat( it, end, ok, n, FloatFormat<char>() );
1066 }
1067 
1068 } // namespace cxxtools
1069 
1070 #endif
1071