1 // Three-state boolean logic library
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
10 #include <boost/logic/tribool.hpp>
11 #include <boost/detail/workaround.hpp>
12 #include <boost/noncopyable.hpp>
14 #if BOOST_WORKAROUND(_MSC_VER, >= 1200)
18 #ifndef BOOST_NO_STD_LOCALE
25 namespace boost
{ namespace logic
{
27 #ifdef BOOST_NO_STD_LOCALE
30 * \brief Returns a string containing the default name for the \c
31 * false value of a tribool with the given character type T.
33 * This function only exists when the C++ standard library
34 * implementation does not support locales.
36 template<typename T
> std::basic_string
<T
> default_false_name();
39 * \brief Returns the character string "false".
41 * This function only exists when the C++ standard library
42 * implementation does not support locales.
45 inline std::basic_string
<char> default_false_name
<char>()
48 # ifndef BOOST_NO_WCHAR_T
50 * \brief Returns the wide character string L"false".
52 * This function only exists when the C++ standard library
53 * implementation does not support locales.
56 inline std::basic_string
<wchar_t> default_false_name
<wchar_t>()
61 * \brief Returns a string containing the default name for the \c true
62 * value of a tribool with the given character type T.
64 * This function only exists when the C++ standard library
65 * implementation does not support locales.
67 template<typename T
> std::basic_string
<T
> default_true_name();
70 * \brief Returns the character string "true".
72 * This function only exists when the C++ standard library
73 * implementation does not support locales.
76 inline std::basic_string
<char> default_true_name
<char>()
79 # ifndef BOOST_NO_WCHAR_T
81 * \brief Returns the wide character string L"true".
83 * This function only exists * when the C++ standard library
84 * implementation does not support * locales.
87 inline std::basic_string
<wchar_t> default_true_name
<wchar_t>()
93 * \brief Returns a string containing the default name for the indeterminate
94 * value of a tribool with the given character type T.
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.
100 template<typename T
> std::basic_string
<T
> get_default_indeterminate_name();
102 /// Returns the character string "indeterminate".
104 inline std::basic_string
<char> get_default_indeterminate_name
<char>()
105 { return "indeterminate"; }
107 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
108 // VC++ 6.0 chokes on the specialization below, so we're stuck without
109 // wchar_t support. What a pain. TODO: it might just need a the template
110 // parameter as function parameter...
112 # ifndef BOOST_NO_WCHAR_T
113 /// Returns the wide character string L"indeterminate".
115 inline std::basic_string
<wchar_t> get_default_indeterminate_name
<wchar_t>()
116 { return L
"indeterminate"; }
120 // http://www.cantrip.org/locale.html
122 #ifndef BOOST_NO_STD_LOCALE
124 * \brief A locale facet specifying the name of the indeterminate
125 * value of a tribool.
127 * The facet is used to perform I/O on tribool values when \c
128 * std::boolalpha has been specified. This class template is only
129 * available if the C++ standard library implementation supports
132 template<typename CharT
>
133 class indeterminate_name
: public std::locale::facet
, private boost::noncopyable
136 typedef CharT char_type
;
137 typedef std::basic_string
<CharT
> string_type
;
139 /// Construct the facet with the default name
140 indeterminate_name() : name_(get_default_indeterminate_name
<CharT
>()) {}
142 /// Construct the facet with the given name for the indeterminate value
143 explicit indeterminate_name(const string_type
& name
) : name_(name
) {}
145 /// Returns the name for the indeterminate value
146 string_type
name() const { return name_
; }
148 /// Uniquily identifies this facet with the locale.
149 static std::locale::id id
;
155 template<typename CharT
> std::locale::id indeterminate_name
<CharT
>::id
;
159 * \brief Writes the value of a tribool to a stream.
161 * When the value of @p x is either \c true or \c false, this routine
162 * is semantically equivalent to:
163 * \code out << static_cast<bool>(x); \endcode
165 * When @p x has an indeterminate value, it outputs either the integer
166 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
167 * or the name of the indeterminate value. The name of the
168 * indeterminate value comes from the indeterminate_name facet (if it
169 * is defined in the output stream's locale), or from the
170 * get_default_indeterminate_name function (if it is not defined in the
171 * locale or if the C++ standard library implementation does not
176 template<typename CharT
, typename Traits
>
177 inline std::basic_ostream
<CharT
, Traits
>&
178 operator<<(std::basic_ostream
<CharT
, Traits
>& out
, tribool x
)
180 if (!indeterminate(x
)) {
181 out
<< static_cast<bool>(x
);
183 typename
std::basic_ostream
<CharT
, Traits
>::sentry
cerberus(out
);
185 if (out
.flags() & std::ios_base::boolalpha
) {
186 #ifndef BOOST_NO_STD_LOCALE
187 if (BOOST_HAS_FACET(indeterminate_name
<CharT
>, out
.getloc())) {
188 const indeterminate_name
<CharT
>& facet
=
189 BOOST_USE_FACET(indeterminate_name
<CharT
>, out
.getloc());
192 out
<< get_default_indeterminate_name
<CharT
>();
195 out
<< get_default_indeterminate_name
<CharT
>();
206 * \brief Writes the indeterminate tribool value to a stream.
208 * This routine outputs either the integer
209 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
210 * or the name of the indeterminate value. The name of the
211 * indeterminate value comes from the indeterminate_name facet (if it
212 * is defined in the output stream's locale), or from the
213 * get_default_indeterminate_name function (if it is not defined in the
214 * locale or if the C++ standard library implementation does not
219 template<typename CharT
, typename Traits
>
220 inline std::basic_ostream
<CharT
, Traits
>&
221 operator<<(std::basic_ostream
<CharT
, Traits
>& out
,
222 bool (*)(tribool
, detail::indeterminate_t
))
223 { return out
<< tribool(indeterminate
); }
226 * \brief Reads a tribool value from a stream.
228 * When <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>, this
229 * function reads a \c long value from the input stream @p in and
230 * converts that value to a tribool. If that value is 0, @p x becomes
231 * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes
232 * \c indetermine; otherwise, the operation fails (and the fail bit is
233 * set on the input stream @p in).
235 * When <tt>(out.flags() & std::ios_base::boolalpha) != 0</tt>, this
236 * function first determines the names of the false, true, and
237 * indeterminate values. The false and true names are extracted from
238 * the \c std::numpunct facet of the input stream's locale (if the C++
239 * standard library implementation supports locales), or from the \c
240 * default_false_name and \c default_true_name functions (if there is
241 * no locale support). The indeterminate name is extracted from the
242 * appropriate \c indeterminate_name facet (if it is available in the
243 * input stream's locale), or from the \c get_default_indeterminate_name
244 * function (if the C++ standard library implementation does not
245 * support locales, or the \c indeterminate_name facet is not
246 * specified for this locale object). The input is then matched to
247 * each of these names, and the tribool @p x is assigned the value
248 * corresponding to the longest name that matched. If no name is
249 * matched or all names are empty, the operation fails (and the fail
250 * bit is set on the input stream @p in).
254 template<typename CharT
, typename Traits
>
255 inline std::basic_istream
<CharT
, Traits
>&
256 operator>>(std::basic_istream
<CharT
, Traits
>& in
, tribool
& x
)
258 if (in
.flags() & std::ios_base::boolalpha
) {
259 typename
std::basic_istream
<CharT
, Traits
>::sentry
cerberus(in
);
261 typedef std::basic_string
<CharT
> string_type
;
263 #ifndef BOOST_NO_STD_LOCALE
264 const std::numpunct
<CharT
>& numpunct_facet
=
265 BOOST_USE_FACET(std::numpunct
<CharT
>, in
.getloc());
267 string_type falsename
= numpunct_facet
.falsename();
268 string_type truename
= numpunct_facet
.truename();
270 string_type othername
;
271 if (BOOST_HAS_FACET(indeterminate_name
<CharT
>, in
.getloc())) {
273 BOOST_USE_FACET(indeterminate_name
<CharT
>, in
.getloc()).name();
275 othername
= get_default_indeterminate_name
<CharT
>();
278 string_type falsename
= default_false_name
<CharT
>();
279 string_type truename
= default_true_name
<CharT
>();
280 string_type othername
= get_default_indeterminate_name
<CharT
>();
283 typename
string_type::size_type pos
= 0;
284 bool falsename_ok
= true, truename_ok
= true, othername_ok
= true;
286 // Modeled after the code from Library DR 17
287 while (falsename_ok
&& pos
< falsename
.size()
288 || truename_ok
&& pos
< truename
.size()
289 || othername_ok
&& pos
< othername
.size()) {
290 typename
Traits::int_type c
= in
.get();
291 if (c
== Traits::eof())
294 bool matched
= false;
295 if (falsename_ok
&& pos
< falsename
.size()) {
296 if (Traits::eq(Traits::to_char_type(c
), falsename
[pos
]))
299 falsename_ok
= false;
302 if (truename_ok
&& pos
< truename
.size()) {
303 if (Traits::eq(Traits::to_char_type(c
), truename
[pos
]))
309 if (othername_ok
&& pos
< othername
.size()) {
310 if (Traits::eq(Traits::to_char_type(c
), othername
[pos
]))
313 othername_ok
= false;
316 if (matched
) { ++pos
; }
317 if (pos
> falsename
.size()) falsename_ok
= false;
318 if (pos
> truename
.size()) truename_ok
= false;
319 if (pos
> othername
.size()) othername_ok
= false;
323 in
.setstate(std::ios_base::failbit
);
325 if (falsename_ok
) x
= false;
326 else if (truename_ok
) x
= true;
327 else if (othername_ok
) x
= indeterminate
;
328 else in
.setstate(std::ios_base::failbit
);
335 case 0: x
= false; break;
336 case 1: x
= true; break;
337 case 2: x
= indeterminate
; break;
338 default: in
.setstate(std::ios_base::failbit
); break;
346 } } // end namespace boost::logic
348 #endif // BOOST_LOGIC_TRIBOOL_IO_HPP