OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libobjc/] [protocols.c] - Blame information for rev 739

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 739 jeremybenn
/* GNU Objective C Runtime protocol related functions.
2
   Copyright (C) 2010 Free Software Foundation, Inc.
3
   Contributed by Nicola Pero
4
 
5
This file is part of GCC.
6
 
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.
10
 
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.
15
 
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.
19
 
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/>.  */
24
 
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.  */
34
 
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;
40
 
41
/* A mutex protecting the protocol_hashtable.  */
42
static objc_mutex_t __protocols_hashtable_lock = NULL;
43
 
44
/* Called at startup by init.c.  */
45
void
46
__objc_protocols_init (void)
47
{
48
  __protocols_hashtable_lock = objc_mutex_allocate ();
49
 
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);
54
}
55
 
56
/* Add a protocol to the hashtable.  */
57
void
58
__objc_protocols_add_protocol (const char *name, struct objc_protocol *object)
59
{
60
  objc_mutex_lock (__protocols_hashtable_lock);
61
 
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))
72
    objc_hash_add (&__protocols_hashtable, name, object);
73
 
74
  objc_mutex_unlock (__protocols_hashtable_lock);
75
}
76
 
77
Protocol *
78
objc_getProtocol (const char *name)
79
{
80
  Protocol *protocol;
81
 
82
  if (name == NULL)
83
    return NULL;
84
 
85
  objc_mutex_lock (__protocols_hashtable_lock);
86
  protocol = (Protocol *)(objc_hash_value_for_key (__protocols_hashtable, name));
87
  objc_mutex_unlock (__protocols_hashtable_lock);
88
 
89
  return protocol;
90
}
91
 
92
Protocol **
93
objc_copyProtocolList (unsigned int *numberOfReturnedProtocols)
94
{
95
  unsigned int count = 0;
96
  Protocol **returnValue = NULL;
97
  node_ptr node;
98
 
99
  objc_mutex_lock (__protocols_hashtable_lock);
100
 
101
  /* Count how many protocols we have.  */
102
  node = objc_hash_next (__protocols_hashtable, NULL);
103
  while (node)
104
    {
105
      count++;
106
      node = objc_hash_next (__protocols_hashtable, node);
107
    }
108
 
109
  if (count != 0)
110
    {
111
      unsigned int i = 0;
112
 
113
      /* Allocate enough memory to hold them.  */
114
      returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
115
 
116
      /* Copy the protocols.  */
117
      node = objc_hash_next (__protocols_hashtable, NULL);
118
      while (node)
119
        {
120
          returnValue[i] = node->value;
121
          i++;
122
          node = objc_hash_next (__protocols_hashtable, node);
123
        }
124
 
125
      returnValue[i] = NULL;
126
    }
127
  objc_mutex_unlock (__protocols_hashtable_lock);
128
 
129
  if (numberOfReturnedProtocols)
130
    *numberOfReturnedProtocols = count;
131
 
132
  return returnValue;
133
}
134
 
135
BOOL
136
class_addProtocol (Class class_, Protocol *protocol)
137
{
138
  struct objc_protocol_list *protocols;
139
 
140
  if (class_ == Nil  ||  protocol == NULL)
141
    return NO;
142
 
143
  if (class_conformsToProtocol (class_, protocol))
144
    return NO;
145
 
146
  /* Check that it is a Protocol object before casting it to (struct
147
     objc_protocol *).  */
148
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
149
    return NO;
150
 
151
  objc_mutex_lock (__objc_runtime_mutex);
152
 
153
  /* Create the objc_protocol_list.  */
154
  protocols = malloc (sizeof (struct objc_protocol_list));
155
  protocols->count = 1;
156
  protocols->list[0] = (struct objc_protocol *)protocol;
157
 
158
  /* Attach it to the list of class protocols.  */
159
  protocols->next = class_->protocols;
160
  class_->protocols = protocols;
161
 
162
  objc_mutex_unlock (__objc_runtime_mutex);
163
 
164
  return YES;
165
}
166
 
167
BOOL
168
class_conformsToProtocol (Class class_, Protocol *protocol)
169
{
170
  struct objc_protocol_list* proto_list;
171
 
172
  if (class_ == Nil  ||  protocol == NULL)
173
    return NO;
174
 
175
  /* Check that it is a Protocol object before casting it to (struct
176
     objc_protocol *).  */
177
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
178
    return NO;
179
 
180
  /* Acquire the runtime lock because the list of protocols for a
181
     class may be modified concurrently, for example if another thread
182
     calls class_addProtocol(), or dynamically loads from a file a
183
     category of the class.  */
184
  objc_mutex_lock (__objc_runtime_mutex);
185
  proto_list = class_->protocols;
186
 
187
  while (proto_list)
188
    {
189
      size_t i;
190
      for (i = 0; i < proto_list->count; i++)
191
        {
192
          if (proto_list->list[i] == (struct objc_protocol *)protocol
193
              || protocol_conformsToProtocol ((Protocol *)proto_list->list[i],
194
                                              protocol))
195
            {
196
              objc_mutex_unlock (__objc_runtime_mutex);
197
              return YES;
198
            }
199
        }
200
      proto_list = proto_list->next;
201
    }
202
 
203
  objc_mutex_unlock (__objc_runtime_mutex);
204
  return NO;
205
}
206
 
207
Protocol **
208
class_copyProtocolList (Class class_, unsigned int *numberOfReturnedProtocols)
209
{
210
  unsigned int count = 0;
211
  Protocol **returnValue = NULL;
212
  struct objc_protocol_list* proto_list;
213
 
214
  if (class_ == Nil)
215
    {
216
      if (numberOfReturnedProtocols)
217
        *numberOfReturnedProtocols = 0;
218
      return NULL;
219
    }
220
 
221
  /* Lock the runtime mutex because the class protocols may be
222
     concurrently modified.  */
223
  objc_mutex_lock (__objc_runtime_mutex);
224
 
225
  /* Count how many protocols we have.  */
226
  proto_list = class_->protocols;
227
 
228
  while (proto_list)
229
    {
230
      count = count + proto_list->count;
231
      proto_list = proto_list->next;
232
    }
233
 
234
  if (count != 0)
235
    {
236
      unsigned int i = 0;
237
 
238
      /* Allocate enough memory to hold them.  */
239
      returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
240
 
241
      /* Copy the protocols.  */
242
      proto_list = class_->protocols;
243
 
244
      while (proto_list)
245
        {
246
          size_t j;
247
          for (j = 0; j < proto_list->count; j++)
248
            {
249
              returnValue[i] = (Protocol *)proto_list->list[j];
250
              i++;
251
            }
252
          proto_list = proto_list->next;
253
        }
254
 
255
      returnValue[i] = NULL;
256
    }
257
  objc_mutex_unlock (__objc_runtime_mutex);
258
 
259
  if (numberOfReturnedProtocols)
260
    *numberOfReturnedProtocols = count;
261
 
262
  return returnValue;
263
}
264
 
265
BOOL
266
protocol_conformsToProtocol (Protocol *protocol, Protocol *anotherProtocol)
267
{
268
  struct objc_protocol_list* proto_list;
269
 
270
  if (protocol == NULL  ||  anotherProtocol == NULL)
271
    return NO;
272
 
273
  if (protocol == anotherProtocol)
274
    return YES;
275
 
276
  /* Check that the objects are Protocol objects before casting them
277
     to (struct objc_protocol *).  */
278
  if (protocol->class_pointer != anotherProtocol->class_pointer)
279
    return NO;
280
 
281
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
282
    return NO;
283
 
284
  if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
285
              ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
286
    return YES;
287
 
288
  /* We do not acquire any lock because protocols are currently
289
     immutable.  We can freely iterate over a protocol structure.  */
290
  proto_list = ((struct objc_protocol *)protocol)->protocol_list;
291
  while (proto_list)
292
    {
293
      size_t i;
294
 
295
      for (i = 0; i < proto_list->count; i++)
296
        {
297
          if (protocol_conformsToProtocol ((Protocol *)proto_list->list[i], anotherProtocol))
298
            return YES;
299
        }
300
      proto_list = proto_list->next;
301
    }
302
 
303
  return NO;
304
}
305
 
306
BOOL
307
protocol_isEqual (Protocol *protocol, Protocol *anotherProtocol)
308
{
309
  if (protocol == anotherProtocol)
310
    return YES;
311
 
312
  if (protocol == NULL  ||  anotherProtocol == NULL)
313
    return NO;
314
 
315
  /* Check that the objects are Protocol objects before casting them
316
     to (struct objc_protocol *).  */
317
  if (protocol->class_pointer != anotherProtocol->class_pointer)
318
    return NO;
319
 
320
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
321
    return NO;
322
 
323
  /* Equality between formal protocols is only formal (nothing to do
324
     with actually checking the list of methods they have!).  Two
325
     formal Protocols are equal if and only if they have the same
326
     name.
327
 
328
     Please note (for comparisons with other implementations) that
329
     checking the names is equivalent to checking that Protocol A
330
     conforms to Protocol B and Protocol B conforms to Protocol A,
331
     because this happens iff they have the same name.  If they have
332
     different names, A conforms to B if and only if A includes B, but
333
     the situation where A includes B and B includes A is a circular
334
     dependency between Protocols which is forbidden by the compiler,
335
     so A conforms to B and B conforms to A with A and B having
336
     different names is an impossible case.  */
337
  if (strcmp (((struct objc_protocol *)protocol)->protocol_name,
338
              ((struct objc_protocol *)anotherProtocol)->protocol_name) == 0)
339
    return YES;
340
 
341
  return NO;
342
}
343
 
344
const char *
345
protocol_getName (Protocol *protocol)
346
{
347
  /* Check that it is a Protocol object before casting it to (struct
348
     objc_protocol *).  */
349
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
350
    return NULL;
351
 
352
  return ((struct objc_protocol *)protocol)->protocol_name;
353
}
354
 
355
struct objc_method_description protocol_getMethodDescription (Protocol *protocol,
356
                                                              SEL selector,
357
                                                              BOOL requiredMethod,
358
                                                              BOOL instanceMethod)
359
{
360
  struct objc_method_description no_result = { NULL, NULL };
361
  struct objc_method_description_list *methods;
362
  int i;
363
 
364
  /* TODO: New ABI.  */
365
  /* The current ABI does not have any information on optional protocol methods.  */
366
  if (! requiredMethod)
367
    return no_result;
368
 
369
  /* Check that it is a Protocol object before casting it to (struct
370
     objc_protocol *).  */
371
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
372
    return no_result;
373
 
374
  if (instanceMethod)
375
    methods = ((struct objc_protocol *)protocol)->instance_methods;
376
  else
377
    methods = ((struct objc_protocol *)protocol)->class_methods;
378
 
379
  if (methods)
380
    {
381
      for (i = 0; i < methods->count; i++)
382
        {
383
          if (sel_isEqual (methods->list[i].name, selector))
384
            return methods->list[i];
385
          /*
386
          if (strcmp (sel_getName (methods->list[i].name), selector_name) == 0)
387
            return methods->list[i];
388
          */
389
        }
390
    }
391
 
392
  return no_result;
393
}
394
 
395
struct objc_method_description *protocol_copyMethodDescriptionList (Protocol *protocol,
396
                                                                    BOOL requiredMethod,
397
                                                                    BOOL instanceMethod,
398
                                                                    unsigned int *numberOfReturnedMethods)
399
{
400
  struct objc_method_description_list *methods;
401
  unsigned int count = 0;
402
  struct objc_method_description *returnValue = NULL;
403
 
404
  /* TODO: New ABI */
405
  /* The current ABI does not have any information on optional protocol methods.  */
406
  if (! requiredMethod)
407
    {
408
      if (numberOfReturnedMethods)
409
        *numberOfReturnedMethods = 0;
410
 
411
      return NULL;
412
    }
413
 
414
  /* Check that it is a Protocol object before casting it to (struct
415
     objc_protocol *).  */
416
  if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
417
    {
418
      if (numberOfReturnedMethods)
419
        *numberOfReturnedMethods = 0;
420
 
421
      return NULL;
422
    }
423
 
424
  /* We do not acquire any lock because protocols are currently
425
     immutable.  We can freely iterate over a protocol structure.  */
426
 
427
  if (instanceMethod)
428
    methods = ((struct objc_protocol *)protocol)->instance_methods;
429
  else
430
    methods = ((struct objc_protocol *)protocol)->class_methods;
431
 
432
  if (methods)
433
    {
434
      unsigned int i;
435
      count = methods->count;
436
 
437
      /* Allocate enough memory to hold them.  */
438
      returnValue = (struct objc_method_description *)(malloc (sizeof (struct objc_method_description) * (count + 1)));
439
 
440
      /* Copy them.  */
441
      for (i = 0; i < count; i++)
442
        {
443
          returnValue[i].name = methods->list[i].name;
444
          returnValue[i].types = methods->list[i].types;
445
        }
446
      returnValue[i].name = NULL;
447
      returnValue[i].types = NULL;
448
    }
449
 
450
  if (numberOfReturnedMethods)
451
    *numberOfReturnedMethods = count;
452
 
453
  return returnValue;
454
}
455
 
456
Property protocol_getProperty (Protocol *protocol, const char *propertyName,
457
                               BOOL requiredProperty, BOOL instanceProperty)
458
{
459
  if (protocol == NULL  ||  propertyName == NULL)
460
    return NULL;
461
 
462
  if (!requiredProperty  ||  !instanceProperty)
463
    return NULL;
464
 
465
  /* Check that it is a Protocol object before casting it to (struct
466
     objc_protocol *).  */
467
  if (protocol->class_pointer != objc_lookUpClass ("Protocol"))
468
    return NULL;
469
 
470
  /* TODO: New ABI.  */
471
  /* The current ABI does not have any information on protocol properties.  */
472
  return NULL;
473
}
474
 
475
Property *protocol_copyPropertyList (Protocol *protocol, unsigned int *numberOfReturnedProperties)
476
{
477
  unsigned int count = 0;
478
  Property *returnValue = NULL;
479
 
480
  /* Check that it is a Protocol object before casting it to (struct
481
     objc_protocol *).  */
482
  if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
483
    {
484
      if (numberOfReturnedProperties)
485
        *numberOfReturnedProperties = 0;
486
 
487
      return NULL;
488
    }
489
 
490
  /* We do not acquire any lock because protocols are currently
491
     immutable.  We can freely iterate over a protocol structure.  */
492
 
493
  /* TODO: New ABI.  */
494
  /* The current ABI does not have any information on protocol properties.  */
495
  if (numberOfReturnedProperties)
496
    *numberOfReturnedProperties = count;
497
 
498
  return returnValue;
499
}
500
 
501
Protocol **protocol_copyProtocolList (Protocol *protocol, unsigned int *numberOfReturnedProtocols)
502
{
503
  unsigned int count = 0;
504
  Protocol **returnValue = NULL;
505
  struct objc_protocol_list* proto_list;
506
 
507
  /* Check that it is a Protocol object before casting it to (struct
508
     objc_protocol *).  */
509
  if (protocol == NULL  ||  protocol->class_pointer != objc_lookUpClass ("Protocol"))
510
    {
511
      if (numberOfReturnedProtocols)
512
        *numberOfReturnedProtocols = 0;
513
 
514
      return NULL;
515
    }
516
 
517
  /* We do not acquire any lock because protocols are currently
518
     immutable.  We can freely iterate over a protocol structure.  */
519
 
520
  /* Count how many protocols we have.  */
521
  proto_list = ((struct objc_protocol *)protocol)->protocol_list;
522
 
523
  while (proto_list)
524
    {
525
      count = count + proto_list->count;
526
      proto_list = proto_list->next;
527
    }
528
 
529
  if (count != 0)
530
    {
531
      unsigned int i = 0;
532
 
533
      /* Allocate enough memory to hold them.  */
534
      returnValue = (Protocol **)(malloc (sizeof (Protocol *) * (count + 1)));
535
 
536
      /* Copy the protocols.  */
537
      proto_list = ((struct objc_protocol *)protocol)->protocol_list;
538
 
539
      while (proto_list)
540
        {
541
          size_t j;
542
          for (j = 0; j < proto_list->count; j++)
543
            {
544
              returnValue[i] = (Protocol *)proto_list->list[j];
545
              i++;
546
            }
547
          proto_list = proto_list->next;
548
        }
549
 
550
      returnValue[i] = NULL;
551
    }
552
 
553
  if (numberOfReturnedProtocols)
554
    *numberOfReturnedProtocols = count;
555
 
556
  return returnValue;
557
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.