33#include <Pt/ConversionError.h>
34#include <Pt/TypeTraits.h>
46template <
bool signedX,
bool signedY>
49 template <
class X,
class Y>
50 static bool check(X x, Y y_min)
56struct LessThanMin<false, true>
58 template <
class X,
class Y>
59 static bool check(X, Y)
65struct LessThanMin<true, false>
67 template <
class X,
class Y>
68 static bool check(X x, Y)
73template <
bool signedX,
bool signedY>
77 template <
class X,
class Y>
78 static bool check(X x, Y ymax)
84struct GreaterThanMax<false, true>
87 template <
class X,
class Y>
88 static bool check(X x, Y ymax)
90 return x >
static_cast<X
>(ymax);
96struct 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;
111template<
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);
134template <
typename OutIterT,
typename T,
typename FormatT>
135inline OutIterT
formatInt(OutIterT it, T i,
const FormatT& fmt);
141template <
typename OutIterT,
typename T>
142inline OutIterT
formatInt(OutIterT it, T i);
148template <
typename CharT,
typename T,
typename FormatT>
149inline CharT*
formatInt(CharT* buf, std::size_t buflen, T si,
const FormatT& fmt);
156template <
typename OutIterT,
typename T,
typename FormatT>
158 const FormatT& fmt,
int precision,
bool fixed =
false);
164template <
typename OutIterT,
typename T>
171template <
typename OutIterT,
typename T>
172OutIterT
formatFloat(OutIterT it, T d,
int precision,
bool fixed =
false);
179template <
typename InIterT,
typename T,
typename FormatT>
180InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok);
186template <
typename InIterT,
typename T,
typename FormatT>
187InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt)
191 InIterT r =
parseInt(it, end, n, fmt, ok);
202template <
typename InIterT,
typename T>
203InIterT
parseInt(InIterT it, InIterT end, T& n,
bool& ok);
209template <
typename InIterT,
typename T>
214 InIterT r =
parseInt(it, end, n, ok);
225template <
typename T,
typename InIter>
231 InIter r =
parseInt(it, end, n, ok);
232 if( ! ok || r != end )
243template <
typename InIterT,
typename T,
typename FormatT>
244InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok);
250template <
typename InIterT,
typename T,
typename FormatT>
251InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt)
266template <
typename InIterT,
typename T>
267InIterT
parseFloat(InIterT it, InIterT end, T& n,
bool& ok);
273template <
typename InIterT,
typename T>
286template <
typename CharType>
289 typedef CharType CharT;
291 static bool isSpace(CharT ch)
292 {
return (ch == 0x20) || (ch > 0x08 && ch < 0x0e); }
302template <
typename CharType>
303struct 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);
334template <
typename CharType>
335struct 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);
368template <
typename CharType>
369struct 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 ];
412template <
typename CharType>
413struct 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);
444template <
typename CharType>
445struct 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 };
501inline unsigned char getAbs(
char i,
bool& isNeg)
504 unsigned char u = isNeg ? -i :
static_cast<unsigned char>(i);
509inline unsigned char getAbs(
unsigned char i,
bool& isNeg)
516inline unsigned short getAbs(
short i,
bool& isNeg)
519 unsigned short u = isNeg ? -i :
static_cast<unsigned short>(i);
524inline unsigned short getAbs(
unsigned short i,
bool& isNeg)
531inline unsigned int getAbs(
int i,
bool& isNeg)
534 unsigned int u = isNeg ? -i :
static_cast<unsigned int>(i);
539inline unsigned int getAbs(
unsigned int i,
bool& isNeg)
546inline unsigned long getAbs(
long i,
bool& isNeg)
549 unsigned long u = isNeg ? -i :
static_cast<unsigned long>(i);
554inline unsigned long getAbs(
unsigned long i,
bool& isNeg)
561inline unsigned long long getAbs(
long long i,
bool& isNeg)
564 unsigned long long u = isNeg ? -i :
static_cast<unsigned long long>(i);
569inline unsigned long long getAbs(
unsigned long long i,
bool& isNeg)
576template <
typename CharT,
typename T,
typename FormatT>
577inline 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 unsigned char lsd =
static_cast<unsigned char>(u % base);
594 *cur = fmt.toChar(lsd);
596 while(u != 0 && cur != buf);
611template <
typename CharT,
typename T>
612inline CharT*
formatInt(CharT* buf, std::size_t buflen, T i,
const BinaryFormat<CharT>& fmt)
614 CharT* end = buf + buflen;
621 unsigned char d =
static_cast<unsigned char>(i & mask);
622 *cur = fmt.toChar(d);
625 while(i != 0 && cur != buf);
634template <
typename OutIterT,
typename T,
typename FormatT>
635inline OutIterT
formatInt(OutIterT it, T i,
const FormatT& fmt)
638 const std::size_t buflen = (
sizeof(T) * 8) + 1;
639 typename FormatT::CharT buf[buflen];
640 typename FormatT::CharT* p =
Pt::formatInt(buf, buflen, i, fmt);
642 typename FormatT::CharT* end = buf + buflen;
650template <
typename OutIterT,
typename T>
653 DecimalFormat<char> fmt;
658template <
typename CharT,
typename T,
typename FormatT>
659inline int formatFloat(CharT* fraction,
int fractSize,
int& intpart,
int& exp, T n,
660 const FormatT& fmt,
int precision,
bool fixed)
665 if(n == T(0.0) || n != n)
668 const bool neg = n < 0;
672 if( n == std::numeric_limits<T>::infinity() )
675 exp =
static_cast<int>( std::floor( std::log10(n) ) );
680 precision += exp + 1;
682 if(precision > fractSize)
683 precision = fractSize;
691 n *= std::pow(T(10.0), precision - exp);
695 bool trailZero =
true;
696 for(
int d = precision - 1; d >= 0; --d)
699 T q = std::floor(p) * T(10.0);
700 int digit =
static_cast<int>( std::floor(n - q) );
704 trailZero = trailZero && (digit == 0);
709 CharT c = fmt.toChar(
static_cast<unsigned char>(digit) );
710 assert(d < fractSize);
716 intpart =
static_cast<int>( std::floor(n) );
732template <
typename OutIterT,
typename T,
typename FormatT>
734 const FormatT& fmt,
int precision,
bool fixed)
736 typedef typename FormatT::CharT CharT;
737 CharT zero = fmt.toChar(0);
742 for(
const CharT* nanstr = fmt.nan(); *nanstr != 0; ++nanstr)
758 T num = std::fabs(d);
761 if( num == std::numeric_limits<T>::infinity() )
763 for(
const CharT* infstr = fmt.infinity(); *infstr != 0; ++infstr)
772 const int bufsize = std::numeric_limits<T>::digits10;
773 CharT fract[bufsize];
776 int fractSize =
Pt::formatFloat(fract, bufsize, i, e, num, fmt, precision, fixed);
777 int fillSize = fractSize;
782 *it++ = fmt.toChar(i);
785 *it++ = (n < fractSize) ? fract[n] : zero;
790 *it++ = (n < fractSize) ? fract[n] : zero;
795 fillSize = n + precision - 1;
804 e = std::max(-precision, e);
805 fillSize = precision + e;
811 *it++ = fmt.toChar(i);
814 for(; n < fillSize; ++n)
815 *it++ = (n < fractSize) ? fract[n] : zero;
821template <
typename OutIterT,
typename T>
824 const int precision = std::numeric_limits<T>::digits10;
825 FloatFormat<char> fmt;
830template <
typename OutIterT,
typename T>
833 FloatFormat<char> fmt;
838template <
typename InIterT,
typename FormatT>
839InIterT getWhitespace(InIterT it, InIterT end,
const FormatT& fmt)
841 while( it != end && fmt.isSpace(*it) )
848template <
typename InIterT,
typename FormatT>
849InIterT getSign(InIterT it, InIterT end,
bool& pos,
const FormatT& fmt)
856 if( *it == fmt.minus() )
861 else if( *it == fmt.plus() )
870template <
typename InIterT,
typename T,
typename FormatT>
871InIterT
parseInt(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok)
873 typedef typename IntTraits<T>::Unsigned UnsignedInt;
874 typedef typename IntTraits<T>::Signed SignedInt;
878 UnsignedInt max =
static_cast<UnsignedInt
>( std::numeric_limits<T>::max() );
880 it = getWhitespace(it, end, fmt);
883 it = getSign(it, end, pos, fmt);
892 if( isNeg != std::numeric_limits<T>::is_signed)
896 SignedInt smin = std::numeric_limits<T>::min();
897 max =
static_cast<UnsignedInt
>(-smin);
902 const UnsignedInt base = fmt.base;
906 if( ! fmt.isDigit(*it) )
909 d = fmt.toDigit(*it);
911 if ( u != 0u && base > (max/u) )
916 if(
static_cast<UnsignedInt
>(d) > max - u)
919 u +=
static_cast<UnsignedInt
>(d);
924 n =
static_cast<T
>(u * -1);
926 n =
static_cast<T
>(u);
933template <
typename InIterT,
typename T>
934InIterT
parseInt(InIterT it, InIterT end, T& n,
bool& ok)
936 typedef typename std::iterator_traits<InIterT>::value_type CharType;
937 return parseInt(it, end, n, DecimalFormat<CharType>(), ok );
941template <
typename InIterT,
typename T,
typename FormatT>
942InIterT
parseFloat(InIterT it, InIterT end, T& n,
const FormatT& fmt,
bool& ok)
944 typedef typename FormatT::CharT CharT;
945 CharT zero = fmt.toChar(0);
949 it = getWhitespace(it, end, fmt);
952 it = getSign(it, end, pos, fmt);
958 if( fmt.isNan(*it, strpos, ok) )
960 while( ++it != end && fmt.isNan(*it, ++strpos, ok) )
964 n = std::numeric_limits<T>::quiet_NaN();
970 if( fmt.isInfinity(*it, strpos, ok) )
972 while( ++it != end && fmt.isInfinity(*it, ++strpos, ok) )
977 n = pos ? std::numeric_limits<T>::infinity()
978 : std::numeric_limits<T>::infinity() * -1;
988 bool withFractional =
false;
989 for( ; it != end; ++it)
991 if( *it == fmt.point() )
993 withFractional =
true;
998 if( ! fmt.isDigit(*it) )
1001 unsigned digit = fmt.toDigit(*it);
1021 unsigned short fractDigits = 0;
1022 std::size_t maxDigits = std::numeric_limits<unsigned short>::max() - std::numeric_limits<T>::digits10;
1023 while(it != end && *it == zero)
1025 if( fractDigits > maxDigits )
1033 unsigned short significants = 0;
1035 for( ; it != end; ++it)
1037 if( ! fmt.isDigit(*it) )
1040 unsigned digit = fmt.toDigit(*it);
1042 if( significants <= std::numeric_limits<T>::digits10 )
1053 fraction /= std::pow(base, T(fractDigits));
1058 if(it != end && fmt.isE(*it) )
1064 it =
parseInt(it, end, exp, fmt, ok);
1068 n *= std::pow(base, T(exp));
1079template <
typename InIterT,
typename T>
1082 typedef typename std::iterator_traits<InIterT>::value_type CharType;
1083 return parseFloat( it, end, n, FloatFormat<CharType>(), ok);
ConversionError(const std::string &msg)
Construct with error message.
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:635
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:942
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:733
InIterT parseInt(InIterT it, InIterT end, T &n, const FormatT &fmt, bool &ok)
Parses an integer value in a given format.
Definition Convert.h:871
Core module.
Definition Allocator.h:33