Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:30

0001 // Three-state boolean logic library
0002 
0003 // Copyright Douglas Gregor 2002-2004. Use, modification and
0004 // distribution is subject to the Boost Software License, Version
0005 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt)
0007 #ifndef BOOST_LOGIC_TRIBOOL_IO_HPP
0008 #define BOOST_LOGIC_TRIBOOL_IO_HPP
0009 
0010 #include <boost/logic/tribool.hpp>
0011 #include <boost/detail/workaround.hpp>
0012 #include <boost/noncopyable.hpp>
0013 
0014 #if defined(_MSC_VER)
0015 #  pragma once
0016 #endif
0017 
0018 #ifndef BOOST_NO_STD_LOCALE
0019 #  include <locale>
0020 #endif
0021 
0022 #include <string>
0023 #include <iostream>
0024 
0025 namespace boost { namespace logic {
0026 
0027 #ifdef BOOST_NO_STD_LOCALE
0028 
0029 /**
0030  * \brief Returns a string containing the default name for the \c
0031  * false value of a tribool with the given character type T.
0032  *
0033  * This function only exists when the C++ standard library
0034  * implementation does not support locales.
0035  */
0036 template<typename T> std::basic_string<T> default_false_name();
0037 
0038 /**
0039  * \brief Returns the character string "false".
0040  *
0041  * This function only exists when the C++ standard library
0042  * implementation does not support locales.
0043  */
0044 template<>
0045 inline std::basic_string<char> default_false_name<char>()
0046 { return "false"; }
0047 
0048 #  if !defined(BOOST_NO_CWCHAR)
0049 /**
0050  * \brief Returns the wide character string L"false".
0051  *
0052  * This function only exists when the C++ standard library
0053  * implementation does not support locales.
0054  */
0055 template<>
0056 inline std::basic_string<wchar_t> default_false_name<wchar_t>()
0057 { return L"false"; }
0058 #  endif
0059 
0060 /**
0061  * \brief Returns a string containing the default name for the \c true
0062  * value of a tribool with the given character type T.
0063  *
0064  * This function only exists when the C++ standard library
0065  * implementation does not support locales.
0066  */
0067 template<typename T> std::basic_string<T> default_true_name();
0068 
0069 /**
0070  * \brief Returns the character string "true".
0071  *
0072  * This function only exists when the C++ standard library
0073  * implementation does not support locales.
0074  */
0075 template<>
0076 inline std::basic_string<char> default_true_name<char>()
0077 { return "true"; }
0078 
0079 #  if !defined(BOOST_NO_CWCHAR)
0080 /**
0081  * \brief Returns the wide character string L"true".
0082  *
0083  *  This function only exists * when the C++ standard library
0084  *  implementation does not support * locales.
0085  */
0086 template<>
0087 inline std::basic_string<wchar_t> default_true_name<wchar_t>()
0088 { return L"true"; }
0089 #  endif
0090 #endif
0091 
0092 /**
0093  * \brief Returns a string containing the default name for the indeterminate
0094  * value of a tribool with the given character type T.
0095  *
0096  * This routine is used by the input and output streaming operators
0097  * for tribool when there is no locale support or the stream's locale
0098  * does not contain the indeterminate_name facet.
0099  */
0100 template<typename T> std::basic_string<T> get_default_indeterminate_name();
0101 
0102 /// Returns the character string "indeterminate".
0103 template<>
0104 inline std::basic_string<char> get_default_indeterminate_name<char>()
0105 { return "indeterminate"; }
0106 
0107 #if !defined(BOOST_NO_CWCHAR)
0108 /// Returns the wide character string L"indeterminate".
0109 template<>
0110 inline std::basic_string<wchar_t> get_default_indeterminate_name<wchar_t>()
0111 { return L"indeterminate"; }
0112 #endif
0113 
0114 // http://www.cantrip.org/locale.html
0115 
0116 #ifndef BOOST_NO_STD_LOCALE
0117 /**
0118  * \brief A locale facet specifying the name of the indeterminate
0119  * value of a tribool.
0120  *
0121  * The facet is used to perform I/O on tribool values when \c
0122  * std::boolalpha has been specified. This class template is only
0123  * available if the C++ standard library implementation supports
0124  * locales.
0125  */
0126 template<typename CharT>
0127 class indeterminate_name : public std::locale::facet, private boost::noncopyable
0128 {
0129 public:
0130   typedef CharT char_type;
0131   typedef std::basic_string<CharT> string_type;
0132 
0133   /// Construct the facet with the default name
0134   indeterminate_name() : name_(get_default_indeterminate_name<CharT>()) {}
0135 
0136   /// Construct the facet with the given name for the indeterminate value
0137   explicit indeterminate_name(const string_type& initial_name)
0138   : name_(initial_name) {}
0139 
0140   /// Returns the name for the indeterminate value
0141   string_type name() const { return name_; }
0142 
0143   /// Uniquily identifies this facet with the locale.
0144   static std::locale::id id;
0145 
0146 private:
0147   string_type name_;
0148 };
0149 
0150 template<typename CharT> std::locale::id indeterminate_name<CharT>::id;
0151 #endif
0152 
0153 /**
0154  * \brief Writes the value of a tribool to a stream.
0155  *
0156  * When the value of @p x is either \c true or \c false, this routine
0157  * is semantically equivalent to:
0158  * \code out << static_cast<bool>(x); \endcode
0159  *
0160  * When @p x has an indeterminate value, it outputs either the integer
0161  * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
0162  * or the name of the indeterminate value. The name of the
0163  * indeterminate value comes from the indeterminate_name facet (if it
0164  * is defined in the output stream's locale), or from the
0165  * get_default_indeterminate_name function (if it is not defined in the
0166  * locale or if the C++ standard library implementation does not
0167  * support locales).
0168  *
0169  * \returns @p out
0170  */
0171 template<typename CharT, typename Traits>
0172 inline std::basic_ostream<CharT, Traits>&
0173 operator<<(std::basic_ostream<CharT, Traits>& out, tribool x)
0174 {
0175   if (!indeterminate(x)) {
0176     out << static_cast<bool>(x);
0177   } else {
0178     typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
0179     if (cerberus) {
0180       if (out.flags() & std::ios_base::boolalpha) {
0181 #ifndef BOOST_NO_STD_LOCALE
0182         if (BOOST_HAS_FACET(indeterminate_name<CharT>, out.getloc())) {
0183           const indeterminate_name<CharT>& facet =
0184             BOOST_USE_FACET(indeterminate_name<CharT>, out.getloc());
0185           out << facet.name();
0186         } else {
0187           out << get_default_indeterminate_name<CharT>();
0188         }
0189 #else
0190         out << get_default_indeterminate_name<CharT>();
0191 #endif
0192       }
0193       else
0194         out << 2;
0195     }
0196   }
0197   return out;
0198 }
0199 
0200 /**
0201  * \brief Writes the indeterminate tribool value to a stream.
0202  *
0203  * This routine outputs either the integer
0204  * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
0205  * or the name of the indeterminate value. The name of the
0206  * indeterminate value comes from the indeterminate_name facet (if it
0207  * is defined in the output stream's locale), or from the
0208  * get_default_indeterminate_name function (if it is not defined in the
0209  * locale or if the C++ standard library implementation does not
0210  * support locales).
0211  *
0212  * \returns @p out
0213  */
0214 template<typename CharT, typename Traits>
0215 inline std::basic_ostream<CharT, Traits>&
0216 operator<<(std::basic_ostream<CharT, Traits>& out, 
0217            bool (*)(tribool, detail::indeterminate_t))
0218 { return out << tribool(indeterminate); } 
0219 
0220 /**
0221  * \brief Reads a tribool value from a stream.
0222  *
0223  * When <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>, this
0224  * function reads a \c long value from the input stream @p in and
0225  * converts that value to a tribool. If that value is 0, @p x becomes
0226  * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes
0227  * \c indetermine; otherwise, the operation fails (and the fail bit is
0228  * set on the input stream @p in).
0229  *
0230  * When <tt>(out.flags() & std::ios_base::boolalpha) != 0</tt>, this
0231  * function first determines the names of the false, true, and
0232  * indeterminate values. The false and true names are extracted from
0233  * the \c std::numpunct facet of the input stream's locale (if the C++
0234  * standard library implementation supports locales), or from the \c
0235  * default_false_name and \c default_true_name functions (if there is
0236  * no locale support). The indeterminate name is extracted from the
0237  * appropriate \c indeterminate_name facet (if it is available in the
0238  * input stream's locale), or from the \c get_default_indeterminate_name
0239  * function (if the C++ standard library implementation does not
0240  * support locales, or the \c indeterminate_name facet is not
0241  * specified for this locale object). The input is then matched to
0242  * each of these names, and the tribool @p x is assigned the value
0243  * corresponding to the longest name that matched. If no name is
0244  * matched or all names are empty, the operation fails (and the fail
0245  * bit is set on the input stream @p in).
0246  *
0247  * \returns @p in
0248  */
0249 template<typename CharT, typename Traits>
0250 inline std::basic_istream<CharT, Traits>&
0251 operator>>(std::basic_istream<CharT, Traits>& in, tribool& x)
0252 {
0253   if (in.flags() & std::ios_base::boolalpha) {
0254     typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
0255     if (cerberus) {
0256       typedef std::basic_string<CharT> string_type;
0257 
0258 #ifndef BOOST_NO_STD_LOCALE
0259       const std::numpunct<CharT>& numpunct_facet =
0260         BOOST_USE_FACET(std::numpunct<CharT>, in.getloc());
0261 
0262       string_type falsename = numpunct_facet.falsename();
0263       string_type truename = numpunct_facet.truename();
0264 
0265       string_type othername;
0266       if (BOOST_HAS_FACET(indeterminate_name<CharT>, in.getloc())) {
0267         othername =
0268           BOOST_USE_FACET(indeterminate_name<CharT>, in.getloc()).name();
0269       } else {
0270         othername = get_default_indeterminate_name<CharT>();
0271       }
0272 #else
0273       string_type falsename = default_false_name<CharT>();
0274       string_type truename = default_true_name<CharT>();
0275       string_type othername = get_default_indeterminate_name<CharT>();
0276 #endif
0277 
0278       typename string_type::size_type pos = 0;
0279       bool falsename_ok = true, truename_ok = true, othername_ok = true;
0280 
0281       // Modeled after the code from Library DR 17
0282       while ((falsename_ok && pos < falsename.size())
0283              || (truename_ok && pos < truename.size())
0284              || (othername_ok && pos < othername.size())) {
0285         typename Traits::int_type c = in.get();
0286         if (c == Traits::eof())
0287           return in;
0288 
0289         bool matched = false;
0290         if (falsename_ok && pos < falsename.size()) {
0291           if (Traits::eq(Traits::to_char_type(c), falsename[pos]))
0292             matched = true;
0293           else
0294             falsename_ok = false;
0295         }
0296 
0297         if (truename_ok && pos < truename.size()) {
0298           if (Traits::eq(Traits::to_char_type(c), truename[pos]))
0299             matched = true;
0300           else
0301             truename_ok = false;
0302         }
0303 
0304         if (othername_ok && pos < othername.size()) {
0305           if (Traits::eq(Traits::to_char_type(c), othername[pos]))
0306             matched = true;
0307           else
0308             othername_ok = false;
0309         }
0310 
0311         if (matched) { ++pos; }
0312         if (pos > falsename.size()) falsename_ok = false;
0313         if (pos > truename.size())  truename_ok = false;
0314         if (pos > othername.size()) othername_ok = false;
0315       }
0316 
0317       if (pos == 0)
0318         in.setstate(std::ios_base::failbit);
0319       else {
0320         if (falsename_ok)      x = false;
0321         else if (truename_ok)  x = true;
0322         else if (othername_ok) x = indeterminate;
0323         else in.setstate(std::ios_base::failbit);
0324       }
0325     }
0326   } else {
0327     long value;
0328     if (in >> value) {
0329       switch (value) {
0330       case 0: x = false; break;
0331       case 1: x = true; break;
0332       case 2: x = indeterminate; break;
0333       default: in.setstate(std::ios_base::failbit); break;
0334       }
0335     }
0336   }
0337 
0338   return in;
0339 }
0340 
0341 } } // end namespace boost::logic
0342 
0343 #endif // BOOST_LOGIC_TRIBOOL_IO_HPP