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