]> git.tdb.fi Git - libs/core.git/blobdiff - source/lexicalcast.cpp
Move files around to prepare for assimilation into core
[libs/core.git] / source / lexicalcast.cpp
diff --git a/source/lexicalcast.cpp b/source/lexicalcast.cpp
deleted file mode 100644 (file)
index 5903bb1..0000000
+++ /dev/null
@@ -1,623 +0,0 @@
-/* $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