|
@@ -0,0 +1,203 @@
|
|
|
|
|
+#ifndef TRIBOOL_H
|
|
|
|
|
+#define TRIBOOL_H
|
|
|
|
|
+
|
|
|
|
|
+#include <iostream>
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+namespace Utilities {
|
|
|
|
|
+
|
|
|
|
|
+class Tribool
|
|
|
|
|
+{
|
|
|
|
|
+public:
|
|
|
|
|
+ struct IndeterminateType
|
|
|
|
|
+ {
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ typedef bool (*IndeterminateKeywordType)(Tribool, IndeterminateType);
|
|
|
|
|
+
|
|
|
|
|
+public:
|
|
|
|
|
+ Tribool();
|
|
|
|
|
+ Tribool(bool value);
|
|
|
|
|
+ Tribool(const IndeterminateKeywordType& value);
|
|
|
|
|
+
|
|
|
|
|
+ explicit operator bool() const;
|
|
|
|
|
+ Tribool operator!() const;
|
|
|
|
|
+
|
|
|
|
|
+ Tribool operator&&(const Tribool& other) const;
|
|
|
|
|
+ friend Tribool operator&&(const Tribool& lhs, bool rhs);
|
|
|
|
|
+ friend Tribool operator&&(bool lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator&&(const IndeterminateKeywordType& lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator&&(const Tribool& lhs, const IndeterminateKeywordType& rhs);
|
|
|
|
|
+
|
|
|
|
|
+ Tribool operator||(const Tribool& other) const;
|
|
|
|
|
+ friend Tribool operator||(const Tribool& lhs, bool rhs);
|
|
|
|
|
+ friend Tribool operator||(bool lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator||(const IndeterminateKeywordType& lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator||(const Tribool& lhs, const IndeterminateKeywordType& rhs);
|
|
|
|
|
+
|
|
|
|
|
+ Tribool operator==(const Tribool& other) const;
|
|
|
|
|
+ friend Tribool operator==(const Tribool& lhs, bool rhs);
|
|
|
|
|
+ friend Tribool operator==(bool lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator==(const IndeterminateKeywordType& lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator==(const Tribool& lhs, const IndeterminateKeywordType& rhs);
|
|
|
|
|
+
|
|
|
|
|
+ Tribool operator!=(const Tribool& other) const;
|
|
|
|
|
+ friend Tribool operator!=(const Tribool& lhs, bool rhs);
|
|
|
|
|
+ friend Tribool operator!=(bool lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator!=(const IndeterminateKeywordType& lhs, const Tribool& rhs);
|
|
|
|
|
+ friend Tribool operator!=(const Tribool& lhs, const IndeterminateKeywordType& rhs);
|
|
|
|
|
+
|
|
|
|
|
+ static inline bool Indeterminate(Tribool x, Tribool::IndeterminateType = Tribool::IndeterminateType())
|
|
|
|
|
+ {
|
|
|
|
|
+ return x.m_value == Tribool::TriboolValue::Indeterminate;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ class TriboolValue
|
|
|
|
|
+ {
|
|
|
|
|
+ public:
|
|
|
|
|
+ enum type
|
|
|
|
|
+ {
|
|
|
|
|
+ True,
|
|
|
|
|
+ False,
|
|
|
|
|
+ Indeterminate
|
|
|
|
|
+ };
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+private:
|
|
|
|
|
+ TriboolValue::type m_value;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+template<typename CharT, typename Traits>
|
|
|
|
|
+inline std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& out, Tribool x)
|
|
|
|
|
+{
|
|
|
|
|
+ if (!Tribool::Indeterminate(x)) {
|
|
|
|
|
+ out << static_cast<bool>(x);
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ typename std::basic_ostream<CharT, Traits>::sentry cerberus(out);
|
|
|
|
|
+ if (cerberus)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (out.flags() & std::ios_base::boolalpha)
|
|
|
|
|
+ out << "indeterminate";
|
|
|
|
|
+ else
|
|
|
|
|
+ out << 2;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return out;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename CharT, typename Traits>
|
|
|
|
|
+inline std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& out, bool (*)(Tribool, Tribool::IndeterminateType))
|
|
|
|
|
+{
|
|
|
|
|
+ return out << Tribool(Tribool::Indeterminate);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+template<typename CharT, typename Traits>
|
|
|
|
|
+std::basic_istream<CharT, Traits>& operator>>(std::basic_istream<CharT, Traits>& in, Tribool& x)
|
|
|
|
|
+{
|
|
|
|
|
+ if (in.flags() & std::ios_base::boolalpha)
|
|
|
|
|
+ {
|
|
|
|
|
+ typename std::basic_istream<CharT, Traits>::sentry cerberus(in);
|
|
|
|
|
+ if (cerberus)
|
|
|
|
|
+ {
|
|
|
|
|
+ typedef std::basic_string<CharT> string_type;
|
|
|
|
|
+
|
|
|
|
|
+ string_type falsename = "false";
|
|
|
|
|
+ string_type truename = "true";
|
|
|
|
|
+ string_type indeterminatename = "indeterminate";
|
|
|
|
|
+
|
|
|
|
|
+ typename string_type::size_type pos = 0;
|
|
|
|
|
+ bool falsename_ok = true;
|
|
|
|
|
+ bool truename_ok = true;
|
|
|
|
|
+ bool indeterminatename_ok = true;
|
|
|
|
|
+
|
|
|
|
|
+ while ((falsename_ok && pos < falsename.size()) || (truename_ok && pos < truename.size()) || (indeterminatename_ok && pos < indeterminatename.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 (indeterminatename_ok && pos < indeterminatename.size())
|
|
|
|
|
+ {
|
|
|
|
|
+ if (Traits::eq(Traits::to_char_type(c), indeterminatename[pos]))
|
|
|
|
|
+ matched = true;
|
|
|
|
|
+ else
|
|
|
|
|
+ indeterminatename_ok = false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (matched)
|
|
|
|
|
+ ++pos;
|
|
|
|
|
+ if (pos > falsename.size())
|
|
|
|
|
+ falsename_ok = false;
|
|
|
|
|
+ if (pos > truename.size())
|
|
|
|
|
+ truename_ok = false;
|
|
|
|
|
+ if (pos > indeterminatename.size())
|
|
|
|
|
+ indeterminatename_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 (indeterminatename_ok)
|
|
|
|
|
+ x = Tribool::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 = Tribool::Indeterminate;
|
|
|
|
|
+ break;
|
|
|
|
|
+ default:
|
|
|
|
|
+ in.setstate(std::ios_base::failbit);
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return in;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+} // namespace Utilities
|
|
|
|
|
+
|
|
|
|
|
+#endif // TRIBOOL_H
|