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