Program Listing for File TriBool.hpp

Return to documentation for file (src/rdf4cpp/TriBool.hpp)

#ifndef RDF4CPP_UTIL_TRIBOOL_HPP
#define RDF4CPP_UTIL_TRIBOOL_HPP

#include <array>
#include <cstddef>
#include <cstdint>

namespace rdf4cpp {

struct TriBool {
    static TriBool const True;
    static TriBool const False;
    static TriBool const Err;

private:
    enum struct inner_value_type : int8_t {
        Err = -1,
        False = 0,
        True = 1
    };

    inner_value_type value;

    [[nodiscard]] constexpr size_t into_logic_table_index() const noexcept {
        return static_cast<std::underlying_type_t<inner_value_type>>(this->value) + 1;
    }

    static constexpr std::array<std::array<inner_value_type, 3>, 3> and_logic_table{
            /* lhs \ rhs               Err                      False                    True */
            /* Err       */ std::array{inner_value_type::Err,   inner_value_type::False, inner_value_type::Err},
            /* False     */ std::array{inner_value_type::False, inner_value_type::False, inner_value_type::False},
            /* True      */ std::array{inner_value_type::Err,   inner_value_type::False, inner_value_type::True}};

    static constexpr std::array<std::array<inner_value_type, 3>, 3> or_logic_table{
            /* lhs \ rhs               Err                     False                    True */
            /* Err       */ std::array{inner_value_type::Err,  inner_value_type::Err,   inner_value_type::True},
            /* False     */ std::array{inner_value_type::Err,  inner_value_type::False, inner_value_type::True},
            /* True      */ std::array{inner_value_type::True, inner_value_type::True,  inner_value_type::True}};

    static constexpr std::array<inner_value_type, 3> not_logic_table{
            /* Err         False        True */
            inner_value_type::Err, inner_value_type::True, inner_value_type::False};

    constexpr TriBool(inner_value_type const value) noexcept : value{value} {}

public:
    constexpr TriBool(bool const b) noexcept : value{static_cast<std::underlying_type_t<inner_value_type>>(b)} {}

    constexpr bool operator==(TriBool const &) const noexcept = default;
    constexpr bool operator!=(TriBool const &) const noexcept = default;

    constexpr operator bool() const noexcept {
        return this->value == inner_value_type::True;
    }

    friend constexpr TriBool operator!(TriBool const b) noexcept {
        return not_logic_table[b.into_logic_table_index()];
    }

    friend constexpr TriBool operator&&(TriBool const l, TriBool const r) noexcept {
        return and_logic_table[l.into_logic_table_index()][r.into_logic_table_index()];
    }

    friend constexpr TriBool operator&&(TriBool const l, bool const r) noexcept {
        return l && TriBool{r};
    }

    friend constexpr TriBool operator&&(bool const l, TriBool const r) noexcept {
        return TriBool{l} && r;
    }

    friend constexpr TriBool operator||(TriBool const l, TriBool const r) noexcept {
        return or_logic_table[l.into_logic_table_index()][r.into_logic_table_index()];
    }

    friend constexpr TriBool operator||(TriBool const l, bool const r) noexcept {
        return l || TriBool{r};
    }

    friend constexpr TriBool operator||(bool const l, TriBool const r) noexcept {
        return TriBool{l} || r;
    }
};

inline constexpr TriBool TriBool::True{TriBool::inner_value_type::True};
inline constexpr TriBool TriBool::False{TriBool::inner_value_type::False};
inline constexpr TriBool TriBool::Err{TriBool::inner_value_type::Err};

namespace util {

constexpr TriBool partial_weak_ordering_eq(std::partial_ordering const l, std::weak_ordering const r) noexcept {
    if (l == std::partial_ordering::unordered) {
        return TriBool::Err;
    }

    return l == r;
}

} // namespace util

} // namespace rdf4cpp

#endif // RDF4CPP_UTIL_TRIBOOL_HPP