• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The PDFium Authors
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 CORE_FXCRT_MASK_H_
6 #define CORE_FXCRT_MASK_H_
7 
8 #include <type_traits>
9 
10 namespace fxcrt {
11 
12 // Provides extremely strict type-checking on masks of enum class bitflags,
13 // for code where flags may not be passed consistently.
14 template <typename E>
15 class Mask {
16  public:
17   using UnderlyingType = typename std::underlying_type<E>::type;
18 
19   // Escape hatch for when value comes aross an API, say.
FromUnderlyingUnchecked(UnderlyingType val)20   static Mask FromUnderlyingUnchecked(UnderlyingType val) { return Mask(val); }
21 
22   constexpr Mask() = default;
23   constexpr Mask(const Mask& that) = default;
24 
25   // NOLINTNEXTLINE(runtime/explicit)
Mask(E val)26   constexpr Mask(E val) : val_(static_cast<UnderlyingType>(val)) {}
27 
28   // Unfortunately, std::initializer_list<> can't be used in constexpr
29   // methods per C++ standards, and we need constexpr for a zero-cost
30   // abstraction.  Hence, expand out constructors of various arity.
Mask(E v1,E v2)31   constexpr Mask(E v1, E v2)
32       : val_(static_cast<UnderlyingType>(v1) |
33              static_cast<UnderlyingType>(v2)) {}
34 
Mask(E v1,E v2,E v3)35   constexpr Mask(E v1, E v2, E v3)
36       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
37              static_cast<UnderlyingType>(v3)) {}
38 
Mask(E v1,E v2,E v3,E v4)39   constexpr Mask(E v1, E v2, E v3, E v4)
40       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
41              static_cast<UnderlyingType>(v3) |
42              static_cast<UnderlyingType>(v4)) {}
43 
Mask(E v1,E v2,E v3,E v4,E v5)44   constexpr Mask(E v1, E v2, E v3, E v4, E v5)
45       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
46              static_cast<UnderlyingType>(v3) | static_cast<UnderlyingType>(v4) |
47              static_cast<UnderlyingType>(v5)) {}
48 
Mask(E v1,E v2,E v3,E v4,E v5,E v6)49   constexpr Mask(E v1, E v2, E v3, E v4, E v5, E v6)
50       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
51              static_cast<UnderlyingType>(v3) | static_cast<UnderlyingType>(v4) |
52              static_cast<UnderlyingType>(v5) |
53              static_cast<UnderlyingType>(v6)) {}
54 
Mask(E v1,E v2,E v3,E v4,E v5,E v6,E v7)55   constexpr Mask(E v1, E v2, E v3, E v4, E v5, E v6, E v7)
56       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
57              static_cast<UnderlyingType>(v3) | static_cast<UnderlyingType>(v4) |
58              static_cast<UnderlyingType>(v5) | static_cast<UnderlyingType>(v6) |
59              static_cast<UnderlyingType>(v7)) {}
60 
Mask(E v1,E v2,E v3,E v4,E v5,E v6,E v7,E v8)61   constexpr Mask(E v1, E v2, E v3, E v4, E v5, E v6, E v7, E v8)
62       : val_(static_cast<UnderlyingType>(v1) | static_cast<UnderlyingType>(v2) |
63              static_cast<UnderlyingType>(v3) | static_cast<UnderlyingType>(v4) |
64              static_cast<UnderlyingType>(v5) | static_cast<UnderlyingType>(v6) |
65              static_cast<UnderlyingType>(v7) |
66              static_cast<UnderlyingType>(v8)) {}
67 
68   explicit operator bool() const { return !!val_; }
69   Mask operator~() const { return Mask(~val_); }
70   constexpr Mask operator|(const Mask& that) const {
71     return Mask(val_ | that.val_);
72   }
73   constexpr Mask operator&(const Mask& that) const {
74     return Mask(val_ & that.val_);
75   }
76   constexpr Mask operator^(const Mask& that) const {
77     return Mask(val_ ^ that.val_);
78   }
79   Mask& operator=(const Mask& that) {
80     val_ = that.val_;
81     return *this;
82   }
83   Mask& operator|=(const Mask& that) {
84     val_ |= that.val_;
85     return *this;
86   }
87   Mask& operator&=(const Mask& that) {
88     val_ &= that.val_;
89     return *this;
90   }
91   Mask& operator^=(const Mask& that) {
92     val_ ^= that.val_;
93     return *this;
94   }
95   bool operator==(const Mask& that) const { return val_ == that.val_; }
96   bool operator!=(const Mask& that) const { return val_ != that.val_; }
97 
TestAll(const Mask & that)98   bool TestAll(const Mask& that) const {
99     return (val_ & that.val_) == that.val_;
100   }
101 
102   // Because ~ can't be applied to enum class without casting.
Clear(const Mask & that)103   void Clear(const Mask& that) { val_ &= ~that.val_; }
104 
105   // Escape hatch, usage should be minimized.
UncheckedValue()106   UnderlyingType UncheckedValue() const { return val_; }
107 
108  private:
Mask(UnderlyingType val)109   explicit constexpr Mask(UnderlyingType val) : val_(val) {}
110 
111   UnderlyingType val_ = 0;
112 };
113 
114 }  // namespace fxcrt
115 
116 using fxcrt::Mask;
117 
118 #endif  // CORE_FXCRT_MASK_H_
119