1 /*
2 * Copyright (c) 2023 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 MAPLE_UTIL_PTR_H
17 #define MAPLE_UTIL_PTR_H
18 #include <functional>
19
20 namespace maple {
21 namespace utils {
22 template <typename T>
23 using PtrCheckerType = void (*)(const T *);
24
25 template <typename T>
CheckNothing(const T *)26 inline constexpr void CheckNothing(const T *)
27 {
28 }
29
30 template <typename T, PtrCheckerType<T> Check = CheckNothing<T>>
31 class Ptr {
32 public:
33 using Pointer = T *;
34 using ElementType = T;
35
pointer(nullptr)36 constexpr Ptr() noexcept : pointer(nullptr)
37 {
38 Check(nullptr);
39 }
40
pointer(nullptr)41 constexpr explicit Ptr(std::nullptr_t) noexcept : pointer(nullptr)
42 {
43 Check(nullptr);
44 }
45
Ptr(Pointer ptr)46 explicit Ptr(Pointer ptr) : pointer(ptr)
47 {
48 Check(ptr);
49 }
50
Ptr(Pointer ref, PtrCheckerType<T> checker)51 Ptr(Pointer ref, PtrCheckerType<T> checker) : pointer(ref)
52 {
53 checker(pointer);
54 }
55
Ptr(T &ref)56 explicit Ptr(T &ref) : pointer(&ref)
57 {
58 Check(pointer);
59 }
60
Ptr(T &ref, PtrCheckerType<T> checker)61 Ptr(T &ref, PtrCheckerType<T> checker) : pointer(&ref)
62 {
63 checker(pointer);
64 }
65
66 explicit Ptr(T &&ref) = delete;
67
68 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(U *ptr)69 explicit Ptr(U *ptr) : pointer(ptr)
70 {
71 Check(pointer);
72 }
73
74 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(U &ref)75 explicit Ptr(U &ref) : pointer(&ref)
76 {
77 Check(pointer);
78 }
79
80 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(U &ref, PtrCheckerType<T> checker)81 Ptr(U &ref, PtrCheckerType<T> checker) : pointer(&ref)
82 {
83 checker(pointer);
84 }
85
86 template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
87 explicit Ptr(U &&ref) = delete;
88
Ptr(const Ptr &other)89 explicit Ptr(const Ptr &other) : pointer(other.get()) {}
90
pointer(other.get())91 explicit Ptr(Ptr &&other) noexcept : pointer(other.get()) {}
92
93 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(const Ptr<U, CheckU> &other)94 explicit Ptr(const Ptr<U, CheckU> &other) : pointer(other.get())
95 {
96 Check(pointer);
97 }
98
99 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(const Ptr<U, CheckU> &other, PtrCheckerType<T> checker)100 Ptr(const Ptr<U, CheckU> &other, PtrCheckerType<T> checker) : pointer(other.get())
101 {
102 checker(pointer);
103 }
104
105 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(Ptr<U, CheckU> &&other)106 explicit Ptr(Ptr<U, CheckU> &&other) : pointer(other.get())
107 {
108 Check(pointer);
109 }
110
111 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
Ptr(Ptr<U, CheckU> &&other, PtrCheckerType<T> checker)112 Ptr(Ptr<U, CheckU> &&other, PtrCheckerType<T> checker) : pointer(other.get())
113 {
114 checker(pointer);
115 }
116
117 ~Ptr() = default;
118
119 Ptr &operator=(Pointer ptr) noexcept
120 {
121 Check(ptr);
122 pointer = ptr;
123 return *this;
124 }
125
126 Ptr &operator=(std::nullptr_t) noexcept
127 {
128 Check(nullptr);
129 reset();
130 return *this;
131 }
132
133 Ptr &operator=(const Ptr &ptr) noexcept
134 {
135 if (&ptr != this) {
136 pointer = ptr.pointer;
137 }
138 return *this;
139 }
140
141 Ptr &operator=(Ptr &&ptr) noexcept
142 {
143 if (&ptr != this) {
144 pointer = std::move(ptr.pointer);
145 }
146 return *this;
147 }
148
149 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
150 Ptr &operator=(const Ptr<U, CheckU> &ptr) noexcept
151 {
152 if (this->get() != ptr.get()) {
153 Check(ptr.get());
154 pointer = ptr.get();
155 }
156 return *this;
157 }
158
159 template <typename U, PtrCheckerType<U> CheckU, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
160 Ptr &operator=(Ptr<U, CheckU> &&ptr) noexcept
161 {
162 if (this->get() != ptr.get()) {
163 Check(ptr.get());
164 pointer = std::move(ptr.get());
165 }
166 return *this;
167 }
168
169 Pointer release() noexcept = delete;
170
171 void reset(Pointer ptr = Pointer()) noexcept
172 {
173 Check(ptr);
174 pointer = ptr;
175 }
176
177 void swap(Ptr &other) noexcept
178 {
179 std::swap(pointer, other.pointer);
180 }
181
182 T *get() const noexcept
183 {
184 return pointer;
185 }
186
187 explicit operator bool() const noexcept
188 {
189 return get() != nullptr;
190 }
191
operator *() const192 T &operator*() const
193 {
194 return *get();
195 }
196
197 T *operator->() const noexcept
198 {
199 return get();
200 }
201
202 T &operator[](size_t i) const = delete;
203
204 Ptr &operator++() = delete;
205
206 const Ptr operator++(int) = delete;
207
208 Ptr &operator--() = delete;
209
210 const Ptr operator--(int) = delete;
211
212 Ptr &operator+=(std::ptrdiff_t) = delete;
213
214 Ptr &operator-=(std::ptrdiff_t) = delete;
215
216 private:
217 T *pointer;
218 };
219
220 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator ==(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)221 inline bool operator==(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
222 {
223 return lhs.get() == rhs.get();
224 }
225
226 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator !=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)227 inline bool operator!=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
228 {
229 return !(lhs == rhs);
230 }
231
232 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator <(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)233 inline bool operator<(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
234 {
235 return lhs.get() < rhs.get();
236 }
237
238 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator <=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)239 inline bool operator<=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
240 {
241 return lhs.get() <= rhs.get();
242 }
243
244 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator >(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)245 inline bool operator>(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
246 {
247 return !(lhs <= rhs);
248 }
249
250 template <typename T, PtrCheckerType<T> CheckT, typename U, PtrCheckerType<U> CheckU>
operator >=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)251 inline bool operator>=(const Ptr<T, CheckT> &lhs, const Ptr<U, CheckU> &rhs)
252 {
253 return !(lhs < rhs);
254 }
255
256 template <typename T, PtrCheckerType<T> CheckT>
operator ==(const Ptr<T, CheckT> &lhs, std::nullptr_t)257 inline bool operator==(const Ptr<T, CheckT> &lhs, std::nullptr_t)
258 {
259 return !static_cast<bool>(lhs);
260 }
261
262 template <typename T, PtrCheckerType<T> CheckT>
operator ==(std::nullptr_t, const Ptr<T, CheckT> &rhs)263 inline bool operator==(std::nullptr_t, const Ptr<T, CheckT> &rhs)
264 {
265 return !static_cast<bool>(rhs);
266 }
267
268 template <typename T, PtrCheckerType<T> CheckT>
operator !=(const Ptr<T, CheckT> &lhs, std::nullptr_t)269 inline bool operator!=(const Ptr<T, CheckT> &lhs, std::nullptr_t)
270 {
271 return static_cast<bool>(lhs);
272 }
273
274 template <typename T, PtrCheckerType<T> CheckT>
operator !=(std::nullptr_t, const Ptr<T, CheckT> &rhs)275 inline bool operator!=(std::nullptr_t, const Ptr<T, CheckT> &rhs)
276 {
277 return static_cast<bool>(rhs);
278 }
279
280 template <typename T, PtrCheckerType<T> CheckT>
operator <(const Ptr<T, CheckT> &lhs, std::nullptr_t)281 inline bool operator<(const Ptr<T, CheckT> &lhs, std::nullptr_t)
282 {
283 return std::less<typename Ptr<T, CheckT>::Pointer>()(lhs.get(), nullptr);
284 }
285
286 template <typename T, PtrCheckerType<T> CheckT>
operator <(std::nullptr_t, const Ptr<T, CheckT> &rhs)287 inline bool operator<(std::nullptr_t, const Ptr<T, CheckT> &rhs)
288 {
289 return std::less<typename Ptr<T, CheckT>::Pointer>()(nullptr, rhs.get());
290 }
291
292 template <typename T, PtrCheckerType<T> CheckT>
operator <=(const Ptr<T, CheckT> &lhs, std::nullptr_t)293 inline bool operator<=(const Ptr<T, CheckT> &lhs, std::nullptr_t)
294 {
295 return !(lhs > nullptr);
296 }
297
298 template <typename T, PtrCheckerType<T> CheckT>
operator <=(std::nullptr_t, const Ptr<T, CheckT> &rhs)299 inline bool operator<=(std::nullptr_t, const Ptr<T, CheckT> &rhs)
300 {
301 return !(rhs < nullptr);
302 }
303
304 template <typename T, PtrCheckerType<T> CheckT>
operator >(const Ptr<T, CheckT> &lhs, std::nullptr_t)305 inline bool operator>(const Ptr<T, CheckT> &lhs, std::nullptr_t)
306 {
307 return !(lhs <= nullptr);
308 }
309
310 template <typename T, PtrCheckerType<T> CheckT>
operator >(std::nullptr_t, const Ptr<T, CheckT> &rhs)311 inline bool operator>(std::nullptr_t, const Ptr<T, CheckT> &rhs)
312 {
313 return !(rhs >= nullptr);
314 }
315
316 template <typename T, PtrCheckerType<T> CheckT>
operator >=(const Ptr<T, CheckT> &lhs, std::nullptr_t)317 inline bool operator>=(const Ptr<T, CheckT> &lhs, std::nullptr_t)
318 {
319 return !(lhs < nullptr);
320 }
321
322 template <typename T, PtrCheckerType<T> CheckT>
operator >=(std::nullptr_t, const Ptr<T, CheckT> &rhs)323 inline bool operator>=(std::nullptr_t, const Ptr<T, CheckT> &rhs)
324 {
325 return !(rhs > nullptr);
326 }
327 } // namespace utils
328 } // namespace maple
329 #endif // DIY_CPLUSPLUS_SAFE_PTR_H