1 //  Unit test for boost::lexical_cast.
2 //
3 //  See http://www.boost.org for most recent version, including documentation.
4 //
5 //  Copyright Antony Polukhin, 2011-2012.
6 //
7 //  Distributed under the Boost
8 //  Software License, Version 1.0. (See accompanying file
9 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
10 
11 
12 #include <boost/config.hpp>
13 #include <boost/test/unit_test.hpp>
14 
15 #include <boost/lexical_cast.hpp>
16 
17 #include <iostream>
18 
19 
20 ///////////////////////// char streamable classes ///////////////////////////////////////////
21 
22 struct streamable_easy { enum ENU {value = 0}; };
operator <<(std::ostream & ostr,const streamable_easy &)23 std::ostream& operator << (std::ostream& ostr, const streamable_easy&) {
24     return ostr << streamable_easy::value;
25 }
operator >>(std::istream & istr,const streamable_easy &)26 std::istream& operator >> (std::istream& istr, const streamable_easy&) {
27     int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value);
28     return istr;
29 }
30 
31 struct streamable_medium { enum ENU {value = 1}; };
32 template <class CharT>
33 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT>&>::type
operator <<(std::basic_ostream<CharT> & ostr,const streamable_medium &)34 operator << (std::basic_ostream<CharT>& ostr, const streamable_medium&) {
35     return ostr << streamable_medium::value;
36 }
37 template <class CharT>
38 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT>&>::type
operator >>(std::basic_istream<CharT> & istr,const streamable_medium &)39 operator >> (std::basic_istream<CharT>& istr, const streamable_medium&) {
40     int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value);
41     return istr;
42 }
43 
44 struct streamable_hard { enum ENU {value = 2}; };
45 template <class CharT, class TraitsT>
46 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT, TraitsT>&>::type
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const streamable_hard &)47 operator << (std::basic_ostream<CharT, TraitsT>& ostr, const streamable_hard&) {
48     return ostr << streamable_hard::value;
49 }
50 template <class CharT, class TraitsT>
51 typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT, TraitsT>&>::type
operator >>(std::basic_istream<CharT,TraitsT> & istr,const streamable_hard &)52 operator >> (std::basic_istream<CharT, TraitsT>& istr, const streamable_hard&) {
53     int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value);
54     return istr;
55 }
56 
57 struct streamable_hard2 { enum ENU {value = 3}; };
58 template <class TraitsT>
operator <<(std::basic_ostream<char,TraitsT> & ostr,const streamable_hard2 &)59 std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const streamable_hard2&) {
60     return ostr << streamable_hard2::value;
61 }
62 template <class TraitsT>
operator >>(std::basic_istream<char,TraitsT> & istr,const streamable_hard2 &)63 std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const streamable_hard2&) {
64     int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value);
65     return istr;
66 }
67 
68 
69 ///////////////////////// wchar_t streamable classes ///////////////////////////////////////////
70 
71 struct wstreamable_easy { enum ENU {value = 4}; };
operator <<(std::wostream & ostr,const wstreamable_easy &)72 std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) {
73     return ostr << wstreamable_easy::value;
74 }
operator >>(std::wistream & istr,const wstreamable_easy &)75 std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) {
76     int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value);
77     return istr;
78 }
79 
80 struct wstreamable_medium { enum ENU {value = 5}; };
81 template <class CharT>
82 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT>& >::type
operator <<(std::basic_ostream<CharT> & ostr,const wstreamable_medium &)83 operator << (std::basic_ostream<CharT>& ostr, const wstreamable_medium&) {
84     return ostr << wstreamable_medium::value;
85 }
86 template <class CharT>
87 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT>& >::type
operator >>(std::basic_istream<CharT> & istr,const wstreamable_medium &)88 operator >> (std::basic_istream<CharT>& istr, const wstreamable_medium&) {
89     int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value);
90     return istr;
91 }
92 
93 struct wstreamable_hard { enum ENU {value = 6}; };
94 template <class CharT, class TraitsT>
95 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT, TraitsT>&>::type
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const wstreamable_hard &)96 operator << (std::basic_ostream<CharT, TraitsT>& ostr, const wstreamable_hard&) {
97     return ostr << wstreamable_hard::value;
98 }
99 template <class CharT, class TraitsT>
100 typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT, TraitsT>&>::type
operator >>(std::basic_istream<CharT,TraitsT> & istr,const wstreamable_hard &)101 operator >> (std::basic_istream<CharT, TraitsT>& istr, const wstreamable_hard&) {
102     int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value);
103     return istr;
104 }
105 
106 struct wstreamable_hard2 { enum ENU {value = 7}; };
107 template <class TraitsT>
operator <<(std::basic_ostream<wchar_t,TraitsT> & ostr,const wstreamable_hard2 &)108 std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const wstreamable_hard2&) {
109     return ostr << wstreamable_hard2::value;
110 }
111 template <class TraitsT>
operator >>(std::basic_istream<wchar_t,TraitsT> & istr,const wstreamable_hard2 &)112 std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const wstreamable_hard2&) {
113     int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value);
114     return istr;
115 }
116 
117 ///////////////////////// char and wchar_t streamable classes ///////////////////////////////////////////
118 
119 
120 struct bistreamable_easy { enum ENU {value = 8}; };
operator <<(std::ostream & ostr,const bistreamable_easy &)121 std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) {
122     return ostr << bistreamable_easy::value;
123 }
operator >>(std::istream & istr,const bistreamable_easy &)124 std::istream& operator >> (std::istream& istr, const bistreamable_easy&) {
125     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value);
126     return istr;
127 }
128 
operator <<(std::wostream & ostr,const bistreamable_easy &)129 std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) {
130     return ostr << bistreamable_easy::value + 100;
131 }
operator >>(std::wistream & istr,const bistreamable_easy &)132 std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) {
133     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100);
134     return istr;
135 }
136 
137 struct bistreamable_medium { enum ENU {value = 9}; };
138 template <class CharT>
operator <<(std::basic_ostream<CharT> & ostr,const bistreamable_medium &)139 std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& ostr, const bistreamable_medium&) {
140     return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100);
141 }
142 template <class CharT>
operator >>(std::basic_istream<CharT> & istr,const bistreamable_medium &)143 std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, const bistreamable_medium&) {
144     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100));
145     return istr;
146 }
147 
148 struct bistreamable_hard { enum ENU {value = 10}; };
149 template <class CharT, class TraitsT>
operator <<(std::basic_ostream<CharT,TraitsT> & ostr,const bistreamable_hard &)150 std::basic_ostream<CharT, TraitsT>& operator << (std::basic_ostream<CharT, TraitsT>& ostr, const bistreamable_hard&) {
151     return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100);
152 }
153 template <class CharT, class TraitsT>
operator >>(std::basic_istream<CharT,TraitsT> & istr,const bistreamable_hard &)154 std::basic_istream<CharT, TraitsT>& operator >> (std::basic_istream<CharT, TraitsT>& istr, const bistreamable_hard&) {
155     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100));
156     return istr;
157 }
158 
159 struct bistreamable_hard2 { enum ENU {value = 11}; };
160 template <class TraitsT>
operator <<(std::basic_ostream<char,TraitsT> & ostr,const bistreamable_hard2 &)161 std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const bistreamable_hard2&) {
162     return ostr << bistreamable_hard2::value;
163 }
164 template <class TraitsT>
operator >>(std::basic_istream<char,TraitsT> & istr,const bistreamable_hard2 &)165 std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const bistreamable_hard2&) {
166     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value);
167     return istr;
168 }
169 
170 template <class TraitsT>
operator <<(std::basic_ostream<wchar_t,TraitsT> & ostr,const bistreamable_hard2 &)171 std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const bistreamable_hard2&) {
172     return ostr << bistreamable_hard2::value + 100;
173 }
174 template <class TraitsT>
operator >>(std::basic_istream<wchar_t,TraitsT> & istr,const bistreamable_hard2 &)175 std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const bistreamable_hard2&) {
176     int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100);
177     return istr;
178 }
179 
180 
181 void test_ostream_character_detection();
182 void test_istream_character_detection();
183 void test_mixed_stream_character_detection();
184 
init_unit_test_suite(int,char * [])185 boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
186 {
187     boost::unit_test::test_suite *suite =
188         BOOST_TEST_SUITE("lexical_cast stream character detection");
189     suite->add(BOOST_TEST_CASE(&test_ostream_character_detection));
190     suite->add(BOOST_TEST_CASE(&test_istream_character_detection));
191     suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection));
192 
193     return suite;
194 }
195 
196 template <class T>
test_ostr_impl()197 static void test_ostr_impl() {
198     T streamable;
199     BOOST_CHECK_EQUAL(T::value,  boost::lexical_cast<int>(streamable));
200     BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value),  boost::lexical_cast<std::string>(streamable));
201 }
202 
203 template <class T>
test_wostr_impl()204 static void test_wostr_impl() {
205     T streamable;
206     BOOST_CHECK_EQUAL(T::value,  boost::lexical_cast<int>(streamable));
207     // BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable)); // Shall not compile???
208     BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value) == boost::lexical_cast<std::wstring>(streamable));
209 }
210 
211 template <class T>
test_bistr_impl()212 static void test_bistr_impl() {
213     T streamable;
214 
215     BOOST_CHECK_EQUAL(T::value,  boost::lexical_cast<int>(streamable));
216     BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value),  boost::lexical_cast<std::string>(streamable));
217 
218     BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value + 100) == boost::lexical_cast<std::wstring>(streamable));
219 }
220 
test_ostream_character_detection()221 void test_ostream_character_detection() {
222     test_ostr_impl<streamable_easy>();
223     test_ostr_impl<streamable_medium>();
224     test_ostr_impl<streamable_hard>();
225     test_ostr_impl<streamable_hard2>();
226 
227     test_wostr_impl<wstreamable_easy>();
228     test_wostr_impl<wstreamable_medium>();
229     test_wostr_impl<wstreamable_hard>();
230     test_wostr_impl<wstreamable_hard2>();
231 
232     test_bistr_impl<bistreamable_easy>();
233     test_bistr_impl<bistreamable_medium>();
234     test_bistr_impl<bistreamable_hard>();
235     test_bistr_impl<bistreamable_hard2>();
236 }
237 
238 
239 template <class T>
test_istr_impl()240 static void test_istr_impl() {
241     boost::lexical_cast<T>(T::value);
242     boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
243 }
244 
245 template <class T>
test_wistr_impl()246 static void test_wistr_impl() {
247     boost::lexical_cast<T>(T::value);
248     //boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value)); // Shall not compile???
249     boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value));
250 }
251 
252 template <class T>
test_bistr_instr_impl()253 static void test_bistr_instr_impl() {
254     boost::lexical_cast<T>(T::value);
255     boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
256     boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value + 100));
257 }
258 
test_istream_character_detection()259 void test_istream_character_detection() {
260     test_istr_impl<streamable_easy>();
261     test_istr_impl<streamable_medium>();
262     test_istr_impl<streamable_hard>();
263     test_istr_impl<streamable_hard2>();
264 
265     test_wistr_impl<wstreamable_easy>();
266     test_wistr_impl<wstreamable_medium>();
267     test_wistr_impl<wstreamable_hard>();
268     test_wistr_impl<wstreamable_hard2>();
269 
270     test_bistr_instr_impl<bistreamable_easy>();
271     test_bistr_instr_impl<bistreamable_medium>();
272     test_bistr_instr_impl<bistreamable_hard>();
273     test_bistr_instr_impl<bistreamable_hard2>();
274 }
275 
276 
277 
278 
279 
280 
281 struct wistreamble_ostreamable { enum ENU {value = 200}; };
operator <<(std::ostream & ostr,const wistreamble_ostreamable &)282 std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) {
283     return ostr << wistreamble_ostreamable::value;
284 }
operator >>(std::wistream & istr,const wistreamble_ostreamable &)285 std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) {
286     int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value);
287     return istr;
288 }
289 
290 struct istreamble_wostreamable { enum ENU {value = 201}; };
operator <<(std::wostream & ostr,const istreamble_wostreamable &)291 std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) {
292     return ostr << istreamble_wostreamable::value;
293 }
operator >>(std::istream & istr,const istreamble_wostreamable &)294 std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) {
295     int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value);
296     return istr;
297 }
298 
test_mixed_stream_character_detection()299 void test_mixed_stream_character_detection() {
300     //boost::lexical_cast<std::wstring>(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION!
301 
302     boost::lexical_cast<wistreamble_ostreamable>(wistreamble_ostreamable::value);
303     BOOST_CHECK_EQUAL(boost::lexical_cast<int>(wistreamble_ostreamable()), wistreamble_ostreamable::value);
304 
305     boost::lexical_cast<istreamble_wostreamable>(istreamble_wostreamable::value);
306     BOOST_CHECK_EQUAL(boost::lexical_cast<int>(istreamble_wostreamable()), istreamble_wostreamable::value);
307 }
308