Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:35:11

0001 // Copyright (c) 2009-2020 Vladimir Batov.
0002 // Use, modification and distribution are subject to the Boost Software License,
0003 // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
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     // C01. In string-to-type conversions the "string" must be a CONTIGUOUS ARRAY of
0045     //      characters because "ibuffer_type" uses/relies on that (it deals with char_type*).
0046     // C02. Use the provided "string_in" as the input (read-from) buffer and, consequently,
0047     //      avoid the overhead associated with stream_.str(string_in) --
0048     //      copying of the content into internal buffer.
0049     // C03. The "strbuf.gptr() != strbuf.egptr()" check replaces "istream.eof() != true"
0050     //      which for some reason does not work when we try converting the "true" string
0051     //      to "bool" with std::boolalpha set. Seems that istream state gets unsynced compared
0052     //      to the actual underlying buffer.
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) //C01
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     // Resolve ambiguity of string-to-string
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     // Formatters
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();            // Clear the flags
0180     stream_.str(stdstr_type()); // Clear/empty the content of the stream
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); // Instead of stream_.str();
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); //C02
0208 
0209     istream.rdbuf(&newbuf);
0210     istream.clear(); // Clear the flags
0211 
0212     istream >> *(result_out = boost::make_default<out_type>());
0213 
0214     if (istream.fail() || newbuf.gptr() != newbuf.egptr()/*C03*/)
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 // BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP