Chris@16: // Three-state boolean logic library Chris@16: Chris@16: // Copyright Douglas Gregor 2002-2004. Use, modification and Chris@16: // distribution is subject to the Boost Software License, Version Chris@16: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: #ifndef BOOST_LOGIC_TRIBOOL_IO_HPP Chris@16: #define BOOST_LOGIC_TRIBOOL_IO_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@101: #if defined(_MSC_VER) Chris@16: # pragma once Chris@16: #endif Chris@16: Chris@16: #ifndef BOOST_NO_STD_LOCALE Chris@16: # include Chris@16: #endif Chris@16: Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { namespace logic { Chris@16: Chris@16: #ifdef BOOST_NO_STD_LOCALE Chris@16: Chris@16: /** Chris@16: * \brief Returns a string containing the default name for the \c Chris@16: * false value of a tribool with the given character type T. Chris@16: * Chris@16: * This function only exists when the C++ standard library Chris@16: * implementation does not support locales. Chris@16: */ Chris@16: template std::basic_string default_false_name(); Chris@16: Chris@16: /** Chris@16: * \brief Returns the character string "false". Chris@16: * Chris@16: * This function only exists when the C++ standard library Chris@16: * implementation does not support locales. Chris@16: */ Chris@16: template<> Chris@16: inline std::basic_string default_false_name() Chris@16: { return "false"; } Chris@16: Chris@16: # ifndef BOOST_NO_WCHAR_T Chris@16: /** Chris@16: * \brief Returns the wide character string L"false". Chris@16: * Chris@16: * This function only exists when the C++ standard library Chris@16: * implementation does not support locales. Chris@16: */ Chris@16: template<> Chris@16: inline std::basic_string default_false_name() Chris@16: { return L"false"; } Chris@16: # endif Chris@16: Chris@16: /** Chris@16: * \brief Returns a string containing the default name for the \c true Chris@16: * value of a tribool with the given character type T. Chris@16: * Chris@16: * This function only exists when the C++ standard library Chris@16: * implementation does not support locales. Chris@16: */ Chris@16: template std::basic_string default_true_name(); Chris@16: Chris@16: /** Chris@16: * \brief Returns the character string "true". Chris@16: * Chris@16: * This function only exists when the C++ standard library Chris@16: * implementation does not support locales. Chris@16: */ Chris@16: template<> Chris@16: inline std::basic_string default_true_name() Chris@16: { return "true"; } Chris@16: Chris@16: # ifndef BOOST_NO_WCHAR_T Chris@16: /** Chris@16: * \brief Returns the wide character string L"true". Chris@16: * Chris@16: * This function only exists * when the C++ standard library Chris@16: * implementation does not support * locales. Chris@16: */ Chris@16: template<> Chris@16: inline std::basic_string default_true_name() Chris@16: { return L"true"; } Chris@16: # endif Chris@16: #endif Chris@16: Chris@16: /** Chris@16: * \brief Returns a string containing the default name for the indeterminate Chris@16: * value of a tribool with the given character type T. Chris@16: * Chris@16: * This routine is used by the input and output streaming operators Chris@16: * for tribool when there is no locale support or the stream's locale Chris@16: * does not contain the indeterminate_name facet. Chris@16: */ Chris@16: template std::basic_string get_default_indeterminate_name(); Chris@16: Chris@16: /// Returns the character string "indeterminate". Chris@16: template<> Chris@16: inline std::basic_string get_default_indeterminate_name() Chris@16: { return "indeterminate"; } Chris@16: Chris@101: #ifndef BOOST_NO_WCHAR_T Chris@16: /// Returns the wide character string L"indeterminate". Chris@16: template<> Chris@16: inline std::basic_string get_default_indeterminate_name() Chris@16: { return L"indeterminate"; } Chris@16: #endif Chris@16: Chris@16: // http://www.cantrip.org/locale.html Chris@16: Chris@16: #ifndef BOOST_NO_STD_LOCALE Chris@16: /** Chris@16: * \brief A locale facet specifying the name of the indeterminate Chris@16: * value of a tribool. Chris@16: * Chris@16: * The facet is used to perform I/O on tribool values when \c Chris@16: * std::boolalpha has been specified. This class template is only Chris@16: * available if the C++ standard library implementation supports Chris@16: * locales. Chris@16: */ Chris@16: template Chris@16: class indeterminate_name : public std::locale::facet, private boost::noncopyable Chris@16: { Chris@16: public: Chris@16: typedef CharT char_type; Chris@16: typedef std::basic_string string_type; Chris@16: Chris@16: /// Construct the facet with the default name Chris@16: indeterminate_name() : name_(get_default_indeterminate_name()) {} Chris@16: Chris@16: /// Construct the facet with the given name for the indeterminate value Chris@16: explicit indeterminate_name(const string_type& initial_name) Chris@16: : name_(initial_name) {} Chris@16: Chris@16: /// Returns the name for the indeterminate value Chris@16: string_type name() const { return name_; } Chris@16: Chris@16: /// Uniquily identifies this facet with the locale. Chris@16: static std::locale::id id; Chris@16: Chris@16: private: Chris@16: string_type name_; Chris@16: }; Chris@16: Chris@16: template std::locale::id indeterminate_name::id; Chris@16: #endif Chris@16: Chris@16: /** Chris@16: * \brief Writes the value of a tribool to a stream. Chris@16: * Chris@16: * When the value of @p x is either \c true or \c false, this routine Chris@16: * is semantically equivalent to: Chris@16: * \code out << static_cast(x); \endcode Chris@16: * Chris@16: * When @p x has an indeterminate value, it outputs either the integer Chris@16: * value 2 (if (out.flags() & std::ios_base::boolalpha) == 0) Chris@16: * or the name of the indeterminate value. The name of the Chris@16: * indeterminate value comes from the indeterminate_name facet (if it Chris@16: * is defined in the output stream's locale), or from the Chris@16: * get_default_indeterminate_name function (if it is not defined in the Chris@16: * locale or if the C++ standard library implementation does not Chris@16: * support locales). Chris@16: * Chris@16: * \returns @p out Chris@16: */ Chris@16: template Chris@16: inline std::basic_ostream& Chris@16: operator<<(std::basic_ostream& out, tribool x) Chris@16: { Chris@16: if (!indeterminate(x)) { Chris@16: out << static_cast(x); Chris@16: } else { Chris@16: typename std::basic_ostream::sentry cerberus(out); Chris@16: if (cerberus) { Chris@16: if (out.flags() & std::ios_base::boolalpha) { Chris@16: #ifndef BOOST_NO_STD_LOCALE Chris@16: if (BOOST_HAS_FACET(indeterminate_name, out.getloc())) { Chris@16: const indeterminate_name& facet = Chris@16: BOOST_USE_FACET(indeterminate_name, out.getloc()); Chris@16: out << facet.name(); Chris@16: } else { Chris@16: out << get_default_indeterminate_name(); Chris@16: } Chris@16: #else Chris@16: out << get_default_indeterminate_name(); Chris@16: #endif Chris@16: } Chris@16: else Chris@16: out << 2; Chris@16: } Chris@16: } Chris@16: return out; Chris@16: } Chris@16: Chris@16: /** Chris@16: * \brief Writes the indeterminate tribool value to a stream. Chris@16: * Chris@16: * This routine outputs either the integer Chris@16: * value 2 (if (out.flags() & std::ios_base::boolalpha) == 0) Chris@16: * or the name of the indeterminate value. The name of the Chris@16: * indeterminate value comes from the indeterminate_name facet (if it Chris@16: * is defined in the output stream's locale), or from the Chris@16: * get_default_indeterminate_name function (if it is not defined in the Chris@16: * locale or if the C++ standard library implementation does not Chris@16: * support locales). Chris@16: * Chris@16: * \returns @p out Chris@16: */ Chris@16: template Chris@16: inline std::basic_ostream& Chris@16: operator<<(std::basic_ostream& out, Chris@16: bool (*)(tribool, detail::indeterminate_t)) Chris@16: { return out << tribool(indeterminate); } Chris@16: Chris@16: /** Chris@16: * \brief Reads a tribool value from a stream. Chris@16: * Chris@16: * When (out.flags() & std::ios_base::boolalpha) == 0, this Chris@16: * function reads a \c long value from the input stream @p in and Chris@16: * converts that value to a tribool. If that value is 0, @p x becomes Chris@16: * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes Chris@16: * \c indetermine; otherwise, the operation fails (and the fail bit is Chris@16: * set on the input stream @p in). Chris@16: * Chris@16: * When (out.flags() & std::ios_base::boolalpha) != 0, this Chris@16: * function first determines the names of the false, true, and Chris@16: * indeterminate values. The false and true names are extracted from Chris@16: * the \c std::numpunct facet of the input stream's locale (if the C++ Chris@16: * standard library implementation supports locales), or from the \c Chris@16: * default_false_name and \c default_true_name functions (if there is Chris@16: * no locale support). The indeterminate name is extracted from the Chris@16: * appropriate \c indeterminate_name facet (if it is available in the Chris@16: * input stream's locale), or from the \c get_default_indeterminate_name Chris@16: * function (if the C++ standard library implementation does not Chris@16: * support locales, or the \c indeterminate_name facet is not Chris@16: * specified for this locale object). The input is then matched to Chris@16: * each of these names, and the tribool @p x is assigned the value Chris@16: * corresponding to the longest name that matched. If no name is Chris@16: * matched or all names are empty, the operation fails (and the fail Chris@16: * bit is set on the input stream @p in). Chris@16: * Chris@16: * \returns @p in Chris@16: */ Chris@16: template Chris@16: inline std::basic_istream& Chris@16: operator>>(std::basic_istream& in, tribool& x) Chris@16: { Chris@16: if (in.flags() & std::ios_base::boolalpha) { Chris@16: typename std::basic_istream::sentry cerberus(in); Chris@16: if (cerberus) { Chris@16: typedef std::basic_string string_type; Chris@16: Chris@16: #ifndef BOOST_NO_STD_LOCALE Chris@16: const std::numpunct& numpunct_facet = Chris@16: BOOST_USE_FACET(std::numpunct, in.getloc()); Chris@16: Chris@16: string_type falsename = numpunct_facet.falsename(); Chris@16: string_type truename = numpunct_facet.truename(); Chris@16: Chris@16: string_type othername; Chris@16: if (BOOST_HAS_FACET(indeterminate_name, in.getloc())) { Chris@16: othername = Chris@16: BOOST_USE_FACET(indeterminate_name, in.getloc()).name(); Chris@16: } else { Chris@16: othername = get_default_indeterminate_name(); Chris@16: } Chris@16: #else Chris@16: string_type falsename = default_false_name(); Chris@16: string_type truename = default_true_name(); Chris@16: string_type othername = get_default_indeterminate_name(); Chris@16: #endif Chris@16: Chris@16: typename string_type::size_type pos = 0; Chris@16: bool falsename_ok = true, truename_ok = true, othername_ok = true; Chris@16: Chris@16: // Modeled after the code from Library DR 17 Chris@101: while ((falsename_ok && pos < falsename.size()) Chris@101: || (truename_ok && pos < truename.size()) Chris@101: || (othername_ok && pos < othername.size())) { Chris@16: typename Traits::int_type c = in.get(); Chris@16: if (c == Traits::eof()) Chris@16: return in; Chris@16: Chris@16: bool matched = false; Chris@16: if (falsename_ok && pos < falsename.size()) { Chris@16: if (Traits::eq(Traits::to_char_type(c), falsename[pos])) Chris@16: matched = true; Chris@16: else Chris@16: falsename_ok = false; Chris@16: } Chris@16: Chris@16: if (truename_ok && pos < truename.size()) { Chris@16: if (Traits::eq(Traits::to_char_type(c), truename[pos])) Chris@16: matched = true; Chris@16: else Chris@16: truename_ok = false; Chris@16: } Chris@16: Chris@16: if (othername_ok && pos < othername.size()) { Chris@16: if (Traits::eq(Traits::to_char_type(c), othername[pos])) Chris@16: matched = true; Chris@16: else Chris@16: othername_ok = false; Chris@16: } Chris@16: Chris@16: if (matched) { ++pos; } Chris@16: if (pos > falsename.size()) falsename_ok = false; Chris@16: if (pos > truename.size()) truename_ok = false; Chris@16: if (pos > othername.size()) othername_ok = false; Chris@16: } Chris@16: Chris@16: if (pos == 0) Chris@16: in.setstate(std::ios_base::failbit); Chris@16: else { Chris@16: if (falsename_ok) x = false; Chris@16: else if (truename_ok) x = true; Chris@16: else if (othername_ok) x = indeterminate; Chris@16: else in.setstate(std::ios_base::failbit); Chris@16: } Chris@16: } Chris@16: } else { Chris@16: long value; Chris@16: if (in >> value) { Chris@16: switch (value) { Chris@16: case 0: x = false; break; Chris@16: case 1: x = true; break; Chris@16: case 2: x = indeterminate; break; Chris@16: default: in.setstate(std::ios_base::failbit); break; Chris@16: } Chris@16: } Chris@16: } Chris@16: Chris@16: return in; Chris@16: } Chris@16: Chris@16: } } // end namespace boost::logic Chris@16: Chris@16: #endif // BOOST_LOGIC_TRIBOOL_IO_HPP