• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__
17 #define PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__
18 
19 #include "macros.h"
20 
21 #include <functional>
22 // included for nullopt_t
23 #include <optional>
24 
25 namespace panda::verifier {
26 
27 template <typename T>
28 struct OptionalRef;
29 
30 template <typename T>
31 struct OptionalConstRef {
32 public:
OptionalConstRefOptionalConstRef33     OptionalConstRef() : value {nullptr} {}
34     // These are intentionally implicit for consistency with std::optional
35     // NOLINTNEXTLINE(google-explicit-constructor)
OptionalConstRefOptionalConstRef36     OptionalConstRef(std::nullopt_t) : value {nullptr} {}
37     // NOLINTNEXTLINE(google-explicit-constructor)
OptionalConstRefOptionalConstRef38     OptionalConstRef(const T &reference) : value {const_cast<T *>(&reference)} {}
39     // NOLINTNEXTLINE(google-explicit-constructor)
OptionalConstRefOptionalConstRef40     OptionalConstRef(std::reference_wrapper<const T> reference) : OptionalConstRef(reference.get()) {}
OptionalConstRefOptionalConstRef41     explicit OptionalConstRef(const T *ptr) : value {const_cast<T *>(ptr)} {}
42 
HasRefOptionalConstRef43     bool HasRef() const
44     {
45         return value != nullptr;
46     }
47 
GetOptionalConstRef48     const T &Get() const
49     {
50         ASSERT(HasRef());
51         return *value;
52     }
53 
54     const T &operator*() const
55     {
56         return Get();
57     }
58 
AsPointerOptionalConstRef59     const T *AsPointer() const
60     {
61         return &Get();
62     }
63 
64     const T *operator->() const
65     {
66         return AsPointer();
67     }
68 
AsWrapperOptionalConstRef69     std::reference_wrapper<const T> AsWrapper() const
70     {
71         return Get();
72     }
73 
74     /**
75      * @brief The unsafe direction of const_cast, though without UB. Try to avoid using.
76      */
UnconstOptionalConstRef77     OptionalRef<T> Unconst() const
78     {
79         return OptionalRef<T> {value};
80     }
81 
82     DEFAULT_COPY_SEMANTIC(OptionalConstRef);
83     DEFAULT_MOVE_SEMANTIC(OptionalConstRef);
84 
85 protected:
OptionalConstRefOptionalConstRef86     explicit OptionalConstRef(T *ptr) : value {ptr} {}
87     // not const to let OptionalRef inherit this without unsafe behavior
88     T *value;
89 };
90 
91 /**
92  * @brief Morally equivalent to std::optional<std::reference_wrapper<T>>, but nicer to use and takes less memory
93  *
94  * @tparam T The referenced type
95  */
96 template <typename T>
97 struct OptionalRef : public OptionalConstRef<T> {
98 public:
99     using OptionalConstRef<T>::OptionalConstRef;
100     using OptionalConstRef<T>::Get;
101     using OptionalConstRef<T>::AsPointer;
102     using OptionalConstRef<T>::AsWrapper;
103     using OptionalConstRef<T>::operator->;
104     using OptionalConstRef<T>::operator*;
105     // NOLINTNEXTLINE(google-explicit-constructor)
OptionalRefOptionalRef106     OptionalRef(T &reference) : OptionalConstRef<T>(&reference) {}
107     // NOLINTNEXTLINE(google-explicit-constructor)
OptionalRefOptionalRef108     OptionalRef(std::reference_wrapper<T> reference) : OptionalRef(reference.get()) {}
109 
GetOptionalRef110     T &Get()
111     {
112         ASSERT(OptionalConstRef<T>::HasRef());
113         return *OptionalConstRef<T>::value;
114     }
115 
116     T &operator*()
117     {
118         return Get();
119     }
120 
AsPointerOptionalRef121     T *AsPointer()
122     {
123         return &Get();
124     }
125 
126     T *operator->()
127     {
128         return AsPointer();
129     }
130 
AsWrapperOptionalRef131     std::reference_wrapper<T> AsWrapper()
132     {
133         return Get();
134     }
135 
136     DEFAULT_COPY_SEMANTIC(OptionalRef);
137     DEFAULT_MOVE_SEMANTIC(OptionalRef);
138 
139 private:
140     // makes the inherited protected constructor public
141     friend struct OptionalConstRef<T>;
142 };
143 
144 }  // namespace panda::verifier
145 
146 #endif  // !PANDA_VERIFIER_UTIL_STRUCT_FIELD_H__
147