]> git.tdb.fi Git - libs/core.git/blob - source/lexicalcast.h
Rewrite lexical_cast to use internal conversion routines
[libs/core.git] / source / lexicalcast.h
1 /* $Id$
2
3 This file is part of libmspstrings
4 Copyright © 2006-2008 Mikko Rasa
5 Distributed under the LGPL
6 */
7
8 #ifndef MSP_STRINGS_LEXICALCAST_H_
9 #define MSP_STRINGS_LEXICALCAST_H_
10
11 #include <sstream>
12 #include <string>
13 #include <msp/core/except.h>
14 #include "fmt.h"
15
16 namespace Msp {
17
18 /**
19 Thrown for errors in lexical conversions
20 */
21 class LexicalError: public Exception
22 {
23 public:
24         LexicalError(const std::string &w_): Exception(w_) { }
25 };
26
27 /**
28 Helper class for lexical_cast to facilitate operator overloading.
29 */
30 class LexicalConverter
31 {
32 private:
33         Fmt fmt;
34         std::string buf;
35
36 public:
37         LexicalConverter(const Fmt &f): fmt(f) { }
38         LexicalConverter(const std::string &s, const Fmt &f): fmt(f), buf(s) { }
39
40         const Fmt &get_fmt() const { return fmt; }
41         const std::string &get() const { return buf; }
42         void result(const std::string &);
43 };
44
45 void operator<<(LexicalConverter &, char);
46 void operator<<(LexicalConverter &, signed char);
47 void operator<<(LexicalConverter &, short);
48 void operator<<(LexicalConverter &, int);
49 void operator<<(LexicalConverter &, long);
50 void operator<<(LexicalConverter &, unsigned char);
51 void operator<<(LexicalConverter &, unsigned short);
52 void operator<<(LexicalConverter &, unsigned);
53 void operator<<(LexicalConverter &, unsigned long);
54 #ifdef __GNUC__
55 void operator<<(LexicalConverter &, long long);
56 void operator<<(LexicalConverter &, unsigned long long);
57 #endif
58 void operator<<(LexicalConverter &, bool);
59 void operator<<(LexicalConverter &, float);
60 void operator<<(LexicalConverter &, double);
61 void operator<<(LexicalConverter &, long double);
62 void operator<<(LexicalConverter &, const std::string &);
63 void operator<<(LexicalConverter &, const char *);
64 void operator<<(LexicalConverter &, const void *);
65
66 void operator>>(const LexicalConverter &, char &);
67 void operator>>(const LexicalConverter &, signed char &);
68 void operator>>(const LexicalConverter &, short &);
69 void operator>>(const LexicalConverter &, int &);
70 void operator>>(const LexicalConverter &, long &);
71 void operator>>(const LexicalConverter &, unsigned char &);
72 void operator>>(const LexicalConverter &, unsigned short &);
73 void operator>>(const LexicalConverter &, unsigned int &);
74 void operator>>(const LexicalConverter &, unsigned long &);
75 #ifdef __GNUC__
76 void operator>>(const LexicalConverter &, long long &);
77 void operator>>(const LexicalConverter &, unsigned long long &);
78 #endif
79 void operator>>(const LexicalConverter &, bool &);
80 void operator>>(const LexicalConverter &, float &);
81 void operator>>(const LexicalConverter &, double &);
82 void operator>>(const LexicalConverter &, long double &);
83 void operator>>(const LexicalConverter &, std::string &);
84
85 // Generic operators using stringstream
86
87 template<typename T>
88 void operator<<(LexicalConverter &c, const T &v)
89 {
90         std::ostringstream ss;
91         ss<<c.get_fmt()<<v;
92         c.result(ss.str());
93 }
94
95 template<typename T>
96 void operator>>(const LexicalConverter &c, T &v)
97 {
98         std::istringstream ss(c.get());
99         ss.setf(std::ios_base::fmtflags(0), std::ios_base::skipws);
100         ss>>v;
101         if(ss.fail() || !ss.eof())
102                 throw LexicalError("Conversion failure");
103 }
104
105 // The main interface to the lexical conversion machinery
106
107 template<typename T>
108 inline T lexical_cast(const std::string &s, const Fmt &f=Fmt())
109 {
110         LexicalConverter conv(s, f);
111         T result;
112         conv>>result;
113         return result;
114 }
115
116 template<typename T>
117 inline std::string lexical_cast(const T &v, const Fmt &f=Fmt())
118 {
119         LexicalConverter conv(f);
120         conv<<v;
121         return conv.get();
122 }
123
124 } // namespace Msp
125
126 #endif