]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/convert/include/boost/convert/stream.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / convert / include / boost / convert / stream.hpp
1 // Copyright (c) 2009-2016 Vladimir Batov.
2 // Use, modification and distribution are subject to the Boost Software License,
3 // Version 1.0. See http://www.boost.org/LICENSE_1_0.txt.
4
5 #ifndef BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
6 #define BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP
7
8 #include <boost/convert/parameters.hpp>
9 #include <boost/convert/detail/is_string.hpp>
10 #include <boost/make_default.hpp>
11 #include <sstream>
12 #include <iomanip>
13
14 #define BOOST_CNV_STRING_ENABLE \
15 template<typename string_type, typename type> \
16 typename boost::enable_if<cnv::is_string<string_type>, void>::type \
17 operator()
18
19 #define BOOST_CNV_PARAM(PARAM_NAME, PARAM_TYPE) \
20 this_type& \
21 operator()(boost::parameter::aux::tag<boost::cnv::parameter::type::PARAM_NAME, PARAM_TYPE>::type const& arg)
22
23 namespace boost { namespace cnv
24 {
25 template<class Char> struct basic_stream;
26
27 typedef boost::cnv::basic_stream<char> cstream;
28 typedef boost::cnv::basic_stream<wchar_t> wstream;
29 }}
30
31 template<class Char>
32 struct boost::cnv::basic_stream : boost::noncopyable
33 {
34 // C01. In string-to-type conversions the "string" must be a CONTIGUOUS ARRAY of
35 // characters because "ibuffer_type" uses/relies on that (it deals with char_type*).
36 // C02. Use the provided "string_in" as the input (read-from) buffer and, consequently,
37 // avoid the overhead associated with stream_.str(string_in) --
38 // copying of the content into internal buffer.
39 // C03. The "strbuf.gptr() != strbuf.egptr()" check replaces "istream.eof() != true"
40 // which for some reason does not work when we try converting the "true" string
41 // to "bool" with std::boolalpha set. Seems that istream state gets unsynced compared
42 // to the actual underlying buffer.
43
44 typedef Char char_type;
45 typedef boost::cnv::basic_stream<char_type> this_type;
46 typedef std::basic_stringstream<char_type> stream_type;
47 typedef std::basic_istream<char_type> istream_type;
48 typedef std::basic_streambuf<char_type> buffer_type;
49 typedef std::basic_string<char_type> stdstr_type;
50 typedef std::ios_base& (*manipulator_type)(std::ios_base&);
51
52 struct ibuffer_type : public buffer_type
53 {
54 using buffer_type::eback;
55 using buffer_type::gptr;
56 using buffer_type::egptr;
57
58 ibuffer_type(char_type const* beg, std::size_t sz) //C01
59 {
60 char_type* b = const_cast<char_type*>(beg);
61
62 buffer_type::setg(b, b, b + sz);
63 }
64 };
65 struct obuffer_type : public buffer_type
66 {
67 using buffer_type::pbase;
68 using buffer_type::pptr;
69 using buffer_type::epptr;
70 };
71
72 basic_stream() : stream_(std::ios_base::in | std::ios_base::out) {}
73 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
74 basic_stream(this_type&& other) : stream_(std::move(other.stream_)) {}
75 #endif
76
77 BOOST_CNV_STRING_ENABLE(type const& v, optional<string_type>& s) const { to_str(v, s); }
78 BOOST_CNV_STRING_ENABLE(string_type const& s, optional<type>& r) const { str_to(cnv::range<string_type const>(s), r); }
79 // Resolve ambiguity of string-to-string
80 template<typename type> void operator()( char_type const* s, optional<type>& r) const { str_to(cnv::range< char_type const*>(s), r); }
81 template<typename type> void operator()(stdstr_type const& s, optional<type>& r) const { str_to(cnv::range<stdstr_type const>(s), r); }
82
83 // Formatters
84 template<typename manipulator>
85 this_type& operator() (manipulator m) { return (stream_ << m, *this); }
86 this_type& operator() (manipulator_type m) { return (m(stream_), *this); }
87 this_type& operator() (std::locale const& l) { return (stream_.imbue(l), *this); }
88
89 BOOST_CNV_PARAM(locale, std::locale const) { return (stream_.imbue(arg[cnv::parameter::locale]), *this); }
90 BOOST_CNV_PARAM(precision, int const) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
91 BOOST_CNV_PARAM(precision, int) { return (stream_.precision(arg[cnv::parameter::precision]), *this); }
92 BOOST_CNV_PARAM(width, int const) { return (stream_.width(arg[cnv::parameter::width]), *this); }
93 BOOST_CNV_PARAM(fill, char const) { return (stream_.fill(arg[cnv::parameter::fill]), *this); }
94 BOOST_CNV_PARAM(uppercase, bool const)
95 {
96 bool uppercase = arg[cnv::parameter::uppercase];
97 uppercase ? (void) stream_.setf(std::ios::uppercase) : stream_.unsetf(std::ios::uppercase);
98 return *this;
99 }
100 BOOST_CNV_PARAM(skipws, bool const)
101 {
102 bool skipws = arg[cnv::parameter::skipws];
103 skipws ? (void) stream_.setf(std::ios::skipws) : stream_.unsetf(std::ios::skipws);
104 return *this;
105 }
106 BOOST_CNV_PARAM(adjust, boost::cnv::adjust::type const)
107 {
108 cnv::adjust::type adjust = arg[cnv::parameter::adjust];
109
110 /**/ if (adjust == cnv::adjust:: left) stream_.setf(std::ios::adjustfield, std::ios:: left);
111 else if (adjust == cnv::adjust::right) stream_.setf(std::ios::adjustfield, std::ios::right);
112 else BOOST_ASSERT(!"Not implemented");
113
114 return *this;
115 }
116 BOOST_CNV_PARAM(base, boost::cnv::base::type const)
117 {
118 cnv::base::type base = arg[cnv::parameter::base];
119
120 /**/ if (base == cnv::base::dec) std::dec(stream_);
121 else if (base == cnv::base::hex) std::hex(stream_);
122 else if (base == cnv::base::oct) std::oct(stream_);
123 else BOOST_ASSERT(!"Not implemented");
124
125 return *this;
126 }
127 BOOST_CNV_PARAM(notation, boost::cnv::notation::type const)
128 {
129 cnv::notation::type notation = arg[cnv::parameter::notation];
130
131 /**/ if (notation == cnv::notation:: fixed) std::fixed(stream_);
132 else if (notation == cnv::notation::scientific) std::scientific(stream_);
133 else BOOST_ASSERT(!"Not implemented");
134
135 return *this;
136 }
137
138 private:
139
140 template<typename string_type, typename out_type> void str_to(cnv::range<string_type>, optional<out_type>&) const;
141 template<typename string_type, typename in_type> void to_str(in_type const&, optional<string_type>&) const;
142
143 mutable stream_type stream_;
144 };
145
146 template<typename char_type>
147 template<typename string_type, typename in_type>
148 inline
149 void
150 boost::cnv::basic_stream<char_type>::to_str(
151 in_type const& value_in,
152 boost::optional<string_type>& string_out) const
153 {
154 stream_.clear(); // Clear the flags
155 stream_.str(stdstr_type()); // Clear/empty the content of the stream
156
157 if (!(stream_ << value_in).fail())
158 {
159 buffer_type* buf = stream_.rdbuf();
160 obuffer_type* obuf = static_cast<obuffer_type*>(buf);
161 char_type const* beg = obuf->pbase();
162 char_type const* end = obuf->pptr();
163
164 string_out = string_type(beg, end); // Instead of stream_.str();
165 }
166 }
167
168 template<typename char_type>
169 template<typename string_type, typename out_type>
170 inline
171 void
172 boost::cnv::basic_stream<char_type>::str_to(
173 boost::cnv::range<string_type> string_in,
174 boost::optional<out_type>& result_out) const
175 {
176 if (string_in.empty ()) return;
177
178 istream_type& istream = stream_;
179 buffer_type* oldbuf = istream.rdbuf();
180 char_type const* beg = &*string_in.begin();
181 std::size_t sz = string_in.end() - string_in.begin();
182 ibuffer_type newbuf (beg, sz); //C02
183
184 istream.rdbuf(&newbuf);
185 istream.clear(); // Clear the flags
186
187 istream >> *(result_out = boost::make_default<out_type>());
188
189 if (istream.fail() || newbuf.gptr() != newbuf.egptr()/*C03*/)
190 result_out = boost::none;
191
192 istream.rdbuf(oldbuf);
193 }
194
195 #undef BOOST_CNV_STRING_ENABLE
196 #undef BOOST_CNV_PARAM
197
198 #endif // BOOST_CONVERT_STRINGSTREAM_BASED_CONVERTER_HPP