308 lines
12 KiB
C++
308 lines
12 KiB
C++
// Unit test for boost::lexical_cast.
|
|
//
|
|
// See http://www.boost.org for most recent version, including documentation.
|
|
//
|
|
// Copyright Antony Polukhin, 2011-2019.
|
|
//
|
|
// Distributed under the Boost
|
|
// Software License, Version 1.0. (See accompanying file
|
|
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt).
|
|
|
|
|
|
#include <boost/config.hpp>
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
///////////////////////// char streamable classes ///////////////////////////////////////////
|
|
|
|
struct streamable_easy { enum ENU {value = 0}; };
|
|
std::ostream& operator << (std::ostream& ostr, const streamable_easy&) {
|
|
return ostr << streamable_easy::value;
|
|
}
|
|
std::istream& operator >> (std::istream& istr, const streamable_easy&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_easy::value);
|
|
return istr;
|
|
}
|
|
|
|
struct streamable_medium { enum ENU {value = 1}; };
|
|
template <class CharT>
|
|
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_ostream<CharT>&>::type
|
|
operator << (std::basic_ostream<CharT>& ostr, const streamable_medium&) {
|
|
return ostr << streamable_medium::value;
|
|
}
|
|
template <class CharT>
|
|
typename boost::enable_if<boost::is_same<CharT, char>, std::basic_istream<CharT>&>::type
|
|
operator >> (std::basic_istream<CharT>& istr, const streamable_medium&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_medium::value);
|
|
return istr;
|
|
}
|
|
|
|
struct streamable_hard { enum ENU {value = 2}; };
|
|
template <class CharT, class TraitsT>
|
|
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&) {
|
|
return ostr << streamable_hard::value;
|
|
}
|
|
template <class CharT, class TraitsT>
|
|
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&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard::value);
|
|
return istr;
|
|
}
|
|
|
|
struct streamable_hard2 { enum ENU {value = 3}; };
|
|
template <class TraitsT>
|
|
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const streamable_hard2&) {
|
|
return ostr << streamable_hard2::value;
|
|
}
|
|
template <class TraitsT>
|
|
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const streamable_hard2&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, streamable_hard2::value);
|
|
return istr;
|
|
}
|
|
|
|
|
|
///////////////////////// wchar_t streamable classes ///////////////////////////////////////////
|
|
|
|
struct wstreamable_easy { enum ENU {value = 4}; };
|
|
std::wostream& operator << (std::wostream& ostr, const wstreamable_easy&) {
|
|
return ostr << wstreamable_easy::value;
|
|
}
|
|
std::wistream& operator >> (std::wistream& istr, const wstreamable_easy&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_easy::value);
|
|
return istr;
|
|
}
|
|
|
|
struct wstreamable_medium { enum ENU {value = 5}; };
|
|
template <class CharT>
|
|
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_ostream<CharT>& >::type
|
|
operator << (std::basic_ostream<CharT>& ostr, const wstreamable_medium&) {
|
|
return ostr << wstreamable_medium::value;
|
|
}
|
|
template <class CharT>
|
|
typename boost::enable_if<boost::is_same<CharT, wchar_t>, std::basic_istream<CharT>& >::type
|
|
operator >> (std::basic_istream<CharT>& istr, const wstreamable_medium&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_medium::value);
|
|
return istr;
|
|
}
|
|
|
|
struct wstreamable_hard { enum ENU {value = 6}; };
|
|
template <class CharT, class TraitsT>
|
|
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&) {
|
|
return ostr << wstreamable_hard::value;
|
|
}
|
|
template <class CharT, class TraitsT>
|
|
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&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard::value);
|
|
return istr;
|
|
}
|
|
|
|
struct wstreamable_hard2 { enum ENU {value = 7}; };
|
|
template <class TraitsT>
|
|
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const wstreamable_hard2&) {
|
|
return ostr << wstreamable_hard2::value;
|
|
}
|
|
template <class TraitsT>
|
|
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const wstreamable_hard2&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, wstreamable_hard2::value);
|
|
return istr;
|
|
}
|
|
|
|
///////////////////////// char and wchar_t streamable classes ///////////////////////////////////////////
|
|
|
|
|
|
struct bistreamable_easy { enum ENU {value = 8}; };
|
|
std::ostream& operator << (std::ostream& ostr, const bistreamable_easy&) {
|
|
return ostr << bistreamable_easy::value;
|
|
}
|
|
std::istream& operator >> (std::istream& istr, const bistreamable_easy&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value);
|
|
return istr;
|
|
}
|
|
|
|
std::wostream& operator << (std::wostream& ostr, const bistreamable_easy&) {
|
|
return ostr << bistreamable_easy::value + 100;
|
|
}
|
|
std::wistream& operator >> (std::wistream& istr, const bistreamable_easy&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_easy::value + 100);
|
|
return istr;
|
|
}
|
|
|
|
struct bistreamable_medium { enum ENU {value = 9}; };
|
|
template <class CharT>
|
|
std::basic_ostream<CharT>& operator << (std::basic_ostream<CharT>& ostr, const bistreamable_medium&) {
|
|
return ostr << bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100);
|
|
}
|
|
template <class CharT>
|
|
std::basic_istream<CharT>& operator >> (std::basic_istream<CharT>& istr, const bistreamable_medium&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_medium::value + (sizeof(CharT) == 1 ? 0 : 100));
|
|
return istr;
|
|
}
|
|
|
|
struct bistreamable_hard { enum ENU {value = 10}; };
|
|
template <class CharT, class TraitsT>
|
|
std::basic_ostream<CharT, TraitsT>& operator << (std::basic_ostream<CharT, TraitsT>& ostr, const bistreamable_hard&) {
|
|
return ostr << bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100);
|
|
}
|
|
template <class CharT, class TraitsT>
|
|
std::basic_istream<CharT, TraitsT>& operator >> (std::basic_istream<CharT, TraitsT>& istr, const bistreamable_hard&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard::value + (sizeof(CharT) == 1 ? 0 : 100));
|
|
return istr;
|
|
}
|
|
|
|
struct bistreamable_hard2 { enum ENU {value = 11}; };
|
|
template <class TraitsT>
|
|
std::basic_ostream<char, TraitsT>& operator << (std::basic_ostream<char, TraitsT>& ostr, const bistreamable_hard2&) {
|
|
return ostr << bistreamable_hard2::value;
|
|
}
|
|
template <class TraitsT>
|
|
std::basic_istream<char, TraitsT>& operator >> (std::basic_istream<char, TraitsT>& istr, const bistreamable_hard2&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value);
|
|
return istr;
|
|
}
|
|
|
|
template <class TraitsT>
|
|
std::basic_ostream<wchar_t, TraitsT>& operator << (std::basic_ostream<wchar_t, TraitsT>& ostr, const bistreamable_hard2&) {
|
|
return ostr << bistreamable_hard2::value + 100;
|
|
}
|
|
template <class TraitsT>
|
|
std::basic_istream<wchar_t, TraitsT>& operator >> (std::basic_istream<wchar_t, TraitsT>& istr, const bistreamable_hard2&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, bistreamable_hard2::value + 100);
|
|
return istr;
|
|
}
|
|
|
|
|
|
void test_ostream_character_detection();
|
|
void test_istream_character_detection();
|
|
void test_mixed_stream_character_detection();
|
|
|
|
boost::unit_test::test_suite *init_unit_test_suite(int, char *[])
|
|
{
|
|
boost::unit_test::test_suite *suite =
|
|
BOOST_TEST_SUITE("lexical_cast stream character detection");
|
|
suite->add(BOOST_TEST_CASE(&test_ostream_character_detection));
|
|
suite->add(BOOST_TEST_CASE(&test_istream_character_detection));
|
|
suite->add(BOOST_TEST_CASE(&test_mixed_stream_character_detection));
|
|
|
|
return suite;
|
|
}
|
|
|
|
template <class T>
|
|
static void test_ostr_impl() {
|
|
T streamable;
|
|
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
|
|
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
|
|
}
|
|
|
|
template <class T>
|
|
static void test_wostr_impl() {
|
|
T streamable;
|
|
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
|
|
// BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable)); // Shall not compile???
|
|
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value) == boost::lexical_cast<std::wstring>(streamable));
|
|
}
|
|
|
|
template <class T>
|
|
static void test_bistr_impl() {
|
|
T streamable;
|
|
|
|
BOOST_CHECK_EQUAL(T::value, boost::lexical_cast<int>(streamable));
|
|
BOOST_CHECK_EQUAL(boost::lexical_cast<std::string>(T::value), boost::lexical_cast<std::string>(streamable));
|
|
|
|
BOOST_CHECK(boost::lexical_cast<std::wstring>(T::value + 100) == boost::lexical_cast<std::wstring>(streamable));
|
|
}
|
|
|
|
void test_ostream_character_detection() {
|
|
test_ostr_impl<streamable_easy>();
|
|
test_ostr_impl<streamable_medium>();
|
|
test_ostr_impl<streamable_hard>();
|
|
test_ostr_impl<streamable_hard2>();
|
|
|
|
test_wostr_impl<wstreamable_easy>();
|
|
test_wostr_impl<wstreamable_medium>();
|
|
test_wostr_impl<wstreamable_hard>();
|
|
test_wostr_impl<wstreamable_hard2>();
|
|
|
|
test_bistr_impl<bistreamable_easy>();
|
|
test_bistr_impl<bistreamable_medium>();
|
|
test_bistr_impl<bistreamable_hard>();
|
|
test_bistr_impl<bistreamable_hard2>();
|
|
}
|
|
|
|
|
|
template <class T>
|
|
static void test_istr_impl() {
|
|
boost::lexical_cast<T>(T::value);
|
|
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
|
|
}
|
|
|
|
template <class T>
|
|
static void test_wistr_impl() {
|
|
boost::lexical_cast<T>(T::value);
|
|
//boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value)); // Shall not compile???
|
|
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value));
|
|
}
|
|
|
|
template <class T>
|
|
static void test_bistr_instr_impl() {
|
|
boost::lexical_cast<T>(T::value);
|
|
boost::lexical_cast<T>(boost::lexical_cast<std::string>(T::value));
|
|
boost::lexical_cast<T>(boost::lexical_cast<std::wstring>(T::value + 100));
|
|
}
|
|
|
|
void test_istream_character_detection() {
|
|
test_istr_impl<streamable_easy>();
|
|
test_istr_impl<streamable_medium>();
|
|
test_istr_impl<streamable_hard>();
|
|
test_istr_impl<streamable_hard2>();
|
|
|
|
test_wistr_impl<wstreamable_easy>();
|
|
test_wistr_impl<wstreamable_medium>();
|
|
test_wistr_impl<wstreamable_hard>();
|
|
test_wistr_impl<wstreamable_hard2>();
|
|
|
|
test_bistr_instr_impl<bistreamable_easy>();
|
|
test_bistr_instr_impl<bistreamable_medium>();
|
|
test_bistr_instr_impl<bistreamable_hard>();
|
|
test_bistr_instr_impl<bistreamable_hard2>();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct wistreamble_ostreamable { enum ENU {value = 200}; };
|
|
std::ostream& operator << (std::ostream& ostr, const wistreamble_ostreamable&) {
|
|
return ostr << wistreamble_ostreamable::value;
|
|
}
|
|
std::wistream& operator >> (std::wistream& istr, const wistreamble_ostreamable&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, wistreamble_ostreamable::value);
|
|
return istr;
|
|
}
|
|
|
|
struct istreamble_wostreamable { enum ENU {value = 201}; };
|
|
std::wostream& operator << (std::wostream& ostr, const istreamble_wostreamable&) {
|
|
return ostr << istreamble_wostreamable::value;
|
|
}
|
|
std::istream& operator >> (std::istream& istr, const istreamble_wostreamable&) {
|
|
int i; istr >> i; BOOST_CHECK_EQUAL(i, istreamble_wostreamable::value);
|
|
return istr;
|
|
}
|
|
|
|
void test_mixed_stream_character_detection() {
|
|
//boost::lexical_cast<std::wstring>(std::string("qwe")); // TODO: ALLOW IT AS EXTENSION!
|
|
|
|
boost::lexical_cast<wistreamble_ostreamable>(wistreamble_ostreamable::value);
|
|
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(wistreamble_ostreamable()), wistreamble_ostreamable::value);
|
|
|
|
boost::lexical_cast<istreamble_wostreamable>(istreamble_wostreamable::value);
|
|
BOOST_CHECK_EQUAL(boost::lexical_cast<int>(istreamble_wostreamable()), istreamble_wostreamable::value);
|
|
}
|