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 LIBPANDABASE_MEM_OBJECT_POINTER_H
17#define LIBPANDABASE_MEM_OBJECT_POINTER_H
18
19#include "mem.h"
20
21namespace panda {
22
23/**
24 * @class ObjectPointer<class Object>
25 *
26 * \brief This class is wrapper for object types.
27 *
28 * Wraps pointer Object * into class ObjectPointer<Object> and provides interfaces to work with it as a pointer.
29 * This is needed to use object pointers of size 32 bits in 64-bit architectures.
30 */
31template <class Object>
32class ObjectPointer final {
33public:
34    ObjectPointer() = default;
35    // NOLINTNEXTLINE(google-explicit-constructor)
36    ObjectPointer(Object *object) : object_(ToObjPtrType(object))
37    {
38#ifdef PANDA_USE_32_BIT_POINTER
39        ASSERT(IsInObjectsAddressSpace(ToUintPtr(object)));
40#endif
41    }
42    // NOLINTNEXTLINE(google-explicit-constructor)
43    ObjectPointer(std::nullptr_t a_nullptr) noexcept : object_(ToObjPtrType(a_nullptr)) {}
44
45    DEFAULT_COPY_SEMANTIC(ObjectPointer);
46    DEFAULT_NOEXCEPT_MOVE_SEMANTIC(ObjectPointer);
47
48    ObjectPointer &operator=(std::nullptr_t a_nullptr)
49    {
50        object_ = ToObjPtrType(a_nullptr);
51        return *this;
52    }
53
54    ObjectPointer &operator=(const Object *object)
55    {
56#ifdef PANDA_USE_32_BIT_POINTER
57        ASSERT(IsInObjectsAddressSpace(ToUintPtr(object)));
58#endif
59        object_ = ToObjPtrType(object);
60        return *this;
61    }
62
63    ALWAYS_INLINE Object *operator->()
64    {
65        ASSERT(object_ != 0);
66        return ToObjectPtr(object_);
67    }
68
69    // NOLINTNEXTLINE(google-explicit-constructor)
70    ALWAYS_INLINE operator Object *()
71    {
72        return ToObjectPtr(object_);
73    }
74
75    ALWAYS_INLINE Object &operator*()
76    {
77        ASSERT(object_ != 0);
78        return *ToObjectPtr(object_);
79    }
80
81    ALWAYS_INLINE bool operator==(const ObjectPointer &other) const noexcept
82    {
83        return object_ == other.object_;
84    }
85
86    ALWAYS_INLINE bool operator!=(const ObjectPointer &other) const noexcept
87    {
88        return object_ != other.object_;
89    }
90
91    ALWAYS_INLINE bool operator==(Object *other) const noexcept
92    {
93        return ToObjectPtr(object_) == other;
94    }
95
96    ALWAYS_INLINE bool operator!=(Object *other) const noexcept
97    {
98        return ToObjectPtr(object_) != other;
99    }
100
101    ALWAYS_INLINE bool operator==(std::nullptr_t) const noexcept
102    {
103        return ToObjectPtr(object_) == nullptr;
104    }
105
106    ALWAYS_INLINE bool operator!=(std::nullptr_t) const noexcept
107    {
108        return ToObjectPtr(object_) != nullptr;
109    }
110
111    ALWAYS_INLINE Object &operator[](size_t index)
112    {
113        return ToObjectPtr(object_)[index];
114    }
115
116    ALWAYS_INLINE const Object &operator[](size_t index) const
117    {
118        return ToObjectPtr(object_)[index];
119    }
120
121    template <class U>
122    ALWAYS_INLINE U ReinterpretCast() const noexcept
123    {
124        return reinterpret_cast<U>(ToObjectPtr(object_));
125    }
126
127    ~ObjectPointer() = default;
128
129private:
130    object_pointer_type object_ {};
131
132    ALWAYS_INLINE static Object *ToObjectPtr(const object_pointer_type pointer) noexcept
133    {
134        return ToNativePtr<Object>(static_cast<uintptr_t>(pointer));
135    }
136};
137
138// size of ObjectPointer<T> must be equal size of object_pointer_type
139static_assert(sizeof(ObjectPointer<bool>) == sizeof(object_pointer_type));
140
141}  // namespace panda
142
143#endif  // LIBPANDABASE_MEM_OBJECT_POINTER_H
144