X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Flexicalcast.cpp;fp=source%2Flexicalcast.cpp;h=0000000000000000000000000000000000000000;hp=5903bb1197d6364382714dd4f1772b477844b919;hb=b42ed73a1b241c0e93ee03c43c4584b41c549bac;hpb=5b1368cb791cab043f0435628cacbaff36e39b7b diff --git a/source/lexicalcast.cpp b/source/lexicalcast.cpp deleted file mode 100644 index 5903bb1..0000000 --- a/source/lexicalcast.cpp +++ /dev/null @@ -1,623 +0,0 @@ -/* $Id$ - -This file is part of libmspstrings -Copyright © 2006-2008 Mikko Rasa -Distributed under the LGPL -*/ - -#include -#include -#include "lexicalcast.h" - -using namespace std; - -namespace { - -using namespace Msp; - -template -struct IsSigned -{ enum { result = !(static_cast(-1)>0) }; }; - -templatesizeof(unsigned long))> -struct Temporary -{ typedef unsigned long Type; }; - -template -struct Temporary -{ -#ifdef WIN32 - typedef __int64 Type; -#else - typedef unsigned long long Type; -#endif -}; - -/* Helper to avoid warnings about an unsigned type never being < 0 */ -template::result> -struct IsNegative -{ static bool eval(T v) { return v<0; } }; - -template -struct IsNegative -{ 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::result> -struct Absolute -{ static T eval(T v) { return v<0 ? -v : v; } }; - -template -struct Absolute -{ static T eval(T v) { return v; } }; - - -/*** Integer conversions ***/ - -const char udigits[] = "0123456789ABCDEF"; -const char ldigits[] = "0123456789abcdef"; - -template -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::Type w = Absolute::eval(v); - while(w) - { - *--ptr = digits[w%base]; - w /= base; - } - } - else - *--ptr = digits[0]; - - char sign = (IsNegative::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 -string int_to_str(T v, const Fmt &f) -{ - unsigned size = max(f.get_width(), max(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 -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::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 -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()=10) - { - long double div = 1; - while(div*10=static_cast(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(digits)); - if(w>10) - { - // Rounding bumped us to the next exponent, deal with it - w /= 10; - if(mode==Fmt::AUTOFLT && exp+1==static_cast(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(i)>=-exp) - { - int digit = static_cast(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 -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(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()(p), c.get_fmt())); } - - -/*** operator>> ***/ - -void operator>>(const LexicalConverter &c, char &v) -{ - if(c.get_fmt().get_type()==Fmt::NUM) - v = str_to_int(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(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, short &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, int &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, long &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, unsigned char &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, unsigned short &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, unsigned int &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, unsigned long &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -#ifdef __GNUC__ -void operator>>(const LexicalConverter &c, long long &v) -{ v = str_to_int(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, unsigned long long &v) -{ v = str_to_int(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(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, double &v) -{ v = str_to_flt(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, long double &v) -{ v = str_to_flt(c.get(), c.get_fmt()); } - -void operator>>(const LexicalConverter &c, string &s) -{ s = str_to_str(c.get(), c.get_fmt()); } - -} // namespace Msp