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