]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/logic/tribool_io.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / logic / tribool_io.hpp
CommitLineData
7c673cae
FG
1// Three-state boolean logic library
2
3// Copyright Douglas Gregor 2002-2004. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7#ifndef BOOST_LOGIC_TRIBOOL_IO_HPP
8#define BOOST_LOGIC_TRIBOOL_IO_HPP
9
10#include <boost/logic/tribool.hpp>
11#include <boost/detail/workaround.hpp>
12#include <boost/noncopyable.hpp>
13
14#if defined(_MSC_VER)
15# pragma once
16#endif
17
18#ifndef BOOST_NO_STD_LOCALE
19# include <locale>
20#endif
21
22#include <string>
23#include <iostream>
24
25namespace boost { namespace logic {
26
27#ifdef BOOST_NO_STD_LOCALE
28
29/**
30 * \brief Returns a string containing the default name for the \c
31 * false value of a tribool with the given character type T.
32 *
33 * This function only exists when the C++ standard library
34 * implementation does not support locales.
35 */
36template<typename T> std::basic_string<T> default_false_name();
37
38/**
39 * \brief Returns the character string "false".
40 *
41 * This function only exists when the C++ standard library
42 * implementation does not support locales.
43 */
44template<>
45inline std::basic_string<char> default_false_name<char>()
46{ return "false"; }
47
92f5a8d4 48# if !defined(BOOST_NO_CWCHAR)
7c673cae
FG
49/**
50 * \brief Returns the wide character string L"false".
51 *
52 * This function only exists when the C++ standard library
53 * implementation does not support locales.
54 */
55template<>
56inline std::basic_string<wchar_t> default_false_name<wchar_t>()
57{ return L"false"; }
58# endif
59
60/**
61 * \brief Returns a string containing the default name for the \c true
62 * value of a tribool with the given character type T.
63 *
64 * This function only exists when the C++ standard library
65 * implementation does not support locales.
66 */
67template<typename T> std::basic_string<T> default_true_name();
68
69/**
70 * \brief Returns the character string "true".
71 *
72 * This function only exists when the C++ standard library
73 * implementation does not support locales.
74 */
75template<>
76inline std::basic_string<char> default_true_name<char>()
77{ return "true"; }
78
92f5a8d4 79# if !defined(BOOST_NO_CWCHAR)
7c673cae
FG
80/**
81 * \brief Returns the wide character string L"true".
82 *
83 * This function only exists * when the C++ standard library
84 * implementation does not support * locales.
85 */
86template<>
87inline std::basic_string<wchar_t> default_true_name<wchar_t>()
88{ return L"true"; }
89# endif
90#endif
91
92/**
93 * \brief Returns a string containing the default name for the indeterminate
94 * value of a tribool with the given character type T.
95 *
96 * This routine is used by the input and output streaming operators
97 * for tribool when there is no locale support or the stream's locale
98 * does not contain the indeterminate_name facet.
99 */
100template<typename T> std::basic_string<T> get_default_indeterminate_name();
101
102/// Returns the character string "indeterminate".
103template<>
104inline std::basic_string<char> get_default_indeterminate_name<char>()
105{ return "indeterminate"; }
106
92f5a8d4 107#if !defined(BOOST_NO_CWCHAR)
7c673cae
FG
108/// Returns the wide character string L"indeterminate".
109template<>
110inline std::basic_string<wchar_t> get_default_indeterminate_name<wchar_t>()
111{ return L"indeterminate"; }
112#endif
113
114// http://www.cantrip.org/locale.html
115
116#ifndef BOOST_NO_STD_LOCALE
117/**
118 * \brief A locale facet specifying the name of the indeterminate
119 * value of a tribool.
120 *
121 * The facet is used to perform I/O on tribool values when \c
122 * std::boolalpha has been specified. This class template is only
123 * available if the C++ standard library implementation supports
124 * locales.
125 */
126template<typename CharT>
127class indeterminate_name : public std::locale::facet, private boost::noncopyable
128{
129public:
130 typedef CharT char_type;
131 typedef std::basic_string<CharT> string_type;
132
133 /// Construct the facet with the default name
134 indeterminate_name() : name_(get_default_indeterminate_name<CharT>()) {}
135
136 /// Construct the facet with the given name for the indeterminate value
137 explicit indeterminate_name(const string_type& initial_name)
138 : name_(initial_name) {}
139
140 /// Returns the name for the indeterminate value
141 string_type name() const { return name_; }
142
143 /// Uniquily identifies this facet with the locale.
144 static std::locale::id id;
145
146private:
147 string_type name_;
148};
149
150template<typename CharT> std::locale::id indeterminate_name<CharT>::id;
151#endif
152
153/**
154 * \brief Writes the value of a tribool to a stream.
155 *
156 * When the value of @p x is either \c true or \c false, this routine
157 * is semantically equivalent to:
158 * \code out << static_cast<bool>(x); \endcode
159 *
160 * When @p x has an indeterminate value, it outputs either the integer
161 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
162 * or the name of the indeterminate value. The name of the
163 * indeterminate value comes from the indeterminate_name facet (if it
164 * is defined in the output stream's locale), or from the
165 * get_default_indeterminate_name function (if it is not defined in the
166 * locale or if the C++ standard library implementation does not
167 * support locales).
168 *
169 * \returns @p out
170 */
171template<typename CharT, typename Traits>
172inline std::basic_ostream<CharT, Traits>&
173operator<<(std::basic_ostream<CharT, Traits>& out, tribool x)
174{
175 if (!indeterminate(x)) {
176 out << static_cast<bool>(x);
177 } else {
178 typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
179 if (cerberus) {
180 if (out.flags() & std::ios_base::boolalpha) {
181#ifndef BOOST_NO_STD_LOCALE
182 if (BOOST_HAS_FACET(indeterminate_name<CharT>, out.getloc())) {
183 const indeterminate_name<CharT>& facet =
184 BOOST_USE_FACET(indeterminate_name<CharT>, out.getloc());
185 out << facet.name();
186 } else {
187 out << get_default_indeterminate_name<CharT>();
188 }
189#else
190 out << get_default_indeterminate_name<CharT>();
191#endif
192 }
193 else
194 out << 2;
195 }
196 }
197 return out;
198}
199
200/**
201 * \brief Writes the indeterminate tribool value to a stream.
202 *
203 * This routine outputs either the integer
204 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
205 * or the name of the indeterminate value. The name of the
206 * indeterminate value comes from the indeterminate_name facet (if it
207 * is defined in the output stream's locale), or from the
208 * get_default_indeterminate_name function (if it is not defined in the
209 * locale or if the C++ standard library implementation does not
210 * support locales).
211 *
212 * \returns @p out
213 */
214template<typename CharT, typename Traits>
215inline std::basic_ostream<CharT, Traits>&
216operator<<(std::basic_ostream<CharT, Traits>& out,
217 bool (*)(tribool, detail::indeterminate_t))
218{ return out << tribool(indeterminate); }
219
220/**
221 * \brief Reads a tribool value from a stream.
222 *
223 * When <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>, this
224 * function reads a \c long value from the input stream @p in and
225 * converts that value to a tribool. If that value is 0, @p x becomes
226 * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes
227 * \c indetermine; otherwise, the operation fails (and the fail bit is
228 * set on the input stream @p in).
229 *
230 * When <tt>(out.flags() & std::ios_base::boolalpha) != 0</tt>, this
231 * function first determines the names of the false, true, and
232 * indeterminate values. The false and true names are extracted from
233 * the \c std::numpunct facet of the input stream's locale (if the C++
234 * standard library implementation supports locales), or from the \c
235 * default_false_name and \c default_true_name functions (if there is
236 * no locale support). The indeterminate name is extracted from the
237 * appropriate \c indeterminate_name facet (if it is available in the
238 * input stream's locale), or from the \c get_default_indeterminate_name
239 * function (if the C++ standard library implementation does not
240 * support locales, or the \c indeterminate_name facet is not
241 * specified for this locale object). The input is then matched to
242 * each of these names, and the tribool @p x is assigned the value
243 * corresponding to the longest name that matched. If no name is
244 * matched or all names are empty, the operation fails (and the fail
245 * bit is set on the input stream @p in).
246 *
247 * \returns @p in
248 */
249template<typename CharT, typename Traits>
250inline std::basic_istream<CharT, Traits>&
251operator>>(std::basic_istream<CharT, Traits>& in, tribool& x)
252{
253 if (in.flags() & std::ios_base::boolalpha) {
254 typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
255 if (cerberus) {
256 typedef std::basic_string<CharT> string_type;
257
258#ifndef BOOST_NO_STD_LOCALE
259 const std::numpunct<CharT>& numpunct_facet =
260 BOOST_USE_FACET(std::numpunct<CharT>, in.getloc());
261
262 string_type falsename = numpunct_facet.falsename();
263 string_type truename = numpunct_facet.truename();
264
265 string_type othername;
266 if (BOOST_HAS_FACET(indeterminate_name<CharT>, in.getloc())) {
267 othername =
268 BOOST_USE_FACET(indeterminate_name<CharT>, in.getloc()).name();
269 } else {
270 othername = get_default_indeterminate_name<CharT>();
271 }
272#else
273 string_type falsename = default_false_name<CharT>();
274 string_type truename = default_true_name<CharT>();
275 string_type othername = get_default_indeterminate_name<CharT>();
276#endif
277
278 typename string_type::size_type pos = 0;
279 bool falsename_ok = true, truename_ok = true, othername_ok = true;
280
281 // Modeled after the code from Library DR 17
282 while ((falsename_ok && pos < falsename.size())
283 || (truename_ok && pos < truename.size())
284 || (othername_ok && pos < othername.size())) {
285 typename Traits::int_type c = in.get();
286 if (c == Traits::eof())
287 return in;
288
289 bool matched = false;
290 if (falsename_ok && pos < falsename.size()) {
291 if (Traits::eq(Traits::to_char_type(c), falsename[pos]))
292 matched = true;
293 else
294 falsename_ok = false;
295 }
296
297 if (truename_ok && pos < truename.size()) {
298 if (Traits::eq(Traits::to_char_type(c), truename[pos]))
299 matched = true;
300 else
301 truename_ok = false;
302 }
303
304 if (othername_ok && pos < othername.size()) {
305 if (Traits::eq(Traits::to_char_type(c), othername[pos]))
306 matched = true;
307 else
308 othername_ok = false;
309 }
310
311 if (matched) { ++pos; }
312 if (pos > falsename.size()) falsename_ok = false;
313 if (pos > truename.size()) truename_ok = false;
314 if (pos > othername.size()) othername_ok = false;
315 }
316
317 if (pos == 0)
318 in.setstate(std::ios_base::failbit);
319 else {
320 if (falsename_ok) x = false;
321 else if (truename_ok) x = true;
322 else if (othername_ok) x = indeterminate;
323 else in.setstate(std::ios_base::failbit);
324 }
325 }
326 } else {
327 long value;
328 if (in >> value) {
329 switch (value) {
330 case 0: x = false; break;
331 case 1: x = true; break;
332 case 2: x = indeterminate; break;
333 default: in.setstate(std::ios_base::failbit); break;
334 }
335 }
336 }
337
338 return in;
339}
340
341} } // end namespace boost::logic
342
343#endif // BOOST_LOGIC_TRIBOOL_IO_HPP