/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef HIDUTIL_TRISTATE_H_ #define HIDUTIL_TRISTATE_H_ #include #include namespace HidUtil { template class TriState { public: // constructor TriState() : mIsSet(false) { } TriState(const TriState &other) : mIsSet(other.mIsSet), mValue(other.mValue) { } explicit TriState(const T &value) : mIsSet(true), mValue(value) { } void clear() { mValue = T(); mIsSet = false; } bool isSet() const { return mIsSet; } const T get(const T &defaultValue) const { return isSet() ? mValue : defaultValue; } // operator overloading explicit operator T () const { assert(mIsSet); return mValue; } TriState& operator=(const TriState &other) { mIsSet = other.mIsSet; mValue = other.mValue; return *this; } TriState& operator=(const T& value) { mIsSet = true; mValue = value; return *this; } TriState& operator++() { if (mIsSet) { mValue++; } return *this; } TriState operator++(int) { TriState tmp(*this); operator++(); return tmp; } TriState& operator--() { if (mIsSet) { mValue--; } return *this; } TriState operator--(int) { TriState tmp(*this); operator--(); return tmp; } #define UNARY_OP(op) \ TriState operator op() { \ TriState tmp(*this); \ if (mIsSet) { \ tmp.mValue = op tmp.mValue; \ } \ return tmp; \ } UNARY_OP(!); UNARY_OP(-); UNARY_OP(~); #undef UNARY_OP #define COMPOUND_ASSIGN_OP(op) \ TriState& operator op (const TriState& rhs) { \ if (mIsSet && rhs.mIsSet) { \ mValue op rhs.mValue; \ } else { \ mIsSet = false; \ } \ return *this; \ } \ TriState& operator op(const T& rhs) { \ if (mIsSet) { \ mValue op rhs; \ } \ return *this; \ } COMPOUND_ASSIGN_OP(+=); COMPOUND_ASSIGN_OP(-=); COMPOUND_ASSIGN_OP(*=); COMPOUND_ASSIGN_OP(/=); COMPOUND_ASSIGN_OP(%=); COMPOUND_ASSIGN_OP(&=); COMPOUND_ASSIGN_OP(|=); COMPOUND_ASSIGN_OP(^=); #undef COMPOUND_ASSIGN_OP TriState& operator >>=(int i) { if (mIsSet) { mValue >>= i; } return *this; \ } TriState& operator <<=(int i) { if (mIsSet) { mValue <<= i; } return *this; \ } TriState operator <<(int i) { \ TriState tmp(*this); operator<<(i); return tmp; } TriState operator >>(int i) { \ TriState tmp(*this); operator>>(i); return tmp; } #define BINARY_OP(op, compound_op) \ friend TriState operator op(TriState lhs, const TriState& rhs) { \ lhs compound_op rhs; \ return lhs; \ }\ friend TriState operator op(TriState lhs, const T& rhs) { \ lhs compound_op rhs; \ return lhs; \ }\ friend TriState operator op(const T &lhs, const TriState& rhs) { \ TriState tmp(lhs); \ return tmp op rhs; \ } BINARY_OP(+, +=); BINARY_OP(-, -=); BINARY_OP(*, *=); BINARY_OP(/, /=); BINARY_OP(%, %=); BINARY_OP(&, &=); BINARY_OP(|, |=); BINARY_OP(^, ^=); #undef BINARY_OP #define RELATION_OP(op) \ friend TriState operator op(const TriState& lhs, const TriState& rhs) { \ if (lhs.mIsSet && rhs.mIsSet) { \ return TriState(lhs.mValue op rhs.mValue); \ } else { \ return TriState(); \ } \ } \ friend TriState operator op(const TriState& lhs, const T& rhs) { \ if (lhs.mIsSet) { \ return TriState(lhs.mValue op rhs); \ } else { \ return TriState(); \ } \ } \ friend TriState operator op(const T& lhs, const TriState& rhs) { \ if (rhs.mIsSet) { \ return TriState(lhs op rhs.mValue); \ } else { \ return TriState(); \ } \ } RELATION_OP(==); RELATION_OP(!=); RELATION_OP(>=); RELATION_OP(<=); RELATION_OP(>); RELATION_OP(<); #undef RELATION_OP friend TriState operator &&(TriState& lhs, const TriState& rhs) { if (lhs.mIsSet && rhs.mIsSet) { return TriState(lhs.mValue && rhs.mValue); } else { return TriState(); } } friend TriState operator ||(TriState& lhs, const TriState& rhs) { if (lhs.mIsSet && rhs.mIsSet) { return TriState(lhs.mValue || rhs.mValue); } else { return TriState(); } } friend std::ostream& operator <<(std::ostream &os, const TriState &v) { if (v.mIsSet) { os << v.mValue; } else { os << "[not set]"; } return os; } friend std::istream& operator >>(std::istream &is, const TriState &v) { T a; is >> a; v = TriState(a); return is; } private: bool mIsSet; T mValue; }; // commonly used ones typedef TriState tri_uint; typedef TriState tri_int; typedef TriState tri_uint32_t; typedef TriState tri_int32_t; typedef TriState tri_uint8_t; typedef TriState tri_uint16_t; } #endif // HIDUTIL_TRISTATE_H_