3 #include <msp/core/inttypes.h>
5 #include "lexicalcast.h"
15 { enum { result = !(static_cast<T>(-1)>0) }; };
17 /* Helper to avoid warnings about an unsigned type never being < 0 */
18 template<typename T, bool f = IsSigned<T>::result>
20 { static bool eval(T v) { return v<0; } };
23 struct IsNegative<T, false>
24 { static bool eval(T) { return false; } };
26 /* Helper to avoid errors about ambiguous function calls since there are no
27 overloads of abs for unsigned types */
28 template<typename T, bool f = IsSigned<T>::result>
30 { static T eval(T v) { return v<0 ? -v : v; } };
33 struct Absolute<T, false>
34 { static T eval(T v) { return v; } };
37 /*** Integer conversions ***/
39 const char udigits[] = "0123456789ABCDEF";
40 const char ldigits[] = "0123456789abcdef";
43 char *int_to_str(T v, const Fmt &f, char *end)
45 if(f.get_type()==Fmt::CHAR)
53 // Find out the base to use
54 unsigned base = f.get_base();
58 // Format the number, starting from the least significant digit
59 const char *digits = (f.get_uppercase() ? udigits : ldigits);
62 typename MatchingInt<T>::UnsignedType w = Absolute<T>::eval(v);
65 *--ptr = digits[w%base];
72 char sign = (IsNegative<T>::eval(v) ? '-' : f.get_showpos() ? '+' : 0);
75 /* Zero-fill, taking base/sign size into account. The expression is a
76 bit ugly, but saves having to write code for creating the prefix both
78 unsigned pfxsize = ((f.get_showbase() && base!=10) ? base==8 ? 1 : 2 : 0) + (sign!=0);
79 for(unsigned i=(end-ptr)+pfxsize; i<f.get_width(); ++i)
83 if(f.get_showbase() && v!=0)
87 *--ptr = (f.get_uppercase() ? 'B' : 'b');
89 *--ptr = (f.get_uppercase() ? 'X' : 'x');
101 string int_to_str(T v, const Fmt &f)
103 unsigned size = max(f.get_width(), max<unsigned>(f.get_precision(), sizeof(T)*8+3));
104 char *buf = new char[size];
105 string result(int_to_str(v, f, buf+size), buf+size);
111 T str_to_int(const std::string &s, const Fmt &f)
114 throw lexical_error("conversion of '' to integer");
116 std::string::const_iterator i = s.begin();
118 // See if the input starts with a sign
122 if(!IsSigned<T>::result)
123 throw lexical_error(format("conversion of '%s' to unsigned integer", s));
130 // Must have some digits to convert
132 throw lexical_error(format("conversion of '%s' to integer", s));
134 T base = f.get_base();
135 if(!base && i!=s.end())
137 // Automatic base detection requested, figure it out
138 if(*i=='0' && ++i!=s.end())
140 if(*i=='x' || *i=='X')
145 else if(*i=='b' || *i=='B')
159 for(; i!=s.end(); ++i)
162 if(*i>='0' && *i<='9')
164 else if(*i>='A' && *i<='F')
166 else if(*i>='a' && *i<='f')
169 throw lexical_error(format("conversion of '%s' to integer (base-%d)", s, base));
170 T next = result*base+digit;
171 if(next/base!=result)
172 throw lexical_error(format("conversion of '%s' to %d-bit integer", s, sizeof(T)*8));
183 /*** Boolean conversions ***/
185 string bool_to_str(bool b, const Fmt &f)
187 if(f.get_type()==Fmt::STR)
188 return b ? "true" : "false";
190 return b ? "1" : "0";
193 bool str_to_bool(const string &s)
196 throw lexical_error("conversion of '' to boolean");
198 if(s=="1" || s=="true" || s=="yes" || s=="on")
200 else if(s=="0" || s=="false" || s=="no" || s=="off")
203 throw lexical_error(format("conversion of '%s' to boolean", s));
207 /*** Floating-point conversions ***/
210 string flt_to_str(T v, const Fmt &f)
212 if(f.get_type()==Fmt::CHAR)
213 throw format_mismatch("floating-point conversion with character format");
215 Fmt::FloatMode mode = f.get_floatmode();
216 long double w = abs(v);
217 char sign = (v<0 ? '-' : f.get_showpos() ? '+' : 0);
219 // Handle infinity and not-a-number as special cases
226 result += (f.get_uppercase() ? "NAN" : "nan");
228 result += (f.get_uppercase() ? "INF" : "inf");
229 if(result.size()<f.get_width())
230 result = string(f.get_width()-result.size(), ' ')+result;
234 /* Find out the base-10 exponent. Building up the multiplier / divisor
235 first helps with accuracy in some cases. */
247 else if(mode!=Fmt::FIXED && w<1 && w!=0)
258 // Decide how to format the number
260 unsigned leading_zeroes = 0;
262 bool showexp = false;
266 digits = point+f.get_precision();
268 else if(mode==Fmt::SCI)
270 digits = f.get_precision()+1;
275 digits = max(f.get_precision(), 1U);
276 if(exp<-4 || exp>=static_cast<int>(digits))
284 leading_zeroes = -exp;
291 w += 5.0l/pow(10.0l, static_cast<long double>(digits));
294 // Rounding bumped us to the next exponent, deal with it
296 if(mode==Fmt::AUTOFLT && exp+1==static_cast<int>(digits))
314 digits += leading_zeroes;
316 // Create a buffer and start from the end
317 unsigned size = max(f.get_width(), digits+8);
318 char *buf = new char[size];
319 char *end = buf+size;
325 ptr = int_to_str(exp, Fmt().showpos().fill('0').width(3), ptr);
326 *--ptr = (f.get_uppercase() ? 'E' : 'e');
329 // Format mantissa left-to-right
331 ptr -= digits+(point<digits || f.get_showpoint());
333 for(unsigned i=0; i<digits; ++i)
339 int digit = static_cast<int>(w);
350 if(f.get_showpoint())
352 // Radix point requested but not displayed yet, add it
356 else if(mode==Fmt::AUTOFLT && digits>point)
358 // Remove trailing zeroes from fraction and a lone radix point
371 // Add filling and sign
372 if(f.get_fill()=='0')
374 unsigned pfxlen = (sign!=0);
375 while(end-ptr+pfxlen<f.get_width())
381 string result(ptr, end);
387 T str_to_flt(const string &s, const Fmt &)
390 throw lexical_error("conversion of '' to floating-point");
392 std::string::const_iterator i = s.begin();
394 // See if the input starts with a sign
404 // Must have some digits to convert
406 throw lexical_error(format("conversion of '%s' to floating-point", s));
412 bool point_seen = false;
413 for(; i!=s.end(); ++i)
418 throw lexical_error(format("conversion of '%s' to floating-point", s));
421 else if(*i>='0' && *i<='9')
427 else if(*i=='e' || *i=='E')
429 // We have an exponent
432 exp += str_to_int<int>(string(i, s.end()), Fmt());
433 // str_to_int has eaten the rest of the input or thrown
437 throw lexical_error(format("conversion of '%s' to floating-point", s));
440 // Scale and negate the result as needed
459 /*** String conversions ***/
461 string str_to_str(const string &s, const Fmt &f)
463 if(f.get_type()==Fmt::NUM)
464 throw format_mismatch("string conversion with numeric format");
472 void LexicalConverter::result(const string &s)
475 if(s.size()<fmt.get_width())
477 if(fmt.get_align()==Fmt::RIGHT)
478 buf = string(fmt.get_width()-s.size(), fmt.get_fill())+s;
480 buf = s+string(fmt.get_width()-s.size(), fmt.get_fill());
486 const string &LexicalConverter::get() const
489 throw lexical_error("conversion not performed");
496 void operator<<(LexicalConverter &c, char v)
498 Fmt::Type type = c.get_fmt().get_type();
500 c.result(int_to_str(v, c.get_fmt()));
502 c.result(string(1, v));
505 void operator<<(LexicalConverter &c, signed char v)
506 { c.result(int_to_str(v, c.get_fmt())); }
508 void operator<<(LexicalConverter &c, short v)
509 { c.result(int_to_str(v, c.get_fmt())); }
511 void operator<<(LexicalConverter &c, int v)
512 { c.result(int_to_str(v, c.get_fmt())); }
514 void operator<<(LexicalConverter &c, long v)
515 { c.result(int_to_str(v, c.get_fmt())); }
517 void operator<<(LexicalConverter &c, unsigned char v)
518 { c.result(int_to_str(v, c.get_fmt())); }
520 void operator<<(LexicalConverter &c, unsigned short v)
521 { c.result(int_to_str(v, c.get_fmt())); }
523 void operator<<(LexicalConverter &c, unsigned v)
524 { c.result(int_to_str(v, c.get_fmt())); }
526 void operator<<(LexicalConverter &c, unsigned long v)
527 { c.result(int_to_str(v, c.get_fmt())); }
530 void operator<<(LexicalConverter &c, long long v)
531 { c.result(int_to_str(v, c.get_fmt())); }
533 void operator<<(LexicalConverter &c, unsigned long long v)
534 { c.result(int_to_str(v, c.get_fmt())); }
537 void operator<<(LexicalConverter &c, bool v)
538 { c.result(bool_to_str(v, c.get_fmt())); }
540 void operator<<(LexicalConverter &c, float v)
541 { c.result(flt_to_str(v, c.get_fmt())); }
543 void operator<<(LexicalConverter &c, double v)
544 { c.result(flt_to_str(v, c.get_fmt())); }
546 void operator<<(LexicalConverter &c, long double v)
547 { c.result(flt_to_str(v, c.get_fmt())); }
549 void operator<<(LexicalConverter &c, const string &s)
550 { c.result(str_to_str(s, c.get_fmt())); }
552 void operator<<(LexicalConverter &c, const char *s)
553 { c.result(str_to_str(s, c.get_fmt())); }
555 void operator<<(LexicalConverter &c, const void *p)
556 { c.result(int_to_str(reinterpret_cast<IntPtr>(p), c.get_fmt())); }
561 void operator>>(const LexicalConverter &c, char &v)
563 if(c.get_fmt().get_type()==Fmt::NUM)
564 v = str_to_int<char>(c.get(), c.get_fmt());
567 const std::string &s = c.get();
569 throw lexical_error("conversion of '' to character");
571 throw lexical_error(format("conversion of '%s' to character", s));
576 void operator>>(const LexicalConverter &c, signed char &v)
577 { v = str_to_int<signed char>(c.get(), c.get_fmt()); }
579 void operator>>(const LexicalConverter &c, short &v)
580 { v = str_to_int<short>(c.get(), c.get_fmt()); }
582 void operator>>(const LexicalConverter &c, int &v)
583 { v = str_to_int<int>(c.get(), c.get_fmt()); }
585 void operator>>(const LexicalConverter &c, long &v)
586 { v = str_to_int<long>(c.get(), c.get_fmt()); }
588 void operator>>(const LexicalConverter &c, unsigned char &v)
589 { v = str_to_int<unsigned char>(c.get(), c.get_fmt()); }
591 void operator>>(const LexicalConverter &c, unsigned short &v)
592 { v = str_to_int<unsigned short>(c.get(), c.get_fmt()); }
594 void operator>>(const LexicalConverter &c, unsigned int &v)
595 { v = str_to_int<unsigned int>(c.get(), c.get_fmt()); }
597 void operator>>(const LexicalConverter &c, unsigned long &v)
598 { v = str_to_int<unsigned long>(c.get(), c.get_fmt()); }
601 void operator>>(const LexicalConverter &c, long long &v)
602 { v = str_to_int<long long>(c.get(), c.get_fmt()); }
604 void operator>>(const LexicalConverter &c, unsigned long long &v)
605 { v = str_to_int<unsigned long long>(c.get(), c.get_fmt()); }
608 void operator>>(const LexicalConverter &c, bool &v)
609 { v = str_to_bool(c.get()); }
611 void operator>>(const LexicalConverter &c, float &v)
612 { v = str_to_flt<float>(c.get(), c.get_fmt()); }
614 void operator>>(const LexicalConverter &c, double &v)
615 { v = str_to_flt<double>(c.get(), c.get_fmt()); }
617 void operator>>(const LexicalConverter &c, long double &v)
618 { v = str_to_flt<long double>(c.get(), c.get_fmt()); }
620 void operator>>(const LexicalConverter &c, string &s)
621 { s = str_to_str(c.get(), c.get_fmt()); }