Home | History | Annotate | Line # | Download | only in libobjc
Object.m revision 1.1
      1 /* The implementation of class Object for Objective-C.
      2    Copyright (C) 1993, 1994, 1995, 1997, 2002, 2009 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify it
      7 under the terms of the GNU General Public License as published by the
      8 Free Software Foundation; either version 3, or (at your option) any
      9 later version.
     10 
     11 GCC is distributed in the hope that it will be useful, but WITHOUT
     12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     14 License for more details.
     15 
     16 Under Section 7 of GPL version 3, you are granted additional
     17 permissions described in the GCC Runtime Library Exception, version
     18 3.1, as published by the Free Software Foundation.
     19 
     20 You should have received a copy of the GNU General Public License and
     21 a copy of the GCC Runtime Library Exception along with this program;
     22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 <http://www.gnu.org/licenses/>.  */
     24 
     25 #include <stdarg.h>
     26 #include <errno.h>
     27 #include "objc/Object.h"
     28 #include "objc/Protocol.h"
     29 #include "objc/objc-api.h"
     30 
     31 #define MAX_CLASS_NAME_LEN 256
     32 
     33 @implementation Object
     34 
     35 + initialize
     36 {
     37   return self;
     38 }
     39 
     40 - init
     41 {
     42   return self;
     43 }
     44 
     45 + new
     46 {
     47   return [[self alloc] init];
     48 }
     49 
     50 + alloc
     51 {
     52   return class_create_instance(self);
     53 }
     54 
     55 - free
     56 {
     57   return object_dispose(self);
     58 }
     59 
     60 - copy
     61 {
     62   return [[self shallowCopy] deepen];
     63 }
     64 
     65 - shallowCopy
     66 {
     67   return object_copy(self);
     68 }
     69 
     70 - deepen
     71 {
     72   return self;
     73 }
     74 
     75 - deepCopy
     76 {
     77   return [self copy];
     78 }
     79 
     80 - (Class)class
     81 {
     82   return object_get_class(self);
     83 }
     84 
     85 - (Class)superClass
     86 {
     87   return object_get_super_class(self);
     88 }
     89 
     90 - (MetaClass)metaClass
     91 {
     92   return object_get_meta_class(self);
     93 }
     94 
     95 - (const char *)name
     96 {
     97   return object_get_class_name(self);
     98 }
     99 
    100 - self
    101 {
    102   return self;
    103 }
    104 
    105 - (unsigned int)hash
    106 {
    107   return (size_t)self;
    108 }
    109 
    110 - (BOOL)isEqual:anObject
    111 {
    112   return self==anObject;
    113 }
    114 
    115 - (int)compare:(id)anotherObject;
    116 {
    117   if ([self isEqual:anotherObject])
    118     return 0;
    119   // Ordering objects by their address is pretty useless,
    120   // so subclasses should override this is some useful way.
    121   else if ((id)self > anotherObject)
    122     return 1;
    123   else
    124     return -1;
    125 }
    126 
    127 - (BOOL)isMetaClass
    128 {
    129   return NO;
    130 }
    131 
    132 - (BOOL)isClass
    133 {
    134   return object_is_class(self);
    135 }
    136 
    137 - (BOOL)isInstance
    138 {
    139   return object_is_instance(self);
    140 }
    141 
    142 - (BOOL)isKindOf:(Class)aClassObject
    143 {
    144   Class class;
    145 
    146   for (class = self->isa; class!=Nil; class = class_get_super_class(class))
    147     if (class==aClassObject)
    148       return YES;
    149   return NO;
    150 }
    151 
    152 - (BOOL)isMemberOf:(Class)aClassObject
    153 {
    154   return self->isa==aClassObject;
    155 }
    156 
    157 - (BOOL)isKindOfClassNamed:(const char *)aClassName
    158 {
    159   Class class;
    160 
    161   if (aClassName!=NULL)
    162     for (class = self->isa; class!=Nil; class = class_get_super_class(class))
    163       if (!strcmp(class_get_class_name(class), aClassName))
    164         return YES;
    165   return NO;
    166 }
    167 
    168 - (BOOL)isMemberOfClassNamed:(const char *)aClassName
    169 {
    170   return ((aClassName!=NULL)
    171           &&!strcmp(class_get_class_name(self->isa), aClassName));
    172 }
    173 
    174 + (BOOL)instancesRespondTo:(SEL)aSel
    175 {
    176   return class_get_instance_method(self, aSel)!=METHOD_NULL;
    177 }
    178 
    179 - (BOOL)respondsTo:(SEL)aSel
    180 {
    181   return ((object_is_instance(self)
    182            ?class_get_instance_method(self->isa, aSel)
    183            :class_get_class_method(self->isa, aSel))!=METHOD_NULL);
    184 }
    185 
    186 + (IMP)instanceMethodFor:(SEL)aSel
    187 {
    188   return method_get_imp(class_get_instance_method(self, aSel));
    189 }
    190 
    191 // Indicates if the receiving class or instance conforms to the given protocol
    192 // not usually overridden by subclasses
    193 //
    194 // Modified 9/5/94 to always search the class object's protocol list, rather
    195 // than the meta class.
    196 
    197 + (BOOL) conformsTo: (Protocol*)aProtocol
    198 {
    199   size_t i;
    200   struct objc_protocol_list* proto_list;
    201   id parent;
    202 
    203   for (proto_list = ((Class)self)->protocols;
    204        proto_list; proto_list = proto_list->next)
    205     {
    206       for (i=0; i < proto_list->count; i++)
    207       {
    208         if ([proto_list->list[i] conformsTo: aProtocol])
    209           return YES;
    210       }
    211     }
    212 
    213   if ((parent = [self superClass]))
    214     return [parent conformsTo: aProtocol];
    215   else
    216     return NO;
    217 }
    218 
    219 - (BOOL) conformsTo: (Protocol*)aProtocol
    220 {
    221   return [[self class] conformsTo:aProtocol];
    222 }
    223 
    224 - (IMP)methodFor:(SEL)aSel
    225 {
    226   return (method_get_imp(object_is_instance(self)
    227                          ?class_get_instance_method(self->isa, aSel)
    228                          :class_get_class_method(self->isa, aSel)));
    229 }
    230 
    231 + (struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel
    232 {
    233   return ((struct objc_method_description *)
    234            class_get_instance_method(self, aSel));
    235 }
    236 
    237 - (struct objc_method_description *)descriptionForMethod:(SEL)aSel
    238 {
    239   return ((struct objc_method_description *)
    240            (object_is_instance(self)
    241             ?class_get_instance_method(self->isa, aSel)
    242             :class_get_class_method(self->isa, aSel)));
    243 }
    244 
    245 - perform:(SEL)aSel
    246 {
    247   IMP msg = objc_msg_lookup(self, aSel);
    248   if (!msg)
    249     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
    250   return (*msg)(self, aSel);
    251 }
    252 
    253 - perform:(SEL)aSel with:anObject
    254 {
    255   IMP msg = objc_msg_lookup(self, aSel);
    256   if (!msg)
    257     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
    258   return (*msg)(self, aSel, anObject);
    259 }
    260 
    261 - perform:(SEL)aSel with:anObject1 with:anObject2
    262 {
    263   IMP msg = objc_msg_lookup(self, aSel);
    264   if (!msg)
    265     return [self error:"invalid selector passed to %s", sel_get_name(_cmd)];
    266   return (*msg)(self, aSel, anObject1, anObject2);
    267 }
    268 
    269 - (retval_t)forward:(SEL)aSel :(arglist_t)argFrame
    270 {
    271   (void) argFrame; /* UNUSED */
    272   return (retval_t)[self doesNotRecognize: aSel];
    273 }
    274 
    275 - (retval_t)performv:(SEL)aSel :(arglist_t)argFrame
    276 {
    277   return objc_msg_sendv(self, aSel, argFrame);
    278 }
    279 
    280 + poseAs:(Class)aClassObject
    281 {
    282   return class_pose_as(self, aClassObject);
    283 }
    284 
    285 - (Class)transmuteClassTo:(Class)aClassObject
    286 {
    287   if (object_is_instance(self))
    288     if (class_is_class(aClassObject))
    289       if (class_get_instance_size(aClassObject)==class_get_instance_size(isa))
    290         if ([self isKindOf:aClassObject])
    291           {
    292             Class old_isa = isa;
    293             isa = aClassObject;
    294             return old_isa;
    295           }
    296   return nil;
    297 }
    298 
    299 - subclassResponsibility:(SEL)aSel
    300 {
    301   return [self error:"subclass should override %s", sel_get_name(aSel)];
    302 }
    303 
    304 - notImplemented:(SEL)aSel
    305 {
    306   return [self error:"method %s not implemented", sel_get_name(aSel)];
    307 }
    308 
    309 - shouldNotImplement:(SEL)aSel
    310 {
    311   return [self error:"%s should not implement %s",
    312 	             object_get_class_name(self), sel_get_name(aSel)];
    313 }
    314 
    315 - doesNotRecognize:(SEL)aSel
    316 {
    317   return [self error:"%s does not recognize %s",
    318                      object_get_class_name(self), sel_get_name(aSel)];
    319 }
    320 
    321 - error:(const char *)aString, ...
    322 {
    323 #define FMT "error: %s (%s)\n%s\n"
    324   char fmt[(strlen((char*)FMT)+strlen((char*)object_get_class_name(self))
    325             +((aString!=NULL)?strlen((char*)aString):0)+8)];
    326   va_list ap;
    327 
    328   sprintf(fmt, FMT, object_get_class_name(self),
    329                     object_is_instance(self)?"instance":"class",
    330                     (aString!=NULL)?aString:"");
    331   va_start(ap, aString);
    332   objc_verror(self, OBJC_ERR_UNKNOWN, fmt, ap);
    333   va_end(ap);
    334   return nil;
    335 #undef FMT
    336 }
    337 
    338 + (int)version
    339 {
    340   return class_get_version(self);
    341 }
    342 
    343 + setVersion:(int)aVersion
    344 {
    345   class_set_version(self, aVersion);
    346   return self;
    347 }
    348 
    349 + (int)streamVersion: (TypedStream*)aStream
    350 {
    351   if (aStream->mode == OBJC_READONLY)
    352     return objc_get_stream_class_version (aStream, self);
    353   else
    354     return class_get_version (self);
    355 }
    356 
    357 // These are used to write or read the instance variables
    358 // declared in this particular part of the object.  Subclasses
    359 // should extend these, by calling [super read/write: aStream]
    360 // before doing their own archiving.  These methods are private, in
    361 // the sense that they should only be called from subclasses.
    362 
    363 - read: (TypedStream*)aStream
    364 {
    365   (void) aStream; /* UNUSED */
    366   // [super read: aStream];
    367   return self;
    368 }
    369 
    370 - write: (TypedStream*)aStream
    371 {
    372   (void) aStream; /* UNUSED */
    373   // [super write: aStream];
    374   return self;
    375 }
    376 
    377 - awake
    378 {
    379   // [super awake];
    380   return self;
    381 }
    382 
    383 @end
    384