]> git.tdb.fi Git - libs/core.git/blob - source/strings/lexicalcast.h
Add move semantics to Variant
[libs/core.git] / source / strings / lexicalcast.h
1 #ifndef MSP_STRINGS_LEXICALCAST_H_
2 #define MSP_STRINGS_LEXICALCAST_H_
3
4 #include <sstream>
5 #include <string>
6 #include <stdexcept>
7 #include <msp/core/meta.h>
8 #include <msp/core/mspcore_api.h>
9 #include "fmt.h"
10
11 namespace Msp {
12
13 /**
14 Thrown for errors in lexical conversions.
15 */
16 class MSPCORE_API lexical_error: public std::runtime_error
17 {
18 public:
19         lexical_error(const std::string &w): runtime_error(w) { }
20 };
21
22
23 /**
24 Thrown when the format is unsuitable for the type being converted.
25 */
26 class MSPCORE_API format_mismatch: public lexical_error
27 {
28 public:
29         format_mismatch(const std::string &w): lexical_error(w) { }
30 };
31
32
33 /**
34 Helper class for lexical_cast to facilitate operator overloading.
35 */
36 class MSPCORE_API LexicalConverter
37 {
38 private:
39         Fmt fmt;
40         bool filled = false;
41         std::string buf;
42
43 public:
44         LexicalConverter(const Fmt &f): fmt(f) { }
45         LexicalConverter(const std::string &s, const Fmt &f): fmt(f), filled(true), buf(s) { }
46
47         const Fmt &get_fmt() const { return fmt; }
48         const std::string &get() const;
49         void result(const std::string &);
50 };
51
52
53 MSPCORE_API void operator<<(LexicalConverter &, char);
54 MSPCORE_API void operator<<(LexicalConverter &, signed char);
55 MSPCORE_API void operator<<(LexicalConverter &, short);
56 MSPCORE_API void operator<<(LexicalConverter &, int);
57 MSPCORE_API void operator<<(LexicalConverter &, long);
58 MSPCORE_API void operator<<(LexicalConverter &, unsigned char);
59 MSPCORE_API void operator<<(LexicalConverter &, unsigned short);
60 MSPCORE_API void operator<<(LexicalConverter &, unsigned);
61 MSPCORE_API void operator<<(LexicalConverter &, unsigned long);
62 MSPCORE_API void operator<<(LexicalConverter &, long long);
63 MSPCORE_API void operator<<(LexicalConverter &, unsigned long long);
64 MSPCORE_API void operator<<(LexicalConverter &, bool);
65 MSPCORE_API void operator<<(LexicalConverter &, float);
66 MSPCORE_API void operator<<(LexicalConverter &, double);
67 MSPCORE_API void operator<<(LexicalConverter &, long double);
68 MSPCORE_API void operator<<(LexicalConverter &, const std::string &);
69 MSPCORE_API void operator<<(LexicalConverter &, const char *);
70 MSPCORE_API void operator<<(LexicalConverter &, const void *);
71
72 MSPCORE_API void operator>>(const LexicalConverter &, char &);
73 MSPCORE_API void operator>>(const LexicalConverter &, signed char &);
74 MSPCORE_API void operator>>(const LexicalConverter &, short &);
75 MSPCORE_API void operator>>(const LexicalConverter &, int &);
76 MSPCORE_API void operator>>(const LexicalConverter &, long &);
77 MSPCORE_API void operator>>(const LexicalConverter &, unsigned char &);
78 MSPCORE_API void operator>>(const LexicalConverter &, unsigned short &);
79 MSPCORE_API void operator>>(const LexicalConverter &, unsigned int &);
80 MSPCORE_API void operator>>(const LexicalConverter &, unsigned long &);
81 MSPCORE_API void operator>>(const LexicalConverter &, long long &);
82 MSPCORE_API void operator>>(const LexicalConverter &, unsigned long long &);
83 MSPCORE_API void operator>>(const LexicalConverter &, bool &);
84 MSPCORE_API void operator>>(const LexicalConverter &, float &);
85 MSPCORE_API void operator>>(const LexicalConverter &, double &);
86 MSPCORE_API void operator>>(const LexicalConverter &, long double &);
87 MSPCORE_API void operator>>(const LexicalConverter &, std::string &);
88
89 // Generic operators using stringstream
90
91 struct CheckFormattedOutput: Sfinae
92 {
93         static std::ostream &s;
94         template<typename T>
95         static Yes f(int (*)[sizeof(s<<reinterpret_cast<const T &>(s))]);
96         using Sfinae::f;
97 };
98
99 struct CheckFormattedInput: Sfinae
100 {
101         static std::istream &s;
102         template<typename T>
103         static Yes f(int (*)[sizeof(s>>reinterpret_cast<T &>(s))]);
104         using Sfinae::f;
105 };
106
107 template<typename T> struct HasFormattedOutput: Sfinae::Evaluate<CheckFormattedOutput, T> { };
108 template<typename T> struct HasFormattedInput: Sfinae::Evaluate<CheckFormattedInput, T> { };
109
110
111 template<typename T>
112 typename std::enable_if<HasFormattedOutput<T>::value>::type
113 operator<<(LexicalConverter &c, const T &v)
114 {
115         std::ostringstream ss;
116         ss << c.get_fmt() << v;
117         c.result(ss.str());
118 }
119
120 template<typename T>
121 typename std::enable_if<HasFormattedInput<T>::value>::type
122 operator>>(const LexicalConverter &c, T &v)
123 {
124         std::istringstream ss(c.get());
125         ss.setf(std::ios_base::fmtflags(0), std::ios_base::skipws);
126         ss >> v;
127         if(ss.fail() || !ss.eof())
128                 throw lexical_error("conversion failure");
129 }
130
131 /**
132 Helper struct to provide partial template specialization.
133 */
134 template<typename T, typename F>
135 struct LexicalCast;
136
137 template<typename T>
138 struct LexicalCast<T, std::string>
139 {
140         static T cast(const std::string &s, const Fmt &f = Fmt())
141         {
142                 LexicalConverter conv(s, f);
143                 T result;
144                 conv >> result;
145                 return result;
146         }
147 };
148
149 template<typename F>
150 struct LexicalCast<std::string, F>
151 {
152         static std::string cast(const F &v, const Fmt &f = Fmt())
153         {
154                 LexicalConverter conv(f);
155                 conv << v;
156                 return conv.get();
157         }
158 };
159
160 template<>
161 struct LexicalCast<std::string, std::string>
162 {
163         static std::string cast(const std::string &v, const Fmt &f = Fmt())
164         {
165                 LexicalConverter conv(f);
166                 conv << v;
167                 return conv.get();
168         }
169 };
170
171 /** Perform a lexical conversion between a string and another type.  The source
172 type can normally be deduced by the compiler, so this can be used just like the
173 standard C++ casts.  A format may additionally be specified to force a specific
174 interpretation. */
175 template<typename T, typename F>
176 inline T lexical_cast(const F &v, const Fmt &f = Fmt())
177 {
178         return LexicalCast<T, F>::cast(v, f);
179 }
180
181 } // namespace Msp
182
183 #endif