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