os/ossrv/ossrv_pub/boost_apis/boost/logic/tribool_io.hpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
sl@0
     1
// Three-state boolean logic library
sl@0
     2
sl@0
     3
// Copyright Douglas Gregor 2002-2004. Use, modification and
sl@0
     4
// distribution is subject to the Boost Software License, Version
sl@0
     5
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
sl@0
     6
// http://www.boost.org/LICENSE_1_0.txt)
sl@0
     7
#ifndef BOOST_LOGIC_TRIBOOL_IO_HPP
sl@0
     8
#define BOOST_LOGIC_TRIBOOL_IO_HPP
sl@0
     9
sl@0
    10
#include <boost/logic/tribool.hpp>
sl@0
    11
#include <boost/detail/workaround.hpp>
sl@0
    12
#include <boost/noncopyable.hpp>
sl@0
    13
sl@0
    14
#if BOOST_WORKAROUND(_MSC_VER, >= 1200)
sl@0
    15
#  pragma once
sl@0
    16
#endif
sl@0
    17
sl@0
    18
#ifndef BOOST_NO_STD_LOCALE
sl@0
    19
#  include <locale>
sl@0
    20
#endif
sl@0
    21
sl@0
    22
#include <string>
sl@0
    23
#include <iostream>
sl@0
    24
sl@0
    25
namespace boost { namespace logic {
sl@0
    26
sl@0
    27
#ifdef BOOST_NO_STD_LOCALE
sl@0
    28
sl@0
    29
/**
sl@0
    30
 * \brief Returns a string containing the default name for the \c
sl@0
    31
 * false value of a tribool with the given character type T.
sl@0
    32
 *
sl@0
    33
 * This function only exists when the C++ standard library
sl@0
    34
 * implementation does not support locales.
sl@0
    35
 */
sl@0
    36
template<typename T> std::basic_string<T> default_false_name();
sl@0
    37
sl@0
    38
/**
sl@0
    39
 * \brief Returns the character string "false".
sl@0
    40
 *
sl@0
    41
 * This function only exists when the C++ standard library
sl@0
    42
 * implementation does not support locales.
sl@0
    43
 */
sl@0
    44
template<>
sl@0
    45
inline std::basic_string<char> default_false_name<char>()
sl@0
    46
{ return "false"; }
sl@0
    47
sl@0
    48
#  ifndef BOOST_NO_WCHAR_T
sl@0
    49
/**
sl@0
    50
 * \brief Returns the wide character string L"false".
sl@0
    51
 *
sl@0
    52
 * This function only exists when the C++ standard library
sl@0
    53
 * implementation does not support locales.
sl@0
    54
 */
sl@0
    55
template<>
sl@0
    56
inline std::basic_string<wchar_t> default_false_name<wchar_t>()
sl@0
    57
{ return L"false"; }
sl@0
    58
#  endif
sl@0
    59
sl@0
    60
/**
sl@0
    61
 * \brief Returns a string containing the default name for the \c true
sl@0
    62
 * value of a tribool with the given character type T.
sl@0
    63
 *
sl@0
    64
 * This function only exists when the C++ standard library
sl@0
    65
 * implementation does not support locales.
sl@0
    66
 */
sl@0
    67
template<typename T> std::basic_string<T> default_true_name();
sl@0
    68
sl@0
    69
/**
sl@0
    70
 * \brief Returns the character string "true".
sl@0
    71
 *
sl@0
    72
 * This function only exists when the C++ standard library
sl@0
    73
 * implementation does not support locales.
sl@0
    74
 */
sl@0
    75
template<>
sl@0
    76
inline std::basic_string<char> default_true_name<char>()
sl@0
    77
{ return "true"; }
sl@0
    78
sl@0
    79
#  ifndef BOOST_NO_WCHAR_T
sl@0
    80
/**
sl@0
    81
 * \brief Returns the wide character string L"true".
sl@0
    82
 *
sl@0
    83
 *  This function only exists * when the C++ standard library
sl@0
    84
 *  implementation does not support * locales.
sl@0
    85
 */
sl@0
    86
template<>
sl@0
    87
inline std::basic_string<wchar_t> default_true_name<wchar_t>()
sl@0
    88
{ return L"true"; }
sl@0
    89
#  endif
sl@0
    90
#endif
sl@0
    91
sl@0
    92
/**
sl@0
    93
 * \brief Returns a string containing the default name for the indeterminate
sl@0
    94
 * value of a tribool with the given character type T.
sl@0
    95
 *
sl@0
    96
 * This routine is used by the input and output streaming operators
sl@0
    97
 * for tribool when there is no locale support or the stream's locale
sl@0
    98
 * does not contain the indeterminate_name facet.
sl@0
    99
 */
sl@0
   100
template<typename T> std::basic_string<T> get_default_indeterminate_name();
sl@0
   101
sl@0
   102
/// Returns the character string "indeterminate".
sl@0
   103
template<>
sl@0
   104
inline std::basic_string<char> get_default_indeterminate_name<char>()
sl@0
   105
{ return "indeterminate"; }
sl@0
   106
sl@0
   107
#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
sl@0
   108
// VC++ 6.0 chokes on the specialization below, so we're stuck without 
sl@0
   109
// wchar_t support. What a pain. TODO: it might just need a the template 
sl@0
   110
// parameter as function parameter...
sl@0
   111
#else
sl@0
   112
#  ifndef BOOST_NO_WCHAR_T
sl@0
   113
/// Returns the wide character string L"indeterminate".
sl@0
   114
template<>
sl@0
   115
inline std::basic_string<wchar_t> get_default_indeterminate_name<wchar_t>()
sl@0
   116
{ return L"indeterminate"; }
sl@0
   117
#  endif
sl@0
   118
#endif
sl@0
   119
sl@0
   120
// http://www.cantrip.org/locale.html
sl@0
   121
sl@0
   122
#ifndef BOOST_NO_STD_LOCALE
sl@0
   123
/**
sl@0
   124
 * \brief A locale facet specifying the name of the indeterminate
sl@0
   125
 * value of a tribool.
sl@0
   126
 *
sl@0
   127
 * The facet is used to perform I/O on tribool values when \c
sl@0
   128
 * std::boolalpha has been specified. This class template is only
sl@0
   129
 * available if the C++ standard library implementation supports
sl@0
   130
 * locales.
sl@0
   131
 */
sl@0
   132
template<typename CharT>
sl@0
   133
class indeterminate_name : public std::locale::facet, private boost::noncopyable
sl@0
   134
{
sl@0
   135
public:
sl@0
   136
  typedef CharT char_type;
sl@0
   137
  typedef std::basic_string<CharT> string_type;
sl@0
   138
sl@0
   139
  /// Construct the facet with the default name
sl@0
   140
  indeterminate_name() : name_(get_default_indeterminate_name<CharT>()) {}
sl@0
   141
sl@0
   142
  /// Construct the facet with the given name for the indeterminate value
sl@0
   143
  explicit indeterminate_name(const string_type& name) : name_(name) {}
sl@0
   144
sl@0
   145
  /// Returns the name for the indeterminate value
sl@0
   146
  string_type name() const { return name_; }
sl@0
   147
sl@0
   148
  /// Uniquily identifies this facet with the locale.
sl@0
   149
  static std::locale::id id;
sl@0
   150
sl@0
   151
private:
sl@0
   152
  string_type name_;
sl@0
   153
};
sl@0
   154
sl@0
   155
template<typename CharT> std::locale::id indeterminate_name<CharT>::id;
sl@0
   156
#endif
sl@0
   157
sl@0
   158
/**
sl@0
   159
 * \brief Writes the value of a tribool to a stream.
sl@0
   160
 *
sl@0
   161
 * When the value of @p x is either \c true or \c false, this routine
sl@0
   162
 * is semantically equivalent to:
sl@0
   163
 * \code out << static_cast<bool>(x); \endcode
sl@0
   164
 *
sl@0
   165
 * When @p x has an indeterminate value, it outputs either the integer
sl@0
   166
 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
sl@0
   167
 * or the name of the indeterminate value. The name of the
sl@0
   168
 * indeterminate value comes from the indeterminate_name facet (if it
sl@0
   169
 * is defined in the output stream's locale), or from the
sl@0
   170
 * get_default_indeterminate_name function (if it is not defined in the
sl@0
   171
 * locale or if the C++ standard library implementation does not
sl@0
   172
 * support locales).
sl@0
   173
 *
sl@0
   174
 * \returns @p out
sl@0
   175
 */
sl@0
   176
template<typename CharT, typename Traits>
sl@0
   177
inline std::basic_ostream<CharT, Traits>&
sl@0
   178
operator<<(std::basic_ostream<CharT, Traits>& out, tribool x)
sl@0
   179
{
sl@0
   180
  if (!indeterminate(x)) {
sl@0
   181
    out << static_cast<bool>(x);
sl@0
   182
  } else {
sl@0
   183
    typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
sl@0
   184
    if (cerberus) {
sl@0
   185
      if (out.flags() & std::ios_base::boolalpha) {
sl@0
   186
#ifndef BOOST_NO_STD_LOCALE
sl@0
   187
        if (BOOST_HAS_FACET(indeterminate_name<CharT>, out.getloc())) {
sl@0
   188
          const indeterminate_name<CharT>& facet =
sl@0
   189
            BOOST_USE_FACET(indeterminate_name<CharT>, out.getloc());
sl@0
   190
          out << facet.name();
sl@0
   191
        } else {
sl@0
   192
          out << get_default_indeterminate_name<CharT>();
sl@0
   193
        }
sl@0
   194
#else
sl@0
   195
        out << get_default_indeterminate_name<CharT>();
sl@0
   196
#endif
sl@0
   197
      }
sl@0
   198
      else
sl@0
   199
        out << 2;
sl@0
   200
    }
sl@0
   201
  }
sl@0
   202
  return out;
sl@0
   203
}
sl@0
   204
sl@0
   205
/**
sl@0
   206
 * \brief Writes the indeterminate tribool value to a stream.
sl@0
   207
 *
sl@0
   208
 * This routine outputs either the integer
sl@0
   209
 * value 2 (if <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>)
sl@0
   210
 * or the name of the indeterminate value. The name of the
sl@0
   211
 * indeterminate value comes from the indeterminate_name facet (if it
sl@0
   212
 * is defined in the output stream's locale), or from the
sl@0
   213
 * get_default_indeterminate_name function (if it is not defined in the
sl@0
   214
 * locale or if the C++ standard library implementation does not
sl@0
   215
 * support locales).
sl@0
   216
 *
sl@0
   217
 * \returns @p out
sl@0
   218
 */
sl@0
   219
template<typename CharT, typename Traits>
sl@0
   220
inline std::basic_ostream<CharT, Traits>&
sl@0
   221
operator<<(std::basic_ostream<CharT, Traits>& out, 
sl@0
   222
           bool (*)(tribool, detail::indeterminate_t))
sl@0
   223
{ return out << tribool(indeterminate); } 
sl@0
   224
sl@0
   225
/**
sl@0
   226
 * \brief Reads a tribool value from a stream.
sl@0
   227
 *
sl@0
   228
 * When <tt>(out.flags() & std::ios_base::boolalpha) == 0</tt>, this
sl@0
   229
 * function reads a \c long value from the input stream @p in and
sl@0
   230
 * converts that value to a tribool. If that value is 0, @p x becomes
sl@0
   231
 * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes
sl@0
   232
 * \c indetermine; otherwise, the operation fails (and the fail bit is
sl@0
   233
 * set on the input stream @p in).
sl@0
   234
 *
sl@0
   235
 * When <tt>(out.flags() & std::ios_base::boolalpha) != 0</tt>, this
sl@0
   236
 * function first determines the names of the false, true, and
sl@0
   237
 * indeterminate values. The false and true names are extracted from
sl@0
   238
 * the \c std::numpunct facet of the input stream's locale (if the C++
sl@0
   239
 * standard library implementation supports locales), or from the \c
sl@0
   240
 * default_false_name and \c default_true_name functions (if there is
sl@0
   241
 * no locale support). The indeterminate name is extracted from the
sl@0
   242
 * appropriate \c indeterminate_name facet (if it is available in the
sl@0
   243
 * input stream's locale), or from the \c get_default_indeterminate_name
sl@0
   244
 * function (if the C++ standard library implementation does not
sl@0
   245
 * support locales, or the \c indeterminate_name facet is not
sl@0
   246
 * specified for this locale object). The input is then matched to
sl@0
   247
 * each of these names, and the tribool @p x is assigned the value
sl@0
   248
 * corresponding to the longest name that matched. If no name is
sl@0
   249
 * matched or all names are empty, the operation fails (and the fail
sl@0
   250
 * bit is set on the input stream @p in).
sl@0
   251
 *
sl@0
   252
 * \returns @p in
sl@0
   253
 */
sl@0
   254
template<typename CharT, typename Traits>
sl@0
   255
inline std::basic_istream<CharT, Traits>&
sl@0
   256
operator>>(std::basic_istream<CharT, Traits>& in, tribool& x)
sl@0
   257
{
sl@0
   258
  if (in.flags() & std::ios_base::boolalpha) {
sl@0
   259
    typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
sl@0
   260
    if (cerberus) {
sl@0
   261
      typedef std::basic_string<CharT> string_type;
sl@0
   262
sl@0
   263
#ifndef BOOST_NO_STD_LOCALE
sl@0
   264
      const std::numpunct<CharT>& numpunct_facet =
sl@0
   265
        BOOST_USE_FACET(std::numpunct<CharT>, in.getloc());
sl@0
   266
sl@0
   267
      string_type falsename = numpunct_facet.falsename();
sl@0
   268
      string_type truename = numpunct_facet.truename();
sl@0
   269
sl@0
   270
      string_type othername;
sl@0
   271
      if (BOOST_HAS_FACET(indeterminate_name<CharT>, in.getloc())) {
sl@0
   272
        othername =
sl@0
   273
          BOOST_USE_FACET(indeterminate_name<CharT>, in.getloc()).name();
sl@0
   274
      } else {
sl@0
   275
        othername = get_default_indeterminate_name<CharT>();
sl@0
   276
      }
sl@0
   277
#else
sl@0
   278
      string_type falsename = default_false_name<CharT>();
sl@0
   279
      string_type truename = default_true_name<CharT>();
sl@0
   280
      string_type othername = get_default_indeterminate_name<CharT>();
sl@0
   281
#endif
sl@0
   282
sl@0
   283
      typename string_type::size_type pos = 0;
sl@0
   284
      bool falsename_ok = true, truename_ok = true, othername_ok = true;
sl@0
   285
sl@0
   286
      // Modeled after the code from Library DR 17
sl@0
   287
      while (falsename_ok && pos < falsename.size()
sl@0
   288
             || truename_ok && pos < truename.size()
sl@0
   289
             || othername_ok && pos < othername.size()) {
sl@0
   290
        typename Traits::int_type c = in.get();
sl@0
   291
        if (c == Traits::eof())
sl@0
   292
          return in;
sl@0
   293
sl@0
   294
        bool matched = false;
sl@0
   295
        if (falsename_ok && pos < falsename.size()) {
sl@0
   296
          if (Traits::eq(Traits::to_char_type(c), falsename[pos]))
sl@0
   297
            matched = true;
sl@0
   298
          else
sl@0
   299
            falsename_ok = false;
sl@0
   300
        }
sl@0
   301
sl@0
   302
        if (truename_ok && pos < truename.size()) {
sl@0
   303
          if (Traits::eq(Traits::to_char_type(c), truename[pos]))
sl@0
   304
            matched = true;
sl@0
   305
          else
sl@0
   306
            truename_ok = false;
sl@0
   307
        }
sl@0
   308
sl@0
   309
        if (othername_ok && pos < othername.size()) {
sl@0
   310
          if (Traits::eq(Traits::to_char_type(c), othername[pos]))
sl@0
   311
            matched = true;
sl@0
   312
          else
sl@0
   313
            othername_ok = false;
sl@0
   314
        }
sl@0
   315
sl@0
   316
        if (matched) { ++pos; }
sl@0
   317
        if (pos > falsename.size()) falsename_ok = false;
sl@0
   318
        if (pos > truename.size())  truename_ok = false;
sl@0
   319
        if (pos > othername.size()) othername_ok = false;
sl@0
   320
      }
sl@0
   321
sl@0
   322
      if (pos == 0)
sl@0
   323
        in.setstate(std::ios_base::failbit);
sl@0
   324
      else {
sl@0
   325
        if (falsename_ok)      x = false;
sl@0
   326
        else if (truename_ok)  x = true;
sl@0
   327
        else if (othername_ok) x = indeterminate;
sl@0
   328
        else in.setstate(std::ios_base::failbit);
sl@0
   329
      }
sl@0
   330
    }
sl@0
   331
  } else {
sl@0
   332
    long value;
sl@0
   333
    if (in >> value) {
sl@0
   334
      switch (value) {
sl@0
   335
      case 0: x = false; break;
sl@0
   336
      case 1: x = true; break;
sl@0
   337
      case 2: x = indeterminate; break;
sl@0
   338
      default: in.setstate(std::ios_base::failbit); break;
sl@0
   339
      }
sl@0
   340
    }
sl@0
   341
  }
sl@0
   342
sl@0
   343
  return in;
sl@0
   344
}
sl@0
   345
sl@0
   346
} } // end namespace boost::logic
sl@0
   347
sl@0
   348
#endif // BOOST_LOGIC_TRIBOOL_IO_HPP