]> git.saurik.com Git - apple/objc4.git/blob - runtime/Object.mm
objc4-750.tar.gz
[apple/objc4.git] / runtime / Object.mm
1 /*
2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23 /*
24 Object.m
25 Copyright 1988-1996 NeXT Software, Inc.
26 */
27
28 #include "objc-private.h"
29
30 #undef id
31 #undef Class
32
33 typedef struct objc_class *Class;
34 typedef struct objc_object *id;
35
36 #if __OBJC2__
37
38 @implementation Object
39
40 + (id)initialize
41 {
42 return self;
43 }
44
45 + (id)class
46 {
47 return self;
48 }
49
50 -(id) retain
51 {
52 return _objc_rootRetain(self);
53 }
54
55 -(void) release
56 {
57 _objc_rootRelease(self);
58 }
59
60 -(id) autorelease
61 {
62 return _objc_rootAutorelease(self);
63 }
64
65 +(id) retain
66 {
67 return self;
68 }
69
70 +(void) release
71 {
72 }
73
74 +(id) autorelease
75 {
76 return self;
77 }
78
79
80 @end
81
82
83 // __OBJC2__
84 #else
85 // not __OBJC2__
86
87 #include <stdlib.h>
88 #include <stdarg.h>
89 #include <string.h>
90 #include <malloc/malloc.h>
91
92 #include "Object.h"
93 #include "Protocol.h"
94 #include "objc-runtime.h"
95
96
97 // Error Messages
98 static const char
99 _errShouldHaveImp[] = "should have implemented the '%s' method.",
100 _errShouldNotImp[] = "should NOT have implemented the '%s' method.",
101 _errLeftUndone[] = "method '%s' not implemented",
102 _errBadSel[] = "method %s given invalid selector %s",
103 _errDoesntRecognize[] = "does not recognize selector %c%s";
104
105
106 @implementation Object
107
108
109 + (id)initialize
110 {
111 return self;
112 }
113
114 - (id)awake
115 {
116 return self;
117 }
118
119 + (id)poseAs: aFactory
120 {
121 return class_poseAs(self, aFactory);
122 }
123
124 + (id)new
125 {
126 id newObject = (*_alloc)((Class)self, 0);
127 Class metaClass = self->ISA();
128 if (class_getVersion(metaClass) > 1)
129 return [newObject init];
130 else
131 return newObject;
132 }
133
134 + (id)alloc
135 {
136 return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
137 }
138
139 + (id)allocFromZone:(void *) z
140 {
141 return (*_zoneAlloc)((Class)self, 0, z);
142 }
143
144 - (id)init
145 {
146 return self;
147 }
148
149 - (const char *)name
150 {
151 return class_getName(isa);
152 }
153
154 + (const char *)name
155 {
156 return class_getName((Class)self);
157 }
158
159 - (unsigned)hash
160 {
161 return (unsigned)(((uintptr_t)self) >> 2);
162 }
163
164 - (BOOL)isEqual:anObject
165 {
166 return anObject == self;
167 }
168
169 - (id)free
170 {
171 return (*_dealloc)(self);
172 }
173
174 + (id)free
175 {
176 return nil;
177 }
178
179 - (id)self
180 {
181 return self;
182 }
183
184
185 -(id)class
186 {
187 return (id)isa;
188 }
189
190 + (id)class
191 {
192 return self;
193 }
194
195 - (void *)zone
196 {
197 void *z = malloc_zone_from_ptr(self);
198 return z ? z : malloc_default_zone();
199 }
200
201 + (id)superclass
202 {
203 return self->superclass;
204 }
205
206 - (id)superclass
207 {
208 return isa->superclass;
209 }
210
211 + (int) version
212 {
213 return class_getVersion((Class)self);
214 }
215
216 + (id)setVersion: (int) aVersion
217 {
218 class_setVersion((Class)self, aVersion);
219 return self;
220 }
221
222 - (BOOL)isKindOf:aClass
223 {
224 Class cls;
225 for (cls = isa; cls; cls = cls->superclass)
226 if (cls == (Class)aClass)
227 return YES;
228 return NO;
229 }
230
231 - (BOOL)isMemberOf:aClass
232 {
233 return isa == (Class)aClass;
234 }
235
236 - (BOOL)isKindOfClassNamed:(const char *)aClassName
237 {
238 Class cls;
239 for (cls = isa; cls; cls = cls->superclass)
240 if (strcmp(aClassName, class_getName(cls)) == 0)
241 return YES;
242 return NO;
243 }
244
245 - (BOOL)isMemberOfClassNamed:(const char *)aClassName
246 {
247 return strcmp(aClassName, class_getName(isa)) == 0;
248 }
249
250 + (BOOL)instancesRespondTo:(SEL)aSelector
251 {
252 return class_respondsToMethod((Class)self, aSelector);
253 }
254
255 - (BOOL)respondsTo:(SEL)aSelector
256 {
257 return class_respondsToMethod(isa, aSelector);
258 }
259
260 - (id)copy
261 {
262 return [self copyFromZone: [self zone]];
263 }
264
265 - (id)copyFromZone:(void *)z
266 {
267 return (*_zoneCopy)(self, 0, z);
268 }
269
270 - (IMP)methodFor:(SEL)aSelector
271 {
272 return class_lookupMethod(isa, aSelector);
273 }
274
275 + (IMP)instanceMethodFor:(SEL)aSelector
276 {
277 return class_lookupMethod(self, aSelector);
278 }
279
280 - (id)perform:(SEL)aSelector
281 {
282 if (aSelector)
283 return ((id(*)(id, SEL))objc_msgSend)(self, aSelector);
284 else
285 return [self error:_errBadSel, sel_getName(_cmd), aSelector];
286 }
287
288 - (id)perform:(SEL)aSelector with:anObject
289 {
290 if (aSelector)
291 return ((id(*)(id, SEL, id))objc_msgSend)(self, aSelector, anObject);
292 else
293 return [self error:_errBadSel, sel_getName(_cmd), aSelector];
294 }
295
296 - (id)perform:(SEL)aSelector with:obj1 with:obj2
297 {
298 if (aSelector)
299 return ((id(*)(id, SEL, id, id))objc_msgSend)(self, aSelector, obj1, obj2);
300 else
301 return [self error:_errBadSel, sel_getName(_cmd), aSelector];
302 }
303
304 - (id)subclassResponsibility:(SEL)aSelector
305 {
306 return [self error:_errShouldHaveImp, sel_getName(aSelector)];
307 }
308
309 - (id)notImplemented:(SEL)aSelector
310 {
311 return [self error:_errLeftUndone, sel_getName(aSelector)];
312 }
313
314 - (id)doesNotRecognize:(SEL)aMessage
315 {
316 return [self error:_errDoesntRecognize,
317 class_isMetaClass(isa) ? '+' : '-', sel_getName(aMessage)];
318 }
319
320 - (id)error:(const char *)aCStr, ...
321 {
322 va_list ap;
323 va_start(ap,aCStr);
324 (*_error)(self, aCStr, ap);
325 _objc_error (self, aCStr, ap); /* In case (*_error)() returns. */
326 va_end(ap);
327 return nil;
328 }
329
330 - (void) printForDebugger:(void *)stream
331 {
332 }
333
334 - (id)write:(void *) stream
335 {
336 return self;
337 }
338
339 - (id)read:(void *) stream
340 {
341 return self;
342 }
343
344 - (id)forward: (SEL) sel : (marg_list) args
345 {
346 return [self doesNotRecognize: sel];
347 }
348
349 /* this method is not part of the published API */
350
351 - (unsigned)methodArgSize:(SEL)sel
352 {
353 Method method = class_getInstanceMethod((Class)isa, sel);
354 if (! method) return 0;
355 return method_getSizeOfArguments(method);
356 }
357
358 - (id)performv: (SEL) sel : (marg_list) args
359 {
360 unsigned size;
361
362 // Messages to nil object always return nil
363 if (! self) return nil;
364
365 // Calculate size of the marg_list from the method's
366 // signature. This looks for the method in self
367 // and its superclasses.
368 size = [self methodArgSize: sel];
369
370 // If neither self nor its superclasses implement
371 // it, forward the message because self might know
372 // someone who does. This is a "chained" forward...
373 if (! size) return [self forward: sel: args];
374
375 // Message self with the specified selector and arguments
376 return objc_msgSendv (self, sel, size, args);
377 }
378
379 /* Testing protocol conformance */
380
381 - (BOOL) conformsTo: (Protocol *)aProtocolObj
382 {
383 return [(id)isa conformsTo:aProtocolObj];
384 }
385
386 + (BOOL) conformsTo: (Protocol *)aProtocolObj
387 {
388 Class cls;
389 for (cls = self; cls; cls = cls->superclass)
390 {
391 if (class_conformsToProtocol(cls, aProtocolObj)) return YES;
392 }
393 return NO;
394 }
395
396
397 /* Looking up information for a method */
398
399 - (struct objc_method_description *) descriptionForMethod:(SEL)aSelector
400 {
401 Class cls;
402 struct objc_method_description *m;
403
404 /* Look in the protocols first. */
405 for (cls = isa; cls; cls = cls->superclass)
406 {
407 if (cls->ISA()->version >= 3)
408 {
409 struct objc_protocol_list *protocols =
410 (struct objc_protocol_list *)cls->protocols;
411
412 while (protocols)
413 {
414 int i;
415
416 for (i = 0; i < protocols->count; i++)
417 {
418 Protocol *p = protocols->list[i];
419
420 if (class_isMetaClass(cls))
421 m = [p descriptionForClassMethod:aSelector];
422 else
423 m = [p descriptionForInstanceMethod:aSelector];
424
425 if (m) {
426 return m;
427 }
428 }
429
430 if (cls->ISA()->version <= 4)
431 break;
432
433 protocols = protocols->next;
434 }
435 }
436 }
437
438 /* Then try the class implementations. */
439 for (cls = isa; cls; cls = cls->superclass) {
440 void *iterator = 0;
441 int i;
442 struct objc_method_list *mlist;
443 while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
444 for (i = 0; i < mlist->method_count; i++)
445 if (mlist->method_list[i].method_name == aSelector) {
446 m = (struct objc_method_description *)&mlist->method_list[i];
447 return m;
448 }
449 }
450 }
451 return 0;
452 }
453
454 + (struct objc_method_description *) descriptionForInstanceMethod:(SEL)aSelector
455 {
456 Class cls;
457
458 /* Look in the protocols first. */
459 for (cls = self; cls; cls = cls->superclass)
460 {
461 if (cls->ISA()->version >= 3)
462 {
463 struct objc_protocol_list *protocols =
464 (struct objc_protocol_list *)cls->protocols;
465
466 while (protocols)
467 {
468 int i;
469
470 for (i = 0; i < protocols->count; i++)
471 {
472 Protocol *p = protocols->list[i];
473 struct objc_method_description *m;
474
475 if ((m = [p descriptionForInstanceMethod:aSelector]))
476 return m;
477 }
478
479 if (cls->ISA()->version <= 4)
480 break;
481
482 protocols = protocols->next;
483 }
484 }
485 }
486
487 /* Then try the class implementations. */
488 for (cls = self; cls; cls = cls->superclass) {
489 void *iterator = 0;
490 int i;
491 struct objc_method_list *mlist;
492 while ( (mlist = class_nextMethodList( cls, &iterator )) ) {
493 for (i = 0; i < mlist->method_count; i++)
494 if (mlist->method_list[i].method_name == aSelector) {
495 struct objc_method_description *m;
496 m = (struct objc_method_description *)&mlist->method_list[i];
497 return m;
498 }
499 }
500 }
501 return 0;
502 }
503
504
505 /* Obsolete methods (for binary compatibility only). */
506
507 + (id)superClass
508 {
509 return [self superclass];
510 }
511
512 - (id)superClass
513 {
514 return [self superclass];
515 }
516
517 - (BOOL)isKindOfGivenName:(const char *)aClassName
518 {
519 return [self isKindOfClassNamed: aClassName];
520 }
521
522 - (BOOL)isMemberOfGivenName:(const char *)aClassName
523 {
524 return [self isMemberOfClassNamed: aClassName];
525 }
526
527 - (struct objc_method_description *) methodDescFor:(SEL)aSelector
528 {
529 return [self descriptionForMethod: aSelector];
530 }
531
532 + (struct objc_method_description *) instanceMethodDescFor:(SEL)aSelector
533 {
534 return [self descriptionForInstanceMethod: aSelector];
535 }
536
537 - (id)findClass:(const char *)aClassName
538 {
539 return objc_lookUpClass(aClassName);
540 }
541
542 - (id)shouldNotImplement:(SEL)aSelector
543 {
544 return [self error:_errShouldNotImp, sel_getName(aSelector)];
545 }
546
547
548 @end
549
550 #endif