ObjFW
private.h
1 /*
2  * Copyright (c) 2008-2023 Jonathan Schleifer <js@nil.im>
3  *
4  * All rights reserved.
5  *
6  * This file is part of ObjFW. It may be distributed under the terms of the
7  * Q Public License 1.0, which can be found in the file LICENSE.QPL included in
8  * the packaging of this file.
9  *
10  * Alternatively, it may be distributed under the terms of the GNU General
11  * Public License, either version 2 or 3, which can be found in the file
12  * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
13  * file.
14  */
15 
16 #include "config.h"
17 
18 #import "macros.h"
19 
20 #if !defined(__has_feature) || !__has_feature(nullability)
21 # ifndef _Nonnull
22 # define _Nonnull
23 # endif
24 # ifndef _Nullable
25 # define _Nullable
26 # endif
27 #endif
28 
29 typedef uint32_t (*_Nonnull objc_hashtable_hash_func)(const void *_Nonnull key);
30 typedef bool (*_Nonnull objc_hashtable_equal_func)(const void *_Nonnull key1,
31  const void *_Nonnull key2);
32 
33 struct objc_class {
34  Class _Nonnull isa;
35  Class _Nullable superclass;
36  const char *_Nonnull name;
37  unsigned long version;
38  unsigned long info;
39  long instanceSize;
40  struct objc_ivar_list *_Nullable ivars;
41  struct objc_method_list *_Nullable methodList;
42  struct objc_dtable *_Nullable dTable;
43  Class _Nullable *_Nullable subclassList;
44  void *_Nullable siblingClass;
45  struct objc_protocol_list *_Nullable protocols;
46  void *_Nullable GCObjectType;
47  unsigned long ABIVersion;
48  int32_t *_Nonnull *_Nullable ivarOffsets;
49  struct objc_property_list *_Nullable propertyList;
50 };
51 
52 enum objc_class_info {
53  OBJC_CLASS_INFO_CLASS = 0x001,
54  OBJC_CLASS_INFO_METACLASS = 0x002,
55  OBJC_CLASS_INFO_NEW_ABI = 0x010,
56  OBJC_CLASS_INFO_SETUP = 0x100,
57  OBJC_CLASS_INFO_LOADED = 0x200,
58  OBJC_CLASS_INFO_DTABLE = 0x400,
59  OBJC_CLASS_INFO_INITIALIZED = 0x800
60 };
61 
62 struct objc_object {
63  Class _Nonnull isa;
64 };
65 
66 struct objc_selector {
67  uintptr_t UID;
68  const char *_Nullable typeEncoding;
69 };
70 
71 struct objc_method {
72  struct objc_selector selector;
73  IMP _Nonnull implementation;
74 };
75 
76 struct objc_method_list {
77  struct objc_method_list *_Nullable next;
78  unsigned int count;
79  struct objc_method methods[1];
80 };
81 
82 struct objc_category {
83  const char *_Nonnull categoryName;
84  const char *_Nonnull className;
85  struct objc_method_list *_Nullable instanceMethods;
86  struct objc_method_list *_Nullable classMethods;
87  struct objc_protocol_list *_Nullable protocols;
88 };
89 
90 struct objc_ivar {
91  const char *_Nonnull name;
92  const char *_Nonnull typeEncoding;
93  unsigned int offset;
94 };
95 
96 struct objc_ivar_list {
97  unsigned int count;
98  struct objc_ivar ivars[1];
99 };
100 
101 struct objc_method_description {
102  const char *_Nonnull name;
103  const char *_Nonnull typeEncoding;
104 };
105 
106 struct objc_method_description_list {
107  int count;
108  struct objc_method_description list[1];
109 };
110 
111 struct objc_protocol_list {
112  struct objc_protocol_list *_Nullable next;
113  long count;
114  Protocol *__unsafe_unretained _Nonnull list[1];
115 };
116 
117 #if __has_attribute(__objc_root_class__)
118 __attribute__((__objc_root_class__))
119 #endif
120 @interface Protocol
121 {
122 @public
123  Class _Nonnull isa;
124  const char *_Nonnull name;
125  struct objc_protocol_list *_Nullable protocolList;
126  struct objc_method_description_list *_Nullable instanceMethods;
127  struct objc_method_description_list *_Nullable classMethods;
128 }
129 @end
130 
131 enum objc_property_attributes {
132  OBJC_PROPERTY_READONLY = 0x01,
133  OBJC_PROPERTY_GETTER = 0x02,
134  OBJC_PROPERTY_ASSIGN = 0x04,
135  OBJC_PROPERTY_READWRITE = 0x08,
136  OBJC_PROPERTY_RETAIN = 0x10,
137  OBJC_PROPERTY_COPY = 0x20,
138  OBJC_PROPERTY_NONATOMIC = 0x40,
139  OBJC_PROPERTY_SETTER = 0x80
140 };
141 
142 enum objc_property_extended_attributes {
143  OBJC_PROPERTY_SYNTHESIZED = 0x1,
144  OBJC_PROPERTY_DYNAMIC = 0x2,
145  OBJC_PROPERTY_PROTOCOL = 0x3,
146  OBJC_PROPERTY_ATOMIC = 0x4,
147  OBJC_PROPERTY_WEAK = 0x8,
148  OBJC_PROPERTY_STRONG = 0x10,
149  OBJC_PROPERTY_UNSAFE_UNRETAINED = 0x20
150 };
151 
152 struct objc_property {
153  const char *_Nonnull name;
154  unsigned char attributes, extendedAttributes;
155  struct {
156  const char *_Nullable name;
157  const char *_Nullable typeEncoding;
158  } getter, setter;
159 };
160 
161 struct objc_property_list {
162  unsigned int count;
163  struct objc_property_list *_Nullable next;
164  struct objc_property properties[1];
165 };
166 
167 struct objc_static_instances {
168  const char *_Nonnull className;
169  id _Nullable instances[1];
170 };
171 
172 struct objc_symtab {
173  unsigned long unknown;
174  struct objc_selector *_Nullable selectorRefs;
175  uint16_t classDefsCount;
176  uint16_t categoryDefsCount;
177  void *_Nonnull defs[1];
178 };
179 
180 struct objc_module {
181  unsigned long version; /* 9 = non-fragile */
182  unsigned long size;
183  const char *_Nullable name;
184  struct objc_symtab *_Nonnull symtab;
185 };
186 
187 struct objc_hashtable_bucket {
188  const void *_Nonnull key, *_Nonnull object;
189  uint32_t hash;
190 };
191 
192 struct objc_hashtable {
193  objc_hashtable_hash_func hash;
194  objc_hashtable_equal_func equal;
195  uint32_t count, size;
196  struct objc_hashtable_bucket *_Nonnull *_Nullable data;
197 };
198 
199 struct objc_sparsearray {
200  struct objc_sparsearray_data {
201  void *_Nullable next[256];
202  } *_Nonnull data;
203  uint8_t levels;
204 };
205 
206 struct objc_dtable {
207  struct objc_dtable_level2 {
208 #ifdef OF_SELUID24
209  struct objc_dtable_level3 {
210  IMP _Nullable buckets[256];
211  } *_Nonnull buckets[256];
212 #else
213  IMP _Nullable buckets[256];
214 #endif
215  } *_Nonnull buckets[256];
216 };
217 
218 extern void objc_registerAllCategories(struct objc_symtab *_Nonnull);
219 extern struct objc_category *_Nullable *_Nullable
220  objc_categoriesForClass(Class _Nonnull);
221 extern void objc_unregisterAllCategories(void);
222 extern void objc_initializeClass(Class _Nonnull);
223 extern void objc_updateDTable(Class _Nonnull);
224 extern void objc_registerAllClasses(struct objc_symtab *_Nonnull);
225 extern Class _Nullable objc_classnameToClass(const char *_Nonnull, bool);
226 extern void objc_unregisterClass(Class _Nonnull);
227 extern void objc_unregisterAllClasses(void);
228 extern uint32_t objc_string_hash(const void *_Nonnull);
229 extern bool objc_string_equal(const void *_Nonnull, const void *_Nonnull);
230 extern struct objc_hashtable *_Nonnull objc_hashtable_new(
231  objc_hashtable_hash_func, objc_hashtable_equal_func, uint32_t);
232 extern struct objc_hashtable_bucket objc_deletedBucket;
233 extern void objc_hashtable_set(struct objc_hashtable *_Nonnull,
234  const void *_Nonnull, const void *_Nonnull);
235 extern void *_Nullable objc_hashtable_get(struct objc_hashtable *_Nonnull,
236  const void *_Nonnull);
237 extern void objc_hashtable_delete(struct objc_hashtable *_Nonnull,
238  const void *_Nonnull);
239 extern void objc_hashtable_free(struct objc_hashtable *_Nonnull);
240 extern void objc_registerSelector(struct objc_selector *_Nonnull);
241 extern void objc_registerAllSelectors(struct objc_symtab *_Nonnull);
242 extern void objc_unregisterAllSelectors(void);
243 extern struct objc_sparsearray *_Nonnull objc_sparsearray_new(uint8_t);
244 extern void *_Nullable objc_sparsearray_get(struct objc_sparsearray *_Nonnull,
245  uintptr_t);
246 extern void objc_sparsearray_set(struct objc_sparsearray *_Nonnull, uintptr_t,
247  void *_Nullable);
248 extern void objc_sparsearray_free(struct objc_sparsearray *_Nonnull);
249 extern struct objc_dtable *_Nonnull objc_dtable_new(void);
250 extern void objc_dtable_copy(struct objc_dtable *_Nonnull,
251  struct objc_dtable *_Nonnull);
252 extern void objc_dtable_set(struct objc_dtable *_Nonnull, uint32_t,
253  IMP _Nullable);
254 extern void objc_dtable_free(struct objc_dtable *_Nonnull);
255 extern void objc_dtable_cleanup(void);
256 extern void objc_initStaticInstances(struct objc_symtab *_Nonnull);
257 extern void objc_forgetPendingStaticInstances(void);
258 extern void objc_zeroWeakReferences(id _Nonnull);
259 extern Class _Nullable object_getTaggedPointerClass(id _Nonnull);
260 #ifdef OF_HAVE_THREADS
261 extern void objc_globalMutex_lock(void);
262 extern void objc_globalMutex_unlock(void);
263 extern void objc_globalMutex_free(void);
264 #else
265 # define objc_globalMutex_lock()
266 # define objc_globalMutex_unlock()
267 # define objc_globalMutex_free()
268 #endif
269 extern char *_Nullable objc_strdup(const char *_Nonnull string);
270 
271 static inline IMP _Nullable
272 objc_dtable_get(const struct objc_dtable *_Nonnull dtable, uint32_t idx)
273 {
274 #ifdef OF_SELUID24
275  uint8_t i = idx >> 16;
276  uint8_t j = idx >> 8;
277  uint8_t k = idx;
278 
279  return dtable->buckets[i]->buckets[j]->buckets[k];
280 #else
281  uint8_t i = idx >> 8;
282  uint8_t j = idx;
283 
284  return dtable->buckets[i]->buckets[j];
285 #endif
286 }
287 
288 extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull title,
289  const char *_Nonnull format, ...);
290 #define OBJC_ERROR(...) \
291  objc_error("ObjFWRT @ " __FILE__ ":" OF_STRINGIFY(__LINE__), \
292  __VA_ARGS__)
293 
294 #if defined(OF_ELF)
295 # if defined(OF_AMD64) || defined(OF_X86) || \
296  defined(OF_POWERPC64) || defined(OF_POWERPC) || \
297  defined(OF_ARM64) || defined(OF_ARM) || \
298  defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
299  defined(OF_SPARC64) || defined(OF_SPARC)
300 # define OF_ASM_LOOKUP
301 # endif
302 #elif defined(OF_WINDOWS)
303 # if defined(OF_AMD64) || defined(OF_X86)
304 # define OF_ASM_LOOKUP
305 # endif
306 #endif
307 
308 @interface DummyObject
309 {
310  Class _Nonnull isa;
311 }
312 
313 @property (readonly, nonatomic) bool allowsWeakReference;
314 
315 + (void)initialize;
316 + (bool)resolveClassMethod: (nonnull SEL)selector;
317 + (bool)resolveInstanceMethod: (nonnull SEL)selector;
318 - (nonnull id)retain;
319 - (void)release;
320 - (nonnull id)autorelease;
321 - (nonnull id)copy;
322 - (nonnull id)mutableCopy;
323 - (bool)retainWeakReference;
324 @end
id(* IMP)(id object, SEL selector,...)
A method implemenation.
Definition: ObjFWRT.h:142
const struct objc_protocol * Protocol
A protocol.
Definition: ObjFWRT.h:113
A pointer to a class.
Definition: private.h:33
A pointer to any object.
Definition: private.h:62