Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libobjc / protocols.c
blob05a750758c75a77ebdeb0d3638c97057351e68f2
1 /* GNU Objective C Runtime protocol related functions.
2 Copyright (C) 2010 Free Software Foundation, Inc.
3 Contributed by Nicola Pero
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under the
8 terms of the GNU General Public License as published by the Free Software
9 Foundation; either version 3, or (at your option) any later version.
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 details.
16 Under Section 7 of GPL version 3, you are granted additional
17 permissions described in the GCC Runtime Library Exception, version
18 3.1, as published by the Free Software Foundation.
20 You should have received a copy of the GNU General Public License and
21 a copy of the GCC Runtime Library Exception along with this program;
22 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 <http://www.gnu.org/licenses/>. */
25 #include "objc-private/common.h"
26 #include "objc/runtime.h"
27 #include "objc-private/module-abi-8.h" /* For runtime structures */
28 #include "objc/thr.h"
29 #include "objc-private/runtime.h" /* the kitchen sink */
30 #include "objc-private/hash.h" /* For the hash table of protocols. */
31 #include "objc-private/protocols.h" /* For __objc_protocols_init() and
32 __objc_protocols_add_protocol(). */
33 #include <stdlib.h> /* For malloc. */
35 /* This is a table that maps a name to a Protocol instance with that
36 name. Because there may be multiple Protocol instances with the
37 same name (no harm in that) the table records only one
38 instance. */
39 static cache_ptr __protocols_hashtable;
41 /* A mutex protecting the protocol_hashtable. */
42 static objc_mutex_t __protocols_hashtable_lock = NULL;
44 /* Called at startup by init.c. */
45 void
46 __objc_protocols_init (void)
48 __protocols_hashtable_lock = objc_mutex_allocate ();
50 /* The keys in the table are strings, and the values are Protocol
51 objects. */
52 __protocols_hashtable = objc_hash_new (64, (hash_func_type) objc_hash_string,
53 (compare_func_type) objc_compare_strings);
56 /* Add a protocol to the hashtable. */
57 void
58 __objc_protocols_add_protocol (const char *name, Protocol *object)
60 objc_mutex_lock (__protocols_hashtable_lock);
62 /* If we find a protocol with the same name already in the
63 hashtable, we do not need to add the new one, because it will be
64 identical to it. This in the reasonable assumption that two
65 protocols with the same name are identical, which is expected in
66 any sane program. If we are really paranoid, we would compare
67 the protocols and abort if they are not identical.
68 Unfortunately, this would slow down the startup of all
69 Objective-C programs while trying to catch a problem that has
70 never been seen in practice, so we don't do it. */
71 if (! objc_hash_is_key_in_hash (__protocols_hashtable, name))
73 objc_hash_add (&__protocols_hashtable, name, object);
76 objc_mutex_unlock (__protocols_hashtable_lock);
79 Protocol *
80 objc_getProtocol (const char *name)
82 Protocol *protocol;
84 if (name == NULL)
85 return NULL;
87 objc_mutex_lock (__protocols_hashtable_lock);
88 protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
89 objc_mutex_unlock (__protocols_hashtable_lock);
91 return protocol;
94 Protocol **
95 objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
97 unsigned int count = 0;
98 Protocol **returnValue = NULL;
99 node_ptr node;
101 objc_mutex_lock (__protocols_hashtable_lock);
103 /* Count how many protocols we have. */
104 node = objc_hash_next (__protocols_hashtable, NULL);
105 while (node)
107 count++;
108 node = objc_hash_next (__protocols_hashtable, node);
111 if (count != 0)
113 unsigned int i = 0;
115 /* Allocate enough memory to hold them. */
116 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
118 /* Copy the protocols. */
119 node = objc_hash_next (__protocols_hashtable, NULL);
120 while (node)
122 returnValue[i] = node->value;
123 i++;
124 node = objc_hash_next (__protocols_hashtable, node);
127 returnValue[i] = NULL;
129 objc_mutex_unlock (__protocols_hashtable_lock);
131 if (numberOfReturnedProtocols)
132 *numberOfReturnedProtocols = count;
134 return returnValue;
137 BOOL
138 class_addProtocol (Class class_, Protocol *protocol)
140 struct objc_protocol_list *protocols;
142 if (class_ == Nil || protocol == NULL)
143 return NO;
145 if (class_conformsToProtocol (class_, protocol))
146 return NO;
148 /* Check that it is a Protocol object before casting it to (struct
149 objc_protocol *). */
150 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
151 return NO;
153 objc_mutex_lock (__objc_runtime_mutex);
155 /* Create the objc_protocol_list. */
156 protocols = malloc (sizeof (struct objc_protocol_list));
157 protocols->count = 1;
158 protocols->list[0] = protocol;
160 /* Attach it to the list of class protocols. */
161 protocols->next = class_->protocols;
162 class_->protocols = protocols;
164 objc_mutex_unlock (__objc_runtime_mutex);
166 return YES;
169 BOOL
170 class_conformsToProtocol (Class class_, Protocol *protocol)
172 struct objc_protocol_list* proto_list;
174 if (class_ == Nil || protocol == NULL)
175 return NO;
177 /* Check that it is a Protocol object before casting it to (struct
178 objc_protocol *). */
179 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
180 return NO;
182 /* Acquire the runtime lock because the list of protocols for a
183 class may be modified concurrently, for example if another thread
184 calls class_addProtocol(), or dynamically loads from a file a
185 category of the class. */
186 objc_mutex_lock (__objc_runtime_mutex);
187 proto_list = class_->protocols;
189 while (proto_list)
191 size_t i;
192 for (i = 0; i < proto_list->count; i++)
194 if (proto_list->list[i] == protocol
195 || protocol_conformsToProtocol (proto_list->list[i],
196 protocol))
198 objc_mutex_unlock (__objc_runtime_mutex);
199 return YES;
202 proto_list = proto_list->next;
205 objc_mutex_unlock (__objc_runtime_mutex);
206 return NO;
209 Protocol **
210 class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
212 unsigned int count = 0;
213 Protocol **returnValue = NULL;
214 struct objc_protocol_list* proto_list;
216 if (class_ == Nil)
218 if (numberOfReturnedProtocols)
219 *numberOfReturnedProtocols = 0;
220 return NULL;
223 /* Lock the runtime mutex because the class protocols may be
224 concurrently modified. */
225 objc_mutex_lock (__objc_runtime_mutex);
227 /* Count how many protocols we have. */
228 proto_list = class_->protocols;
230 while (proto_list)
232 count = count + proto_list->count;
233 proto_list = proto_list->next;
236 if (count != 0)
238 unsigned int i = 0;
240 /* Allocate enough memory to hold them. */
241 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
243 /* Copy the protocols. */
244 proto_list = class_->protocols;
246 while (proto_list)
248 size_t j;
249 for (j = 0; j < proto_list->count; j++)
251 returnValue[i] = proto_list->list[j];
252 i++;
254 proto_list = proto_list->next;
257 returnValue[i] = NULL;
259 objc_mutex_unlock (__objc_runtime_mutex);
261 if (numberOfReturnedProtocols)
262 *numberOfReturnedProtocols = count;
264 return returnValue;
267 BOOL
268 protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
270 struct objc_protocol_list* proto_list;
272 if (protocol == NULL || anotherProtocol == NULL)
273 return NO;
275 if (protocol == anotherProtocol)
276 return YES;
278 /* Check that the objects are Protocol objects before casting them
279 to (struct objc_protocol *). */
280 if (protocol->class_pointer != anotherProtocol->class_pointer)
281 return NO;
283 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
284 return NO;
286 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
287 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
288 return YES;
290 /* We do not acquire any lock because protocols are currently
291 immutable. We can freely iterate over a protocol structure. */
292 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
293 while (proto_list)
295 size_t i;
297 for (i = 0; i < proto_list->count; i++)
299 if (protocol_conformsToProtocol (proto_list->list[i], anotherProtocol))
300 return YES;
302 proto_list = proto_list->next;
305 return NO;
308 BOOL
309 protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
311 if (protocol == anotherProtocol)
312 return YES;
314 if (protocol == NULL || anotherProtocol == NULL)
315 return NO;
317 /* Check that the objects are Protocol objects before casting them
318 to (struct objc_protocol *). */
319 if (protocol->class_pointer != anotherProtocol->class_pointer)
320 return NO;
322 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
323 return NO;
325 /* Equality between formal protocols is only formal (nothing to do
326 with actually checking the list of methods they have!). Two
327 formal Protocols are equal if and only if they have the same
328 name.
330 Please note (for comparisons with other implementations) that
331 checking the names is equivalent to checking that Protocol A
332 conforms to Protocol B and Protocol B conforms to Protocol A,
333 because this happens iff they have the same name. If they have
334 different names, A conforms to B if and only if A includes B, but
335 the situation where A includes B and B includes A is a circular
336 dependency between Protocols which is forbidden by the compiler,
337 so A conforms to B and B conforms to A with A and B having
338 different names is an impossible case. */
339 if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
340 ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
341 return YES;
343 return NO;
346 const char *
347 protocol_getName (Protocol *protocol)
349 /* Check that it is a Protocol object before casting it to (struct
350 objc_protocol *). */
351 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
352 return NULL;
354 return ((struct objc_protocol *)protocol)->protocol_name;
357 struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
358 SEL selector,
359 BOOL requiredMethod,
360 BOOL instanceMethod)
362 struct objc_method_description no_result = { NULL, NULL };
363 struct objc_method_description_list *methods;
364 int i;
366 /* TODO: New ABI. */
367 /* The current ABI does not have any information on optional protocol methods. */
368 if (! requiredMethod)
369 return no_result;
371 /* Check that it is a Protocol object before casting it to (struct
372 objc_protocol *). */
373 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
374 return no_result;
376 if (instanceMethod)
377 methods = ((struct objc_protocol *)protocol)->instance_methods;
378 else
379 methods = ((struct objc_protocol *)protocol)->class_methods;
381 if (methods)
383 for (i = 0; i < methods->count; i++)
385 if (sel_isEqual (methods->list[i].name, selector))
386 return methods->list[i];
388 if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
389 return methods->list[i];
394 return no_result;
397 struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
398 BOOL requiredMethod,
399 BOOL instanceMethod,
400 unsigned int *numberOfReturnedMethods)
402 struct objc_method_description_list *methods;
403 unsigned int count = 0;
404 struct objc_method_description *returnValue = NULL;
406 /* TODO: New ABI */
407 /* The current ABI does not have any information on optional protocol methods. */
408 if (! requiredMethod)
410 if (numberOfReturnedMethods)
411 *numberOfReturnedMethods = 0;
413 return NULL;
416 /* Check that it is a Protocol object before casting it to (struct
417 objc_protocol *). */
418 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
420 if (numberOfReturnedMethods)
421 *numberOfReturnedMethods = 0;
423 return NULL;
426 /* We do not acquire any lock because protocols are currently
427 immutable. We can freely iterate over a protocol structure. */
429 if (instanceMethod)
430 methods = ((struct objc_protocol *)protocol)->instance_methods;
431 else
432 methods = ((struct objc_protocol *)protocol)->class_methods;
434 if (methods)
436 unsigned int i;
437 count = methods->count;
439 /* Allocate enough memory to hold them. */
440 returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
442 /* Copy them. */
443 for (i = 0; i < count; i++)
445 returnValue[i].name = methods->list[i].name;
446 returnValue[i].types = methods->list[i].types;
448 returnValue[i].name = NULL;
449 returnValue[i].types = NULL;
452 if (numberOfReturnedMethods)
453 *numberOfReturnedMethods = count;
455 return returnValue;
458 Property protocol_getProperty (Protocol *protocol, const char *propertyName,
459 BOOL requiredProperty, BOOL instanceProperty)
461 if (protocol == NULL || propertyName == NULL)
462 return NULL;
464 if (!requiredProperty || !instanceProperty)
465 return NULL;
467 /* Check that it is a Protocol object before casting it to (struct
468 objc_protocol *). */
469 if (protocol->class_pointer != objc_lookupClass ("Protocol"))
470 return NULL;
472 /* TODO: New ABI. */
473 /* The current ABI does not have any information on protocol properties. */
474 return NULL;
477 Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
479 unsigned int count = 0;
480 Property *returnValue = NULL;
482 /* Check that it is a Protocol object before casting it to (struct
483 objc_protocol *). */
484 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
486 if (numberOfReturnedProperties)
487 *numberOfReturnedProperties = 0;
489 return NULL;
492 /* We do not acquire any lock because protocols are currently
493 immutable. We can freely iterate over a protocol structure. */
495 /* TODO: New ABI. */
496 /* The current ABI does not have any information on protocol properties. */
497 if (numberOfReturnedProperties)
498 *numberOfReturnedProperties = count;
500 return returnValue;
503 Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
505 unsigned int count = 0;
506 Protocol **returnValue = NULL;
507 struct objc_protocol_list* proto_list;
509 /* Check that it is a Protocol object before casting it to (struct
510 objc_protocol *). */
511 if (protocol == NULL || protocol->class_pointer != objc_lookupClass ("Protocol"))
513 if (numberOfReturnedProtocols)
514 *numberOfReturnedProtocols = 0;
516 return NULL;
519 /* We do not acquire any lock because protocols are currently
520 immutable. We can freely iterate over a protocol structure. */
522 /* Count how many protocols we have. */
523 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
525 while (proto_list)
527 count = count + proto_list->count;
528 proto_list = proto_list->next;
531 if (count != 0)
533 unsigned int i = 0;
535 /* Allocate enough memory to hold them. */
536 returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
538 /* Copy the protocols. */
539 proto_list = ((struct objc_protocol *)protocol)->protocol_list;
541 while (proto_list)
543 size_t j;
544 for (j = 0; j < proto_list->count; j++)
546 returnValue[i] = proto_list->list[j];
547 i++;
549 proto_list = proto_list->next;
552 returnValue[i] = NULL;
555 if (numberOfReturnedProtocols)
556 *numberOfReturnedProtocols = count;
558 return returnValue;