Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / logic / tribool_io.hpp
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