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