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