Home | History | Annotate | Download | only in base
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_BASE_FLAGS_H_
      6 #define V8_BASE_FLAGS_H_
      7 
      8 #include <cstddef>
      9 
     10 #include "src/base/compiler-specific.h"
     11 
     12 namespace v8 {
     13 namespace base {
     14 
     15 // The Flags class provides a type-safe way of storing OR-combinations of enum
     16 // values. The Flags<T, S> class is a template class, where T is an enum type,
     17 // and S is the underlying storage type (usually int).
     18 //
     19 // The traditional C++ approach for storing OR-combinations of enum values is to
     20 // use an int or unsigned int variable. The inconvenience with this approach is
     21 // that there's no type checking at all; any enum value can be OR'd with any
     22 // other enum value and passed on to a function that takes an int or unsigned
     23 // int.
     24 template <typename T, typename S = int>
     25 class Flags final {
     26  public:
     27   typedef T flag_type;
     28   typedef S mask_type;
     29 
     30   Flags() : mask_(0) {}
     31   Flags(flag_type flag)  // NOLINT(runtime/explicit)
     32       : mask_(static_cast<S>(flag)) {}
     33   explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
     34 
     35   bool operator==(flag_type flag) const {
     36     return mask_ == static_cast<S>(flag);
     37   }
     38   bool operator!=(flag_type flag) const {
     39     return mask_ != static_cast<S>(flag);
     40   }
     41 
     42   Flags& operator&=(const Flags& flags) {
     43     mask_ &= flags.mask_;
     44     return *this;
     45   }
     46   Flags& operator|=(const Flags& flags) {
     47     mask_ |= flags.mask_;
     48     return *this;
     49   }
     50   Flags& operator^=(const Flags& flags) {
     51     mask_ ^= flags.mask_;
     52     return *this;
     53   }
     54 
     55   Flags operator&(const Flags& flags) const { return Flags(*this) &= flags; }
     56   Flags operator|(const Flags& flags) const { return Flags(*this) |= flags; }
     57   Flags operator^(const Flags& flags) const { return Flags(*this) ^= flags; }
     58 
     59   Flags& operator&=(flag_type flag) { return operator&=(Flags(flag)); }
     60   Flags& operator|=(flag_type flag) { return operator|=(Flags(flag)); }
     61   Flags& operator^=(flag_type flag) { return operator^=(Flags(flag)); }
     62 
     63   Flags operator&(flag_type flag) const { return operator&(Flags(flag)); }
     64   Flags operator|(flag_type flag) const { return operator|(Flags(flag)); }
     65   Flags operator^(flag_type flag) const { return operator^(Flags(flag)); }
     66 
     67   Flags operator~() const { return Flags(~mask_); }
     68 
     69   operator mask_type() const { return mask_; }
     70   bool operator!() const { return !mask_; }
     71 
     72   friend size_t hash_value(const Flags& flags) { return flags.mask_; }
     73 
     74  private:
     75   mask_type mask_;
     76 };
     77 
     78 
     79 #define DEFINE_OPERATORS_FOR_FLAGS(Type)                                      \
     80   inline Type operator&(                                                      \
     81       Type::flag_type lhs,                                                    \
     82       Type::flag_type rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT;               \
     83   inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) {           \
     84     return Type(lhs) & rhs;                                                   \
     85   }                                                                           \
     86   inline Type operator&(Type::flag_type lhs,                                  \
     87                         const Type& rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
     88   inline Type operator&(Type::flag_type lhs, const Type& rhs) {               \
     89     return rhs & lhs;                                                         \
     90   }                                                                           \
     91   inline void operator&(Type::flag_type lhs,                                  \
     92                         Type::mask_type rhs)ALLOW_UNUSED_TYPE;                \
     93   inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {}          \
     94   inline Type operator|(Type::flag_type lhs, Type::flag_type rhs)             \
     95       ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT;                                   \
     96   inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) {           \
     97     return Type(lhs) | rhs;                                                   \
     98   }                                                                           \
     99   inline Type operator|(Type::flag_type lhs, const Type& rhs)                 \
    100       ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT;                                   \
    101   inline Type operator|(Type::flag_type lhs, const Type& rhs) {               \
    102     return rhs | lhs;                                                         \
    103   }                                                                           \
    104   inline void operator|(Type::flag_type lhs, Type::mask_type rhs)             \
    105       ALLOW_UNUSED_TYPE;                                                      \
    106   inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {}          \
    107   inline Type operator^(Type::flag_type lhs, Type::flag_type rhs)             \
    108       ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT;                                   \
    109   inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) {           \
    110     return Type(lhs) ^ rhs;                                                   \
    111   } inline Type                                                               \
    112   operator^(Type::flag_type lhs, const Type& rhs)                             \
    113       ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT;                                   \
    114   inline Type operator^(Type::flag_type lhs, const Type& rhs) {               \
    115     return rhs ^ lhs;                                                         \
    116   } inline void                                                               \
    117   operator^(Type::flag_type lhs, Type::mask_type rhs) ALLOW_UNUSED_TYPE;      \
    118   inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {           \
    119   } inline Type                                                               \
    120   operator~(Type::flag_type val)ALLOW_UNUSED_TYPE;                            \
    121   inline Type operator~(Type::flag_type val) { return ~Type(val); }
    122 
    123 }  // namespace base
    124 }  // namespace v8
    125 
    126 #endif  // V8_BASE_FLAGS_H_
    127