33 #include <Pt/ConversionError.h>
34 #include <Pt/TypeTraits.h>
46 template <
bool signedX,
bool signedY>
49 template <
class X,
class Y>
50 static bool check(X x, Y y_min)
56 struct LessThanMin<false, true>
58 template <
class X,
class Y>
59 static bool check(X, Y)
65 struct LessThanMin<true, false>
67 template <
class X,
class Y>
68 static bool check(X x, Y)
73 template <
bool signedX,
bool signedY>
77 template <
class X,
class Y>
78 static bool check(X x, Y ymax)
84 struct GreaterThanMax<false, true>
87 template <
class X,
class Y>
88 static bool check(X x, Y ymax)
90 return x >
static_cast<X
>(ymax);
96 struct GreaterThanMax<true, false>
99 template <
class X,
class Y>
100 static bool check(X x, Y ymax)
102 return x > 0 &&
static_cast<Y
>(x) > ymax;
111 template<
typename R,
typename T>
114 typedef std::numeric_limits<T> SourceTraits;
115 typedef std::numeric_limits<R> ResultTraits;
117 const bool fromSigned = SourceTraits::is_signed;
118 const bool toSigned = ResultTraits::is_signed;
120 if( LessThanMin<fromSigned, toSigned>::check( from, ResultTraits::min() )
121 || GreaterThanMax<fromSigned, toSigned>::check( from, ResultTraits::max() ) )
126 return static_cast<R
>(from);
134 template <
typename OutIterT,
typename T,
typename FormatT>
135 inline OutIterT
formatInt(OutIterT it, T i,
const FormatT& fmt);
141 template <
typename OutIterT,
typename T>
142 inline OutIterT
formatInt(OutIterT it, T i);
148 template <
typename CharT,
typename T,
typename FormatT>
149 inline CharT*
formatInt(CharT* buf, std::size_t buflen, T si,
const FormatT& fmt);
156 template <
typename OutIterT,
typename T,
typename FormatT>
158 const FormatT& fmt,
int precision,
bool fixed =
false);
164 template <
typename OutIterT,
typename T>
171 template <
typename OutIterT,
typename T>
172 OutIterT
formatFloat(OutIterT it, T d,
int precision,
bool fixed =
false);
179 template <
typename InIterT,
typename T,
typename FormatT>
180 InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok);
186 template <
typename InIterT,
typename T,
typename FormatT>
187 InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt)
191 InIterT r =
parseInt(it, end, n, fmt, ok);
202 template <
typename InIterT,
typename T>
203 InIterT
parseInt(InIterT it, InIterT end, T& n,
bool& ok);
209 template <
typename InIterT,
typename T>
214 InIterT r =
parseInt(it, end, n, ok);
225 template <
typename InIter,
typename T>
231 InIter r =
parseInt(it, end, n, ok);
232 if( ! ok || r != end )
243 template <
typename InIterT,
typename T,
typename FormatT>
244 InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok);
250 template <
typename InIterT,
typename T,
typename FormatT>
251 InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt)
266 template <
typename InIterT,
typename T>
267 InIterT
parseFloat(InIterT it, InIterT end, T& n,
bool& ok);
273 template <
typename InIterT,
typename T>
286 template <
typename CharType>
289 typedef CharType CharT;
291 static bool isSpace(CharT ch)
292 {
return (ch == 0x20) || (ch > 0x08 && ch < 0x0e); }
302 template <
typename CharType>
303 struct DecimalFormat :
public NumberFormat<CharType>
305 typedef CharType CharT;
307 static const unsigned base = 10;
311 static CharT toChar(
unsigned char n)
318 static bool isDigit(CharT ch)
320 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
321 return cc > 47 && cc < 58;
326 static unsigned toDigit(CharT ch)
328 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
329 return static_cast<unsigned>(cc - 48);
334 template <
typename CharType>
335 struct OctalFormat :
public NumberFormat<CharType>
337 typedef CharType CharT;
339 static const unsigned base = 8;
343 static CharT toChar(
unsigned char n)
350 static bool isDigit(CharT ch)
352 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
353 return cc > 47 && cc < 56;
358 static unsigned toDigit(CharT ch)
360 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
363 return static_cast<unsigned>(cc - 48);
368 template <
typename CharType>
369 struct HexFormat :
public NumberFormat<CharType>
371 typedef CharType CharT;
373 static const unsigned base = 16;
377 static CharT toChar(
unsigned char n)
380 static const char* digtab =
"0123456789abcdef";
386 static bool isDigit(CharT ch)
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);
394 static unsigned toDigit(CharT ch)
396 static const unsigned char chartab[64] =
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,
404 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
406 unsigned idx =
static_cast<unsigned>(cc - 48);
407 return chartab[ idx ];
412 template <
typename CharType>
413 struct BinaryFormat :
public NumberFormat<CharType>
415 typedef CharType CharT;
417 static const unsigned base = 2;
421 static CharT toChar(
unsigned char n)
428 static bool isDigit(CharT ch)
430 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
431 return cc > 47 && cc < 50;
436 static unsigned toDigit(CharT ch)
438 typename std::char_traits<CharT>::int_type cc = std::char_traits<CharT>::to_int_type(ch);
439 return static_cast<unsigned>(cc - 48);
444 template <
typename CharType>
445 struct FloatFormat :
public DecimalFormat<CharType>
447 typedef CharType CharT;
455 static bool isE(CharT ch)
456 {
return ch ==
'E' || ch ==
'e'; }
458 static bool isNan(CharT ch,
unsigned pos,
bool& isNan)
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;
467 return (ch > 46 && ch < 58) || (ch > 64 && ch < 91) || (ch > 96 && ch < 123);
470 static bool isInfinity(CharT ch,
unsigned pos,
bool& isInf)
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;
487 static const CharT* nan()
489 static const CharT nanstr[] = {
'n',
'a',
'n', 0 };
493 static const CharT* infinity()
495 static const CharT nanstr[] = {
'i',
'n',
'f', 0 };
501 inline unsigned char getAbs(
char i,
bool& isNeg)
504 unsigned char u = isNeg ? -i :
static_cast<unsigned char>(i);
509 inline unsigned char getAbs(
unsigned char i,
bool& isNeg)
516 inline unsigned short getAbs(
short i,
bool& isNeg)
519 unsigned short u = isNeg ? -i :
static_cast<unsigned short>(i);
524 inline unsigned short getAbs(
unsigned short i,
bool& isNeg)
531 inline unsigned int getAbs(
int i,
bool& isNeg)
534 unsigned int u = isNeg ? -i :
static_cast<unsigned int>(i);
539 inline unsigned int getAbs(
unsigned int i,
bool& isNeg)
546 inline unsigned long getAbs(
long i,
bool& isNeg)
549 unsigned long u = isNeg ? -i :
static_cast<unsigned long>(i);
554 inline unsigned long getAbs(
unsigned long i,
bool& isNeg)
561 inline unsigned long long getAbs(
long long i,
bool& isNeg)
564 unsigned long long u = isNeg ? -i :
static_cast<unsigned long long>(i);
569 inline unsigned long long getAbs(
unsigned long long i,
bool& isNeg)
576 template <
typename CharT,
typename T,
typename FormatT>
577 inline CharT*
formatInt(CharT* buf, std::size_t buflen, T si,
const FormatT& fmt)
579 typedef typename IntTraits<T>::Unsigned UnsignedInt;
581 CharT* end = buf + buflen;
584 const unsigned base = fmt.base;
587 UnsignedInt u = getAbs(si, isNeg);
591 UnsignedInt lsd = u % base;
594 *cur = fmt.toChar(
unsigned(lsd) );
596 while(u != 0 && cur != buf);
611 template <
typename CharT,
typename T>
612 inline CharT*
formatInt(CharT* buf, std::size_t buflen, T i,
const BinaryFormat<CharT>& fmt)
614 CharT* end = buf + buflen;
621 *cur = fmt.toChar(
unsigned(i & mask));
624 while(i != 0 && cur != buf);
633 template <
typename OutIterT,
typename T,
typename FormatT>
634 inline OutIterT
formatInt(OutIterT it, T i,
const FormatT& fmt)
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);
641 typename FormatT::CharT* end = buf + buflen;
649 template <
typename OutIterT,
typename T>
652 DecimalFormat<char> fmt;
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)
664 if(n == T(0.0) || n != n)
667 const bool neg = n < 0;
671 if( n == std::numeric_limits<T>::infinity() )
674 exp =
static_cast<int>( std::floor( std::log10(n) ) );
679 precision += exp + 1;
681 if(precision > fractSize)
682 precision = fractSize;
690 n *= std::pow(T(10.0), precision - exp);
694 bool trailZero =
true;
695 for(
int d = precision - 1; d >= 0; --d)
698 T q = std::floor(p) * T(10.0);
699 int digit =
static_cast<int>( std::floor(n - q) );
703 trailZero = trailZero && (digit == 0);
708 CharT c = fmt.toChar(digit);
709 assert(d < fractSize);
715 intpart =
static_cast<int>( std::floor(n) );
731 template <
typename OutIterT,
typename T,
typename FormatT>
733 const FormatT& fmt,
int precision,
bool fixed)
735 typedef typename FormatT::CharT CharT;
736 CharT zero = fmt.toChar(0);
741 for(
const CharT* nanstr = fmt.nan(); *nanstr != 0; ++nanstr)
757 T num = std::fabs(d);
760 if( num == std::numeric_limits<T>::infinity() )
762 for(
const CharT* infstr = fmt.infinity(); *infstr != 0; ++infstr)
771 const int bufsize = std::numeric_limits<T>::digits10;
772 CharT fract[bufsize];
775 int fractSize =
Pt::formatFloat(fract, bufsize, i, e, num, fmt, precision, fixed);
776 int fillSize = fractSize;
781 *it++ = fmt.toChar(i);
784 *it++ = (n < fractSize) ? fract[n] : zero;
789 *it++ = (n < fractSize) ? fract[n] : zero;
794 fillSize = n + precision - 1;
803 e = std::max(-precision, e);
804 fillSize = precision + e;
810 *it++ = fmt.toChar(i);
813 for(; n < fillSize; ++n)
814 *it++ = (n < fractSize) ? fract[n] : zero;
820 template <
typename OutIterT,
typename T>
823 const int precision = std::numeric_limits<T>::digits10;
824 FloatFormat<char> fmt;
829 template <
typename OutIterT,
typename T>
832 FloatFormat<char> fmt;
837 template <
typename InIterT,
typename FormatT>
838 InIterT getWhitespace(InIterT it, InIterT end,
const FormatT& fmt)
840 while( it != end && fmt.isSpace(*it) )
847 template <
typename InIterT,
typename FormatT>
848 InIterT getSign(InIterT it, InIterT end,
bool& pos,
const FormatT& fmt)
855 if( *it == fmt.minus() )
860 else if( *it == fmt.plus() )
869 template <
typename InIterT,
typename T,
typename FormatT>
870 InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok)
872 typedef typename IntTraits<T>::Unsigned UnsignedInt;
873 typedef typename IntTraits<T>::Signed SignedInt;
877 UnsignedInt max =
static_cast<UnsignedInt
>( std::numeric_limits<T>::max() );
879 it = getWhitespace(it, end, fmt);
882 it = getSign(it, end, pos, fmt);
891 if( isNeg != std::numeric_limits<T>::is_signed)
895 SignedInt smin = std::numeric_limits<T>::min();
896 max =
static_cast<UnsignedInt
>(-smin);
901 const UnsignedInt base = fmt.base;
905 if( ! fmt.isDigit(*it) )
908 d = fmt.toDigit(*it);
910 if ( u != 0u && base > (max/u) )
915 if(static_cast<unsigned char>(d) > max - u)
923 n =
static_cast<T
>(u * -1);
925 n =
static_cast<T
>(u);
932 template <
typename InIterT,
typename T>
933 InIterT
parseInt(InIterT it, InIterT end, T& n,
bool& ok)
935 typedef typename std::iterator_traits<InIterT>::value_type CharType;
936 return parseInt(it, end, n, DecimalFormat<CharType>(), ok );
940 template <
typename InIterT,
typename T,
typename FormatT>
941 InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok)
943 typedef typename FormatT::CharT CharT;
944 CharT zero = fmt.toChar(0);
948 it = getWhitespace(it, end, fmt);
951 it = getSign(it, end, pos, fmt);
957 if( fmt.isNan(*it, strpos, ok) )
959 while( ++it != end && fmt.isNan(*it, ++strpos, ok) )
963 n = std::numeric_limits<T>::quiet_NaN();
969 if( fmt.isInfinity(*it, strpos, ok) )
971 while( ++it != end && fmt.isInfinity(*it, ++strpos, ok) )
976 n = pos ? std::numeric_limits<T>::infinity()
977 : std::numeric_limits<T>::infinity() * -1;
987 bool withFractional =
false;
988 for( ; it != end; ++it)
990 if( *it == fmt.point() || fmt.isE(*it) )
992 if( *it == fmt.point() )
994 withFractional =
true;
1000 if( ! fmt.isDigit(*it) )
1003 unsigned digit = fmt.toDigit(*it);
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)
1027 if( fractDigits > maxDigits )
1035 unsigned short significants = 0;
1037 for( ; it != end; ++it)
1039 if( ! fmt.isDigit(*it) )
1042 unsigned digit = fmt.toDigit(*it);
1044 if( significants <= std::numeric_limits<T>::digits10 )
1055 fraction /= std::pow(base, T(fractDigits));
1060 if(it != end && fmt.isE(*it) )
1066 it =
parseInt(it, end, exp, fmt, ok);
1070 n *= std::pow(base, T(exp));
1081 template <
typename InIterT,
typename T>
1084 typedef typename std::iterator_traits<InIterT>::value_type CharType;
1085 return parseFloat( it, end, n, FloatFormat<CharType>(), ok);
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