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