commit e3146f2584c15ca4dbe542f5c561d96aa5723710 Author: Douglas Gregor Date: Mon Jul 12 02:47:43 2004 +0000 Initial checkin of tribool library [SVN r23452] diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..3e84d7c --- /dev/null +++ b/.gitattributes @@ -0,0 +1,96 @@ +* text=auto !eol svneol=native#text/plain +*.gitattributes text svneol=native#text/plain + +# Scriptish formats +*.bat text svneol=native#text/plain +*.bsh text svneol=native#text/x-beanshell +*.cgi text svneol=native#text/plain +*.cmd text svneol=native#text/plain +*.js text svneol=native#text/javascript +*.php text svneol=native#text/x-php +*.pl text svneol=native#text/x-perl +*.pm text svneol=native#text/x-perl +*.py text svneol=native#text/x-python +*.sh eol=lf svneol=LF#text/x-sh +configure eol=lf svneol=LF#text/x-sh + +# Image formats +*.bmp binary svneol=unset#image/bmp +*.gif binary svneol=unset#image/gif +*.ico binary svneol=unset#image/ico +*.jpeg binary svneol=unset#image/jpeg +*.jpg binary svneol=unset#image/jpeg +*.png binary svneol=unset#image/png +*.tif binary svneol=unset#image/tiff +*.tiff binary svneol=unset#image/tiff +*.svg text svneol=native#image/svg%2Bxml + +# Data formats +*.pdf binary svneol=unset#application/pdf +*.avi binary svneol=unset#video/avi +*.doc binary svneol=unset#application/msword +*.dsp text svneol=crlf#text/plain +*.dsw text svneol=crlf#text/plain +*.eps binary svneol=unset#application/postscript +*.gz binary svneol=unset#application/gzip +*.mov binary svneol=unset#video/quicktime +*.mp3 binary svneol=unset#audio/mpeg +*.ppt binary svneol=unset#application/vnd.ms-powerpoint +*.ps binary svneol=unset#application/postscript +*.psd binary svneol=unset#application/photoshop +*.rdf binary svneol=unset#text/rdf +*.rss text svneol=unset#text/xml +*.rtf binary svneol=unset#text/rtf +*.sln text svneol=native#text/plain +*.swf binary svneol=unset#application/x-shockwave-flash +*.tgz binary svneol=unset#application/gzip +*.vcproj text svneol=native#text/xml +*.vcxproj text svneol=native#text/xml +*.vsprops text svneol=native#text/xml +*.wav binary svneol=unset#audio/wav +*.xls binary svneol=unset#application/vnd.ms-excel +*.zip binary svneol=unset#application/zip + +# Text formats +.htaccess text svneol=native#text/plain +*.bbk text svneol=native#text/xml +*.cmake text svneol=native#text/plain +*.css text svneol=native#text/css +*.dtd text svneol=native#text/xml +*.htm text svneol=native#text/html +*.html text svneol=native#text/html +*.ini text svneol=native#text/plain +*.log text svneol=native#text/plain +*.mak text svneol=native#text/plain +*.qbk text svneol=native#text/plain +*.rst text svneol=native#text/plain +*.sql text svneol=native#text/x-sql +*.txt text svneol=native#text/plain +*.xhtml text svneol=native#text/xhtml%2Bxml +*.xml text svneol=native#text/xml +*.xsd text svneol=native#text/xml +*.xsl text svneol=native#text/xml +*.xslt text svneol=native#text/xml +*.xul text svneol=native#text/xul +*.yml text svneol=native#text/plain +boost-no-inspect text svneol=native#text/plain +CHANGES text svneol=native#text/plain +COPYING text svneol=native#text/plain +INSTALL text svneol=native#text/plain +Jamfile text svneol=native#text/plain +Jamroot text svneol=native#text/plain +Jamfile.v2 text svneol=native#text/plain +Jamrules text svneol=native#text/plain +Makefile* text svneol=native#text/plain +README text svneol=native#text/plain +TODO text svneol=native#text/plain + +# Code formats +*.c text svneol=native#text/plain +*.cpp text svneol=native#text/plain +*.h text svneol=native#text/plain +*.hpp text svneol=native#text/plain +*.ipp text svneol=native#text/plain +*.tpp text svneol=native#text/plain +*.jam text svneol=native#text/plain +*.java text svneol=native#text/plain diff --git a/include/boost/logic/tribool.hpp b/include/boost/logic/tribool.hpp new file mode 100644 index 0000000..86b09a1 --- /dev/null +++ b/include/boost/logic/tribool.hpp @@ -0,0 +1,460 @@ +// Three-state boolean logic library + +// Copyright Doug Gregor 2002-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// For more information, see http://www.boost.org +#ifndef BOOST_LOGIC_TRIBOOL_HPP +#define BOOST_LOGIC_TRIBOOL_HPP + +#include +#include +#include + +#if BOOST_WORKAROUND(_MSC_VER, >= 1200) +# pragma once +#endif + +namespace boost { namespace logic { + +/// INTERNAL ONLY +namespace detail { +/** + * INTERNAL ONLY + * + * \brief A type used only to uniquely identify the 'indeterminate' + * function/keyword. + */ +struct indeterminate_t +{ +#if BOOST_WORKAROUND(__BORLANDC__, < 0x0600) + char dummy_; // BCB would use 8 bytes by default +#endif +}; + +} // end namespace detail + +/** + * INTERNAL ONLY + * The type of the 'indeterminate' keyword. This has the same type as the + * function 'indeterminate' so that we can recognize when the keyword is + * used. + */ +typedef bool (*indeterminate_keyword_t)(tribool, detail::indeterminate_t); + +/** + * \brief Keyword and test function for the indeterminate tribool value + * + * The \c indeterminate function has a dual role. It's first role is + * as a unary function that tells whether the tribool value is in the + * "indeterminate" state. It's second role is as a keyword + * representing the indeterminate (just like "true" and "false" + * represent the true and false states). If you do not like the name + * "indeterminate", and would prefer to use a different name, see the + * macro \c BOOST_TRIBOOL_THIRD_STATE. + * + * \returns x.value == tribool::indeterminate_value + * \throws nothrow + */ +inline bool +indeterminate(tribool x, + detail::indeterminate_t dummy = detail::indeterminate_t()); + +/** + * \brief A 3-state boolean type. + * + * 3-state boolean values are either true, false, or + * indeterminate. + */ +class tribool +{ +private: + /// INTERNAL ONLY + struct dummy { + void nonnull() {}; + }; + + typedef void (dummy::*safe_bool)(); + +public: + /** + * Construct a new 3-state boolean value with the value 'false'. + * + * \throws nothrow + */ + tribool() : value(false_value) {} + + /** + * Construct a new 3-state boolean value with the given boolean + * value, which may be \c true or \c false. + * + * \throws nothrow + */ + tribool(bool value) : value(value? true_value : false_value) {} + + /** + * Construct a new 3-state boolean value with an indeterminate value. + * + * \throws nothrow + */ + tribool(indeterminate_keyword_t) : value(indeterminate_value) {} + + /** + * Use a 3-state boolean in a boolean context. Will evaluate true in a + * boolean context only when the 3-state boolean is definitely true. + * + * \returns true if the 3-state boolean is true, false otherwise + * \throws nothrow + */ + operator safe_bool() const + { + return value == true_value? &dummy::nonnull : 0; + } + + /** + * The actual stored value in this 3-state boolean, which may be false, true, + * or indeterminate. + */ + enum { false_value, true_value, indeterminate_value } value; +}; + +// Check if the given tribool has an indeterminate value. Also doubles as a +// keyword for the 'indeterminate' value +inline bool indeterminate(tribool x, detail::indeterminate_t) +{ + return x.value == tribool::indeterminate_value; +} + +/** @defgroup logical Logical operations + */ +//@{ +/** + * \brief Computes the logical negation of a tribool + * + * \returns the logical negation of the tribool, according to the + * table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
!
+ *
false
true
true
false
indeterminate
indeterminate
+ * \throws nothrow + */ +inline tribool operator!(tribool x) +{ + return x.value == tribool::false_value? tribool(true) + :x.value == tribool::true_value? tribool(false) + :tribool(indeterminate); +} + +/** + * \brief Computes the logical conjuction of two tribools + * + * \returns the result of logically ANDing the two tribool values, + * according to the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
&&
false
true
indeterminate
false
false
false
false
true
false
true
indeterminate
indeterminate
false
indeterminate
indeterminate
+ * \throws nothrow + */ +inline tribool operator&&(tribool x, tribool y) +{ + if (static_cast(!x) || static_cast(!y)) + return false; + else if (static_cast(x) && static_cast(y)) + return true; + else + return indeterminate; +} + +/** + * \overload + */ +inline tribool operator&&(tribool x, bool y) +{ return y? x : tribool(false); } + +/** + * \overload + */ +inline tribool operator&&(bool x, tribool y) +{ return x? y : tribool(false); } + +/** + * \overload + */ +inline tribool operator&&(indeterminate_keyword_t, tribool x) +{ return !x? tribool(false) : tribool(indeterminate); } + +/** + * \overload + */ +inline tribool operator&&(tribool x, indeterminate_keyword_t) +{ return !x? tribool(false) : tribool(indeterminate); } + +/** + * \brief Computes the logical disjunction of two tribools + * + * \returns the result of logically ORing the two tribool values, + * according to the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
||
false
true
indeterminate
false
false
true
indeterminate
true
true
true
true
indeterminate
indeterminate
true
indeterminate
+ * \throws nothrow + */ +inline tribool operator||(tribool x, tribool y) +{ + if (static_cast(!x) && static_cast(!y)) + return false; + else if (static_cast(x) || static_cast(y)) + return true; + else + return indeterminate; +} + +/** + * \overload + */ +inline tribool operator||(tribool x, bool y) +{ return y? tribool(true) : x; } + +/** + * \overload + */ +inline tribool operator||(bool x, tribool y) +{ return x? tribool(true) : y; } + +/** + * \overload + */ +inline tribool operator||(indeterminate_keyword_t, tribool x) +{ return x? tribool(true) : tribool(indeterminate); } + +/** + * \overload + */ +inline tribool operator||(tribool x, indeterminate_keyword_t) +{ return x? tribool(true) : tribool(indeterminate); } +//@} + +/** + * \brief Compare tribools for equality + * + * \returns the result of comparing two tribool values, according to + * the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
==
false
true
indeterminate
false
true
false
indeterminate
true
false
true
indeterminate
indeterminate
indeterminate
indeterminate
indeterminate
+ * \throws nothrow + */ +inline tribool operator==(tribool x, tribool y) +{ + if (indeterminate(x) || indeterminate(y)) + return indeterminate; + else + return x && y || !x && !y; +} + +/** + * \overload + */ +inline tribool operator==(tribool x, bool y) { return x == tribool(y); } + +/** + * \overload + */ +inline tribool operator==(bool x, tribool y) { return tribool(x) == y; } + +/** + * \overload + */ +inline tribool operator==(indeterminate_keyword_t, tribool x) +{ return tribool(indeterminate) == x; } + +/** + * \overload + */ +inline tribool operator==(tribool x, indeterminate_keyword_t) +{ return tribool(indeterminate) == x; } + +/** + * \brief Compare tribools for inequality + * + * \returns the result of comparing two tribool values for inequality, + * according to the following table: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
!=
false
true
indeterminate
false
false
true
indeterminate
true
true
false
indeterminate
indeterminate
indeterminate
indeterminate
indeterminate
+ * \throws nothrow + */ +inline tribool operator!=(tribool x, tribool y) +{ + if (indeterminate(x) || indeterminate(y)) + return indeterminate; + else + return !(x && y || !x && !y); +} + +/** + * \overload + */ +inline tribool operator!=(tribool x, bool y) { return x != tribool(y); } + +/** + * \overload + */ +inline tribool operator!=(bool x, tribool y) { return tribool(x) != y; } + +/** + * \overload + */ +inline tribool operator!=(indeterminate_keyword_t, tribool x) +{ return tribool(indeterminate) != x; } + +/** + * \overload + */ +inline tribool operator!=(tribool x, indeterminate_keyword_t) +{ return x != tribool(indeterminate); } + +} } // end namespace boost::logic + +// Pull tribool and indeterminate into namespace "boost" +namespace boost { + using logic::tribool; + using logic::indeterminate; +} + +/** + * \brief Declare a new name for the third state of a tribool + * + * Use this macro to declare a new name for the third state of a + * tribool. This state can have any number of new names (in addition + * to \c indeterminate), all of which will be equivalent. The new name will be + * placed in the namespace in which the macro is expanded. + * + * Example: + * BOOST_TRIBOOL_THIRD_STATE(true_or_false) + * + * tribool x(true_or_false); + * // potentially set x + * if (true_or_false(x)) { + * // don't know what x is + * } + */ +#define BOOST_TRIBOOL_THIRD_STATE(Name) \ +inline bool \ +Name(boost::logic::tribool x, \ + boost::logic::detail::indeterminate_t dummy = \ + boost::logic::detail::indeterminate_t()) \ +{ return x.value == boost::logic::tribool::indeterminate_value; } + +#endif // BOOST_LOGIC_TRIBOOL_HPP + diff --git a/include/boost/logic/tribool_fwd.hpp b/include/boost/logic/tribool_fwd.hpp new file mode 100644 index 0000000..c764716 --- /dev/null +++ b/include/boost/logic/tribool_fwd.hpp @@ -0,0 +1,15 @@ +// Three-state boolean logic library + +// Copyright Doug Gregor 2002-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +// For more information, see http://www.boost.org +#ifndef BOOST_LOGIC_TRIBOOL_FWD_HPP +#define BOOST_LOGIC_TRIBOOL_FWD_HPP + +namespace boost { namespace logic { class tribool; } } + +#endif // BOOST_LOGIC_TRIBOOL_FWD_HPP \ No newline at end of file diff --git a/include/boost/logic/tribool_io.hpp b/include/boost/logic/tribool_io.hpp new file mode 100644 index 0000000..249c561 --- /dev/null +++ b/include/boost/logic/tribool_io.hpp @@ -0,0 +1,327 @@ +// Three-state boolean logic library + +// Copyright Doug Gregor 2002-2003. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_LOGIC_TRIBOOL_IO_HPP +#define BOOST_LOGIC_TRIBOOL_IO_HPP + +#include +#include +#include + +#if BOOST_WORKAROUND(_MSC_VER, >= 1200) +# pragma once +#endif + +#ifndef BOOST_NO_STD_LOCALE +# include +#endif + +#include +#include + +namespace boost { namespace logic { + +#ifdef BOOST_NO_STD_LOCALE + +/** + * \brief Returns a string containing the default name for the \c + * false value of a tribool with the given character type T. + * + * This function only exists when the C++ standard library + * implementation does not support locales. + */ +template std::basic_string default_false_name(); + +/** + * \brief Returns the character string "false". + * + * This function only exists when the C++ standard library + * implementation does not support locales. + */ +template<> +inline std::basic_string default_false_name() +{ return "false"; } + +# ifndef BOOST_NO_WCHAR_T +/** + * \brief Returns the wide character string L"false". + * + * This function only exists when the C++ standard library + * implementation does not support locales. + */ +template<> +inline std::basic_string default_false_name() +{ return L"false"; } +# endif + +/** + * \brief Returns a string containing the default name for the \c true + * value of a tribool with the given character type T. + * + * This function only exists when the C++ standard library + * implementation does not support locales. + */ +template std::basic_string default_true_name(); + +/** + * \brief Returns the character string "true". + * + * This function only exists when the C++ standard library + * implementation does not support locales. + */ +template<> +inline std::basic_string default_true_name() +{ return "true"; } + +# ifndef BOOST_NO_WCHAR_T +/** + * \brief Returns the wide character string L"true". + * + * This function only exists * when the C++ standard library + * implementation does not support * locales. + */ +template<> +inline std::basic_string default_true_name() +{ return L"true"; } +# endif +#endif + +/** + * \brief Returns a string containing the default name for the indeterminate + * value of a tribool with the given character type T. + * + * This routine is used by the input and output streaming operators + * for tribool when there is no locale support or the stream's locale + * does not contain the indeterminate_name facet. + */ +template std::basic_string get_default_indeterminate_name(); + +/// Returns the character string "indeterminate". +template<> +inline std::basic_string get_default_indeterminate_name() +{ return "indeterminate"; } + +#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200) +// VC++ 6.0 chokes on the specialization below, so we're stuck without +// wchar_t support. What a pain. +#else +# ifndef BOOST_NO_WCHAR_T +/// Returns the wide character string L"indeterminate". +template<> +inline std::basic_string get_default_indeterminate_name() +{ return L"indeterminate"; } +# endif +#endif + +// http://www.cantrip.org/locale.html + +#ifndef BOOST_NO_STD_LOCALE +/** + * \brief A locale facet specifying the name of the indeterminate + * value of a tribool. + * + * The facet is used to perform I/O on tribool values when \c + * std::boolalpha has been specified. This class template is only + * available if the C++ standard library implementation supports + * locales. + */ +template +class indeterminate_name : public std::locale::facet, boost::noncopyable +{ +public: + typedef CharT char_type; + typedef std::basic_string string_type; + + /// Construct the facet with the default name + indeterminate_name() : name_(get_default_indeterminate_name()) {} + + /// Construct the facet with the given name for the indeterminate value + explicit indeterminate_name(const string_type& name) : name_(name) {} + + /// Returns the name for the indeterminate value + string_type name() const { return name_; } + + /// Uniquily identifies this facet with the locale. + static std::locale::id id; + +private: + string_type name_; +}; + +template std::locale::id indeterminate_name::id; +#endif + +/** + * \brief Writes the value of a tribool to a stream. + * + * When the value of @p x is either \c true or \c false, this routine + * is semantically equivalent to: + * \code out << static_cast(x); \endcode + * + * When @p x has an indeterminate value, it outputs either the integer + * value 2 (if (out.flags() & std::ios_base::boolalpha) == 0) + * or the name of the indeterminate value. The name of the + * indeterminate value comes from the indeterminate_name facet (if it + * is defined in the output stream's locale), or from the + * get_default_indeterminate_name function (if it is not defined in the + * locale or if the C++ standard library implementation does not + * support locales). + * + * \returns @p out + */ +template +inline std::basic_ostream& +operator<<(std::basic_ostream& out, tribool x) +{ + if (!indeterminate(x)) { + out << static_cast(x); + } else { + typename std::basic_ostream::sentry cerberus(out); + if (cerberus) { + if (out.flags() & std::ios_base::boolalpha) { +#ifndef BOOST_NO_STD_LOCALE + if (BOOST_HAS_FACET(indeterminate_name, out.getloc())) { + const indeterminate_name& facet = + BOOST_USE_FACET(indeterminate_name, out.getloc()); + out << facet.name(); + } else { + out << get_default_indeterminate_name(); + } +#else + out << get_default_indeterminate_name(); +#endif + } + else + out << 2; + } + } + return out; +} + +/** + * \brief Reads a tribool value from a stream. + * + * When (out.flags() & std::ios_base::boolalpha) == 0, this + * function reads a \c long value from the input stream @p in and + * converts that value to a tribool. If that value is 0, @p x becomes + * \c false; if it is 1, @p x becomes \c true; if it is 2, @p becomes + * \c indetermine; otherwise, the operation fails (and the fail bit is + * set on the input stream @p in). + * + * When (out.flags() & std::ios_base::boolalpha) != 0, this + * function first determines the names of the false, true, and + * indeterminate values. The false and true names are extracted from + * the \c std::numpunct facet of the input stream's locale (if the C++ + * standard library implementation supports locales), or from the \c + * default_false_name and \c default_true_name functions (if there is + * no locale support). The indeterminate name is extracted from the + * appropriate \c indeterminate_name facet (if it is available in the + * input stream's locale), or from the \c get_default_indeterminate_name + * function (if the C++ standard library implementation does not + * support locales, or the \c indeterminate_name facet is not + * specified for this locale object). The input is then matched to + * each of these names, and the tribool @p x is assigned the value + * corresponding to the longest name that matched. If no name is + * matched or all names are empty, the operation fails (and the fail + * bit is set on the input stream @p in). + * + * \returns @p in + */ +template +inline std::basic_istream& +operator>>(std::basic_istream& in, tribool& x) +{ + if (in.flags() & std::ios_base::boolalpha) { + typename std::basic_istream::sentry cerberus(in); + if (cerberus) { + typedef std::basic_string string_type; + +#ifndef BOOST_NO_STD_LOCALE + const std::numpunct& numpunct_facet = + BOOST_USE_FACET(std::numpunct, in.getloc()); + + string_type falsename = numpunct_facet.falsename(); + string_type truename = numpunct_facet.truename(); + + string_type othername; + if (BOOST_HAS_FACET(indeterminate_name, in.getloc())) { + othername = + BOOST_USE_FACET(indeterminate_name, in.getloc()).name(); + } else { + othername = get_default_indeterminate_name(); + } +#else + string_type falsename = default_false_name(); + string_type truename = default_true_name(); + string_type othername = get_default_indeterminate_name(); +#endif + + typename string_type::size_type pos = 0; + bool falsename_ok = true, truename_ok = true, othername_ok = true; + + // Modeled after the code from Library DR 17 + while (falsename_ok && pos < falsename.size() + || truename_ok && pos < truename.size() + || othername_ok && pos < othername.size()) { + typename Traits::int_type c = in.get(); + if (c == Traits::eof()) + return in; + + bool matched = false; + if (falsename_ok && pos < falsename.size()) { + if (Traits::eq(Traits::to_char_type(c), falsename[pos])) + matched = true; + else + falsename_ok = false; + } + + if (truename_ok && pos < truename.size()) { + if (Traits::eq(Traits::to_char_type(c), truename[pos])) + matched = true; + else + truename_ok = false; + } + + if (othername_ok && pos < othername.size()) { + if (Traits::eq(Traits::to_char_type(c), othername[pos])) + matched = true; + else + othername_ok = false; + } + + if (matched) { ++pos; } + if (pos > falsename.size()) falsename_ok = false; + if (pos > truename.size()) truename_ok = false; + if (pos > othername.size()) othername_ok = false; + } + + if (pos == 0) + in.setstate(std::ios_base::failbit); + else { + if (falsename_ok) x = false; + else if (truename_ok) x = true; + else if (othername_ok) x = indeterminate; + else in.setstate(std::ios_base::failbit); + } + } + } else { + long value; + if (in >> value) { + switch (value) { + case 0: x = false; break; + case 1: x = true; break; + case 2: x = indeterminate; break; + default: in.setstate(std::ios_base::failbit); break; + } + } + } + + return in; +} + +} } // end namespace boost::logic + +#endif // BOOST_LOGIC_TRIBOOL_IO_HPP