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 33typedef struct objc_class *Class; 34typedef struct objc_object *id; 35 36#if __OBJC2__ 37 38__OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_NA) 39OBJC_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 106static 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 559