]> git.saurik.com Git - apple/objc4.git/blob - runtime/Protocol.m
90cb3f818d82255e424e961ad5a5ed87d2bfaf00
[apple/objc4.git] / runtime / Protocol.m
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 Protocol.h
26 Copyright 1991-1996 NeXT Software, Inc.
27 */
28
29 #if defined(WIN32)
30 #include <winnt-pdo.h>
31 #endif
32
33 #include "objc-private.h"
34 #import <objc/Protocol.h>
35
36 #include <objc/objc-runtime.h>
37 #include <stdlib.h>
38
39 #if defined(__MACH__)
40 #include <mach-o/dyld.h>
41 #include <mach-o/ldsyms.h>
42 #endif
43
44 /* some forward declarations */
45
46 static struct objc_method_description *
47 lookup_method(struct objc_method_description_list *mlist, SEL aSel);
48
49 static struct objc_method_description *
50 lookup_class_method(struct objc_protocol_list *plist, SEL aSel);
51
52 static struct objc_method_description *
53 lookup_instance_method(struct objc_protocol_list *plist, SEL aSel);
54
55 @implementation Protocol
56
57
58 + _fixup: (OBJC_PROTOCOL_PTR)protos numElements: (int) nentries
59 {
60 int i;
61 for (i = 0; i < nentries; i++)
62 {
63 /* isa has been overloaded by the compiler to indicate version info */
64 protos[i] OBJC_PROTOCOL_DEREF isa = self; // install the class descriptor.
65 }
66
67 return self;
68 }
69
70 + load
71 {
72 OBJC_PROTOCOL_PTR p;
73 int size;
74 headerType **hp;
75 headerType **hdrs;
76 hdrs = _getObjcHeaders();
77
78 for (hp = hdrs; *hp; hp++)
79 {
80 p = (OBJC_PROTOCOL_PTR)_getObjcProtocols((headerType*)*hp, &size);
81 if (p && size) { [self _fixup:p numElements: size]; }
82 }
83 free (hdrs);
84
85 return self;
86 }
87
88 - (BOOL) conformsTo: (Protocol *)aProtocolObj
89 {
90 if (!aProtocolObj)
91 return NO;
92
93 if (strcmp(aProtocolObj->protocol_name, protocol_name) == 0)
94 return YES;
95 else if (protocol_list)
96 {
97 int i;
98
99 for (i = 0; i < protocol_list->count; i++)
100 {
101 Protocol *p = protocol_list->list[i];
102
103 if (strcmp(aProtocolObj->protocol_name, p->protocol_name) == 0)
104 return YES;
105
106 if ([p conformsTo:aProtocolObj])
107 return YES;
108 }
109 return NO;
110 }
111 else
112 return NO;
113 }
114
115 - (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSel
116 {
117 struct objc_method_description *m = lookup_method(instance_methods, aSel);
118
119 if (!m && protocol_list)
120 m = lookup_instance_method(protocol_list, aSel);
121
122 return m;
123 }
124
125 - (struct objc_method_description *) descriptionForClassMethod:(SEL)aSel
126 {
127 struct objc_method_description *m = lookup_method(class_methods, aSel);
128
129 if (!m && protocol_list)
130 m = lookup_class_method(protocol_list, aSel);
131
132 return m;
133 }
134
135 - (const char *)name
136 {
137 return protocol_name;
138 }
139
140 - (BOOL)isEqual:other
141 {
142 return [other isKindOf:[Protocol class]] && [self conformsTo: other] && [other conformsTo: self];
143 }
144
145 - (unsigned int)hash
146 {
147 return 23;
148 }
149
150 static
151 struct objc_method_description *
152 lookup_method(struct objc_method_description_list *mlist, SEL aSel)
153 {
154 if (mlist)
155 {
156 int i;
157 for (i = 0; i < mlist->count; i++)
158 if (mlist->list[i].name == aSel)
159 return mlist->list+i;
160 }
161 return 0;
162 }
163
164 static
165 struct objc_method_description *
166 lookup_instance_method(struct objc_protocol_list *plist, SEL aSel)
167 {
168 int i;
169 struct objc_method_description *m = 0;
170
171 for (i = 0; i < plist->count; i++)
172 {
173 if (plist->list[i]->instance_methods)
174 m = lookup_method(plist->list[i]->instance_methods, aSel);
175
176 /* depth first search */
177 if (!m && plist->list[i]->protocol_list)
178 m = lookup_instance_method(plist->list[i]->protocol_list, aSel);
179
180 if (m)
181 return m;
182 }
183 return 0;
184 }
185
186 static
187 struct objc_method_description *
188 lookup_class_method(struct objc_protocol_list *plist, SEL aSel)
189 {
190 int i;
191 struct objc_method_description *m = 0;
192
193 for (i = 0; i < plist->count; i++)
194 {
195 if (plist->list[i]->class_methods)
196 m = lookup_method(plist->list[i]->class_methods, aSel);
197
198 /* depth first search */
199 if (!m && plist->list[i]->protocol_list)
200 m = lookup_class_method(plist->list[i]->protocol_list, aSel);
201
202 if (m)
203 return m;
204 }
205 return 0;
206 }
207
208 @end