/* * 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 <cassert> #include <iostream> namespace HidUtil { template<typename T> class TriState { public: // constructor TriState() : mIsSet(false) { } TriState(const TriState<T> &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<T>& operator=(const TriState<T> &other) { mIsSet = other.mIsSet; mValue = other.mValue; return *this; } TriState<T>& operator=(const T& value) { mIsSet = true; mValue = value; return *this; } TriState<T>& operator++() { if (mIsSet) { mValue++; } return *this; } TriState<T> operator++(int) { TriState<T> tmp(*this); operator++(); return tmp; } TriState<T>& operator--() { if (mIsSet) { mValue--; } return *this; } TriState<T> operator--(int) { TriState<T> tmp(*this); operator--(); return tmp; } #define UNARY_OP(op) \ TriState<T> operator op() { \ TriState<T> 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<T>& operator op (const TriState<T>& rhs) { \ if (mIsSet && rhs.mIsSet) { \ mValue op rhs.mValue; \ } else { \ mIsSet = false; \ } \ return *this; \ } \ TriState<T>& 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<T>& operator >>=(int i) { if (mIsSet) { mValue >>= i; } return *this; \ } TriState<T>& operator <<=(int i) { if (mIsSet) { mValue <<= i; } return *this; \ } TriState<T> operator <<(int i) { \ TriState<T> tmp(*this); operator<<(i); return tmp; } TriState<T> operator >>(int i) { \ TriState<T> tmp(*this); operator>>(i); return tmp; } #define BINARY_OP(op, compound_op) \ friend TriState<T> operator op(TriState<T> lhs, const TriState<T>& rhs) { \ lhs compound_op rhs; \ return lhs; \ }\ friend TriState<T> operator op(TriState<T> lhs, const T& rhs) { \ lhs compound_op rhs; \ return lhs; \ }\ friend TriState<T> operator op(const T &lhs, const TriState<T>& rhs) { \ TriState<T> 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<bool> operator op(const TriState<T>& lhs, const TriState<T>& rhs) { \ if (lhs.mIsSet && rhs.mIsSet) { \ return TriState<bool>(lhs.mValue op rhs.mValue); \ } else { \ return TriState<bool>(); \ } \ } \ friend TriState<bool> operator op(const TriState<T>& lhs, const T& rhs) { \ if (lhs.mIsSet) { \ return TriState<bool>(lhs.mValue op rhs); \ } else { \ return TriState<bool>(); \ } \ } \ friend TriState<bool> operator op(const T& lhs, const TriState<T>& rhs) { \ if (rhs.mIsSet) { \ return TriState<bool>(lhs op rhs.mValue); \ } else { \ return TriState<bool>(); \ } \ } RELATION_OP(==); RELATION_OP(!=); RELATION_OP(>=); RELATION_OP(<=); RELATION_OP(>); RELATION_OP(<); #undef RELATION_OP friend TriState<bool> operator &&(TriState<T>& lhs, const TriState<T>& rhs) { if (lhs.mIsSet && rhs.mIsSet) { return TriState<bool>(lhs.mValue && rhs.mValue); } else { return TriState<bool>(); } } friend TriState<bool> operator ||(TriState<T>& lhs, const TriState<T>& rhs) { if (lhs.mIsSet && rhs.mIsSet) { return TriState<bool>(lhs.mValue || rhs.mValue); } else { return TriState<bool>(); } } friend std::ostream& operator <<(std::ostream &os, const TriState<T> &v) { if (v.mIsSet) { os << v.mValue; } else { os << "[not set]"; } return os; } friend std::istream& operator >>(std::istream &is, const TriState<T> &v) { T a; is >> a; v = TriState<T>(a); return is; } private: bool mIsSet; T mValue; }; // commonly used ones typedef TriState<unsigned> tri_uint; typedef TriState<int> tri_int; typedef TriState<uint32_t> tri_uint32_t; typedef TriState<int32_t> tri_int32_t; typedef TriState<uint8_t> tri_uint8_t; typedef TriState<uint16_t> tri_uint16_t; } #endif // HIDUTIL_TRISTATE_H_