forked from boostorg/conversion
Merge from trunk:
* Fix stream related issues with libc++ and clang (fixes #7704, fixes #8267) * Change runtime assert to compile time when converting to pointer (fixes #8267) [SVN r83689]
This commit is contained in:
@@ -278,7 +278,9 @@ limitation of compiler options that you use.
|
||||
|
||||
* [*boost 1.54.0 :]
|
||||
|
||||
* Added code to convert boost::int128_type and boost::uint128_type (requires GCC 4.7 or higher).
|
||||
* Added code to convert `boost::int128_type` and `boost::uint128_type` types (requires GCC 4.7 or higher).
|
||||
* Conversions to pointers will now fail to compile, instead of throwing at runtime.
|
||||
* Restored ability to get pointers to `lexical_cast` function (was broken in 1.53.0).
|
||||
|
||||
* [*boost 1.53.0 :]
|
||||
|
||||
|
@@ -173,6 +173,7 @@ namespace boost
|
||||
#include <boost/math/special_functions/fpclassify.hpp>
|
||||
#include <boost/range/iterator_range_core.hpp>
|
||||
#include <boost/container/container_fwd.hpp>
|
||||
#include <boost/integer.hpp>
|
||||
#ifndef BOOST_NO_CWCHAR
|
||||
# include <cwchar>
|
||||
#endif
|
||||
@@ -1414,23 +1415,97 @@ namespace boost {
|
||||
#endif
|
||||
}
|
||||
|
||||
namespace detail // stl_buf_unlocker
|
||||
namespace detail // parser_buf
|
||||
{
|
||||
template< class BufferType, class CharT >
|
||||
class stl_buf_unlocker: public BufferType{
|
||||
//
|
||||
// class parser_buf:
|
||||
// acts as a stream buffer which wraps around a pair of pointers
|
||||
//
|
||||
// This class is copied (and slightly changed) from
|
||||
// boost/regex/v4/cpp_regex_traits.hpp
|
||||
// Thanks John Maddock for it! (previous version had some
|
||||
// problems with libc++ and some other STL implementations)
|
||||
template <class BufferType, class charT>
|
||||
class parser_buf : public BufferType {
|
||||
typedef BufferType base_type;
|
||||
typedef typename base_type::int_type int_type;
|
||||
typedef typename base_type::char_type char_type;
|
||||
typedef typename base_type::pos_type pos_type;
|
||||
typedef ::std::streamsize streamsize;
|
||||
typedef typename base_type::off_type off_type;
|
||||
|
||||
public:
|
||||
typedef BufferType base_class;
|
||||
parser_buf() : base_type() { setbuf(0, 0); }
|
||||
const charT* getnext() { return this->gptr(); }
|
||||
#ifndef BOOST_NO_USING_TEMPLATE
|
||||
using base_class::pptr;
|
||||
using base_class::pbase;
|
||||
using base_class::setg;
|
||||
using base_class::setp;
|
||||
using base_type::pptr;
|
||||
using base_type::pbase;
|
||||
#else
|
||||
CharT* pptr() const { return base_class::pptr(); }
|
||||
CharT* pbase() const { return base_class::pbase(); }
|
||||
void setg(CharT* gbeg, CharT* gnext, CharT* gend){ return base_class::setg(gbeg, gnext, gend); }
|
||||
void setp(CharT* pbeg, CharT* pend) { return setp(pbeg, pend); }
|
||||
charT* pptr() const { return base_type::pptr(); }
|
||||
charT* pbase() const { return base_type::pbase(); }
|
||||
#endif
|
||||
base_type* setbuf(char_type* s, streamsize n) {
|
||||
this->setg(s, s, s + n);
|
||||
return this;
|
||||
}
|
||||
|
||||
pos_type seekpos(pos_type sp, ::std::ios_base::openmode which) {
|
||||
if(which & ::std::ios_base::out)
|
||||
return pos_type(off_type(-1));
|
||||
off_type size = static_cast<off_type>(this->egptr() - this->eback());
|
||||
charT* g = this->eback();
|
||||
if(off_type(sp) <= size)
|
||||
{
|
||||
this->setg(g, g + off_type(sp), g + size);
|
||||
}
|
||||
return pos_type(off_type(-1));
|
||||
}
|
||||
|
||||
pos_type seekoff(off_type off, ::std::ios_base::seekdir way, ::std::ios_base::openmode which) {
|
||||
typedef typename boost::int_t<sizeof(way) * CHAR_BIT>::least cast_type;
|
||||
|
||||
if(which & ::std::ios_base::out)
|
||||
return pos_type(off_type(-1));
|
||||
std::ptrdiff_t size = this->egptr() - this->eback();
|
||||
std::ptrdiff_t pos = this->gptr() - this->eback();
|
||||
charT* g = this->eback();
|
||||
switch(static_cast<cast_type>(way))
|
||||
{
|
||||
case ::std::ios_base::beg:
|
||||
if((off < 0) || (off > size))
|
||||
return pos_type(off_type(-1));
|
||||
else
|
||||
this->setg(g, g + off, g + size);
|
||||
break;
|
||||
case ::std::ios_base::end:
|
||||
if((off < 0) || (off > size))
|
||||
return pos_type(off_type(-1));
|
||||
else
|
||||
this->setg(g, g + size - off, g + size);
|
||||
break;
|
||||
case ::std::ios_base::cur:
|
||||
{
|
||||
std::ptrdiff_t newpos = static_cast<std::ptrdiff_t>(pos + off);
|
||||
if((newpos < 0) || (newpos > size))
|
||||
return pos_type(off_type(-1));
|
||||
else
|
||||
this->setg(g, g + newpos, g + size);
|
||||
break;
|
||||
}
|
||||
default: ;
|
||||
}
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
return static_cast<pos_type>(this->gptr() - this->eback());
|
||||
#ifdef BOOST_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
}
|
||||
private:
|
||||
parser_buf& operator=(const parser_buf&);
|
||||
parser_buf(const parser_buf&);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1451,13 +1526,12 @@ namespace boost {
|
||||
|
||||
#if defined(BOOST_NO_STRINGSTREAM)
|
||||
typedef std::ostrstream out_stream_t;
|
||||
typedef stl_buf_unlocker<std::strstreambuf, char> unlocked_but_t;
|
||||
#elif defined(BOOST_NO_STD_LOCALE)
|
||||
typedef std::ostringstream out_stream_t;
|
||||
typedef stl_buf_unlocker<std::stringbuf, char> unlocked_but_t;
|
||||
typedef parser_buf<std::streambuf, char> buffer_t;
|
||||
#else
|
||||
typedef std::basic_ostringstream<CharT, Traits> out_stream_t;
|
||||
typedef stl_buf_unlocker<std::basic_stringbuf<CharT, Traits>, CharT> unlocked_but_t;
|
||||
typedef std::basic_ostringstream<CharT, Traits> out_stream_t;
|
||||
typedef parser_buf<std::basic_streambuf<CharT, Traits>, CharT> buffer_t;
|
||||
#endif
|
||||
typedef BOOST_DEDUCED_TYPENAME boost::mpl::if_c<
|
||||
RequiresStringbuffer,
|
||||
@@ -1471,7 +1545,7 @@ namespace boost {
|
||||
deduced_out_stream_t out_stream;
|
||||
|
||||
public:
|
||||
lexical_stream_limited_src(CharT* sta, CharT* fin)
|
||||
lexical_stream_limited_src(CharT* sta, CharT* fin) BOOST_NOEXCEPT
|
||||
: start(sta)
|
||||
, finish(fin)
|
||||
{}
|
||||
@@ -1540,8 +1614,9 @@ namespace boost {
|
||||
BOOST_STATIC_ASSERT((boost::is_same<char, CharT>::value));
|
||||
#endif
|
||||
bool const result = !(out_stream << input).fail();
|
||||
const unlocked_but_t* const p
|
||||
= static_cast<unlocked_but_t*>(out_stream.rdbuf()) ;
|
||||
const buffer_t* const p = static_cast<buffer_t*>(
|
||||
static_cast<std::basic_streambuf<CharT, Traits>*>(out_stream.rdbuf())
|
||||
);
|
||||
start = p->pbase();
|
||||
finish = p->pptr();
|
||||
return result;
|
||||
@@ -1893,35 +1968,34 @@ namespace boost {
|
||||
template<typename InputStreamable>
|
||||
bool shr_using_base_class(InputStreamable& output)
|
||||
{
|
||||
#if (defined _MSC_VER)
|
||||
# pragma warning( push )
|
||||
// conditional expression is constant
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
if(is_pointer<InputStreamable>::value)
|
||||
return false;
|
||||
BOOST_STATIC_ASSERT_MSG(
|
||||
(!boost::is_pointer<InputStreamable>::value),
|
||||
"boost::lexical_cast can not convert to pointers"
|
||||
);
|
||||
|
||||
#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<char, CharT>::value));
|
||||
BOOST_STATIC_ASSERT_MSG((boost::is_same<char, CharT>::value),
|
||||
"boost::lexical_cast can not convert, because your STL library does not "
|
||||
"support such conversions. Try updating it."
|
||||
);
|
||||
#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<CharT, Traits> stream;
|
||||
#endif
|
||||
static_cast<unlocked_but_t*>(stream.rdbuf())
|
||||
->setg(start, start, finish);
|
||||
|
||||
buffer_t buf;
|
||||
buf.setbuf(start, finish - start);
|
||||
#if defined(BOOST_NO_STD_LOCALE)
|
||||
std::istream stream(&buf);
|
||||
#else
|
||||
std::basic_istream<CharT, Traits> stream(&buf);
|
||||
#endif // BOOST_NO_STD_LOCALE
|
||||
#endif // BOOST_NO_STRINGSTREAM
|
||||
|
||||
stream.unsetf(std::ios::skipws);
|
||||
lcast_set_precision(stream, static_cast<InputStreamable*>(0));
|
||||
#if (defined _MSC_VER)
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
return stream >> output &&
|
||||
stream.get() ==
|
||||
#if defined(__GNUC__) && (__GNUC__<3) && defined(BOOST_NO_STD_WSTRING)
|
||||
|
@@ -67,7 +67,6 @@ void test_conversion_to_bool();
|
||||
void test_conversion_with_nonconst_char();
|
||||
void test_conversion_to_string();
|
||||
void test_conversion_from_to_wchar_t_alias();
|
||||
void test_conversion_to_pointer();
|
||||
void test_conversion_from_wchar_t();
|
||||
void test_conversion_to_wchar_t();
|
||||
void test_conversion_from_wstring();
|
||||
@@ -100,7 +99,6 @@ unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_double));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_bool));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_from_to_wchar_t_alias));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_pointer));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_to_string));
|
||||
suite->add(BOOST_TEST_CASE(test_conversion_with_nonconst_char));
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
@@ -312,14 +310,6 @@ void test_conversion_from_to_wchar_t_alias()
|
||||
BOOST_CHECK_EQUAL(std::string("123"), lexical_cast<std::string>(123ul));
|
||||
}
|
||||
|
||||
void test_conversion_to_pointer()
|
||||
{
|
||||
BOOST_CHECK_THROW(lexical_cast<char *>("Test"), bad_lexical_cast);
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
BOOST_CHECK_THROW(lexical_cast<wchar_t *>("Test"), bad_lexical_cast);
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_conversion_from_wchar_t()
|
||||
{
|
||||
#ifndef BOOST_LCAST_NO_WCHAR_T
|
||||
|
@@ -55,5 +55,7 @@ test-suite conversion
|
||||
[ run lexical_cast_integral_types_test.cpp ]
|
||||
[ run lexical_cast_stream_detection_test.cpp ]
|
||||
[ run lexical_cast_stream_traits_test.cpp ]
|
||||
[ compile-fail lexical_cast_to_pointer_test.cpp ]
|
||||
[ run lexical_cast_filesystem_test.cpp ../../filesystem/build//boost_filesystem/<link>static ]
|
||||
;
|
||||
|
||||
|
46
test/lexical_cast_filesystem_test.cpp
Normal file
46
test/lexical_cast_filesystem_test.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
// Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Antony Polukhin, 2013.
|
||||
//
|
||||
// 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).
|
||||
//
|
||||
// Test lexical_cast usage with long filesystem::path. Bug 7704.
|
||||
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
using namespace boost;
|
||||
|
||||
void test_filesystem();
|
||||
|
||||
unit_test::test_suite *init_unit_test_suite(int, char *[])
|
||||
{
|
||||
unit_test::test_suite *suite =
|
||||
BOOST_TEST_SUITE("lexical_cast unit test");
|
||||
suite->add(BOOST_TEST_CASE(&test_filesystem));
|
||||
|
||||
return suite;
|
||||
}
|
||||
|
||||
void test_filesystem()
|
||||
{
|
||||
boost::filesystem::path p;
|
||||
std::string s1 = "aaaaaaaaaaaaaaaaaaaaaaa";
|
||||
p = boost::lexical_cast<boost::filesystem::path>(s1);
|
||||
BOOST_CHECK(!p.empty());
|
||||
BOOST_CHECK_EQUAL(p, s1);
|
||||
p.clear();
|
||||
|
||||
const char ab[] = "aaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
|
||||
p = boost::lexical_cast<boost::filesystem::path>(ab);
|
||||
BOOST_CHECK(!p.empty());
|
||||
BOOST_CHECK_EQUAL(p, ab);
|
||||
}
|
||||
|
21
test/lexical_cast_to_pointer_test.cpp
Normal file
21
test/lexical_cast_to_pointer_test.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
// // Unit test for boost::lexical_cast.
|
||||
//
|
||||
// See http://www.boost.org for most recent version, including documentation.
|
||||
//
|
||||
// Copyright Antony Polukhin, 2013.
|
||||
//
|
||||
// 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/lexical_cast.hpp>
|
||||
#include <boost/type.hpp>
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
boost::lexical_cast<char*>("Hello");
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user