X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fstrings%2Flexicalcast.cpp;h=ab83b110b432ba408f8bdfa3bd2fb53d3e848c8f;hp=5903bb1197d6364382714dd4f1772b477844b919;hb=faeafc9d652ba6caa350ca95dff14408b036ccfb;hpb=b42ed73a1b241c0e93ee03c43c4584b41c549bac diff --git a/source/strings/lexicalcast.cpp b/source/strings/lexicalcast.cpp index 5903bb1..ab83b11 100644 --- a/source/strings/lexicalcast.cpp +++ b/source/strings/lexicalcast.cpp @@ -1,12 +1,7 @@ -/* $Id$ - -This file is part of libmspstrings -Copyright © 2006-2008 Mikko Rasa -Distributed under the LGPL -*/ - #include #include +#include +#include "format.h" #include "lexicalcast.h" using namespace std; @@ -19,20 +14,6 @@ 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 @@ -78,7 +59,7 @@ char *int_to_str(T v, const Fmt &f, char *end) const char *digits = (f.get_uppercase() ? udigits : ldigits); if(v) { - typename Temporary::Type w = Absolute::eval(v); + typename MatchingInt::UnsignedType w = Absolute::eval(v); while(w) { *--ptr = digits[w%base]; @@ -130,7 +111,7 @@ template T str_to_int(const std::string &s, const Fmt &f) { if(s.empty()) - throw LexicalError("Empty input in integer conversion"); + throw lexical_error("conversion of '' to integer"); std::string::const_iterator i = s.begin(); @@ -139,7 +120,7 @@ T str_to_int(const std::string &s, const Fmt &f) if(*i=='-') { if(!IsSigned::result) - throw LexicalError("Negative sign in unsigned integer conversion"); + throw lexical_error(format("conversion of '%s' to unsigned integer", s)); neg = true; ++i; } @@ -148,7 +129,7 @@ T str_to_int(const std::string &s, const Fmt &f) // Must have some digits to convert if(i==s.end()) - throw LexicalError("Missing digits in integer conversion"); + throw lexical_error(format("conversion of '%s' to integer", s)); T base = f.get_base(); if(!base && i!=s.end()) @@ -185,10 +166,10 @@ T str_to_int(const std::string &s, const Fmt &f) else if(*i>='a' && *i<='f') digit = *i-'a'+10; if(digit>=base) - throw LexicalError("Invalid digit in integer conversion"); + throw lexical_error(format("conversion of '%s' to integer (base-%d)", s, base)); T next = result*base+digit; if(next/base!=result) - throw LexicalError("Overflow in integer conversion"); + throw lexical_error(format("conversion of '%s' to %d-bit integer", s, sizeof(T)*8)); result = next; } @@ -212,14 +193,14 @@ string bool_to_str(bool b, const Fmt &f) bool str_to_bool(const string &s) { if(s.empty()) - throw LexicalError("Empty input in boolean conversion"); + throw lexical_error("conversion of '' to boolean"); 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"); + throw lexical_error(format("conversion of '%s' to boolean", s)); } @@ -229,7 +210,7 @@ template string flt_to_str(T v, const Fmt &f) { if(f.get_type()==Fmt::CHAR) - throw LexicalError("Character format in floating-point conversion"); + throw format_mismatch("floating-point conversion with character format"); Fmt::FloatMode mode = f.get_floatmode(); long double w = abs(v); @@ -256,7 +237,7 @@ string flt_to_str(T v, const Fmt &f) if(w>=10) { long double div = 1; - while(div*10(digits)); - if(w>10) + if(w>=10) { // Rounding bumped us to the next exponent, deal with it w /= 10; @@ -317,13 +300,19 @@ string flt_to_str(T v, const Fmt &f) } if(!showexp) { - ++digits; - ++point; + if(mode==Fmt::FIXED) + ++digits; + if(leading_zeroes) + --leading_zeroes; + else + ++point; } else ++exp; } + digits += leading_zeroes; + // Create a buffer and start from the end unsigned size = max(f.get_width(), digits+8); char *buf = new char[size]; @@ -345,14 +334,17 @@ string flt_to_str(T v, const Fmt &f) { if(i==point) *mptr++ = '.'; - if(showexp || static_cast(i)>=-exp) + if(!leading_zeroes) { int digit = static_cast(w); *mptr++ = '0'+digit; w = (w-digit)*10; } else + { *mptr++ = '0'; + --leading_zeroes; + } } if(f.get_showpoint()) @@ -395,7 +387,7 @@ template T str_to_flt(const string &s, const Fmt &) { if(s.empty()) - throw LexicalError("Empty input in floating-point conversion"); + throw lexical_error("conversion of '' to floating-point"); std::string::const_iterator i = s.begin(); @@ -411,7 +403,7 @@ T str_to_flt(const string &s, const Fmt &) // Must have some digits to convert if(i==s.end()) - throw LexicalError("Missing digits in floating-point conversion"); + throw lexical_error(format("conversion of '%s' to floating-point", s)); long double v = 0; int exp = 0; @@ -423,7 +415,7 @@ T str_to_flt(const string &s, const Fmt &) if(*i=='.') { if(point_seen) - throw LexicalError("Extra point in floating-point conversion"); + throw lexical_error(format("conversion of '%s' to floating-point", s)); point_seen = true; } else if(*i>='0' && *i<='9') @@ -442,7 +434,7 @@ T str_to_flt(const string &s, const Fmt &) break; } else - throw LexicalError("Invalid digit in floating-point conversion"); + throw lexical_error(format("conversion of '%s' to floating-point", s)); } // Scale and negate the result as needed @@ -469,7 +461,7 @@ T str_to_flt(const string &s, const Fmt &) string str_to_str(const string &s, const Fmt &f) { if(f.get_type()==Fmt::NUM) - throw LexicalError("Numeric format in string conversion"); + throw format_mismatch("string conversion with numeric format"); return s; } @@ -553,7 +545,7 @@ 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(p), c.get_fmt())); } +{ c.result(int_to_str(reinterpret_cast(p), c.get_fmt())); } /*** operator>> ***/ @@ -566,9 +558,9 @@ void operator>>(const LexicalConverter &c, char &v) { const std::string &s = c.get(); if(s.empty()) - throw LexicalError("Empty input in character conversion"); + throw lexical_error("conversion of '' to character"); if(s.size()>1) - throw LexicalError("Extra input in character conversion"); + throw lexical_error(format("conversion of '%s' to character", s)); v = s[0]; } }