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 BOOST_WORKAROUND(_MSC_VER, >= 1200)
|
---|
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 |
|
---|
25 | namespace 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 | */
|
---|
36 | template<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 | */
|
---|
44 | template<>
|
---|
45 | inline std::basic_string<char> default_false_name<char>()
|
---|
46 | { return "false"; }
|
---|
47 |
|
---|
48 | # ifndef BOOST_NO_WCHAR_T
|
---|
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 | */
|
---|
55 | template<>
|
---|
56 | inline 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 | */
|
---|
67 | template<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 | */
|
---|
75 | template<>
|
---|
76 | inline std::basic_string<char> default_true_name<char>()
|
---|
77 | { return "true"; }
|
---|
78 |
|
---|
79 | # ifndef BOOST_NO_WCHAR_T
|
---|
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 | */
|
---|
86 | template<>
|
---|
87 | inline 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 | */
|
---|
100 | template<typename T> std::basic_string<T> get_default_indeterminate_name();
|
---|
101 |
|
---|
102 | /// Returns the character string "indeterminate".
|
---|
103 | template<>
|
---|
104 | inline std::basic_string<char> get_default_indeterminate_name<char>()
|
---|
105 | { return "indeterminate"; }
|
---|
106 |
|
---|
107 | #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
|
---|
108 | // VC++ 6.0 chokes on the specialization below, so we're stuck without
|
---|
109 | // wchar_t support. What a pain.
|
---|
110 | #else
|
---|
111 | # ifndef BOOST_NO_WCHAR_T
|
---|
112 | /// Returns the wide character string L"indeterminate".
|
---|
113 | template<>
|
---|
114 | inline std::basic_string<wchar_t> get_default_indeterminate_name<wchar_t>()
|
---|
115 | { return L"indeterminate"; }
|
---|
116 | # endif
|
---|
117 | #endif
|
---|
118 |
|
---|
119 | // http://www.cantrip.org/locale.html
|
---|
120 |
|
---|
121 | #ifndef BOOST_NO_STD_LOCALE
|
---|
122 | /**
|
---|
123 | * \brief A locale facet specifying the name of the indeterminate
|
---|
124 | * value of a tribool.
|
---|
125 | *
|
---|
126 | * The facet is used to perform I/O on tribool values when \c
|
---|
127 | * std::boolalpha has been specified. This class template is only
|
---|
128 | * available if the C++ standard library implementation supports
|
---|
129 | * locales.
|
---|
130 | */
|
---|
131 | template<typename CharT>
|
---|
132 | class indeterminate_name : public std::locale::facet, private boost::noncopyable
|
---|
133 | {
|
---|
134 | public:
|
---|
135 | typedef CharT char_type;
|
---|
136 | typedef std::basic_string<CharT> string_type;
|
---|
137 |
|
---|
138 | /// Construct the facet with the default name
|
---|
139 | indeterminate_name() : name_(get_default_indeterminate_name<CharT>()) {}
|
---|
140 |
|
---|
141 | /// Construct the facet with the given name for the indeterminate value
|
---|
142 | explicit indeterminate_name(const string_type& name) : name_(name) {}
|
---|
143 |
|
---|
144 | /// Returns the name for the indeterminate value
|
---|
145 | string_type name() const { return name_; }
|
---|
146 |
|
---|
147 | /// Uniquily identifies this facet with the locale.
|
---|
148 | static std::locale::id id;
|
---|
149 |
|
---|
150 | private:
|
---|
151 | string_type name_;
|
---|
152 | };
|
---|
153 |
|
---|
154 | template<typename CharT> std::locale::id indeterminate_name<CharT>::id;
|
---|
155 | #endif
|
---|
156 |
|
---|
157 | /**
|
---|
158 | * \brief Writes the value of a tribool to a stream.
|
---|
159 | *
|
---|
160 | * When the value of @p x is either \c true or \c false, this routine
|
---|
161 | * is semantically equivalent to:
|
---|
162 | * \code out << static_cast<bool>(x); \endcode
|
---|
163 | *
|
---|
164 | * When @p x has an indeterminate value, it outputs either the integer
|
---|
165 | * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
|
---|
166 | * or the name of the indeterminate value. The name of the
|
---|
167 | * indeterminate value comes from the indeterminate_name facet (if it
|
---|
168 | * is defined in the output stream's locale), or from the
|
---|
169 | * get_default_indeterminate_name function (if it is not defined in the
|
---|
170 | * locale or if the C++ standard library implementation does not
|
---|
171 | * support locales).
|
---|
172 | *
|
---|
173 | * \returns @p out
|
---|
174 | */
|
---|
175 | template<typename CharT, typename Traits>
|
---|
176 | inline std::basic_ostream<CharT, Traits>&
|
---|
177 | operator<<(std::basic_ostream<CharT, Traits>& out, tribool x)
|
---|
178 | {
|
---|
179 | if (!indeterminate(x)) {
|
---|
180 | out << static_cast<bool>(x);
|
---|
181 | } else {
|
---|
182 | typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
|
---|
183 | if (cerberus) {
|
---|
184 | if (out.flags() & std::ios_base::boolalpha) {
|
---|
185 | #ifndef BOOST_NO_STD_LOCALE
|
---|
186 | if (BOOST_HAS_FACET(indeterminate_name<CharT>, out.getloc())) {
|
---|
187 | const indeterminate_name<CharT>& facet =
|
---|
188 | BOOST_USE_FACET(indeterminate_name<CharT>, out.getloc());
|
---|
189 | out << facet.name();
|
---|
190 | } else {
|
---|
191 | out << get_default_indeterminate_name<CharT>();
|
---|
192 | }
|
---|
193 | #else
|
---|
194 | out << get_default_indeterminate_name<CharT>();
|
---|
195 | #endif
|
---|
196 | }
|
---|
197 | else
|
---|
198 | out << 2;
|
---|
199 | }
|
---|
200 | }
|
---|
201 | return out;
|
---|
202 | }
|
---|
203 |
|
---|
204 | /**
|
---|
205 | * \brief Writes the indeterminate tribool value to a stream.
|
---|
206 | *
|
---|
207 | * This routine outputs either the integer
|
---|
208 | * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
|
---|
209 | * or the name of the indeterminate value. The name of the
|
---|
210 | * indeterminate value comes from the indeterminate_name facet (if it
|
---|
211 | * is defined in the output stream's locale), or from the
|
---|
212 | * get_default_indeterminate_name function (if it is not defined in the
|
---|
213 | * locale or if the C++ standard library implementation does not
|
---|
214 | * support locales).
|
---|
215 | *
|
---|
216 | * \returns @p out
|
---|
217 | */
|
---|
218 | template<typename CharT, typename Traits>
|
---|
219 | inline std::basic_ostream<CharT, Traits>&
|
---|
220 | operator<<(std::basic_ostream<CharT, Traits>& out,
|
---|
221 | bool (*)(tribool, detail::indeterminate_t))
|
---|
222 | { return out << tribool(indeterminate); }
|
---|
223 |
|
---|
224 | /**
|
---|
225 | * \brief Reads a tribool value from a stream.
|
---|
226 | *
|
---|
227 | * When <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>, this
|
---|
228 | * function reads a \c long value from the input stream @p in and
|
---|
229 | * converts that value to a tribool. If that value is 0, @p x becomes
|
---|
230 | * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes
|
---|
231 | * \c indetermine; otherwise, the operation fails (and the fail bit is
|
---|
232 | * set on the input stream @p in).
|
---|
233 | *
|
---|
234 | * When <tt>(out.flags() & std::ios_base::boolalpha) != 0</tt>, this
|
---|
235 | * function first determines the names of the false, true, and
|
---|
236 | * indeterminate values. The false and true names are extracted from
|
---|
237 | * the \c std::numpunct facet of the input stream's locale (if the C++
|
---|
238 | * standard library implementation supports locales), or from the \c
|
---|
239 | * default_false_name and \c default_true_name functions (if there is
|
---|
240 | * no locale support). The indeterminate name is extracted from the
|
---|
241 | * appropriate \c indeterminate_name facet (if it is available in the
|
---|
242 | * input stream's locale), or from the \c get_default_indeterminate_name
|
---|
243 | * function (if the C++ standard library implementation does not
|
---|
244 | * support locales, or the \c indeterminate_name facet is not
|
---|
245 | * specified for this locale object). The input is then matched to
|
---|
246 | * each of these names, and the tribool @p x is assigned the value
|
---|
247 | * corresponding to the longest name that matched. If no name is
|
---|
248 | * matched or all names are empty, the operation fails (and the fail
|
---|
249 | * bit is set on the input stream @p in).
|
---|
250 | *
|
---|
251 | * \returns @p in
|
---|
252 | */
|
---|
253 | template<typename CharT, typename Traits>
|
---|
254 | inline std::basic_istream<CharT, Traits>&
|
---|
255 | operator>>(std::basic_istream<CharT, Traits>& in, tribool& x)
|
---|
256 | {
|
---|
257 | if (in.flags() & std::ios_base::boolalpha) {
|
---|
258 | typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
|
---|
259 | if (cerberus) {
|
---|
260 | typedef std::basic_string<CharT> string_type;
|
---|
261 |
|
---|
262 | #ifndef BOOST_NO_STD_LOCALE
|
---|
263 | const std::numpunct<CharT>& numpunct_facet =
|
---|
264 | BOOST_USE_FACET(std::numpunct<CharT>, in.getloc());
|
---|
265 |
|
---|
266 | string_type falsename = numpunct_facet.falsename();
|
---|
267 | string_type truename = numpunct_facet.truename();
|
---|
268 |
|
---|
269 | string_type othername;
|
---|
270 | if (BOOST_HAS_FACET(indeterminate_name<CharT>, in.getloc())) {
|
---|
271 | othername =
|
---|
272 | BOOST_USE_FACET(indeterminate_name<CharT>, in.getloc()).name();
|
---|
273 | } else {
|
---|
274 | othername = get_default_indeterminate_name<CharT>();
|
---|
275 | }
|
---|
276 | #else
|
---|
277 | string_type falsename = default_false_name<CharT>();
|
---|
278 | string_type truename = default_true_name<CharT>();
|
---|
279 | string_type othername = get_default_indeterminate_name<CharT>();
|
---|
280 | #endif
|
---|
281 |
|
---|
282 | typename string_type::size_type pos = 0;
|
---|
283 | bool falsename_ok = true, truename_ok = true, othername_ok = true;
|
---|
284 |
|
---|
285 | // Modeled after the code from Library DR 17
|
---|
286 | while (falsename_ok && pos < falsename.size()
|
---|
287 | || truename_ok && pos < truename.size()
|
---|
288 | || othername_ok && pos < othername.size()) {
|
---|
289 | typename Traits::int_type c = in.get();
|
---|
290 | if (c == Traits::eof())
|
---|
291 | return in;
|
---|
292 |
|
---|
293 | bool matched = false;
|
---|
294 | if (falsename_ok && pos < falsename.size()) {
|
---|
295 | if (Traits::eq(Traits::to_char_type(c), falsename[pos]))
|
---|
296 | matched = true;
|
---|
297 | else
|
---|
298 | falsename_ok = false;
|
---|
299 | }
|
---|
300 |
|
---|
301 | if (truename_ok && pos < truename.size()) {
|
---|
302 | if (Traits::eq(Traits::to_char_type(c), truename[pos]))
|
---|
303 | matched = true;
|
---|
304 | else
|
---|
305 | truename_ok = false;
|
---|
306 | }
|
---|
307 |
|
---|
308 | if (othername_ok && pos < othername.size()) {
|
---|
309 | if (Traits::eq(Traits::to_char_type(c), othername[pos]))
|
---|
310 | matched = true;
|
---|
311 | else
|
---|
312 | othername_ok = false;
|
---|
313 | }
|
---|
314 |
|
---|
315 | if (matched) { ++pos; }
|
---|
316 | if (pos > falsename.size()) falsename_ok = false;
|
---|
317 | if (pos > truename.size()) truename_ok = false;
|
---|
318 | if (pos > othername.size()) othername_ok = false;
|
---|
319 | }
|
---|
320 |
|
---|
321 | if (pos == 0)
|
---|
322 | in.setstate(std::ios_base::failbit);
|
---|
323 | else {
|
---|
324 | if (falsename_ok) x = false;
|
---|
325 | else if (truename_ok) x = true;
|
---|
326 | else if (othername_ok) x = indeterminate;
|
---|
327 | else in.setstate(std::ios_base::failbit);
|
---|
328 | }
|
---|
329 | }
|
---|
330 | } else {
|
---|
331 | long value;
|
---|
332 | if (in >> value) {
|
---|
333 | switch (value) {
|
---|
334 | case 0: x = false; break;
|
---|
335 | case 1: x = true; break;
|
---|
336 | case 2: x = indeterminate; break;
|
---|
337 | default: in.setstate(std::ios_base::failbit); break;
|
---|
338 | }
|
---|
339 | }
|
---|
340 | }
|
---|
341 |
|
---|
342 | return in;
|
---|
343 | }
|
---|
344 |
|
---|
345 | } } // end namespace boost::logic
|
---|
346 |
|
---|
347 | #endif // BOOST_LOGIC_TRIBOOL_IO_HPP
|
---|