/usr/include/boost/convert
Edit: /usr/include/boost/convert/stream.hpp (7710B)
// Copyright (c) 2009-2016 Vladimir Batov.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
#ifndef BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
#define BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
#include
#include
#include
#include
#include
#include
#define BOOST_CNV_STRING_ENABLE \
template \
typename boost::enable_if, void>::type \
operator()
#define BOOST_CNV_PARAM(PARAM_NAME, PARAM_TYPE) \
this_type& \
operator()(boost::parameter::aux::tag::type const& arg)
namespace boost { namespace cnv
{
template struct basic_stream;
using cstream = boost::cnv::basic_stream;
using wstream = boost::cnv::basic_stream;
}}
template
struct boost::cnv::basic_stream : boost::noncopyable
{
// C01. In string-to-type conversions the "string" must be a CONTIGUOUS ARRAY of
// characters because "ibuffer_type" uses/relies on that (it deals with char_type*).
// C02. Use the provided "string_in" as the input (read-from) buffer and, consequently,
// avoid the overhead associated with stream_.str(string_in) --
// copying of the content into internal buffer.
// C03. The "strbuf.gptr() != strbuf.egptr()" check replaces "istream.eof() != true"
// which for some reason does not work when we try converting the "true" string
// to "bool" with std::boolalpha set. Seems that istream state gets unsynced compared
// to the actual underlying buffer.
using char_type = Char;
using this_type = boost::cnv::basic_stream;
using stream_type = std::basic_stringstream;
using istream_type = std::basic_istream;
using buffer_type = std::basic_streambuf;
using stdstr_type = std::basic_string;
using manipulator_type = std::ios_base& (*)(std::ios_base&);
struct ibuffer_type : buffer_type
{
using buffer_type::eback;
using buffer_type::gptr;
using buffer_type::egptr;
ibuffer_type(char_type const* beg, std::size_t sz) //C01
{
char_type* b = const_cast(beg);
buffer_type::setg(b, b, b + sz);
}
};
struct obuffer_type : buffer_type
{
using buffer_type::pbase;
using buffer_type::pptr;
using buffer_type::epptr;
};
basic_stream() : stream_(std::ios_base::in | std::ios_base::out) {}
#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
basic_stream(this_type&& other) : stream_(std::move(other.stream_)) {}
#endif
BOOST_CNV_STRING_ENABLE(type const& v, optional& s) const { to_str(v, s); }
BOOST_CNV_STRING_ENABLE(string_type const& s, optional& r) const { str_to(cnv::range(s), r); }
// Resolve ambiguity of string-to-string
template void operator()( char_type const* s, optional& r) const { str_to(cnv::range< char_type const*>(s), r); }
template void operator()(stdstr_type const& s, optional& r) const { str_to(cnv::range(s), r); }
// Formatters
template
this_type& operator() (manipulator m) { return (stream_ << m, *this); }
this_type& operator() (manipulator_type m) { return (m(stream_), *this); }
this_type& operator() (std::locale const& l) { return (stream_.imbue(l), *this); }
BOOST_CNV_PARAM(locale, std::locale) { return (stream_.imbue(arg[cnv::parameter::locale]), *this); }
BOOST_CNV_PARAM(precision, int) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
BOOST_CNV_PARAM(width, int) { return (stream_.width(arg[cnv::parameter::width]), *this); }
BOOST_CNV_PARAM(fill, char) { return (stream_.fill(arg[cnv::parameter::fill]), *this); }
BOOST_CNV_PARAM(uppercase, bool)
{
bool uppercase = arg[cnv::parameter::uppercase];
uppercase ? (void) stream_.setf(std::ios::uppercase) : stream_.unsetf(std::ios::uppercase);
return *this;
}
BOOST_CNV_PARAM(skipws, bool)
{
bool skipws = arg[cnv::parameter::skipws];
skipws ? (void) stream_.setf(std::ios::skipws) : stream_.unsetf(std::ios::skipws);
return *this;
}
BOOST_CNV_PARAM(adjust, boost::cnv::adjust)
{
cnv::adjust adjust = arg[cnv::parameter::adjust];
/**/ if (adjust == cnv::adjust:: left) stream_.setf(std::ios::adjustfield, std::ios:: left);
else if (adjust == cnv::adjust::right) stream_.setf(std::ios::adjustfield, std::ios::right);
else BOOST_ASSERT(!"Not implemented");
return *this;
}
BOOST_CNV_PARAM(base, boost::cnv::base)
{
cnv::base base = arg[cnv::parameter::base];
/**/ if (base == cnv::base::dec) std::dec(stream_);
else if (base == cnv::base::hex) std::hex(stream_);
else if (base == cnv::base::oct) std::oct(stream_);
else BOOST_ASSERT(!"Not implemented");
return *this;
}
BOOST_CNV_PARAM(notation, boost::cnv::notation)
{
cnv::notation notation = arg[cnv::parameter::notation];
/**/ if (notation == cnv::notation:: fixed) std::fixed(stream_);
else if (notation == cnv::notation::scientific) std::scientific(stream_);
else BOOST_ASSERT(!"Not implemented");
return *this;
}
private:
template void str_to(cnv::range, optional&) const;
template void to_str(in_type const&, optional&) const;
mutable stream_type stream_;
};
template
template
inline
void
boost::cnv::basic_stream::to_str(
in_type const& value_in,
boost::optional& string_out) const
{
stream_.clear(); // Clear the flags
stream_.str(stdstr_type()); // Clear/empty the content of the stream
if (!(stream_ << value_in).fail())
{
buffer_type* buf = stream_.rdbuf();
obuffer_type* obuf = reinterpret_cast(buf);
char_type const* beg = obuf->pbase();
char_type const* end = obuf->pptr();
string_out = string_type(beg, end); // Instead of stream_.str();
}
}
template
template
inline
void
boost::cnv::basic_stream::str_to(
boost::cnv::range string_in,
boost::optional& result_out) const
{
if (string_in.empty ()) return;
istream_type& istream = stream_;
buffer_type* oldbuf = istream.rdbuf();
char_type const* beg = &*string_in.begin();
std::size_t sz = string_in.end() - string_in.begin();
ibuffer_type newbuf (beg, sz); //C02
istream.rdbuf(&newbuf);
istream.clear(); // Clear the flags
istream >> *(result_out = boost::make_default());
if (istream.fail() || newbuf.gptr() != newbuf.egptr()/*C03*/)
result_out = boost::none;
istream.rdbuf(oldbuf);
}
#undef BOOST_CNV_STRING_ENABLE
#undef BOOST_CNV_PARAM
#endif // BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP