File indexing completed on 2025-01-30 09:35:11
0001
0002
0003
0004
0005 #ifndef BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
0006 #define BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
0007
0008 #include <boost/convert/parameters.hpp>
0009 #include <boost/convert/detail/is_string.hpp>
0010 #include <boost/make_default.hpp>
0011 #include <sstream>
0012 #include <iomanip>
0013
0014 #define BOOST_CNV_STRING_ENABLE \
0015 template<typename string_type, typename type> \
0016 typename std::enable_if<cnv::is_string<string_type>::value, void>::type \
0017 operator()
0018
0019 #define BOOST_CNV_PARAM_SET(param_name) \
0020 template <typename argument_pack> \
0021 void set_( \
0022 argument_pack const& arg, \
0023 cnv::parameter::type::param_name, \
0024 mpl::true_)
0025
0026 #define BOOST_CNV_PARAM_TRY(param_name) \
0027 this->set_( \
0028 arg, \
0029 cnv::parameter::type::param_name(), \
0030 typename mpl::has_key< \
0031 argument_pack, cnv::parameter::type::param_name>::type());
0032
0033 namespace boost { namespace cnv
0034 {
0035 template<class Char> struct basic_stream;
0036
0037 using cstream = boost::cnv::basic_stream<char>;
0038 using wstream = boost::cnv::basic_stream<wchar_t>;
0039 }}
0040
0041 template<class Char>
0042 struct boost::cnv::basic_stream
0043 {
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 using char_type = Char;
0055 using this_type = boost::cnv::basic_stream<char_type>;
0056 using stream_type = std::basic_stringstream<char_type>;
0057 using istream_type = std::basic_istream<char_type>;
0058 using buffer_type = std::basic_streambuf<char_type>;
0059 using stdstr_type = std::basic_string<char_type>;
0060 using manipulator_type = std::ios_base& (*)(std::ios_base&);
0061
0062 struct ibuffer_type : buffer_type
0063 {
0064 using buffer_type::eback;
0065 using buffer_type::gptr;
0066 using buffer_type::egptr;
0067
0068 ibuffer_type(char_type const* beg, std::size_t sz)
0069 {
0070 char_type* b = const_cast<char_type*>(beg);
0071
0072 buffer_type::setg(b, b, b + sz);
0073 }
0074 };
0075 struct obuffer_type : buffer_type
0076 {
0077 using buffer_type::pbase;
0078 using buffer_type::pptr;
0079 using buffer_type::epptr;
0080 };
0081
0082 basic_stream () : stream_(std::ios_base::in | std::ios_base::out) {}
0083 basic_stream (this_type&& other) : stream_(std::move(other.stream_)) {}
0084
0085 basic_stream(this_type const&) = delete;
0086 this_type& operator=(this_type const&) = delete;
0087
0088 BOOST_CNV_STRING_ENABLE(type const& v, optional<string_type>& s) const { to_str(v, s); }
0089 BOOST_CNV_STRING_ENABLE(string_type const& s, optional<type>& r) const { str_to(cnv::range<string_type const>(s), r); }
0090
0091
0092 template<typename type> void operator()( char_type const* s, optional<type>& r) const { str_to(cnv::range< char_type const*>(s), r); }
0093 template<typename type> void operator()(stdstr_type const& s, optional<type>& r) const { str_to(cnv::range<stdstr_type const>(s), r); }
0094
0095
0096 template<typename manipulator>
0097 typename boost::disable_if<boost::parameter::is_argument_pack<manipulator>, this_type&>::type
0098 operator()(manipulator m) { return (this->stream_ << m, *this); }
0099
0100 this_type& operator() (manipulator_type m) { return (m(stream_), *this); }
0101 this_type& operator() (std::locale const& l) { return (stream_.imbue(l), *this); }
0102
0103 template<typename argument_pack>
0104 typename std::enable_if<boost::parameter::is_argument_pack<argument_pack>::value, this_type&>::type
0105 operator()(argument_pack const& arg)
0106 {
0107 BOOST_CNV_PARAM_TRY(precision);
0108 BOOST_CNV_PARAM_TRY(width);
0109 BOOST_CNV_PARAM_TRY(fill);
0110 BOOST_CNV_PARAM_TRY(uppercase);
0111 BOOST_CNV_PARAM_TRY(skipws);
0112 BOOST_CNV_PARAM_TRY(adjust);
0113 BOOST_CNV_PARAM_TRY(base);
0114 BOOST_CNV_PARAM_TRY(notation);
0115
0116 return *this;
0117 }
0118
0119 private:
0120
0121 template<typename argument_pack, typename keyword_tag>
0122 void set_(argument_pack const&, keyword_tag, mpl::false_) {}
0123
0124 BOOST_CNV_PARAM_SET (locale) { stream_.imbue(arg[cnv::parameter::locale]); }
0125 BOOST_CNV_PARAM_SET (precision) { stream_.precision(arg[cnv::parameter::precision]); }
0126 BOOST_CNV_PARAM_SET (width) { stream_.width(arg[cnv::parameter::width]); }
0127 BOOST_CNV_PARAM_SET (fill) { stream_.fill(arg[cnv::parameter::fill]); }
0128 BOOST_CNV_PARAM_SET (uppercase)
0129 {
0130 bool uppercase = arg[cnv::parameter::uppercase];
0131 uppercase ? (void) stream_.setf(std::ios::uppercase) : stream_.unsetf(std::ios::uppercase);
0132 }
0133 BOOST_CNV_PARAM_SET (skipws)
0134 {
0135 bool skipws = arg[cnv::parameter::skipws];
0136 skipws ? (void) stream_.setf(std::ios::skipws) : stream_.unsetf(std::ios::skipws);
0137 }
0138 BOOST_CNV_PARAM_SET (adjust)
0139 {
0140 cnv::adjust adjust = arg[cnv::parameter::adjust];
0141
0142 if (adjust == cnv::adjust:: left) stream_.setf(std::ios::adjustfield, std::ios:: left);
0143 else if (adjust == cnv::adjust::right) stream_.setf(std::ios::adjustfield, std::ios::right);
0144 else BOOST_ASSERT(!"Not implemented");
0145 }
0146 BOOST_CNV_PARAM_SET (base)
0147 {
0148 cnv::base base = arg[cnv::parameter::base];
0149
0150 if (base == cnv::base::dec) std::dec(stream_);
0151 else if (base == cnv::base::hex) std::hex(stream_);
0152 else if (base == cnv::base::oct) std::oct(stream_);
0153 else BOOST_ASSERT(!"Not implemented");
0154 }
0155 BOOST_CNV_PARAM_SET (notation)
0156 {
0157 cnv::notation notation = arg[cnv::parameter::notation];
0158
0159 if (notation == cnv::notation:: fixed) std::fixed(stream_);
0160 else if (notation == cnv::notation::scientific) std::scientific(stream_);
0161 else if (notation == cnv::notation:: hex) std::hexfloat(stream_);
0162 else BOOST_ASSERT(!"Not implemented");
0163 }
0164
0165 template<typename string_type, typename out_type> void str_to(cnv::range<string_type>, optional<out_type>&) const;
0166 template<typename string_type, typename in_type> void to_str(in_type const&, optional<string_type>&) const;
0167
0168 mutable stream_type stream_;
0169 };
0170
0171 template<typename char_type>
0172 template<typename string_type, typename in_type>
0173 inline
0174 void
0175 boost::cnv::basic_stream<char_type>::to_str(
0176 in_type const& value_in,
0177 boost::optional<string_type>& string_out) const
0178 {
0179 stream_.clear();
0180 stream_.str(stdstr_type());
0181
0182 if (!(stream_ << value_in).fail())
0183 {
0184 buffer_type* buf = stream_.rdbuf();
0185 obuffer_type* obuf = reinterpret_cast<obuffer_type*>(buf);
0186 char_type const* beg = obuf->pbase();
0187 char_type const* end = obuf->pptr();
0188
0189 string_out = string_type(beg, end);
0190 }
0191 }
0192
0193 template<typename char_type>
0194 template<typename string_type, typename out_type>
0195 inline
0196 void
0197 boost::cnv::basic_stream<char_type>::str_to(
0198 boost::cnv::range<string_type> string_in,
0199 boost::optional<out_type>& result_out) const
0200 {
0201 if (string_in.empty ()) return;
0202
0203 istream_type& istream = stream_;
0204 buffer_type* oldbuf = istream.rdbuf();
0205 char_type const* beg = &*string_in.begin();
0206 std::size_t sz = string_in.end() - string_in.begin();
0207 ibuffer_type newbuf (beg, sz);
0208
0209 istream.rdbuf(&newbuf);
0210 istream.clear();
0211
0212 istream >> *(result_out = boost::make_default<out_type>());
0213
0214 if (istream.fail() || newbuf.gptr() != newbuf.egptr())
0215 result_out = boost::none;
0216
0217 istream.rdbuf(oldbuf);
0218 }
0219
0220 #undef BOOST_CNV_STRING_ENABLE
0221 #undef BOOST_CNV_PARAM_SET
0222 #undef BOOST_CNV_PARAM_TRY
0223
0224 #endif