|
1 #ifndef BOOST_LEXICAL_CAST_INCLUDED |
|
2 #define BOOST_LEXICAL_CAST_INCLUDED |
|
3 |
|
4 // Boost lexical_cast.hpp header -------------------------------------------// |
|
5 // |
|
6 // See http://www.boost.org for most recent version including documentation. |
|
7 // See end of this header for rights and permissions. |
|
8 // |
|
9 // what: lexical_cast custom keyword cast |
|
10 // who: contributed by Kevlin Henney, |
|
11 // enhanced with contributions from Terje Slettebų, |
|
12 // with additional fixes and suggestions from Gennaro Prota, |
|
13 // Beman Dawes, Dave Abrahams, Daryle Walker, Peter Dimov, |
|
14 // and other Boosters |
|
15 // when: November 2000, March 2003, June 2005 |
|
16 |
|
17 #include <cstddef> |
|
18 #include <string> |
|
19 #include <typeinfo> |
|
20 #include <boost/config.hpp> |
|
21 #include <boost/limits.hpp> |
|
22 #include <boost/throw_exception.hpp> |
|
23 #include <boost/type_traits/is_pointer.hpp> |
|
24 |
|
25 #ifdef BOOST_NO_STRINGSTREAM |
|
26 #include <strstream> |
|
27 #else |
|
28 #include <sstream> |
|
29 #endif |
|
30 |
|
31 #if defined(BOOST_NO_STRINGSTREAM) || \ |
|
32 defined(BOOST_NO_STD_WSTRING) || \ |
|
33 defined(BOOST_NO_STD_LOCALE) |
|
34 #define DISABLE_WIDE_CHAR_SUPPORT |
|
35 #endif |
|
36 |
|
37 namespace boost |
|
38 { |
|
39 // exception used to indicate runtime lexical_cast failure |
|
40 class bad_lexical_cast : public std::bad_cast |
|
41 { |
|
42 public: |
|
43 bad_lexical_cast() : |
|
44 source(&typeid(void)), target(&typeid(void)) |
|
45 { |
|
46 } |
|
47 bad_lexical_cast( |
|
48 const std::type_info &source_type, |
|
49 const std::type_info &target_type) : |
|
50 source(&source_type), target(&target_type) |
|
51 { |
|
52 } |
|
53 const std::type_info &source_type() const |
|
54 { |
|
55 return *source; |
|
56 } |
|
57 const std::type_info &target_type() const |
|
58 { |
|
59 return *target; |
|
60 } |
|
61 virtual const char *what() const throw() |
|
62 { |
|
63 return "bad lexical cast: " |
|
64 "source type value could not be interpreted as target"; |
|
65 } |
|
66 virtual ~bad_lexical_cast() throw() |
|
67 { |
|
68 } |
|
69 private: |
|
70 const std::type_info *source; |
|
71 const std::type_info *target; |
|
72 }; |
|
73 |
|
74 namespace detail // selectors for choosing stream character type |
|
75 { |
|
76 template<typename Type> |
|
77 struct stream_char |
|
78 { |
|
79 typedef char type; |
|
80 }; |
|
81 |
|
82 #ifndef DISABLE_WIDE_CHAR_SUPPORT |
|
83 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) |
|
84 template<> |
|
85 struct stream_char<wchar_t> |
|
86 { |
|
87 typedef wchar_t type; |
|
88 }; |
|
89 #endif |
|
90 |
|
91 template<> |
|
92 struct stream_char<wchar_t *> |
|
93 { |
|
94 typedef wchar_t type; |
|
95 }; |
|
96 |
|
97 template<> |
|
98 struct stream_char<const wchar_t *> |
|
99 { |
|
100 typedef wchar_t type; |
|
101 }; |
|
102 |
|
103 template<> |
|
104 struct stream_char<std::wstring> |
|
105 { |
|
106 typedef wchar_t type; |
|
107 }; |
|
108 #endif |
|
109 |
|
110 template<typename TargetChar, typename SourceChar> |
|
111 struct widest_char |
|
112 { |
|
113 typedef TargetChar type; |
|
114 }; |
|
115 |
|
116 template<> |
|
117 struct widest_char<char, wchar_t> |
|
118 { |
|
119 typedef wchar_t type; |
|
120 }; |
|
121 } |
|
122 |
|
123 namespace detail // stream wrapper for handling lexical conversions |
|
124 { |
|
125 template<typename Target, typename Source> |
|
126 class lexical_stream |
|
127 { |
|
128 private: |
|
129 typedef typename widest_char< |
|
130 typename stream_char<Target>::type, |
|
131 typename stream_char<Source>::type>::type char_type; |
|
132 |
|
133 public: |
|
134 lexical_stream() |
|
135 { |
|
136 stream.unsetf(std::ios::skipws); |
|
137 |
|
138 if(std::numeric_limits<Target>::is_specialized) |
|
139 stream.precision(std::numeric_limits<Target>::digits10 + 1); |
|
140 else if(std::numeric_limits<Source>::is_specialized) |
|
141 stream.precision(std::numeric_limits<Source>::digits10 + 1); |
|
142 } |
|
143 ~lexical_stream() |
|
144 { |
|
145 #if defined(BOOST_NO_STRINGSTREAM) |
|
146 stream.freeze(false); |
|
147 #endif |
|
148 } |
|
149 bool operator<<(const Source &input) |
|
150 { |
|
151 return !(stream << input).fail(); |
|
152 } |
|
153 template<typename InputStreamable> |
|
154 bool operator>>(InputStreamable &output) |
|
155 { |
|
156 return !is_pointer<InputStreamable>::value && |
|
157 stream >> output && |
|
158 stream.get() == |
|
159 #if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING) |
|
160 // GCC 2.9x lacks std::char_traits<>::eof(). |
|
161 // We use BOOST_NO_STD_WSTRING to filter out STLport and libstdc++-v3 |
|
162 // configurations, which do provide std::char_traits<>::eof(). |
|
163 |
|
164 EOF; |
|
165 #else |
|
166 std::char_traits<char_type>::eof(); |
|
167 #endif |
|
168 } |
|
169 bool operator>>(std::string &output) |
|
170 { |
|
171 #if defined(BOOST_NO_STRINGSTREAM) |
|
172 stream << '\0'; |
|
173 #endif |
|
174 output = stream.str(); |
|
175 return true; |
|
176 } |
|
177 #ifndef DISABLE_WIDE_CHAR_SUPPORT |
|
178 bool operator>>(std::wstring &output) |
|
179 { |
|
180 output = stream.str(); |
|
181 return true; |
|
182 } |
|
183 #endif |
|
184 private: |
|
185 #if defined(BOOST_NO_STRINGSTREAM) |
|
186 std::strstream stream; |
|
187 #elif defined(BOOST_NO_STD_LOCALE) |
|
188 std::stringstream stream; |
|
189 #else |
|
190 std::basic_stringstream<char_type> stream; |
|
191 #endif |
|
192 }; |
|
193 } |
|
194 |
|
195 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION |
|
196 |
|
197 // call-by-const reference version |
|
198 |
|
199 namespace detail |
|
200 { |
|
201 template<class T> |
|
202 struct array_to_pointer_decay |
|
203 { |
|
204 typedef T type; |
|
205 }; |
|
206 |
|
207 template<class T, std::size_t N> |
|
208 struct array_to_pointer_decay<T[N]> |
|
209 { |
|
210 typedef const T * type; |
|
211 }; |
|
212 } |
|
213 |
|
214 template<typename Target, typename Source> |
|
215 Target lexical_cast(const Source &arg) |
|
216 { |
|
217 typedef typename detail::array_to_pointer_decay<Source>::type NewSource; |
|
218 |
|
219 detail::lexical_stream<Target, NewSource> interpreter; |
|
220 Target result = 0; |
|
221 |
|
222 if(!(interpreter << arg && interpreter >> result)) |
|
223 throw_exception(bad_lexical_cast(typeid(NewSource), typeid(Target))); |
|
224 return result; |
|
225 } |
|
226 |
|
227 #else |
|
228 |
|
229 // call-by-value fallback version (deprecated) |
|
230 |
|
231 template<typename Target, typename Source> |
|
232 Target lexical_cast(Source arg) |
|
233 { |
|
234 detail::lexical_stream<Target, Source> interpreter; |
|
235 Target result; |
|
236 |
|
237 if(!(interpreter << arg && interpreter >> result)) |
|
238 throw_exception(bad_lexical_cast(typeid(Source), typeid(Target))); |
|
239 return result; |
|
240 } |
|
241 |
|
242 #endif |
|
243 } |
|
244 |
|
245 // Copyright Kevlin Henney, 2000-2005. All rights reserved. |
|
246 // |
|
247 // Distributed under the Boost Software License, Version 1.0. (See |
|
248 // accompanying file LICENSE_1_0.txt or copy at |
|
249 // http://www.boost.org/LICENSE_1_0.txt) |
|
250 |
|
251 #undef DISABLE_WIDE_CHAR_SUPPORT |
|
252 #endif |