source: NonGTP/Boost/boost/logic/tribool_io.hpp @ 857

Revision 857, 11.4 KB checked in by igarcia, 18 years ago (diff)
Line 
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
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
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 */
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
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 */
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
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".
113template<>
114inline 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 */
131template<typename CharT>
132class indeterminate_name : public std::locale::facet, private boost::noncopyable
133{
134public:
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
150private:
151  string_type name_;
152};
153
154template<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 */
175template<typename CharT, typename Traits>
176inline std::basic_ostream<CharT, Traits>&
177operator<<(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 */
218template<typename CharT, typename Traits>
219inline std::basic_ostream<CharT, Traits>&
220operator<<(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 */
253template<typename CharT, typename Traits>
254inline std::basic_istream<CharT, Traits>&
255operator>>(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
Note: See TracBrowser for help on using the repository browser.