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   constexpr Flags() : mask_(0) {}
     31   constexpr Flags(flag_type flag)  // NOLINT(runtime/explicit)
     32       : mask_(static_cast<S>(flag)) {}
     33   constexpr explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
     34 
     35   constexpr bool operator==(flag_type flag) const {
     36     return mask_ == static_cast<S>(flag);
     37   }
     38   constexpr 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   constexpr Flags operator&(const Flags& flags) const {
     56     return Flags(*this) &= flags;
     57   }
     58   constexpr Flags operator|(const Flags& flags) const {
     59     return Flags(*this) |= flags;
     60   }
     61   constexpr Flags operator^(const Flags& flags) const {
     62     return Flags(*this) ^= flags;
     63   }
     64 
     65   Flags& operator&=(flag_type flag) { return operator&=(Flags(flag)); }
     66   Flags& operator|=(flag_type flag) { return operator|=(Flags(flag)); }
     67   Flags& operator^=(flag_type flag) { return operator^=(Flags(flag)); }
     68 
     69   constexpr Flags operator&(flag_type flag) const {
     70     return operator&(Flags(flag));
     71   }
     72   constexpr Flags operator|(flag_type flag) const {
     73     return operator|(Flags(flag));
     74   }
     75   constexpr Flags operator^(flag_type flag) const {
     76     return operator^(Flags(flag));
     77   }
     78 
     79   constexpr Flags operator~() const { return Flags(~mask_); }
     80 
     81   constexpr operator mask_type() const { return mask_; }
     82   constexpr bool operator!() const { return !mask_; }
     83 
     84   friend size_t hash_value(const Flags& flags) { return flags.mask_; }
     85 
     86  private:
     87   mask_type mask_;
     88 };
     89 
     90 #define DEFINE_OPERATORS_FOR_FLAGS(Type)                             \
     91   inline Type operator&(                                             \
     92       Type::flag_type lhs,                                           \
     93       Type::flag_type rhs)ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;   \
     94   inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) {  \
     95     return Type(lhs) & rhs;                                          \
     96   }                                                                  \
     97   inline Type operator&(                                             \
     98       Type::flag_type lhs,                                           \
     99       const Type& rhs)ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;       \
    100   inline Type operator&(Type::flag_type lhs, const Type& rhs) {      \
    101     return rhs & lhs;                                                \
    102   }                                                                  \
    103   inline void operator&(Type::flag_type lhs,                         \
    104                         Type::mask_type rhs)ALLOW_UNUSED_TYPE;       \
    105   inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \
    106   inline Type operator|(Type::flag_type lhs, Type::flag_type rhs)    \
    107       ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;                       \
    108   inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) {  \
    109     return Type(lhs) | rhs;                                          \
    110   }                                                                  \
    111   inline Type operator|(Type::flag_type lhs, const Type& rhs)        \
    112       ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;                       \
    113   inline Type operator|(Type::flag_type lhs, const Type& rhs) {      \
    114     return rhs | lhs;                                                \
    115   }                                                                  \
    116   inline void operator|(Type::flag_type lhs, Type::mask_type rhs)    \
    117       ALLOW_UNUSED_TYPE;                                             \
    118   inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \
    119   inline Type operator^(Type::flag_type lhs, Type::flag_type rhs)    \
    120       ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;                       \
    121   inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) {  \
    122     return Type(lhs) ^ rhs;                                          \
    123   }                                                                  \
    124   inline Type operator^(Type::flag_type lhs, const Type& rhs)        \
    125       ALLOW_UNUSED_TYPE V8_WARN_UNUSED_RESULT;                       \
    126   inline Type operator^(Type::flag_type lhs, const Type& rhs) {      \
    127     return rhs ^ lhs;                                                \
    128   }                                                                  \
    129   inline void operator^(Type::flag_type lhs, Type::mask_type rhs)    \
    130       ALLOW_UNUSED_TYPE;                                             \
    131   inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {} \
    132   inline Type operator~(Type::flag_type val)ALLOW_UNUSED_TYPE;       \
    133   inline Type operator~(Type::flag_type val) { return ~Type(val); }
    134 
    135 }  // namespace base
    136 }  // namespace v8
    137 
    138 #endif  // V8_BASE_FLAGS_H_
    139