Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/metal-cpp/Foundation/NSObject.hpp
21066 views
1
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
2
//
3
// Foundation/NSObject.hpp
4
//
5
// Copyright 2020-2024 Apple Inc.
6
//
7
// Licensed under the Apache License, Version 2.0 (the "License");
8
// you may not use this file except in compliance with the License.
9
// You may obtain a copy of the License at
10
//
11
// http://www.apache.org/licenses/LICENSE-2.0
12
//
13
// Unless required by applicable law or agreed to in writing, software
14
// distributed under the License is distributed on an "AS IS" BASIS,
15
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
// See the License for the specific language governing permissions and
17
// limitations under the License.
18
//
19
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
20
21
#pragma once
22
23
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
24
25
#include "NSDefines.hpp"
26
#include "NSPrivate.hpp"
27
#include "NSTypes.hpp"
28
29
#include <objc/message.h>
30
#include <objc/runtime.h>
31
32
#include <type_traits>
33
34
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
35
36
namespace NS
37
{
38
class String;
39
40
template <class _Class, class _Base = class Object>
41
class _NS_EXPORT Referencing : public _Base
42
{
43
public:
44
_Class* retain();
45
void release();
46
47
_Class* autorelease();
48
49
UInteger retainCount() const;
50
};
51
52
template <class _Class, class _Base = class Object>
53
class Copying : public Referencing<_Class, _Base>
54
{
55
public:
56
_Class* copy() const;
57
};
58
59
template <class _Class, class _Base = class Object>
60
class SecureCoding : public Referencing<_Class, _Base>
61
{
62
};
63
64
class Object : public Referencing<Object, objc_object>
65
{
66
public:
67
UInteger hash() const;
68
bool isEqual(const Object* pObject) const;
69
70
class String* description() const;
71
class String* debugDescription() const;
72
73
protected:
74
friend class Referencing<Object, objc_object>;
75
76
template <class _Class>
77
static _Class* alloc(const char* pClassName);
78
template <class _Class>
79
static _Class* alloc(const void* pClass);
80
template <class _Class>
81
_Class* init();
82
83
template <class _Dst>
84
static _Dst bridgingCast(const void* pObj);
85
static class MethodSignature* methodSignatureForSelector(const void* pObj, SEL selector);
86
static bool respondsToSelector(const void* pObj, SEL selector);
87
template <typename _Type>
88
static constexpr bool doesRequireMsgSendStret();
89
template <typename _Ret, typename... _Args>
90
static _Ret sendMessage(const void* pObj, SEL selector, _Args... args);
91
template <typename _Ret, typename... _Args>
92
static _Ret sendMessageSafe(const void* pObj, SEL selector, _Args... args);
93
94
private:
95
Object() = delete;
96
Object(const Object&) = delete;
97
~Object() = delete;
98
99
Object& operator=(const Object&) = delete;
100
};
101
}
102
103
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
104
105
template <class _Class, class _Base /* = Object */>
106
_NS_INLINE _Class* NS::Referencing<_Class, _Base>::retain()
107
{
108
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(retain));
109
}
110
111
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
112
113
template <class _Class, class _Base /* = Object */>
114
_NS_INLINE void NS::Referencing<_Class, _Base>::release()
115
{
116
Object::sendMessage<void>(this, _NS_PRIVATE_SEL(release));
117
}
118
119
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
120
121
template <class _Class, class _Base /* = Object */>
122
_NS_INLINE _Class* NS::Referencing<_Class, _Base>::autorelease()
123
{
124
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(autorelease));
125
}
126
127
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
128
129
template <class _Class, class _Base /* = Object */>
130
_NS_INLINE NS::UInteger NS::Referencing<_Class, _Base>::retainCount() const
131
{
132
return Object::sendMessage<UInteger>(this, _NS_PRIVATE_SEL(retainCount));
133
}
134
135
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
136
137
template <class _Class, class _Base /* = Object */>
138
_NS_INLINE _Class* NS::Copying<_Class, _Base>::copy() const
139
{
140
return Object::sendMessage<_Class*>(this, _NS_PRIVATE_SEL(copy));
141
}
142
143
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
144
145
template <class _Dst>
146
_NS_INLINE _Dst NS::Object::bridgingCast(const void* pObj)
147
{
148
#ifdef __OBJC__
149
return (__bridge _Dst)pObj;
150
#else
151
return (_Dst)pObj;
152
#endif // __OBJC__
153
}
154
155
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
156
157
template <typename _Type>
158
_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret()
159
{
160
#if (defined(__i386__) || defined(__x86_64__))
161
constexpr size_t kStructLimit = (sizeof(std::uintptr_t) << 1);
162
163
return sizeof(_Type) > kStructLimit;
164
#elif defined(__arm64__)
165
return false;
166
#elif defined(__arm__)
167
constexpr size_t kStructLimit = sizeof(std::uintptr_t);
168
169
return std::is_class_v<_Type> && (sizeof(_Type) > kStructLimit);
170
#else
171
#error "Unsupported architecture!"
172
#endif
173
}
174
175
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
176
177
template <>
178
_NS_INLINE constexpr bool NS::Object::doesRequireMsgSendStret<void>()
179
{
180
return false;
181
}
182
183
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
184
185
template <typename _Ret, typename... _Args>
186
_NS_INLINE _Ret NS::Object::sendMessage(const void* pObj, SEL selector, _Args... args)
187
{
188
#if (defined(__i386__) || defined(__x86_64__))
189
if constexpr (std::is_floating_point<_Ret>())
190
{
191
using SendMessageProcFpret = _Ret (*)(const void*, SEL, _Args...);
192
193
const SendMessageProcFpret pProc = reinterpret_cast<SendMessageProcFpret>(&objc_msgSend_fpret);
194
195
return (*pProc)(pObj, selector, args...);
196
}
197
else
198
#endif // ( defined( __i386__ ) || defined( __x86_64__ ) )
199
#if !defined(__arm64__)
200
if constexpr (doesRequireMsgSendStret<_Ret>())
201
{
202
using SendMessageProcStret = void (*)(_Ret*, const void*, SEL, _Args...);
203
204
const SendMessageProcStret pProc = reinterpret_cast<SendMessageProcStret>(&objc_msgSend_stret);
205
_Ret ret;
206
207
(*pProc)(&ret, pObj, selector, args...);
208
209
return ret;
210
}
211
else
212
#endif // !defined( __arm64__ )
213
{
214
using SendMessageProc = _Ret (*)(const void*, SEL, _Args...);
215
216
const SendMessageProc pProc = reinterpret_cast<SendMessageProc>(&objc_msgSend);
217
218
return (*pProc)(pObj, selector, args...);
219
}
220
}
221
222
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
223
224
_NS_INLINE NS::MethodSignature* NS::Object::methodSignatureForSelector(const void* pObj, SEL selector)
225
{
226
return sendMessage<MethodSignature*>(pObj, _NS_PRIVATE_SEL(methodSignatureForSelector_), selector);
227
}
228
229
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
230
231
_NS_INLINE bool NS::Object::respondsToSelector(const void* pObj, SEL selector)
232
{
233
return sendMessage<bool>(pObj, _NS_PRIVATE_SEL(respondsToSelector_), selector);
234
}
235
236
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
237
238
template <typename _Ret, typename... _Args>
239
_NS_INLINE _Ret NS::Object::sendMessageSafe(const void* pObj, SEL selector, _Args... args)
240
{
241
if ((respondsToSelector(pObj, selector)) || (nullptr != methodSignatureForSelector(pObj, selector)))
242
{
243
return sendMessage<_Ret>(pObj, selector, args...);
244
}
245
246
if constexpr (!std::is_void<_Ret>::value)
247
{
248
return _Ret(0);
249
}
250
}
251
252
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
253
254
template <class _Class>
255
_NS_INLINE _Class* NS::Object::alloc(const char* pClassName)
256
{
257
return sendMessage<_Class*>(objc_lookUpClass(pClassName), _NS_PRIVATE_SEL(alloc));
258
}
259
260
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
261
262
template <class _Class>
263
_NS_INLINE _Class* NS::Object::alloc(const void* pClass)
264
{
265
return sendMessage<_Class*>(pClass, _NS_PRIVATE_SEL(alloc));
266
}
267
268
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
269
270
template <class _Class>
271
_NS_INLINE _Class* NS::Object::init()
272
{
273
return sendMessage<_Class*>(this, _NS_PRIVATE_SEL(init));
274
}
275
276
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
277
278
_NS_INLINE NS::UInteger NS::Object::hash() const
279
{
280
return sendMessage<UInteger>(this, _NS_PRIVATE_SEL(hash));
281
}
282
283
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
284
285
_NS_INLINE bool NS::Object::isEqual(const Object* pObject) const
286
{
287
return sendMessage<bool>(this, _NS_PRIVATE_SEL(isEqual_), pObject);
288
}
289
290
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
291
292
_NS_INLINE NS::String* NS::Object::description() const
293
{
294
return sendMessage<String*>(this, _NS_PRIVATE_SEL(description));
295
}
296
297
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
298
299
_NS_INLINE NS::String* NS::Object::debugDescription() const
300
{
301
return sendMessageSafe<String*>(this, _NS_PRIVATE_SEL(debugDescription));
302
}
303
304
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
305
306