From b71fb9aada4fa8aee2decf40b17a7f957d9bf4ff Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Mon, 20 Feb 2012 16:20:09 +0000 Subject: [PATCH] Fixes #6441 (compilation error with BOOST_NO_STD_LOCALE defined) [SVN r77077] --- include/boost/lexical_cast.hpp | 53 +++++-- test/Jamfile.v2 | 1 + test/lexical_cast_no_locale_test.cpp | 166 +++++++++++++++++++++ test/lexical_cast_typedefed_wchar_test.cpp | 1 + 4 files changed, 205 insertions(+), 16 deletions(-) create mode 100755 test/lexical_cast_no_locale_test.cpp diff --git a/include/boost/lexical_cast.hpp b/include/boost/lexical_cast.hpp index 4658ab6..398fa25 100644 --- a/include/boost/lexical_cast.hpp +++ b/include/boost/lexical_cast.hpp @@ -1167,7 +1167,7 @@ namespace boost namespace detail { - struct do_not_construct_stringbuffer_t{}; + struct do_not_construct_out_stream_t{}; } namespace detail // optimized stream wrapper @@ -1179,25 +1179,27 @@ namespace boost > class lexical_stream_limited_src { - typedef stl_buf_unlocker, CharT > local_streambuffer_t; #if defined(BOOST_NO_STRINGSTREAM) - typedef stl_buf_unlocker local_stringbuffer_t; + typedef std::ostrstream out_stream_t; + typedef stl_buf_unlocker unlocked_but_t; #elif defined(BOOST_NO_STD_LOCALE) - typedef stl_buf_unlocker local_stringbuffer_t; + typedef std::ostringstream out_stream_t; + typedef stl_buf_unlocker unlocked_but_t; #else - typedef stl_buf_unlocker, CharT > local_stringbuffer_t; + typedef std::basic_ostringstream out_stream_t; + typedef stl_buf_unlocker, CharT> unlocked_but_t; #endif typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::if_c< RequiresStringbuffer, - local_stringbuffer_t, - do_not_construct_stringbuffer_t - >::type deduced_stringbuffer_t; + out_stream_t, + do_not_construct_out_stream_t + >::type deduced_out_stream_t; // A string representation of Source is written to [start, finish). CharT* start; CharT* finish; - deduced_stringbuffer_t stringbuffer; + deduced_out_stream_t out_stream; public: lexical_stream_limited_src(CharT* sta, CharT* fin) @@ -1258,10 +1260,16 @@ namespace boost template bool shl_input_streamable(InputStreamable& input) { - std::basic_ostream stream(&stringbuffer); - bool const result = !(stream << input).fail(); - start = stringbuffer.pbase(); - finish = stringbuffer.pptr(); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // unsupports such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same::value)); +#endif + bool const result = !(out_stream << input).fail(); + const unlocked_but_t* const p + = static_cast(out_stream.rdbuf()) ; + start = p->pbase(); + finish = p->pptr(); return result; } @@ -1526,9 +1534,22 @@ namespace boost if(is_pointer::value) return false; - local_streambuffer_t bb; - bb.setg(start, start, finish); - std::basic_istream stream(&bb); +#if defined(BOOST_NO_STRINGSTREAM) || defined(BOOST_NO_STD_LOCALE) + // If you have compilation error at this point, than your STL library + // unsupports such conversions. Try updating it. + BOOST_STATIC_ASSERT((boost::is_same::value)); +#endif + +#if defined(BOOST_NO_STRINGSTREAM) + std::istrstream stream(start, finish - start); +#elif defined(BOOST_NO_STD_LOCALE) + std::istringstream stream; +#else + std::basic_istringstream stream; +#endif + static_cast(stream.rdbuf()) + ->setg(start, start, finish); + stream.unsetf(std::ios::skipws); lcast_set_precision(stream, static_cast(0)); #if (defined _MSC_VER) diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index c311420..0618516 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -38,5 +38,6 @@ test-suite conversion [ run lexical_cast_pointers_test.cpp ../../test/build//boost_unit_test_framework/static ] [ compile lexical_cast_typedefed_wchar_test.cpp : msvc:on ] [ run lexical_cast_typedefed_wchar_test_runtime.cpp ../../test/build//boost_unit_test_framework/static : : : msvc:on ] + [ run lexical_cast_no_locale_test.cpp ../../test/build//boost_unit_test_framework/static : : : BOOST_NO_STD_LOCALE ] ; diff --git a/test/lexical_cast_no_locale_test.cpp b/test/lexical_cast_no_locale_test.cpp new file mode 100755 index 0000000..3404481 --- /dev/null +++ b/test/lexical_cast_no_locale_test.cpp @@ -0,0 +1,166 @@ +// Unit test for boost::lexical_cast. +// +// See http://www.boost.org for most recent version, including documentation. +// +// Copyright Antony Polukhin, 2012. +// +// 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 + +#if defined(__INTEL_COMPILER) +#pragma warning(disable: 193 383 488 981 1418 1419) +#elif defined(BOOST_MSVC) +#pragma warning(disable: 4097 4100 4121 4127 4146 4244 4245 4511 4512 4701 4800) +#endif + +#include +#include +#include + +using namespace boost; + +// Testing compilation and some basic usage with BOOST_NO_STD_LOCALE +// Tests are mainly copyied from lexical_cast_empty_input_test.cpp (something +// new added to test_empty_3) + +#ifndef BOOST_NO_STD_LOCALE +#error "This test must be compiled with -DBOOST_NO_STD_LOCALE" +#endif + + +template +void do_test_on_empty_input(T& v) +{ + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#if defined(BOOST_HAS_LONG_LONG) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +#elif defined(BOOST_HAS_MS_INT64) + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast<__int64>(v), bad_lexical_cast); +#endif +} + +void test_empty_1() +{ + boost::iterator_range v; + do_test_on_empty_input(v); + BOOST_CHECK_EQUAL(lexical_cast(v), std::string()); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + + boost::iterator_range cv; + do_test_on_empty_input(cv); + BOOST_CHECK_EQUAL(lexical_cast(cv), std::string()); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(cv), bad_lexical_cast); + + const boost::iterator_range ccv; + do_test_on_empty_input(ccv); + BOOST_CHECK_EQUAL(lexical_cast(ccv), std::string()); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(ccv), bad_lexical_cast); +} + +void test_empty_2() +{ + std::string v; + do_test_on_empty_input(v); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + +struct Escape +{ + Escape(){} + Escape(const std::string& s) + : str_(s) + {} + + std::string str_; +}; + +inline std::ostream& operator<< (std::ostream& o, const Escape& rhs) +{ + return o << rhs.str_; +} + +inline std::istream& operator>> (std::istream& i, Escape& rhs) +{ + return i >> rhs.str_; +} + +void test_empty_3() +{ + Escape v(""); + do_test_on_empty_input(v); + + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + + v = lexical_cast(100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100); + BOOST_CHECK_EQUAL(lexical_cast(v), 100); + + v = lexical_cast(0.0); + BOOST_CHECK_EQUAL(lexical_cast(v), 0.0); +} + +namespace std { +inline std::ostream & operator<<(std::ostream & out, const std::vector & v) +{ + std::ostream_iterator it(out); + std::copy(v.begin(), v.end(), it); + assert(out); + return out; +} +} + +void test_empty_4() +{ + std::vector v; + do_test_on_empty_input(v); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); + BOOST_CHECK_THROW(lexical_cast(v), bad_lexical_cast); +} + + +struct my_string { + friend std::ostream &operator<<(std::ostream& sout, my_string const&/* st*/) { + return sout << ""; + } +}; + +void test_empty_5() +{ + my_string st; + BOOST_CHECK_EQUAL(boost::lexical_cast(st), std::string());; +} + +unit_test::test_suite *init_unit_test_suite(int, char *[]) +{ + unit_test::test_suite *suite = + BOOST_TEST_SUITE("lexical_cast. Testing with BOOST_NO_STD_LOCALE"); + suite->add(BOOST_TEST_CASE(&test_empty_1)); + suite->add(BOOST_TEST_CASE(&test_empty_2)); + suite->add(BOOST_TEST_CASE(&test_empty_3)); + suite->add(BOOST_TEST_CASE(&test_empty_4)); + suite->add(BOOST_TEST_CASE(&test_empty_5)); + + return suite; +} + diff --git a/test/lexical_cast_typedefed_wchar_test.cpp b/test/lexical_cast_typedefed_wchar_test.cpp index 82f7cc9..2dc0098 100755 --- a/test/lexical_cast_typedefed_wchar_test.cpp +++ b/test/lexical_cast_typedefed_wchar_test.cpp @@ -23,6 +23,7 @@ void parseDate() boost::date_time::special_values_parser svp; boost::gregorian::date date = parser.parse_date(L"", L"", svp); + (void)date; }