204 lines
4.9 KiB
C++
204 lines
4.9 KiB
C++
#ifndef TRIBOOL_H
|
|
#define TRIBOOL_H
|
|
|
|
#include <iostream>
|
|
|
|
|
|
namespace Tribool {
|
|
|
|
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 Tribool
|
|
|
|
#endif // TRIBOOL_H
|