convert.h
Go to the documentation of this file.
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>
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 
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>
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>
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 
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>
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>
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>
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 {
246  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>
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 
269 template <typename OutIterT, typename T, typename FormatT>
270 inline OutIterT putInt(OutIterT it, T i, const FormatT& fmt);
271 
274 template <typename OutIterT, typename T>
275 inline OutIterT putInt(OutIterT it, T i);
276 
279 template <typename OutIterT, typename T, typename FormatT>
280 OutIterT putFloat(OutIterT it, T d, const FormatT& fmt, int precision);
281 
284 template <typename OutIterT, typename T>
285 OutIterT putFloat(OutIterT it, T d);
286 
287 //
288 // number parsing
289 //
290 
293 template <typename InIterT, typename T, typename FormatT>
294 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt);
295 
298 template <typename InIterT, typename T>
299 InIterT getInt(InIterT it, InIterT end, bool& ok, T& n);
300 
303 template <typename InIterT, typename T, typename FormatT>
304 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n, const FormatT& fmt);
305 
308 template <typename InIterT, typename T>
309 InIterT getFloat(InIterT it, InIterT end, bool& ok, T& n);
310 
311 
312 template <typename CharType>
314 {
315  typedef CharType CharT;
316 
317  static CharT plus()
318  { return CharT('+'); }
319 
320  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 
332  static CharT toChar(unsigned char n)
333  {
334  return CharT(static_cast<char>('0' + n));
335  }
336 
342  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 
359  static CharT toChar(unsigned char n)
360  {
361  return CharT(static_cast<char>('0' + n));
362  }
363 
370  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 
386  static CharT toChar(unsigned char n)
387  {
388  n &= 0x1F; // prevent overrun
389  static const char* digtab = "0123456789abcdef";
390  return digtab[n];
391  }
392 
398  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 
428  static CharT toChar(unsigned char n)
429  {
430  return CharT(static_cast<char>('0' + n));
431  }
432 
439  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 
454  static CharT point()
455  { return CharT('.'); }
456 
457  static CharT e()
458  { return CharT('e'); }
459 
460  static CharT E()
461  { return CharT('E'); }
462 
463  static const CharT* nan()
464  {
465  static const CharT nanstr[] = { CharT('n'), CharT('a'), CharT('n'), 0 };
466  return nanstr;
467  }
468 
469  static const CharT* inf()
470  {
471  static const CharT nanstr[] = { CharT('i'), CharT('n'), CharT('f'), 0 };
472  return nanstr;
473  }
474 };
475 
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 
485 inline unsigned char formatAbs(unsigned char i, bool& isNeg)
486 {
487  isNeg = false;
488  return i;
489 }
490 
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 
500 inline unsigned short formatAbs(unsigned short i, bool& isNeg)
501 {
502  isNeg = false;
503  return i;
504 }
505 
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 
515 inline unsigned int formatAbs(unsigned int i, bool& isNeg)
516 {
517  isNeg = false;
518  return i;
519 }
520 
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 
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 
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 
548 inline unsigned long long formatAbs(unsigned long long i, bool& isNeg)
549 {
550  isNeg = false;
551  return i;
552 }
553 #endif
554 
557 template <typename CharT, typename T, typename FormatT>
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 
593 template <typename CharT, typename T>
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>
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>
632 inline OutIterT putInt(OutIterT it, T i)
633 {
635  return putInt(it, i, fmt);
636 }
637 
638 
639 template <typename OutIterT, typename T, typename FormatT>
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>
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>
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>
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>
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>
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>
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