+++ /dev/null
-/* $Id$
-
-This file is part of libmspstrings
-Copyright © 2006-2008 Mikko Rasa
-Distributed under the LGPL
-*/
-
-#include <cmath>
-#include <limits>
-#include "lexicalcast.h"
-
-using namespace std;
-
-namespace {
-
-using namespace Msp;
-
-template<typename T>
-struct IsSigned
-{ enum { result = !(static_cast<T>(-1)>0) }; };
-
-template<typename T, bool f = (sizeof(T)>sizeof(unsigned long))>
-struct Temporary
-{ typedef unsigned long Type; };
-
-template<typename T>
-struct Temporary<T, true>
-{
-#ifdef WIN32
- typedef __int64 Type;
-#else
- typedef unsigned long long Type;
-#endif
-};
-
-/* Helper to avoid warnings about an unsigned type never being < 0 */
-template<typename T, bool f = IsSigned<T>::result>
-struct IsNegative
-{ static bool eval(T v) { return v<0; } };
-
-template<typename T>
-struct IsNegative<T, false>
-{ static bool eval(T) { return false; } };
-
-/* Helper to avoid errors about ambiguous function calls since there are no
-overloads of abs for unsigned types */
-template<typename T, bool f = IsSigned<T>::result>
-struct Absolute
-{ static T eval(T v) { return v<0 ? -v : v; } };
-
-template<typename T>
-struct Absolute<T, false>
-{ static T eval(T v) { return v; } };
-
-
-/*** Integer conversions ***/
-
-const char udigits[] = "0123456789ABCDEF";
-const char ldigits[] = "0123456789abcdef";
-
-template<typename T>
-char *int_to_str(T v, const Fmt &f, char *end)
-{
- if(f.get_type()==Fmt::CHAR)
- {
- *--end = v;
- return end;
- }
-
- char *ptr = end;
-
- // Find out the base to use
- unsigned base = f.get_base();
- if(!base)
- base = 10;
-
- // Format the number, starting from the least significant digit
- const char *digits = (f.get_uppercase() ? udigits : ldigits);
- if(v)
- {
- typename Temporary<T>::Type w = Absolute<T>::eval(v);
- while(w)
- {
- *--ptr = digits[w%base];
- w /= base;
- }
- }
- else
- *--ptr = digits[0];
-
- char sign = (IsNegative<T>::eval(v) ? '-' : f.get_showpos() ? '+' : 0);
- if(f.get_fill()=='0')
- {
- /* Zero-fill, taking base/sign size into account. The expression is a
- bit ugly, but saves having to write code for creating the prefix both
- ways. */
- unsigned pfxsize = ((f.get_showbase() && base!=10) ? base==8 ? 1 : 2 : 0) + (sign!=0);
- for(unsigned i=(end-ptr)+pfxsize; i<f.get_width(); ++i)
- *--ptr = '0';
- }
-
- if(f.get_showbase() && v!=0)
- {
- // Add base indicator
- if(base==2)
- *--ptr = (f.get_uppercase() ? 'B' : 'b');
- else if(base==16)
- *--ptr = (f.get_uppercase() ? 'X' : 'x');
- if(base!=10)
- *--ptr = '0';
- }
-
- if(sign)
- *--ptr = sign;
-
- return ptr;
-}
-
-template<typename T>
-string int_to_str(T v, const Fmt &f)
-{
- unsigned size = max(f.get_width(), max<unsigned>(f.get_precision(), sizeof(T)*8+3));
- char *buf = new char[size];
- string result(int_to_str(v, f, buf+size), buf+size);
- delete[] buf;
- return result;
-}
-
-template<typename T>
-T str_to_int(const std::string &s, const Fmt &f)
-{
- if(s.empty())
- throw LexicalError("Empty input in integer conversion");
-
- std::string::const_iterator i = s.begin();
-
- // See if the input starts with a sign
- bool neg = false;
- if(*i=='-')
- {
- if(!IsSigned<T>::result)
- throw LexicalError("Negative sign in unsigned integer conversion");
- neg = true;
- ++i;
- }
- else if(*i=='+')
- ++i;
-
- // Must have some digits to convert
- if(i==s.end())
- throw LexicalError("Missing digits in integer conversion");
-
- T base = f.get_base();
- if(!base && i!=s.end())
- {
- // Automatic base detection requested, figure it out
- if(*i=='0' && ++i!=s.end())
- {
- if(*i=='x' || *i=='X')
- {
- base = 16;
- ++i;
- }
- else if(*i=='b' || *i=='B')
- {
- base = 2;
- ++i;
- }
- else
- base = 8;
- }
- else
- base = 10;
- }
-
- // Parse the digits
- T result = 0;
- for(; i!=s.end(); ++i)
- {
- T digit = base;
- if(*i>='0' && *i<='9')
- digit = *i-'0';
- else if(*i>='A' && *i<='F')
- digit = *i-'A'+10;
- else if(*i>='a' && *i<='f')
- digit = *i-'a'+10;
- if(digit>=base)
- throw LexicalError("Invalid digit in integer conversion");
- T next = result*base+digit;
- if(next/base!=result)
- throw LexicalError("Overflow in integer conversion");
- result = next;
- }
-
- if(neg)
- result = -result;
-
- return result;
-}
-
-
-/*** Boolean conversions ***/
-
-string bool_to_str(bool b, const Fmt &f)
-{
- if(f.get_type()==Fmt::STR)
- return b ? "true" : "false";
- else
- return b ? "1" : "0";
-}
-
-bool str_to_bool(const string &s)
-{
- if(s.empty())
- throw LexicalError("Empty input in boolean conversion");
-
- if(s=="1" || s=="true" || s=="yes" || s=="on")
- return true;
- else if(s=="0" || s=="false" || s=="no" || s=="off")
- return false;
-
- throw LexicalError("Invalid input in boolean conversion");
-}
-
-
-/*** Floating-point conversions ***/
-
-template<typename T>
-string flt_to_str(T v, const Fmt &f)
-{
- if(f.get_type()==Fmt::CHAR)
- throw LexicalError("Character format in floating-point conversion");
-
- Fmt::FloatMode mode = f.get_floatmode();
- long double w = abs(v);
- char sign = (v<0 ? '-' : f.get_showpos() ? '+' : 0);
-
- // Handle infinity and not-a-number as special cases
- if(!(w+w>w) && w!=0)
- {
- string result;
- if(sign)
- result += sign;
- if(!(w>=0))
- result += (f.get_uppercase() ? "NAN" : "nan");
- else
- result += (f.get_uppercase() ? "INF" : "inf");
- if(result.size()<f.get_width())
- result = string(f.get_width()-result.size(), ' ')+result;
- return result;
- }
-
- /* Find out the base-10 exponent. Building up the multiplier / divisor
- first helps with accuracy in some cases. */
- int exp = 0;
- if(w>=10)
- {
- long double div = 1;
- while(div*10<w)
- {
- ++exp;
- div *= 10;
- }
- w /= div;
- }
- else if(mode!=Fmt::FIXED && w<1 && w!=0)
- {
- long double mul = 1;
- while(w*mul<1)
- {
- --exp;
- mul *= 10;
- }
- w *= mul;
- }
-
- // Decide how to format the number
- unsigned digits;
- unsigned point = 1;
- bool showexp = false;
- if(mode==Fmt::FIXED)
- {
- point = exp+1;
- digits = point+f.get_precision();
- }
- else if(mode==Fmt::SCI)
- {
- digits = f.get_precision()+1;
- showexp = true;
- }
- else
- {
- digits = max(f.get_precision(), 1U);
- if(exp<-4 || exp>=static_cast<int>(digits))
- {
- point = 1;
- showexp = true;
- }
- else
- {
- point = max(exp, 0)+1;
- if(exp<0)
- digits += -exp;
- }
- }
-
- // Apply rounding
- w += 5.0l/pow(10.0l, static_cast<long double>(digits));
- if(w>10)
- {
- // Rounding bumped us to the next exponent, deal with it
- w /= 10;
- if(mode==Fmt::AUTOFLT && exp+1==static_cast<int>(digits))
- {
- point = 1;
- showexp = true;
- }
- if(!showexp)
- {
- ++digits;
- ++point;
- }
- else
- ++exp;
- }
-
- // Create a buffer and start from the end
- unsigned size = max(f.get_width(), digits+8);
- char *buf = new char[size];
- char *end = buf+size;
- char *ptr = end;
-
- // Format exponent
- if(showexp)
- {
- ptr = int_to_str(exp, Fmt().showpos().fill('0').width(3), ptr);
- *--ptr = (f.get_uppercase() ? 'E' : 'e');
- }
-
- // Format mantissa left-to-right
- char *eptr = ptr;
- ptr -= digits+(point<digits || f.get_showpoint());
- char *mptr = ptr;
- for(unsigned i=0; i<digits; ++i)
- {
- if(i==point)
- *mptr++ = '.';
- if(showexp || static_cast<int>(i)>=-exp)
- {
- int digit = static_cast<int>(w);
- *mptr++ = '0'+digit;
- w = (w-digit)*10;
- }
- else
- *mptr++ = '0';
- }
-
- if(f.get_showpoint())
- {
- // Radix point requested but not displayed yet, add it
- if(digits<=point)
- *mptr++ = '.';
- }
- else if(mode==Fmt::AUTOFLT && digits>point)
- {
- // Remove trailing zeroes from fraction and a lone radix point
- while(mptr[-1]=='0')
- --mptr;
- if(mptr[-1]=='.')
- --mptr;
- if(mptr!=eptr)
- {
- while(mptr!=ptr)
- *--eptr = *--mptr;
- ptr = eptr;
- }
- }
-
- // Add filling and sign
- if(f.get_fill()=='0')
- {
- unsigned pfxlen = (sign!=0);
- while(end-ptr+pfxlen<f.get_width())
- *--ptr = '0';
- }
- if(sign)
- *--ptr = sign;
-
- string result(ptr, end);
- delete[] buf;
- return result;
-}
-
-template<typename T>
-T str_to_flt(const string &s, const Fmt &)
-{
- if(s.empty())
- throw LexicalError("Empty input in floating-point conversion");
-
- std::string::const_iterator i = s.begin();
-
- // See if the input starts with a sign
- bool neg = false;
- if(*i=='-')
- {
- neg = true;
- ++i;
- }
- else if(*i=='+')
- ++i;
-
- // Must have some digits to convert
- if(i==s.end())
- throw LexicalError("Missing digits in floating-point conversion");
-
- long double v = 0;
- int exp = 0;
-
- // Parse mantissa
- bool point_seen = false;
- for(; i!=s.end(); ++i)
- {
- if(*i=='.')
- {
- if(point_seen)
- throw LexicalError("Extra point in floating-point conversion");
- point_seen = true;
- }
- else if(*i>='0' && *i<='9')
- {
- v = v*10+(*i-'0');
- if(point_seen)
- --exp;
- }
- else if(*i=='e' || *i=='E')
- {
- // We have an exponent
- ++i;
-
- exp += str_to_int<int>(string(i, s.end()), Fmt());
- // str_to_int has eaten the rest of the input or thrown
- break;
- }
- else
- throw LexicalError("Invalid digit in floating-point conversion");
- }
-
- // Scale and negate the result as needed
- while(exp>0)
- {
- v *= 10;
- --exp;
- }
- while(exp<0)
- {
- v /= 10;
- ++exp;
- }
-
- if(neg)
- v = -v;
-
- return v;
-}
-
-
-/*** String conversions ***/
-
-string str_to_str(const string &s, const Fmt &f)
-{
- if(f.get_type()==Fmt::NUM)
- throw LexicalError("Numeric format in string conversion");
- return s;
-}
-
-}
-
-namespace Msp {
-
-void LexicalConverter::result(const string &s)
-{
- if(s.size()<fmt.get_width())
- {
- if(fmt.get_align()==Fmt::RIGHT)
- buf = string(fmt.get_width()-s.size(), fmt.get_fill())+s;
- else
- buf = s+string(fmt.get_width()-s.size(), fmt.get_fill());
- }
- else
- buf = s;
-}
-
-
-/*** operator<< ***/
-
-void operator<<(LexicalConverter &c, char v)
-{
- Fmt::Type type = c.get_fmt().get_type();
- if(type==Fmt::NUM)
- c.result(int_to_str(v, c.get_fmt()));
- else
- c.result(string(1, v));
-}
-
-void operator<<(LexicalConverter &c, signed char v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, short v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, int v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, long v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, unsigned char v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, unsigned short v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, unsigned v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, unsigned long v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-#ifdef __GNUC__
-void operator<<(LexicalConverter &c, long long v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, unsigned long long v)
-{ c.result(int_to_str(v, c.get_fmt())); }
-#endif
-
-void operator<<(LexicalConverter &c, bool v)
-{ c.result(bool_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, float v)
-{ c.result(flt_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, double v)
-{ c.result(flt_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, long double v)
-{ c.result(flt_to_str(v, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, const string &s)
-{ c.result(str_to_str(s, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, const char *s)
-{ c.result(str_to_str(s, c.get_fmt())); }
-
-void operator<<(LexicalConverter &c, const void *p)
-{ c.result(int_to_str(reinterpret_cast<unsigned long>(p), c.get_fmt())); }
-
-
-/*** operator>> ***/
-
-void operator>>(const LexicalConverter &c, char &v)
-{
- if(c.get_fmt().get_type()==Fmt::NUM)
- v = str_to_int<char>(c.get(), c.get_fmt());
- else
- {
- const std::string &s = c.get();
- if(s.empty())
- throw LexicalError("Empty input in character conversion");
- if(s.size()>1)
- throw LexicalError("Extra input in character conversion");
- v = s[0];
- }
-}
-
-void operator>>(const LexicalConverter &c, signed char &v)
-{ v = str_to_int<signed char>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, short &v)
-{ v = str_to_int<short>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, int &v)
-{ v = str_to_int<int>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, long &v)
-{ v = str_to_int<long>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, unsigned char &v)
-{ v = str_to_int<unsigned char>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, unsigned short &v)
-{ v = str_to_int<unsigned short>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, unsigned int &v)
-{ v = str_to_int<unsigned int>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, unsigned long &v)
-{ v = str_to_int<unsigned long>(c.get(), c.get_fmt()); }
-
-#ifdef __GNUC__
-void operator>>(const LexicalConverter &c, long long &v)
-{ v = str_to_int<long long>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, unsigned long long &v)
-{ v = str_to_int<unsigned long long>(c.get(), c.get_fmt()); }
-#endif
-
-void operator>>(const LexicalConverter &c, bool &v)
-{ v = str_to_bool(c.get()); }
-
-void operator>>(const LexicalConverter &c, float &v)
-{ v = str_to_flt<float>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, double &v)
-{ v = str_to_flt<double>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, long double &v)
-{ v = str_to_flt<long double>(c.get(), c.get_fmt()); }
-
-void operator>>(const LexicalConverter &c, string &s)
-{ s = str_to_str(c.get(), c.get_fmt()); }
-
-} // namespace Msp