annotate libobjc/protocols.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* GNU Objective C Runtime protocol related functions.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Nicola Pero
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under the
kono
parents:
diff changeset
8 terms of the GNU General Public License as published by the Free Software
kono
parents:
diff changeset
9 Foundation; either version 3, or (at your option) any later version.
kono
parents:
diff changeset
10
kono
parents:
diff changeset
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
kono
parents:
diff changeset
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
kono
parents:
diff changeset
14 details.
kono
parents:
diff changeset
15
kono
parents:
diff changeset
16 Under Section 7 of GPL version 3, you are granted additional
kono
parents:
diff changeset
17 permissions described in the GCC Runtime Library Exception, version
kono
parents:
diff changeset
18 3.1, as published by the Free Software Foundation.
kono
parents:
diff changeset
19
kono
parents:
diff changeset
20 You should have received a copy of the GNU General Public License and
kono
parents:
diff changeset
21 a copy of the GCC Runtime Library Exception along with this program;
kono
parents:
diff changeset
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
kono
parents:
diff changeset
23 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
24
kono
parents:
diff changeset
25 #include "objc-private/common.h"
kono
parents:
diff changeset
26 #include "objc/runtime.h"
kono
parents:
diff changeset
27 #include "objc-private/module-abi-8.h" /* For runtime structures */
kono
parents:
diff changeset
28 #include "objc/thr.h"
kono
parents:
diff changeset
29 #include "objc-private/runtime.h" /* the kitchen sink */
kono
parents:
diff changeset
30 #include "objc-private/hash.h" /* For the hash table of protocols. */
kono
parents:
diff changeset
31 #include "objc-private/protocols.h" /* For __objc_protocols_init() and
kono
parents:
diff changeset
32 __objc_protocols_add_protocol(). */
kono
parents:
diff changeset
33 #include <stdlib.h> /* For malloc. */
kono
parents:
diff changeset
34
kono
parents:
diff changeset
35 /* This is a table that maps a name to a Protocol instance with that
kono
parents:
diff changeset
36 name. Because there may be multiple Protocol instances with the
kono
parents:
diff changeset
37 same name (no harm in that) the table records only one
kono
parents:
diff changeset
38 instance. */
kono
parents:
diff changeset
39 static cache_ptr __protocols_hashtable;
kono
parents:
diff changeset
40
kono
parents:
diff changeset
41 /* A mutex protecting the protocol_hashtable. */
kono
parents:
diff changeset
42 static objc_mutex_t __protocols_hashtable_lock = NULL;
kono
parents:
diff changeset
43
kono
parents:
diff changeset
44 /* Called at startup by init.c. */
kono
parents:
diff changeset
45 void
kono
parents:
diff changeset
46 __objc_protocols_init (void)
kono
parents:
diff changeset
47 {
kono
parents:
diff changeset
48 __protocols_hashtable_lock = objc_mutex_allocate ();
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 /* The keys in the table are strings, and the values are Protocol
kono
parents:
diff changeset
51 objects. */
kono
parents:
diff changeset
52 __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
kono
parents:
diff changeset
53 (compare_func_type) objc_compare_strings);
kono
parents:
diff changeset
54 }
kono
parents:
diff changeset
55
kono
parents:
diff changeset
56 /* Add a protocol to the hashtable. */
kono
parents:
diff changeset
57 void
kono
parents:
diff changeset
58 __objc_protocols_add_protocol (const char *name, struct objc_protocol *object)
kono
parents:
diff changeset
59 {
kono
parents:
diff changeset
60 objc_mutex_lock (__protocols_hashtable_lock);
kono
parents:
diff changeset
61
kono
parents:
diff changeset
62 /* If we find a protocol with the same name already in the
kono
parents:
diff changeset
63 hashtable, we do not need to add the new one, because it will be
kono
parents:
diff changeset
64 identical to it. This in the reasonable assumption that two
kono
parents:
diff changeset
65 protocols with the same name are identical, which is expected in
kono
parents:
diff changeset
66 any sane program. If we are really paranoid, we would compare
kono
parents:
diff changeset
67 the protocols and abort if they are not identical.
kono
parents:
diff changeset
68 Unfortunately, this would slow down the startup of all
kono
parents:
diff changeset
69 Objective-C programs while trying to catch a problem that has
kono
parents:
diff changeset
70 never been seen in practice, so we don't do it. */
kono
parents:
diff changeset
71 if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
kono
parents:
diff changeset
72 objc_hash_add (&__protocols_hashtable, name, object);
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 objc_mutex_unlock (__protocols_hashtable_lock);
kono
parents:
diff changeset
75 }
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 Protocol *
kono
parents:
diff changeset
78 objc_getProtocol (const char *name)
kono
parents:
diff changeset
79 {
kono
parents:
diff changeset
80 Protocol *protocol;
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 if (name == NULL)
kono
parents:
diff changeset
83 return NULL;
kono
parents:
diff changeset
84
kono
parents:
diff changeset
85 objc_mutex_lock (__protocols_hashtable_lock);
kono
parents:
diff changeset
86 protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
kono
parents:
diff changeset
87 objc_mutex_unlock (__protocols_hashtable_lock);
kono
parents:
diff changeset
88
kono
parents:
diff changeset
89 return protocol;
kono
parents:
diff changeset
90 }
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 Protocol **
kono
parents:
diff changeset
93 objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
kono
parents:
diff changeset
94 {
kono
parents:
diff changeset
95 unsigned int count = 0;
kono
parents:
diff changeset
96 Protocol **returnValue = NULL;
kono
parents:
diff changeset
97 node_ptr node;
kono
parents:
diff changeset
98
kono
parents:
diff changeset
99 objc_mutex_lock (__protocols_hashtable_lock);
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 /* Count how many protocols we have. */
kono
parents:
diff changeset
102 node = objc_hash_next (__protocols_hashtable, NULL);
kono
parents:
diff changeset
103 while (node)
kono
parents:
diff changeset
104 {
kono
parents:
diff changeset
105 count++;
kono
parents:
diff changeset
106 node = objc_hash_next (__protocols_hashtable, node);
kono
parents:
diff changeset
107 }
kono
parents:
diff changeset
108
kono
parents:
diff changeset
109 if (count != 0)
kono
parents:
diff changeset
110 {
kono
parents:
diff changeset
111 unsigned int i = 0;
kono
parents:
diff changeset
112
kono
parents:
diff changeset
113 /* Allocate enough memory to hold them. */
kono
parents:
diff changeset
114 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
kono
parents:
diff changeset
115
kono
parents:
diff changeset
116 /* Copy the protocols. */
kono
parents:
diff changeset
117 node = objc_hash_next (__protocols_hashtable, NULL);
kono
parents:
diff changeset
118 while (node)
kono
parents:
diff changeset
119 {
kono
parents:
diff changeset
120 returnValue[i] = node->value;
kono
parents:
diff changeset
121 i++;
kono
parents:
diff changeset
122 node = objc_hash_next (__protocols_hashtable, node);
kono
parents:
diff changeset
123 }
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 returnValue[i] = NULL;
kono
parents:
diff changeset
126 }
kono
parents:
diff changeset
127 objc_mutex_unlock (__protocols_hashtable_lock);
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 if (numberOfReturnedProtocols)
kono
parents:
diff changeset
130 *numberOfReturnedProtocols = count;
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 return returnValue;
kono
parents:
diff changeset
133 }
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 BOOL
kono
parents:
diff changeset
136 class_addProtocol (Class class_, Protocol *protocol)
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 struct objc_protocol_list *protocols;
kono
parents:
diff changeset
139
kono
parents:
diff changeset
140 if (class_ == Nil || protocol == NULL)
kono
parents:
diff changeset
141 return NO;
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 if (class_conformsToProtocol (class_, protocol))
kono
parents:
diff changeset
144 return NO;
kono
parents:
diff changeset
145
kono
parents:
diff changeset
146 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
147 objc_protocol *). */
kono
parents:
diff changeset
148 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
149 return NO;
kono
parents:
diff changeset
150
kono
parents:
diff changeset
151 objc_mutex_lock (__objc_runtime_mutex);
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 /* Create the objc_protocol_list. */
kono
parents:
diff changeset
154 protocols = malloc (sizeof (struct objc_protocol_list));
kono
parents:
diff changeset
155 protocols->count = 1;
kono
parents:
diff changeset
156 protocols->list[0] = (struct objc_protocol *)protocol;
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 /* Attach it to the list of class protocols. */
kono
parents:
diff changeset
159 protocols->next = class_->protocols;
kono
parents:
diff changeset
160 class_->protocols = protocols;
kono
parents:
diff changeset
161
kono
parents:
diff changeset
162 objc_mutex_unlock (__objc_runtime_mutex);
kono
parents:
diff changeset
163
kono
parents:
diff changeset
164 return YES;
kono
parents:
diff changeset
165 }
kono
parents:
diff changeset
166
kono
parents:
diff changeset
167 BOOL
kono
parents:
diff changeset
168 class_conformsToProtocol (Class class_, Protocol *protocol)
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 struct objc_protocol_list* proto_list;
kono
parents:
diff changeset
171
kono
parents:
diff changeset
172 if (class_ == Nil || protocol == NULL)
kono
parents:
diff changeset
173 return NO;
kono
parents:
diff changeset
174
kono
parents:
diff changeset
175 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
176 objc_protocol *). */
kono
parents:
diff changeset
177 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
178 return NO;
kono
parents:
diff changeset
179
kono
parents:
diff changeset
180 /* Acquire the runtime lock because the list of protocols for a
kono
parents:
diff changeset
181 class may be modified concurrently, for example if another thread
kono
parents:
diff changeset
182 calls class_addProtocol(), or dynamically loads from a file a
kono
parents:
diff changeset
183 category of the class. */
kono
parents:
diff changeset
184 objc_mutex_lock (__objc_runtime_mutex);
kono
parents:
diff changeset
185 proto_list = class_->protocols;
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 while (proto_list)
kono
parents:
diff changeset
188 {
kono
parents:
diff changeset
189 size_t i;
kono
parents:
diff changeset
190 for (i = 0; i < proto_list->count; i++)
kono
parents:
diff changeset
191 {
kono
parents:
diff changeset
192 if (proto_list->list[i] == (struct objc_protocol *)protocol
kono
parents:
diff changeset
193 || protocol_conformsToProtocol ((Protocol *)proto_list->list[i],
kono
parents:
diff changeset
194 protocol))
kono
parents:
diff changeset
195 {
kono
parents:
diff changeset
196 objc_mutex_unlock (__objc_runtime_mutex);
kono
parents:
diff changeset
197 return YES;
kono
parents:
diff changeset
198 }
kono
parents:
diff changeset
199 }
kono
parents:
diff changeset
200 proto_list = proto_list->next;
kono
parents:
diff changeset
201 }
kono
parents:
diff changeset
202
kono
parents:
diff changeset
203 objc_mutex_unlock (__objc_runtime_mutex);
kono
parents:
diff changeset
204 return NO;
kono
parents:
diff changeset
205 }
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 Protocol **
kono
parents:
diff changeset
208 class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
kono
parents:
diff changeset
209 {
kono
parents:
diff changeset
210 unsigned int count = 0;
kono
parents:
diff changeset
211 Protocol **returnValue = NULL;
kono
parents:
diff changeset
212 struct objc_protocol_list* proto_list;
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214 if (class_ == Nil)
kono
parents:
diff changeset
215 {
kono
parents:
diff changeset
216 if (numberOfReturnedProtocols)
kono
parents:
diff changeset
217 *numberOfReturnedProtocols = 0;
kono
parents:
diff changeset
218 return NULL;
kono
parents:
diff changeset
219 }
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 /* Lock the runtime mutex because the class protocols may be
kono
parents:
diff changeset
222 concurrently modified. */
kono
parents:
diff changeset
223 objc_mutex_lock (__objc_runtime_mutex);
kono
parents:
diff changeset
224
kono
parents:
diff changeset
225 /* Count how many protocols we have. */
kono
parents:
diff changeset
226 proto_list = class_->protocols;
kono
parents:
diff changeset
227
kono
parents:
diff changeset
228 while (proto_list)
kono
parents:
diff changeset
229 {
kono
parents:
diff changeset
230 count = count + proto_list->count;
kono
parents:
diff changeset
231 proto_list = proto_list->next;
kono
parents:
diff changeset
232 }
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 if (count != 0)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 unsigned int i = 0;
kono
parents:
diff changeset
237
kono
parents:
diff changeset
238 /* Allocate enough memory to hold them. */
kono
parents:
diff changeset
239 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
kono
parents:
diff changeset
240
kono
parents:
diff changeset
241 /* Copy the protocols. */
kono
parents:
diff changeset
242 proto_list = class_->protocols;
kono
parents:
diff changeset
243
kono
parents:
diff changeset
244 while (proto_list)
kono
parents:
diff changeset
245 {
kono
parents:
diff changeset
246 size_t j;
kono
parents:
diff changeset
247 for (j = 0; j < proto_list->count; j++)
kono
parents:
diff changeset
248 {
kono
parents:
diff changeset
249 returnValue[i] = (Protocol *)proto_list->list[j];
kono
parents:
diff changeset
250 i++;
kono
parents:
diff changeset
251 }
kono
parents:
diff changeset
252 proto_list = proto_list->next;
kono
parents:
diff changeset
253 }
kono
parents:
diff changeset
254
kono
parents:
diff changeset
255 returnValue[i] = NULL;
kono
parents:
diff changeset
256 }
kono
parents:
diff changeset
257 objc_mutex_unlock (__objc_runtime_mutex);
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 if (numberOfReturnedProtocols)
kono
parents:
diff changeset
260 *numberOfReturnedProtocols = count;
kono
parents:
diff changeset
261
kono
parents:
diff changeset
262 return returnValue;
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 BOOL
kono
parents:
diff changeset
266 protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
kono
parents:
diff changeset
267 {
kono
parents:
diff changeset
268 struct objc_protocol_list* proto_list;
kono
parents:
diff changeset
269
kono
parents:
diff changeset
270 if (protocol == NULL || anotherProtocol == NULL)
kono
parents:
diff changeset
271 return NO;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 if (protocol == anotherProtocol)
kono
parents:
diff changeset
274 return YES;
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 /* Check that the objects are Protocol objects before casting them
kono
parents:
diff changeset
277 to (struct objc_protocol *). */
kono
parents:
diff changeset
278 if (protocol->class_pointer != anotherProtocol->class_pointer)
kono
parents:
diff changeset
279 return NO;
kono
parents:
diff changeset
280
kono
parents:
diff changeset
281 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
282 return NO;
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
kono
parents:
diff changeset
285 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
kono
parents:
diff changeset
286 return YES;
kono
parents:
diff changeset
287
kono
parents:
diff changeset
288 /* We do not acquire any lock because protocols are currently
kono
parents:
diff changeset
289 immutable. We can freely iterate over a protocol structure. */
kono
parents:
diff changeset
290 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
kono
parents:
diff changeset
291 while (proto_list)
kono
parents:
diff changeset
292 {
kono
parents:
diff changeset
293 size_t i;
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 for (i = 0; i < proto_list->count; i++)
kono
parents:
diff changeset
296 {
kono
parents:
diff changeset
297 if (protocol_conformsToProtocol ((Protocol *)proto_list->list[i], anotherProtocol))
kono
parents:
diff changeset
298 return YES;
kono
parents:
diff changeset
299 }
kono
parents:
diff changeset
300 proto_list = proto_list->next;
kono
parents:
diff changeset
301 }
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 return NO;
kono
parents:
diff changeset
304 }
kono
parents:
diff changeset
305
kono
parents:
diff changeset
306 BOOL
kono
parents:
diff changeset
307 protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
kono
parents:
diff changeset
308 {
kono
parents:
diff changeset
309 if (protocol == anotherProtocol)
kono
parents:
diff changeset
310 return YES;
kono
parents:
diff changeset
311
kono
parents:
diff changeset
312 if (protocol == NULL || anotherProtocol == NULL)
kono
parents:
diff changeset
313 return NO;
kono
parents:
diff changeset
314
kono
parents:
diff changeset
315 /* Check that the objects are Protocol objects before casting them
kono
parents:
diff changeset
316 to (struct objc_protocol *). */
kono
parents:
diff changeset
317 if (protocol->class_pointer != anotherProtocol->class_pointer)
kono
parents:
diff changeset
318 return NO;
kono
parents:
diff changeset
319
kono
parents:
diff changeset
320 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
321 return NO;
kono
parents:
diff changeset
322
kono
parents:
diff changeset
323 /* Equality between formal protocols is only formal (nothing to do
kono
parents:
diff changeset
324 with actually checking the list of methods they have!). Two
kono
parents:
diff changeset
325 formal Protocols are equal if and only if they have the same
kono
parents:
diff changeset
326 name.
kono
parents:
diff changeset
327
kono
parents:
diff changeset
328 Please note (for comparisons with other implementations) that
kono
parents:
diff changeset
329 checking the names is equivalent to checking that Protocol A
kono
parents:
diff changeset
330 conforms to Protocol B and Protocol B conforms to Protocol A,
kono
parents:
diff changeset
331 because this happens iff they have the same name. If they have
kono
parents:
diff changeset
332 different names, A conforms to B if and only if A includes B, but
kono
parents:
diff changeset
333 the situation where A includes B and B includes A is a circular
kono
parents:
diff changeset
334 dependency between Protocols which is forbidden by the compiler,
kono
parents:
diff changeset
335 so A conforms to B and B conforms to A with A and B having
kono
parents:
diff changeset
336 different names is an impossible case. */
kono
parents:
diff changeset
337 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
kono
parents:
diff changeset
338 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
kono
parents:
diff changeset
339 return YES;
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 return NO;
kono
parents:
diff changeset
342 }
kono
parents:
diff changeset
343
kono
parents:
diff changeset
344 const char *
kono
parents:
diff changeset
345 protocol_getName (Protocol *protocol)
kono
parents:
diff changeset
346 {
kono
parents:
diff changeset
347 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
348 objc_protocol *). */
kono
parents:
diff changeset
349 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
350 return NULL;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 return ((struct objc_protocol *)protocol)->protocol_name;
kono
parents:
diff changeset
353 }
kono
parents:
diff changeset
354
kono
parents:
diff changeset
355 struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
kono
parents:
diff changeset
356 SEL selector,
kono
parents:
diff changeset
357 BOOL requiredMethod,
kono
parents:
diff changeset
358 BOOL instanceMethod)
kono
parents:
diff changeset
359 {
kono
parents:
diff changeset
360 struct objc_method_description no_result = { NULL, NULL };
kono
parents:
diff changeset
361 struct objc_method_description_list *methods;
kono
parents:
diff changeset
362 int i;
kono
parents:
diff changeset
363
kono
parents:
diff changeset
364 /* TODO: New ABI. */
kono
parents:
diff changeset
365 /* The current ABI does not have any information on optional protocol methods. */
kono
parents:
diff changeset
366 if (! requiredMethod)
kono
parents:
diff changeset
367 return no_result;
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
370 objc_protocol *). */
kono
parents:
diff changeset
371 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
372 return no_result;
kono
parents:
diff changeset
373
kono
parents:
diff changeset
374 if (instanceMethod)
kono
parents:
diff changeset
375 methods = ((struct objc_protocol *)protocol)->instance_methods;
kono
parents:
diff changeset
376 else
kono
parents:
diff changeset
377 methods = ((struct objc_protocol *)protocol)->class_methods;
kono
parents:
diff changeset
378
kono
parents:
diff changeset
379 if (methods)
kono
parents:
diff changeset
380 {
kono
parents:
diff changeset
381 for (i = 0; i < methods->count; i++)
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 if (sel_isEqual (methods->list[i].name, selector))
kono
parents:
diff changeset
384 return methods->list[i];
kono
parents:
diff changeset
385 /*
kono
parents:
diff changeset
386 if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
kono
parents:
diff changeset
387 return methods->list[i];
kono
parents:
diff changeset
388 */
kono
parents:
diff changeset
389 }
kono
parents:
diff changeset
390 }
kono
parents:
diff changeset
391
kono
parents:
diff changeset
392 return no_result;
kono
parents:
diff changeset
393 }
kono
parents:
diff changeset
394
kono
parents:
diff changeset
395 struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
kono
parents:
diff changeset
396 BOOL requiredMethod,
kono
parents:
diff changeset
397 BOOL instanceMethod,
kono
parents:
diff changeset
398 unsigned int *numberOfReturnedMethods)
kono
parents:
diff changeset
399 {
kono
parents:
diff changeset
400 struct objc_method_description_list *methods;
kono
parents:
diff changeset
401 unsigned int count = 0;
kono
parents:
diff changeset
402 struct objc_method_description *returnValue = NULL;
kono
parents:
diff changeset
403
kono
parents:
diff changeset
404 /* TODO: New ABI */
kono
parents:
diff changeset
405 /* The current ABI does not have any information on optional protocol methods. */
kono
parents:
diff changeset
406 if (! requiredMethod)
kono
parents:
diff changeset
407 {
kono
parents:
diff changeset
408 if (numberOfReturnedMethods)
kono
parents:
diff changeset
409 *numberOfReturnedMethods = 0;
kono
parents:
diff changeset
410
kono
parents:
diff changeset
411 return NULL;
kono
parents:
diff changeset
412 }
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
415 objc_protocol *). */
kono
parents:
diff changeset
416 if (protocol == NULL || protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
417 {
kono
parents:
diff changeset
418 if (numberOfReturnedMethods)
kono
parents:
diff changeset
419 *numberOfReturnedMethods = 0;
kono
parents:
diff changeset
420
kono
parents:
diff changeset
421 return NULL;
kono
parents:
diff changeset
422 }
kono
parents:
diff changeset
423
kono
parents:
diff changeset
424 /* We do not acquire any lock because protocols are currently
kono
parents:
diff changeset
425 immutable. We can freely iterate over a protocol structure. */
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 if (instanceMethod)
kono
parents:
diff changeset
428 methods = ((struct objc_protocol *)protocol)->instance_methods;
kono
parents:
diff changeset
429 else
kono
parents:
diff changeset
430 methods = ((struct objc_protocol *)protocol)->class_methods;
kono
parents:
diff changeset
431
kono
parents:
diff changeset
432 if (methods)
kono
parents:
diff changeset
433 {
kono
parents:
diff changeset
434 unsigned int i;
kono
parents:
diff changeset
435 count = methods->count;
kono
parents:
diff changeset
436
kono
parents:
diff changeset
437 /* Allocate enough memory to hold them. */
kono
parents:
diff changeset
438 returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 /* Copy them. */
kono
parents:
diff changeset
441 for (i = 0; i < count; i++)
kono
parents:
diff changeset
442 {
kono
parents:
diff changeset
443 returnValue[i].name = methods->list[i].name;
kono
parents:
diff changeset
444 returnValue[i].types = methods->list[i].types;
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 returnValue[i].name = NULL;
kono
parents:
diff changeset
447 returnValue[i].types = NULL;
kono
parents:
diff changeset
448 }
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 if (numberOfReturnedMethods)
kono
parents:
diff changeset
451 *numberOfReturnedMethods = count;
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 return returnValue;
kono
parents:
diff changeset
454 }
kono
parents:
diff changeset
455
kono
parents:
diff changeset
456 Property protocol_getProperty (Protocol *protocol, const char *propertyName,
kono
parents:
diff changeset
457 BOOL requiredProperty, BOOL instanceProperty)
kono
parents:
diff changeset
458 {
kono
parents:
diff changeset
459 if (protocol == NULL || propertyName == NULL)
kono
parents:
diff changeset
460 return NULL;
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 if (!requiredProperty || !instanceProperty)
kono
parents:
diff changeset
463 return NULL;
kono
parents:
diff changeset
464
kono
parents:
diff changeset
465 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
466 objc_protocol *). */
kono
parents:
diff changeset
467 if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
468 return NULL;
kono
parents:
diff changeset
469
kono
parents:
diff changeset
470 /* TODO: New ABI. */
kono
parents:
diff changeset
471 /* The current ABI does not have any information on protocol properties. */
kono
parents:
diff changeset
472 return NULL;
kono
parents:
diff changeset
473 }
kono
parents:
diff changeset
474
kono
parents:
diff changeset
475 Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
kono
parents:
diff changeset
476 {
kono
parents:
diff changeset
477 unsigned int count = 0;
kono
parents:
diff changeset
478 Property *returnValue = NULL;
kono
parents:
diff changeset
479
kono
parents:
diff changeset
480 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
481 objc_protocol *). */
kono
parents:
diff changeset
482 if (protocol == NULL || protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
483 {
kono
parents:
diff changeset
484 if (numberOfReturnedProperties)
kono
parents:
diff changeset
485 *numberOfReturnedProperties = 0;
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 return NULL;
kono
parents:
diff changeset
488 }
kono
parents:
diff changeset
489
kono
parents:
diff changeset
490 /* We do not acquire any lock because protocols are currently
kono
parents:
diff changeset
491 immutable. We can freely iterate over a protocol structure. */
kono
parents:
diff changeset
492
kono
parents:
diff changeset
493 /* TODO: New ABI. */
kono
parents:
diff changeset
494 /* The current ABI does not have any information on protocol properties. */
kono
parents:
diff changeset
495 if (numberOfReturnedProperties)
kono
parents:
diff changeset
496 *numberOfReturnedProperties = count;
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 return returnValue;
kono
parents:
diff changeset
499 }
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
kono
parents:
diff changeset
502 {
kono
parents:
diff changeset
503 unsigned int count = 0;
kono
parents:
diff changeset
504 Protocol **returnValue = NULL;
kono
parents:
diff changeset
505 struct objc_protocol_list* proto_list;
kono
parents:
diff changeset
506
kono
parents:
diff changeset
507 /* Check that it is a Protocol object before casting it to (struct
kono
parents:
diff changeset
508 objc_protocol *). */
kono
parents:
diff changeset
509 if (protocol == NULL || protocol->class_pointer != objc_lookUpClass ("Protocol"))
kono
parents:
diff changeset
510 {
kono
parents:
diff changeset
511 if (numberOfReturnedProtocols)
kono
parents:
diff changeset
512 *numberOfReturnedProtocols = 0;
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 return NULL;
kono
parents:
diff changeset
515 }
kono
parents:
diff changeset
516
kono
parents:
diff changeset
517 /* We do not acquire any lock because protocols are currently
kono
parents:
diff changeset
518 immutable. We can freely iterate over a protocol structure. */
kono
parents:
diff changeset
519
kono
parents:
diff changeset
520 /* Count how many protocols we have. */
kono
parents:
diff changeset
521 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
kono
parents:
diff changeset
522
kono
parents:
diff changeset
523 while (proto_list)
kono
parents:
diff changeset
524 {
kono
parents:
diff changeset
525 count = count + proto_list->count;
kono
parents:
diff changeset
526 proto_list = proto_list->next;
kono
parents:
diff changeset
527 }
kono
parents:
diff changeset
528
kono
parents:
diff changeset
529 if (count != 0)
kono
parents:
diff changeset
530 {
kono
parents:
diff changeset
531 unsigned int i = 0;
kono
parents:
diff changeset
532
kono
parents:
diff changeset
533 /* Allocate enough memory to hold them. */
kono
parents:
diff changeset
534 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
kono
parents:
diff changeset
535
kono
parents:
diff changeset
536 /* Copy the protocols. */
kono
parents:
diff changeset
537 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 while (proto_list)
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 size_t j;
kono
parents:
diff changeset
542 for (j = 0; j < proto_list->count; j++)
kono
parents:
diff changeset
543 {
kono
parents:
diff changeset
544 returnValue[i] = (Protocol *)proto_list->list[j];
kono
parents:
diff changeset
545 i++;
kono
parents:
diff changeset
546 }
kono
parents:
diff changeset
547 proto_list = proto_list->next;
kono
parents:
diff changeset
548 }
kono
parents:
diff changeset
549
kono
parents:
diff changeset
550 returnValue[i] = NULL;
kono
parents:
diff changeset
551 }
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 if (numberOfReturnedProtocols)
kono
parents:
diff changeset
554 *numberOfReturnedProtocols = count;
kono
parents:
diff changeset
555
kono
parents:
diff changeset
556 return returnValue;
kono
parents:
diff changeset
557 }