Home | History | Annotate | Download | only in HidUtils
      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
     27     TriState() : mIsSet(false) { }
     28     TriState(const TriState<T> &other) : mIsSet(other.mIsSet), mValue(other.mValue) { }
     29     explicit TriState(const T &value) : mIsSet(true), mValue(value) { }
     30 
     31     void clear() {
     32         mValue = T();
     33         mIsSet = false;
     34     }
     35     bool isSet() const {
     36         return mIsSet;
     37     }
     38 
     39     const T get(const T &defaultValue) const {
     40         return isSet() ? mValue : defaultValue;
     41     }
     42 
     43     // operator overloading
     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