3 This file is part of libmspstrings
4 Copyright © 2006-2008 Mikko Rasa
5 Distributed under the LGPL
11 #include "lexicalcast.h"
21 { enum { result = !(static_cast<T>(-1)>0) }; };
23 template<typename T, bool f = (sizeof(T)>sizeof(unsigned long))>
25 { typedef unsigned long Type; };
28 struct Temporary<T, true>
33 typedef unsigned long long Type;
37 /* Helper to avoid warnings about an unsigned type never being < 0 */
38 template<typename T, bool f = IsSigned<T>::result>
40 { static bool eval(T v) { return v<0; } };
43 struct IsNegative<T, false>
44 { static bool eval(T) { return false; } };
46 /* Helper to avoid errors about ambiguous function calls since there are no
47 overloads of abs for unsigned types */
48 template<typename T, bool f = IsSigned<T>::result>
50 { static T eval(T v) { return v<0 ? -v : v; } };
53 struct Absolute<T, false>
54 { static T eval(T v) { return v; } };
57 /*** Integer conversions ***/
59 const char udigits[] = "0123456789ABCDEF";
60 const char ldigits[] = "0123456789abcdef";
63 char *int_to_str(T v, const Fmt &f, char *end)
65 if(f.get_type()==Fmt::CHAR)
73 // Find out the base to use
74 unsigned base = f.get_base();
78 // Format the number, starting from the least significant digit
79 const char *digits = (f.get_uppercase() ? udigits : ldigits);
82 typename Temporary<T>::Type w = Absolute<T>::eval(v);
85 *--ptr = digits[w%base];
92 char sign = (IsNegative<T>::eval(v) ? '-' : f.get_showpos() ? '+' : 0);
95 /* Zero-fill, taking base/sign size into account. The expression is a
96 bit ugly, but saves having to write code for creating the prefix both
98 unsigned pfxsize = ((f.get_showbase() && base!=10) ? base==8 ? 1 : 2 : 0) + (sign!=0);
99 for(unsigned i=(end-ptr)+pfxsize; i<f.get_width(); ++i)
103 if(f.get_showbase() && v!=0)
105 // Add base indicator
107 *--ptr = (f.get_uppercase() ? 'B' : 'b');
109 *--ptr = (f.get_uppercase() ? 'X' : 'x');
121 string int_to_str(T v, const Fmt &f)
123 unsigned size = max(f.get_width(), max<unsigned>(f.get_precision(), sizeof(T)*8+3));
124 char *buf = new char[size];
125 string result(int_to_str(v, f, buf+size), buf+size);
131 T str_to_int(const std::string &s, const Fmt &f)
134 throw lexical_error("conversion of '' to integer");
136 std::string::const_iterator i = s.begin();
138 // See if the input starts with a sign
142 if(!IsSigned<T>::result)
143 throw lexical_error(format("conversion of '%s' to unsigned integer", s));
150 // Must have some digits to convert
152 throw lexical_error(format("conversion of '%s' to integer", s));
154 T base = f.get_base();
155 if(!base && i!=s.end())
157 // Automatic base detection requested, figure it out
158 if(*i=='0' && ++i!=s.end())
160 if(*i=='x' || *i=='X')
165 else if(*i=='b' || *i=='B')
179 for(; i!=s.end(); ++i)
182 if(*i>='0' && *i<='9')
184 else if(*i>='A' && *i<='F')
186 else if(*i>='a' && *i<='f')
189 throw lexical_error(format("conversion of '%s' to integer (base-%d)", s, base));
190 T next = result*base+digit;
191 if(next/base!=result)
192 throw lexical_error(format("conversion of '%s' to %d-bit integer", s, sizeof(T)*8));
203 /*** Boolean conversions ***/
205 string bool_to_str(bool b, const Fmt &f)
207 if(f.get_type()==Fmt::STR)
208 return b ? "true" : "false";
210 return b ? "1" : "0";
213 bool str_to_bool(const string &s)
216 throw lexical_error("conversion of '' to boolean");
218 if(s=="1" || s=="true" || s=="yes" || s=="on")
220 else if(s=="0" || s=="false" || s=="no" || s=="off")
223 throw lexical_error(format("conversion of '%s' to boolean", s));
227 /*** Floating-point conversions ***/
230 string flt_to_str(T v, const Fmt &f)
232 if(f.get_type()==Fmt::CHAR)
233 throw format_mismatch("floating-point conversion with character format");
235 Fmt::FloatMode mode = f.get_floatmode();
236 long double w = abs(v);
237 char sign = (v<0 ? '-' : f.get_showpos() ? '+' : 0);
239 // Handle infinity and not-a-number as special cases
246 result += (f.get_uppercase() ? "NAN" : "nan");
248 result += (f.get_uppercase() ? "INF" : "inf");
249 if(result.size()<f.get_width())
250 result = string(f.get_width()-result.size(), ' ')+result;
254 /* Find out the base-10 exponent. Building up the multiplier / divisor
255 first helps with accuracy in some cases. */
267 else if(mode!=Fmt::FIXED && w<1 && w!=0)
278 // Decide how to format the number
281 bool showexp = false;
285 digits = point+f.get_precision();
287 else if(mode==Fmt::SCI)
289 digits = f.get_precision()+1;
294 digits = max(f.get_precision(), 1U);
295 if(exp<-4 || exp>=static_cast<int>(digits))
302 point = max(exp, 0)+1;
309 w += 5.0l/pow(10.0l, static_cast<long double>(digits));
312 // Rounding bumped us to the next exponent, deal with it
314 if(mode==Fmt::AUTOFLT && exp+1==static_cast<int>(digits))
328 // Create a buffer and start from the end
329 unsigned size = max(f.get_width(), digits+8);
330 char *buf = new char[size];
331 char *end = buf+size;
337 ptr = int_to_str(exp, Fmt().showpos().fill('0').width(3), ptr);
338 *--ptr = (f.get_uppercase() ? 'E' : 'e');
341 // Format mantissa left-to-right
343 ptr -= digits+(point<digits || f.get_showpoint());
345 for(unsigned i=0; i<digits; ++i)
349 if(showexp || static_cast<int>(i)>=-exp)
351 int digit = static_cast<int>(w);
359 if(f.get_showpoint())
361 // Radix point requested but not displayed yet, add it
365 else if(mode==Fmt::AUTOFLT && digits>point)
367 // Remove trailing zeroes from fraction and a lone radix point
380 // Add filling and sign
381 if(f.get_fill()=='0')
383 unsigned pfxlen = (sign!=0);
384 while(end-ptr+pfxlen<f.get_width())
390 string result(ptr, end);
396 T str_to_flt(const string &s, const Fmt &)
399 throw lexical_error("conversion of '' to floating-point");
401 std::string::const_iterator i = s.begin();
403 // See if the input starts with a sign
413 // Must have some digits to convert
415 throw lexical_error(format("conversion of '%s' to floating-point", s));
421 bool point_seen = false;
422 for(; i!=s.end(); ++i)
427 throw lexical_error(format("conversion of '%s' to floating-point", s));
430 else if(*i>='0' && *i<='9')
436 else if(*i=='e' || *i=='E')
438 // We have an exponent
441 exp += str_to_int<int>(string(i, s.end()), Fmt());
442 // str_to_int has eaten the rest of the input or thrown
446 throw lexical_error(format("conversion of '%s' to floating-point", s));
449 // Scale and negate the result as needed
468 /*** String conversions ***/
470 string str_to_str(const string &s, const Fmt &f)
472 if(f.get_type()==Fmt::NUM)
473 throw format_mismatch("string conversion with numeric format");
481 void LexicalConverter::result(const string &s)
483 if(s.size()<fmt.get_width())
485 if(fmt.get_align()==Fmt::RIGHT)
486 buf = string(fmt.get_width()-s.size(), fmt.get_fill())+s;
488 buf = s+string(fmt.get_width()-s.size(), fmt.get_fill());
497 void operator<<(LexicalConverter &c, char v)
499 Fmt::Type type = c.get_fmt().get_type();
501 c.result(int_to_str(v, c.get_fmt()));
503 c.result(string(1, v));
506 void operator<<(LexicalConverter &c, signed char v)
507 { c.result(int_to_str(v, c.get_fmt())); }
509 void operator<<(LexicalConverter &c, short v)
510 { c.result(int_to_str(v, c.get_fmt())); }
512 void operator<<(LexicalConverter &c, int v)
513 { c.result(int_to_str(v, c.get_fmt())); }
515 void operator<<(LexicalConverter &c, long v)
516 { c.result(int_to_str(v, c.get_fmt())); }
518 void operator<<(LexicalConverter &c, unsigned char v)
519 { c.result(int_to_str(v, c.get_fmt())); }
521 void operator<<(LexicalConverter &c, unsigned short v)
522 { c.result(int_to_str(v, c.get_fmt())); }
524 void operator<<(LexicalConverter &c, unsigned v)
525 { c.result(int_to_str(v, c.get_fmt())); }
527 void operator<<(LexicalConverter &c, unsigned long v)
528 { c.result(int_to_str(v, c.get_fmt())); }
531 void operator<<(LexicalConverter &c, long long v)
532 { c.result(int_to_str(v, c.get_fmt())); }
534 void operator<<(LexicalConverter &c, unsigned long long v)
535 { c.result(int_to_str(v, c.get_fmt())); }
538 void operator<<(LexicalConverter &c, bool v)
539 { c.result(bool_to_str(v, c.get_fmt())); }
541 void operator<<(LexicalConverter &c, float v)
542 { c.result(flt_to_str(v, c.get_fmt())); }
544 void operator<<(LexicalConverter &c, double v)
545 { c.result(flt_to_str(v, c.get_fmt())); }
547 void operator<<(LexicalConverter &c, long double v)
548 { c.result(flt_to_str(v, c.get_fmt())); }
550 void operator<<(LexicalConverter &c, const string &s)
551 { c.result(str_to_str(s, c.get_fmt())); }
553 void operator<<(LexicalConverter &c, const char *s)
554 { c.result(str_to_str(s, c.get_fmt())); }
556 void operator<<(LexicalConverter &c, const void *p)
557 { c.result(int_to_str(reinterpret_cast<unsigned long>(p), c.get_fmt())); }
562 void operator>>(const LexicalConverter &c, char &v)
564 if(c.get_fmt().get_type()==Fmt::NUM)
565 v = str_to_int<char>(c.get(), c.get_fmt());
568 const std::string &s = c.get();
570 throw lexical_error("conversion of '' to character");
572 throw lexical_error(format("conversion of '%s' to character", s));
577 void operator>>(const LexicalConverter &c, signed char &v)
578 { v = str_to_int<signed char>(c.get(), c.get_fmt()); }
580 void operator>>(const LexicalConverter &c, short &v)
581 { v = str_to_int<short>(c.get(), c.get_fmt()); }
583 void operator>>(const LexicalConverter &c, int &v)
584 { v = str_to_int<int>(c.get(), c.get_fmt()); }
586 void operator>>(const LexicalConverter &c, long &v)
587 { v = str_to_int<long>(c.get(), c.get_fmt()); }
589 void operator>>(const LexicalConverter &c, unsigned char &v)
590 { v = str_to_int<unsigned char>(c.get(), c.get_fmt()); }
592 void operator>>(const LexicalConverter &c, unsigned short &v)
593 { v = str_to_int<unsigned short>(c.get(), c.get_fmt()); }
595 void operator>>(const LexicalConverter &c, unsigned int &v)
596 { v = str_to_int<unsigned int>(c.get(), c.get_fmt()); }
598 void operator>>(const LexicalConverter &c, unsigned long &v)
599 { v = str_to_int<unsigned long>(c.get(), c.get_fmt()); }
602 void operator>>(const LexicalConverter &c, long long &v)
603 { v = str_to_int<long long>(c.get(), c.get_fmt()); }
605 void operator>>(const LexicalConverter &c, unsigned long long &v)
606 { v = str_to_int<unsigned long long>(c.get(), c.get_fmt()); }
609 void operator>>(const LexicalConverter &c, bool &v)
610 { v = str_to_bool(c.get()); }
612 void operator>>(const LexicalConverter &c, float &v)
613 { v = str_to_flt<float>(c.get(), c.get_fmt()); }
615 void operator>>(const LexicalConverter &c, double &v)
616 { v = str_to_flt<double>(c.get(), c.get_fmt()); }
618 void operator>>(const LexicalConverter &c, long double &v)
619 { v = str_to_flt<long double>(c.get(), c.get_fmt()); }
621 void operator>>(const LexicalConverter &c, string &s)
622 { s = str_to_str(c.get(), c.get_fmt()); }