os/ossrv/ossrv_pub/boost_apis/boost/logic/tribool_io.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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, < 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...
   111 #else
   112 #  ifndef BOOST_NO_WCHAR_T
   113 /// Returns the wide character string L"indeterminate".
   114 template<>
   115 inline std::basic_string<wchar_t> get_default_indeterminate_name<wchar_t>()
   116 { return L"indeterminate"; }
   117 #  endif
   118 #endif
   119 
   120 // http://www.cantrip.org/locale.html
   121 
   122 #ifndef BOOST_NO_STD_LOCALE
   123 /**
   124  * \brief A locale facet specifying the name of the indeterminate
   125  * value of a tribool.
   126  *
   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
   130  * locales.
   131  */
   132 template<typename CharT>
   133 class indeterminate_name : public std::locale::facet, private boost::noncopyable
   134 {
   135 public:
   136   typedef CharT char_type;
   137   typedef std::basic_string<CharT> string_type;
   138 
   139   /// Construct the facet with the default name
   140   indeterminate_name() : name_(get_default_indeterminate_name<CharT>()) {}
   141 
   142   /// Construct the facet with the given name for the indeterminate value
   143   explicit indeterminate_name(const string_type& name) : name_(name) {}
   144 
   145   /// Returns the name for the indeterminate value
   146   string_type name() const { return name_; }
   147 
   148   /// Uniquily identifies this facet with the locale.
   149   static std::locale::id id;
   150 
   151 private:
   152   string_type name_;
   153 };
   154 
   155 template<typename CharT> std::locale::id indeterminate_name<CharT>::id;
   156 #endif
   157 
   158 /**
   159  * \brief Writes the value of a tribool to a stream.
   160  *
   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
   164  *
   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
   172  * support locales).
   173  *
   174  * \returns @p out
   175  */
   176 template<typename CharT, typename Traits>
   177 inline std::basic_ostream<CharT, Traits>&
   178 operator<<(std::basic_ostream<CharT, Traits>& out, tribool x)
   179 {
   180   if (!indeterminate(x)) {
   181     out << static_cast<bool>(x);
   182   } else {
   183     typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
   184     if (cerberus) {
   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());
   190           out << facet.name();
   191         } else {
   192           out << get_default_indeterminate_name<CharT>();
   193         }
   194 #else
   195         out << get_default_indeterminate_name<CharT>();
   196 #endif
   197       }
   198       else
   199         out << 2;
   200     }
   201   }
   202   return out;
   203 }
   204 
   205 /**
   206  * \brief Writes the indeterminate tribool value to a stream.
   207  *
   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
   215  * support locales).
   216  *
   217  * \returns @p out
   218  */
   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); } 
   224 
   225 /**
   226  * \brief Reads a tribool value from a stream.
   227  *
   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).
   234  *
   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).
   251  *
   252  * \returns @p in
   253  */
   254 template<typename CharT, typename Traits>
   255 inline std::basic_istream<CharT, Traits>&
   256 operator>>(std::basic_istream<CharT, Traits>& in, tribool& x)
   257 {
   258   if (in.flags() & std::ios_base::boolalpha) {
   259     typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
   260     if (cerberus) {
   261       typedef std::basic_string<CharT> string_type;
   262 
   263 #ifndef BOOST_NO_STD_LOCALE
   264       const std::numpunct<CharT>& numpunct_facet =
   265         BOOST_USE_FACET(std::numpunct<CharT>, in.getloc());
   266 
   267       string_type falsename = numpunct_facet.falsename();
   268       string_type truename = numpunct_facet.truename();
   269 
   270       string_type othername;
   271       if (BOOST_HAS_FACET(indeterminate_name<CharT>, in.getloc())) {
   272         othername =
   273           BOOST_USE_FACET(indeterminate_name<CharT>, in.getloc()).name();
   274       } else {
   275         othername = get_default_indeterminate_name<CharT>();
   276       }
   277 #else
   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>();
   281 #endif
   282 
   283       typename string_type::size_type pos = 0;
   284       bool falsename_ok = true, truename_ok = true, othername_ok = true;
   285 
   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())
   292           return in;
   293 
   294         bool matched = false;
   295         if (falsename_ok && pos < falsename.size()) {
   296           if (Traits::eq(Traits::to_char_type(c), falsename[pos]))
   297             matched = true;
   298           else
   299             falsename_ok = false;
   300         }
   301 
   302         if (truename_ok && pos < truename.size()) {
   303           if (Traits::eq(Traits::to_char_type(c), truename[pos]))
   304             matched = true;
   305           else
   306             truename_ok = false;
   307         }
   308 
   309         if (othername_ok && pos < othername.size()) {
   310           if (Traits::eq(Traits::to_char_type(c), othername[pos]))
   311             matched = true;
   312           else
   313             othername_ok = false;
   314         }
   315 
   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;
   320       }
   321 
   322       if (pos == 0)
   323         in.setstate(std::ios_base::failbit);
   324       else {
   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);
   329       }
   330     }
   331   } else {
   332     long value;
   333     if (in >> value) {
   334       switch (value) {
   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;
   339       }
   340     }
   341   }
   342 
   343   return in;
   344 }
   345 
   346 } } // end namespace boost::logic
   347 
   348 #endif // BOOST_LOGIC_TRIBOOL_IO_HPP