1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #ifndef HIDUTIL_TRISTATE_H_ 17 #define HIDUTIL_TRISTATE_H_ 18 19 #include <cassert> 20 #include <iostream> 21 22 namespace HidUtil { 23 template<typename T> 24 class TriState { 25 public: 26 // constructor TriState()27 TriState() : mIsSet(false) { } TriState(const TriState<T> & other)28 TriState(const TriState<T> &other) : mIsSet(other.mIsSet), mValue(other.mValue) { } TriState(const T & value)29 explicit TriState(const T &value) : mIsSet(true), mValue(value) { } 30 clear()31 void clear() { 32 mValue = T(); 33 mIsSet = false; 34 } isSet()35 bool isSet() const { 36 return mIsSet; 37 } 38 get(const T & defaultValue)39 const T get(const T &defaultValue) const { 40 return isSet() ? mValue : defaultValue; 41 } 42 43 // operator overloading T()44 explicit operator T () const { 45 assert(mIsSet); 46 return mValue; 47 } 48 49 TriState<T>& operator=(const TriState<T> &other) { 50 mIsSet = other.mIsSet; 51 mValue = other.mValue; 52 return *this; 53 } 54 55 TriState<T>& operator=(const T& value) { 56 mIsSet = true; 57 mValue = value; 58 return *this; 59 } 60 61 TriState<T>& operator++() { 62 if (mIsSet) { 63 mValue++; 64 } 65 return *this; 66 } 67 68 TriState<T> operator++(int) { 69 TriState<T> tmp(*this); 70 operator++(); 71 return tmp; 72 } 73 74 TriState<T>& operator--() { 75 if (mIsSet) { 76 mValue--; 77 } 78 return *this; 79 } 80 81 TriState<T> operator--(int) { 82 TriState<T> tmp(*this); 83 operator--(); 84 return tmp; 85 } 86 87 #define UNARY_OP(op) \ 88 TriState<T> operator op() { \ 89 TriState<T> tmp(*this); \ 90 if (mIsSet) { \ 91 tmp.mValue = op tmp.mValue; \ 92 } \ 93 return tmp; \ 94 } 95 96 UNARY_OP(!); 97 UNARY_OP(-); 98 UNARY_OP(~); 99 #undef UNARY_OP 100 101 #define COMPOUND_ASSIGN_OP(op) \ 102 TriState<T>& operator op (const TriState<T>& rhs) { \ 103 if (mIsSet && rhs.mIsSet) { \ 104 mValue op rhs.mValue; \ 105 } else { \ 106 mIsSet = false; \ 107 } \ 108 return *this; \ 109 } \ 110 TriState<T>& operator op(const T& rhs) { \ 111 if (mIsSet) { \ 112 mValue op rhs; \ 113 } \ 114 return *this; \ 115 } 116 117 COMPOUND_ASSIGN_OP(+=); 118 COMPOUND_ASSIGN_OP(-=); 119 COMPOUND_ASSIGN_OP(*=); 120 COMPOUND_ASSIGN_OP(/=); 121 COMPOUND_ASSIGN_OP(%=); 122 COMPOUND_ASSIGN_OP(&=); 123 COMPOUND_ASSIGN_OP(|=); 124 COMPOUND_ASSIGN_OP(^=); 125 #undef COMPOUND_ASSIGN_OP 126 127 TriState<T>& operator >>=(int i) { 128 if (mIsSet) { 129 mValue >>= i; 130 } 131 return *this; \ 132 } 133 134 TriState<T>& operator <<=(int i) { 135 if (mIsSet) { 136 mValue <<= i; 137 } 138 return *this; \ 139 } 140 141 TriState<T> operator <<(int i) { \ 142 TriState<T> tmp(*this); 143 operator<<(i); 144 return tmp; 145 } 146 147 TriState<T> operator >>(int i) { \ 148 TriState<T> tmp(*this); 149 operator>>(i); 150 return tmp; 151 } 152 153 #define BINARY_OP(op, compound_op) \ 154 friend TriState<T> operator op(TriState<T> lhs, const TriState<T>& rhs) { \ 155 lhs compound_op rhs; \ 156 return lhs; \ 157 }\ 158 friend TriState<T> operator op(TriState<T> lhs, const T& rhs) { \ 159 lhs compound_op rhs; \ 160 return lhs; \ 161 }\ 162 friend TriState<T> operator op(const T &lhs, const TriState<T>& rhs) { \ 163 TriState<T> tmp(lhs); \ 164 return tmp op rhs; \ 165 } 166 167 BINARY_OP(+, +=); 168 BINARY_OP(-, -=); 169 BINARY_OP(*, *=); 170 BINARY_OP(/, /=); 171 BINARY_OP(%, %=); 172 BINARY_OP(&, &=); 173 BINARY_OP(|, |=); 174 BINARY_OP(^, ^=); 175 #undef BINARY_OP 176 177 #define RELATION_OP(op) \ 178 friend TriState<bool> operator op(const TriState<T>& lhs, const TriState<T>& rhs) { \ 179 if (lhs.mIsSet && rhs.mIsSet) { \ 180 return TriState<bool>(lhs.mValue op rhs.mValue); \ 181 } else { \ 182 return TriState<bool>(); \ 183 } \ 184 } \ 185 friend TriState<bool> operator op(const TriState<T>& lhs, const T& rhs) { \ 186 if (lhs.mIsSet) { \ 187 return TriState<bool>(lhs.mValue op rhs); \ 188 } else { \ 189 return TriState<bool>(); \ 190 } \ 191 } \ 192 friend TriState<bool> operator op(const T& lhs, const TriState<T>& rhs) { \ 193 if (rhs.mIsSet) { \ 194 return TriState<bool>(lhs op rhs.mValue); \ 195 } else { \ 196 return TriState<bool>(); \ 197 } \ 198 } 199 200 RELATION_OP(==); 201 RELATION_OP(!=); 202 RELATION_OP(>=); 203 RELATION_OP(<=); 204 RELATION_OP(>); 205 RELATION_OP(<); 206 #undef RELATION_OP 207 208 friend TriState<bool> operator &&(TriState<T>& lhs, const TriState<T>& rhs) { 209 if (lhs.mIsSet && rhs.mIsSet) { 210 return TriState<bool>(lhs.mValue && rhs.mValue); 211 } else { 212 return TriState<bool>(); 213 } 214 } 215 216 friend TriState<bool> operator ||(TriState<T>& lhs, const TriState<T>& rhs) { 217 if (lhs.mIsSet && rhs.mIsSet) { 218 return TriState<bool>(lhs.mValue || rhs.mValue); 219 } else { 220 return TriState<bool>(); 221 } 222 } 223 224 friend std::ostream& operator <<(std::ostream &os, const TriState<T> &v) { 225 if (v.mIsSet) { 226 os << v.mValue; 227 } else { 228 os << "[not set]"; 229 } 230 return os; 231 } 232 233 friend std::istream& operator >>(std::istream &is, const TriState<T> &v) { 234 T a; 235 is >> a; 236 v = TriState<T>(a); 237 return is; 238 } 239 private: 240 bool mIsSet; 241 T mValue; 242 }; 243 244 // commonly used ones 245 typedef TriState<unsigned> tri_uint; 246 typedef TriState<int> tri_int; 247 248 typedef TriState<uint32_t> tri_uint32_t; 249 typedef TriState<int32_t> tri_int32_t; 250 typedef TriState<uint8_t> tri_uint8_t; 251 typedef TriState<uint16_t> tri_uint16_t; 252 } 253 254 #endif // HIDUTIL_TRISTATE_H_ 255