1 |
/** |
2 |
STObjCRuntime.m |
3 |
Objective C runtime additions |
4 |
|
5 |
Copyright (c) 2002 Free Software Foundation |
6 |
|
7 |
Written by: Stefan Urbanek <urbanek@host.sk> |
8 |
Date: 2000 |
9 |
|
10 |
This file is part of the StepTalk project. |
11 |
|
12 |
This library is free software; you can redistribute it and/or |
13 |
modify it under the terms of the GNU Lesser General Public |
14 |
License as published by the Free Software Foundation; either |
15 |
version 2 of the License, or (at your option) any later version. |
16 |
|
17 |
This library is distributed in the hope that it will be useful, |
18 |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
20 |
Lesser General Public License for more details. |
21 |
|
22 |
You should have received a copy of the GNU Lesser General Public |
23 |
License along with this library; if not, write to the Free Software |
24 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
25 |
|
26 |
*/ |
27 |
|
28 |
#import "STObjCRuntime.h" |
29 |
#import "STExterns.h" |
30 |
|
31 |
#import <Foundation/NSArray.h> |
32 |
#import <Foundation/NSDebug.h> |
33 |
#import <Foundation/NSDictionary.h> |
34 |
#import <Foundation/NSException.h> |
35 |
#import <Foundation/NSMethodSignature.h> |
36 |
#import <Foundation/NSSet.h> |
37 |
#import <Foundation/NSString.h> |
38 |
#import <Foundation/NSValue.h> |
39 |
|
40 |
#define SELECTOR_TYPES_COUNT 10 |
41 |
|
42 |
/* Predefined default selector types up to 10 arguments for fast creation. |
43 |
It should be faster than manually constructing the string. */ |
44 |
static const char *selector_types[] = |
45 |
{ |
46 |
"@8@0:4", |
47 |
"@12@0:4@8", |
48 |
"@16@0:4@8@12", |
49 |
"@20@0:4@8@12@16", |
50 |
"@24@0:4@8@12@16@20", |
51 |
"@28@0:4@8@12@16@20@24" |
52 |
"@32@0:4@8@12@16@20@24@28" |
53 |
"@36@0:4@8@12@16@20@24@28@32" |
54 |
"@40@0:4@8@12@16@20@24@28@32@36" |
55 |
"@44@0:4@8@12@16@20@24@28@32@36@40" |
56 |
}; |
57 |
|
58 |
NSMutableDictionary *STAllObjectiveCClasses(void) |
59 |
{ |
60 |
NSString *name; |
61 |
NSMutableDictionary *dict; |
62 |
void *state = 0; |
63 |
Class class; |
64 |
|
65 |
dict = [NSMutableDictionary dictionary]; |
66 |
|
67 |
while( (class = objc_next_class(&state)) ) |
68 |
{ |
69 |
name = [NSString stringWithCString:class_get_class_name(class)]; |
70 |
|
71 |
[dict setObject:class forKey:name]; |
72 |
} |
73 |
|
74 |
// NSLog(@"%i Objective-C classes found",[dict count]); |
75 |
|
76 |
return dict; |
77 |
} |
78 |
|
79 |
NSDictionary *STClassDictionaryWithNames(NSArray *classNames) |
80 |
{ |
81 |
NSEnumerator *enumerator = [classNames objectEnumerator]; |
82 |
NSString *className; |
83 |
NSMutableDictionary *dict = [NSMutableDictionary dictionary]; |
84 |
Class class; |
85 |
|
86 |
while( (className = [enumerator nextObject]) ) |
87 |
{ |
88 |
class = NSClassFromString(className); |
89 |
if(class) |
90 |
{ |
91 |
[dict setObject:NSClassFromString(className) forKey:className]; |
92 |
} |
93 |
else |
94 |
{ |
95 |
NSLog(@"Warning: Class with name '%@' not found", className); |
96 |
} |
97 |
} |
98 |
|
99 |
return [NSDictionary dictionaryWithDictionary:dict]; |
100 |
} |
101 |
|
102 |
NSValue *STValueFromSelector(SEL sel) |
103 |
{ |
104 |
return [NSValue value:&sel withObjCType:@encode(SEL)]; |
105 |
} |
106 |
|
107 |
SEL STSelectorFromValue(NSValue *val) |
108 |
{ |
109 |
SEL sel; |
110 |
[val getValue:&sel]; |
111 |
return sel; |
112 |
} |
113 |
|
114 |
SEL STSelectorFromString(NSString *aString) |
115 |
{ |
116 |
const char *name = [aString cString]; |
117 |
const char *ptr; |
118 |
int argc = 0; |
119 |
|
120 |
SEL sel; |
121 |
|
122 |
sel = NSSelectorFromString(aString); |
123 |
if(!sel) |
124 |
{ |
125 |
|
126 |
ptr = name; |
127 |
|
128 |
while(*ptr) |
129 |
{ |
130 |
if(*ptr == ':') |
131 |
{ |
132 |
argc ++; |
133 |
} |
134 |
ptr++; |
135 |
} |
136 |
|
137 |
if( argc < SELECTOR_TYPES_COUNT ) |
138 |
{ |
139 |
NSDebugLLog(@"STSending", |
140 |
@"registering selector '%s' " |
141 |
@"with %i arguments, types:'%s'", |
142 |
name,argc,selector_types[argc]); |
143 |
|
144 |
sel = sel_register_typed_name(name, selector_types[argc]); |
145 |
} |
146 |
|
147 |
if(!sel) |
148 |
{ |
149 |
[NSException raise:STInternalInconsistencyException |
150 |
format:@"Unable to register selector '%@'", |
151 |
aString]; |
152 |
return 0; |
153 |
} |
154 |
} |
155 |
else |
156 |
{ |
157 |
/* FIXME: temporary hack */ |
158 |
} |
159 |
|
160 |
return sel; |
161 |
} |
162 |
|
163 |
SEL STCreateTypedSelector(SEL sel) |
164 |
{ |
165 |
const char *name = sel_get_name(sel); |
166 |
const char *ptr; |
167 |
int argc = 0; |
168 |
|
169 |
SEL newSel; |
170 |
|
171 |
NSLog(@"STCreateTypedSelector is deprecated."); |
172 |
|
173 |
ptr = name; |
174 |
|
175 |
while(*ptr) |
176 |
{ |
177 |
if(*ptr == ':') |
178 |
{ |
179 |
argc ++; |
180 |
} |
181 |
ptr++; |
182 |
} |
183 |
|
184 |
if( argc < SELECTOR_TYPES_COUNT ) |
185 |
{ |
186 |
NSDebugLLog(@"STSending", |
187 |
@"registering selector '%s' " |
188 |
@"with %i arguments, types:'%s'", |
189 |
name,argc,selector_types[argc]); |
190 |
|
191 |
newSel = sel_register_typed_name(name, selector_types[argc]); |
192 |
} |
193 |
|
194 |
if(!newSel) |
195 |
{ |
196 |
[NSException raise:STInternalInconsistencyException |
197 |
format:@"Unable to register typed selector '%s'", |
198 |
name]; |
199 |
return 0; |
200 |
} |
201 |
|
202 |
return newSel; |
203 |
} |
204 |
|
205 |
NSMethodSignature *STConstructMethodSignatureForSelector(SEL sel) |
206 |
{ |
207 |
const char *name = sel_get_name(sel); |
208 |
const char *ptr; |
209 |
const char *types = (const char *)0; |
210 |
int argc = 0; |
211 |
|
212 |
ptr = name; |
213 |
|
214 |
while(*ptr) |
215 |
{ |
216 |
if(*ptr == ':') |
217 |
{ |
218 |
argc ++; |
219 |
} |
220 |
ptr++; |
221 |
} |
222 |
|
223 |
if( argc < SELECTOR_TYPES_COUNT ) |
224 |
{ |
225 |
NSDebugLLog(@"STSending", |
226 |
@"registering selector '%s' " |
227 |
@"with %i arguments, types:'%s'", |
228 |
name,argc,selector_types[argc]); |
229 |
|
230 |
types = selector_types[argc]; |
231 |
} |
232 |
|
233 |
if(!types) |
234 |
{ |
235 |
[NSException raise:STInternalInconsistencyException |
236 |
format:@"Unable to construct types for selector '%s'", |
237 |
name]; |
238 |
return 0; |
239 |
} |
240 |
|
241 |
return [NSMethodSignature signatureWithObjCTypes:types]; |
242 |
} |
243 |
|
244 |
NSMethodSignature *STMethodSignatureForSelector(SEL sel) |
245 |
{ |
246 |
const char *types; |
247 |
|
248 |
NSLog(@"STMethodSignatureForSelector is deprecated."); |
249 |
|
250 |
types = sel_get_type(sel); |
251 |
|
252 |
if(!types) |
253 |
{ |
254 |
sel = STCreateTypedSelector(sel); |
255 |
types = sel_get_type(sel); |
256 |
} |
257 |
return [NSMethodSignature signatureWithObjCTypes:types]; |
258 |
} |
259 |
|
260 |
|
261 |
static NSArray *selectors_from_list(struct objc_method_list *methods) |
262 |
{ |
263 |
NSMutableArray *array = [NSMutableArray array]; |
264 |
int count = methods->method_count; |
265 |
int i; |
266 |
|
267 |
for(i=0;i<count;i++) |
268 |
{ |
269 |
[array addObject:NSStringFromSelector(methods->method_list[i].method_name)]; |
270 |
} |
271 |
|
272 |
if(methods->method_next) |
273 |
{ |
274 |
[array addObjectsFromArray:selectors_from_list(methods->method_next)]; |
275 |
} |
276 |
|
277 |
return array; |
278 |
} |
279 |
|
280 |
|
281 |
NSArray *STAllObjectiveCSelectors(void) |
282 |
{ |
283 |
NSMutableArray *array; |
284 |
NSArray *methods; |
285 |
Class class; |
286 |
void *state = 0; |
287 |
|
288 |
array = [[NSMutableArray alloc] init]; |
289 |
|
290 |
while( (class = objc_next_class(&state)) ) |
291 |
{ |
292 |
if(class->methods) |
293 |
{ |
294 |
methods = selectors_from_list(class->methods); |
295 |
[array addObjectsFromArray:methods]; |
296 |
} |
297 |
class = class->class_pointer; |
298 |
|
299 |
if(class->methods) |
300 |
{ |
301 |
methods = selectors_from_list(class->methods); |
302 |
[array addObjectsFromArray:methods]; |
303 |
} |
304 |
} |
305 |
|
306 |
/* get rid of duplicates */ |
307 |
array = (NSMutableArray *)[[NSSet setWithArray:(NSArray *)array] allObjects]; |
308 |
array = (NSMutableArray *)[array sortedArrayUsingSelector:@selector(compare:)]; |
309 |
|
310 |
return array; |
311 |
} |