Okay, y'all...the Ruamoko root class, Object, has been replaced with another

class with the same name. This will break things. To support it, there are
three new classes, one of which is incomplete (AutoreleasePool). It'll get
finished soonish, but the rest of the class lib will need some updating to
work.
This commit is contained in:
Jeff Teunissen 2003-07-29 18:02:03 +00:00
parent f2ad4dea7b
commit 7713a539ca
13 changed files with 579 additions and 227 deletions

View file

@ -31,6 +31,11 @@ integer deathmatch;
ent = [[GameEntity alloc] init];
self.bodies[i] = ent.ent;
}
#if 0
for (i = 0; i < MAX_BODIES; i++) {
self.bodies[i] = [[[GameEntity alloc] init] ent];
}
#endif
}
- (void) addEntity: (GameEntity)ent

View file

@ -0,0 +1,17 @@
#ifndef __ruamoko_AutoreleasePool_h
#define __ruamoko_AutoreleasePool_h
#include "Object.h"
@interface AutoreleasePool: Object
{
/*unsigned*/integer count;
id [] array;
}
+ (void) addObject: (id)anObject;
- (void) addObject: (id)anObject;
@end
#endif // __ruamoko_AutoreleasePool_h

View file

@ -0,0 +1,49 @@
/*
ListNode.h
Stack/Queue/Linked List node class definitions
Copyright (C) 2003 Jeff Teunissen <deek@quakeforge.net>
This file is part of the Ruamoko Standard Library.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __ruamoko_ListNode_h
#define __ruamoko_ListNode_h
#include "Object.h"
@interface ListNode: Object
{
ListNode nextNode;
id data;
}
+ (id) nodeWithObject: (id)anObject;
- (id) initWithObject: (id)anObject;
- (id) object;
- (id) nextNode;
- (void) setNextNode: (id)aNode;
@end
#endif // __ruamoko_ListNode_h

View file

@ -8,4 +8,5 @@ include_HEADERS= \
draw.h key.h \
\
cbuf.h cmd.h cvar.h file.h gib.h hash.h plist.h \
Object.h Array.h Entity.h InputLine.h List.h Point.h Rect.h Size.h
Object.h AutoreleasePool.h Array.h Entity.h List.h ListNode.h \
InputLine.h Point.h Rect.h Size.h

View file

@ -62,76 +62,89 @@ typedef enum {
@extern BOOL (id object) object_is_instance;
@extern BOOL (id object) object_is_meta_class;
@interface Object
@protocol Object // FIXME -- qfcc doesn't like calling this protocol "Object"!
- (Class) class;
- (Class) superclass;
- (BOOL) isEqual: (id)anObject;
- (BOOL) isKindOfClass: (Class)aClass;
- (BOOL) isMemberOfClass: (Class)aClass;
#if 0
- (BOOL) isProxy;
#endif // proxies
- (unsigned) hash;
- (id) self;
- (string) description;
- (id) performSelector: (SEL)aSelector;
- (id) performSelector: (SEL)aSelector
withObject: (id)anObject;
- (id) performSelector: (SEL)aSelector
withObject: (id)anObject
withObject: (id)anotherObject;
- (BOOL) respondsToSelector: (SEL)aSelector;
- (BOOL) conformsToProtocol: (Protocol)aProtocol;
- (id) retain;
#if 0
- (id) autorelease;
#endif // autorelease pools
- (/*oneway*/ void) release;
- (/*unsigned*/integer) retainCount;
@end
@protocol Copying
- copy;
@end
@protocol MutableCopying
- mutableCopy;
@end
@interface Object <Object>
{
Class isa;
Class isa;
integer retainCount;
}
+initialize;
-init;
+ (id) alloc;
+ (id) new;
+ (Class) class;
+ (string) description;
+ (void) initialize;
+ (IMP) instanceMethodForSelector: (SEL)aSelector;
#if 0
+ (MethodSignature) instanceMethodSignatureForSelector: (SEL)aSelector;
#endif // invocations
+ (BOOL) instancesRespondToSelector: (SEL)aSelector;
+ (BOOL) respondsToSelector: (SEL)aSelector;
+ (BOOL) conformsToProtocol: (Protocol)aProtocol;
+ (BOOL) isKindOfClass: (Class)aClass;
+ (void) poseAsClass: (Class)aClass;
+ (Class) superclass;
+new;
+alloc;
-free;
-copy;
-shallowCopy;
-deepen;
-deepCopy;
- (id) init;
- (void) dealloc;
- (void) doesNotRecognizeSelector: (SEL)aSelector;
#if 0
- (void) forwardInvocation: (Invocation)anInvocation;
#endif // invocations
#if 0
- (BOOL) isProxy;
#endif // proxies
- (IMP) methodForSelector: (SEL)aSelector;
#if 0
- (MethodSignature) methodSignatureForSelector: (SEL)aSelector;
#endif // invocations
-(Class)class;
-(Class)superClass;
-(Class)metaClass;
-(string)name;
- (id) copy;
- (id) mutableCopy;
-self;
-(integer)hash;
-(BOOL)isEqual:anObject;
-(integer)compare:anotherObject;
@end
-(BOOL)isMetaClass;
-(BOOL)isClass;
-(BOOL)isInstance;
@interface Object (error)
-(BOOL)isKindOf:(Class)aClassObject;
-(BOOL)isMemberOf:(Class)aClassObject;
-(BOOL)isKindOfClassNamed:(string)aClassName;
-(BOOL)isMemberOfClassNamed:(string)aClassName;
- (void) error: (string)formatString, ...;
+(BOOL)instancesRespondTo:(SEL)aSel;
-(BOOL)respondsTo:(SEL)aSel;
+(BOOL)conformsTo:(Protocol)aProtocol;
-(BOOL)conformsTo:(Protocol)aProtocol;
+(IMP)instanceMethodFor:(SEL)aSel;
-(IMP)methodFor:(SEL)aSel;
//+(struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel;
//-(struct objc_method_description *)descriptionForMethod:(SEL)aSel;
-perform:(SEL)aSel;
-perform:(SEL)aSel with:anObject;
-perform:(SEL)aSel with:anObject1 with:anObject2;
//-(retval_t)forward:(SEL)aSel :(arglist_t)argFrame;
//-(retval_t)performv:(SEL)aSel :(arglist_t)argFrame;
+poseAs:(Class)aClassObject;
-(Class)transmuteClassTo:(Class)aClassObject;
-subclassResponsibility:(SEL)aSel;
-notImplemented:(SEL)aSel;
-shouldNotImplement:(SEL)aSel;
-doesNotRecognize:(SEL)aSel;
-error:(string)aString, ...;
//+(integer)version;
//+setVersion:(integer)aVersion;
//+(integer)streamVersion: (TypedStream*)aStream;
//-read: (TypedStream*)aStream;
//-write: (TypedStream*)aStream;
//-awake;
@end
#endif //__ruamoko_Object_h

49
ruamoko/include/Stack.h Normal file
View file

@ -0,0 +1,49 @@
/*
Stack.h
Stack class definitions
Copyright (C) 2003 Jeff Teunissen <deek@quakeforge.net>
This file is part of the Ruamoko Standard Library.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifndef __ruamoko_Stack_h
#define __ruamoko_Stack_h
#include "Object.h"
@interface Stack: Object
{
id top; // Top of the stack
integer stackSize;
}
- (void) removeAllObjects; // Empty the stack
- (void) addObject: (id)anObject; // Push anObject onto the stack
- (id) pop; // pull top object off
- (id) peek; // Grab the top object without removing it
- (integer) count; // Number of objects on stack
@end
#endif // __ruamoko_Stack_h

View file

@ -22,4 +22,4 @@ typedef _hashtab_t [] hashtab_t;
@extern (void [][]) () Hash_GetList;
@extern void () Hash_Stats;
#endif __ruamoko_hash_h
#endif // __ruamoko_hash_h

View file

@ -0,0 +1,67 @@
#include "AutoreleasePool.h"
#include "Stack.h"
@static AutoreleasePool sharedInstance;
@static Stack poolStack;
@interface AutoreleasePool (Private)
- (void) addItem: (id)anItem;
@end
@implementation AutoreleasePool
- (id) init
{
if (!(self = [super init]))
return NIL;
if (!poolStack)
poolStack = [Stack new];
if (!sharedInstance)
sharedInstance = self;
}
+ (void) addObject: (id)anObject
{
}
- (void) addObject: (id)anObject
{
}
- (id) retain
{
[self error: "Don't send -retain to an autorelease pool."];
}
- (/*oneway*/ void) release
{
if (self == sharedInstance)
sharedInstance = NIL;
[self dealloc];
}
- (void) dealloc
{
local integer i;
local id tmp;
for (i = 0; i < ((AutoreleasePool) self).count; i++)
[((AutoreleasePool) self).array[i] release]; // FIXME
obj_free (((AutoreleasePool) self).array); // FIXME
/*
This may be wrong.
Releasing an autorelease pool should keep popping pools off the stack
until it gets to itself.
*/
do {
tmp = [poolStack pop];
} while (tmp != self);
[super dealloc];
}
@end

64
ruamoko/lib/ListNode.r Normal file
View file

@ -0,0 +1,64 @@
/*
ListNode.h
Stack/Queue/Linked List node class definitions
Copyright (C) 2003 Jeff Teunissen <deek@quakeforge.net>
This file is part of the Ruamoko Standard Library.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#include "Object.h"
#include "ListNode.h"
@implementation ListNode
+ (id) nodeWithObject: (id)anObject
{
return [[[self alloc] initWithObject: anObject] autorelease];
}
- (id) initWithObject: (id)anObject
{
if (!(self = [super init]))
return NIL;
data = [anObject retain];
nextNode = NIL;
}
- (void) dealloc
{
[((ListNode) self).data release]; // FIXME -- acrobatics shouldn't be needed
[super dealloc];
}
- (id) nextNode
{
return nextNode;
}
- (void) setNextNode: (id)aNode
{
nextNode = aNode;
}

View file

@ -30,7 +30,9 @@ libr_a_SOURCES=\
crudefile.r debug.r hash.r entities.r infokey.r math.r message.r \
nq_message.r physics.r plist.r qfile.r qw_message.r qw_physics.r qw_sys.r \
sound.r \
string.r system.r Object.r Array.r Entity.r List.r Point.r Size.r Rect.r
string.r system.r \
Object.r AutoreleasePool.r Array.r Entity.r List.r ListNode.r Point.r \
Rect.r Size.r Stack.r
libr_a_AR=$(PAK) -cf
libgui_a_SOURCES=\

View file

@ -1,4 +1,5 @@
#include "Object.h"
#include "AutoreleasePool.h"
void (obj_module_t [] msg) __obj_exec_class = #0;
void (id object, integer code, string fmt, ...) obj_error = #0;
@ -59,251 +60,258 @@ BOOL (id object) object_is_class = #0;
BOOL (id object) object_is_instance = #0;
BOOL (id object) object_is_meta_class = #0;
@implementation Object (error)
- (void) error: (string)aString, ... = #0;
@end
@implementation Object
+initialize
+ (void) initialize
{
return self;
#if 0
allocDebug = localinfo ("AllocDebug");
autoreleaseClass = [AutoreleasePool class];
autoreleaseSelector = @selector(addObject:);
autoreleaseIMP = [autoreleaseClass methodForSelector: autoreleaseSelector];
#endif
return;
}
-init
{
return self;
}
+new
{
return [[self alloc] init];
}
+alloc
+ (id) alloc
{
return class_create_instance (self);
}
-free
{
return object_dispose (self);
}
-copy
{
return [[self shallowCopy] deepen];
}
-shallowCopy
{
return object_copy (self);
}
-deepen
+ (Class) class
{
return self;
}
-deepCopy
+ (Class) superclass
{
return [self copy];
return class_get_super_class (self);
}
-(Class)class
+ (string) description
{
return class_get_class_name (self);
}
+ (id) new
{
return [[self alloc] init];
}
+ (BOOL) isKindOfClass: (Class)aClass
{
if (aClass == [Object class])
return YES;
return NO;
}
+ (BOOL) conformsToProtocol: (Protocol)aProtocol = #0;
+ (BOOL) instancesRespondToSelector: (SEL)aSelector
{
return class_get_instance_method (self, aSelector) != NIL;
}
+ (BOOL) respondsToSelector: (SEL)aSelector
{
return (class_get_class_method (self, aSelector) != NIL);
}
/*
Returns a pointer to the function providing the instance method that is
used to respond to messages with the selector held in aSelector.
*/
+ (IMP) instanceMethodForSelector: (SEL)aSelector
{
if (!aSelector)
return NIL;
return method_get_imp (class_get_instance_method (self, aSelector));
}
+ (void) poseAsClass: (Class)aClass
{
class_pose_as (self, aClass);
}
/*
INSTANCE METHODS
*/
- (id) init
{
retainCount = 1;
return self;
}
- (void) dealloc
{
object_dispose (self);
}
- (Class) class
{
return object_get_class (self);
}
-(Class)superClass
- (Class) superclass
{
return object_get_super_class (self);
}
-(Class)metaClass
{
return object_get_meta_class (self);
}
-(string)name
- (string) description
{
return object_get_class_name (self);
}
-self
- (id) self
{
return self;
}
-(integer)hash = #0; // can't cast pointer to integer
- (unsigned) hash = #0; // can't cast pointer to integer
-(BOOL)isEqual:anObject
- (BOOL) isEqual: (id)anObject
{
return self == anObject;
}
-(integer)compare:anotherObject = #0; // can only == or != pointers
-(BOOL)isMetaClass
- (BOOL) isKindOfClass: (Class)aClass
{
return NO;
}
local Class class;
-(BOOL)isClass
{
return object_is_class (self);
}
-(BOOL)isInstance
{
return object_is_instance (self);
}
-(BOOL)isKindOf:(Class)aClassObject
{
local Class class;
for (class = self.isa; class; class = class_get_super_class (class))
if (class == aClassObject)
for (class = [self class]; class; class = class_get_super_class (class))
if (class == aClass)
return YES;
return NO;
}
-(BOOL)isMemberOf:(Class)aClassObject
- (BOOL) isMemberOfClass: (Class)aClass
{
return self.isa == aClassObject;
return ([self class] == aClass);
}
-(BOOL)isKindOfClassNamed:(string)aClassName
- (BOOL) respondsToSelector: (SEL)aSelector
{
local Class class;
if (aClassName)
for (class = self.isa; class; class = class_get_super_class (class))
if (class_get_class_name (class) == aClassName)
return YES;
return NO;
return (class_get_instance_method ([self class], aSelector) != NIL);
}
-(BOOL)isMemberOfClassNamed:(string)aClassName
- (BOOL) conformsToProtocol: (Protocol)aProtocol
{
local Class class;
if (aClassName)
for (class = self.isa; class; class = class_get_super_class (class))
if (class_get_class_name (class) == aClassName)
return YES;
return aClassName && class_get_class_name (self.isa) == aClassName;
return [[self class] conformsToProtocol: aProtocol];
}
+(BOOL)instancesRespondTo:(SEL)aSel
/*
Returns a pointer to the function providing the method used to respond to
aSelector. If "self" is an instance, an instance method is returned. If
it's a class, a class method is returned.
*/
- (IMP) methodForSelector: (SEL)aSelector
{
return class_get_instance_method (self, aSel) != NIL;
}
local Class myClass = [self class];
-(BOOL)respondsTo:(SEL)aSel
{
return (object_is_instance (self)
? class_get_instance_method (self.isa, aSel)
: class_get_class_method (self.isa, aSel)) != NIL;
}
if (!aSelector)
return NIL;
+(BOOL)conformsTo:(Protocol)aProtocol = #0;
-(BOOL)conformsTo:(Protocol)aProtocol
{
return [[self class] conformsTo:aProtocol];
}
+(IMP)instanceMethodFor:(SEL)aSel
{
return method_get_imp (class_get_instance_method (self, aSel));
}
-(IMP)methodFor:(SEL)aSel
{
return method_get_imp (object_is_instance (self)
? class_get_instance_method (self.isa, aSel)
: class_get_class_method (self.isa, aSel));
? class_get_instance_method (myClass, aSelector)
: class_get_class_method (myClass, aSelector));
}
//+(struct objc_method_description *)descriptionForInstanceMethod:(SEL)aSel = #0;
//-(struct objc_method_description *)descriptionForMethod:(SEL)aSel = #0;
-perform:(SEL)aSel
- (id) performSelector: (SEL)aSelector
{
local IMP msg = obj_msg_lookup (self, aSel);
local IMP msg;
if (!msg)
return [self error:"invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSel);
if (!aSelector || !(msg = obj_msg_lookup (self, aSelector)))
return [self error: "invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSelector);
}
-perform:(SEL)aSel with:anObject
- (id) performSelector: (SEL)aSelector withObject: (id)anObject
{
local IMP msg = obj_msg_lookup (self, aSel);
local IMP msg;
if (!msg)
return [self error:"invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSel, anObject);
if (!aSelector || !(msg = obj_msg_lookup (self, aSelector)))
return [self error: "invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSelector, anObject);
}
-perform:(SEL)aSel with:anObject1 with:anObject2
- (id) performSelector: (SEL)aSelector
withObject: (id)anObject
withObject: (id)anotherObject
{
local IMP msg = obj_msg_lookup (self, aSel);
local IMP msg;
if (!msg)
return [self error:"invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSel, anObject1, anObject2);
if (!aSelector || !(msg = obj_msg_lookup (self, aSelector)))
return [self error: "invalid selector passed to %s",
sel_get_name (_cmd)];
return msg (self, aSelector, anObject, anotherObject);
}
//-(retval_t)forward:(SEL)aSel :(arglist_t)argFrame = #0;
//-(retval_t)performv:(SEL)aSel :(arglist_t)argFrame = #0;
+poseAs:(Class)aClassObject
- (void) doesNotRecognizeSelector: (SEL)aSelector
{
return class_pose_as (self, aClassObject);
[self error: "%s does not recognize %s",
object_get_class_name (self),
sel_get_name (aSelector)];
}
-(Class)transmuteClassTo:(Class)aClassObject
/*
MEMORY MANAGEMENT
These methods handle the manual garbage collection scheme.
*/
- (id) retain
{
if (object_is_instance (self))
if (class_is_class (aClassObject))
if (class_get_instance_size (aClassObject) == class_get_instance_size (isa))
if ([self isKindOf:aClassObject]) {
local Class old_isa = isa;
isa = aClassObject;
return old_isa;
}
return NIL;
retainCount = [self retainCount] + 1;
return self;
}
-subclassResponsibility:(SEL)aSel
- (/*oneway*/ void) release
{
return [self error:"subclass should override %s",
sel_get_name(aSel)];
if ([self retainCount] == 1) // don't let retain count actually reach zero
[self dealloc];
else
retainCount--;
}
-notImplemented:(SEL)aSel
- (id) autorelease
{
return [self error:"methos %s not implemented",
sel_get_name(aSel)];
}
-shouldNotImplement:(SEL)aSel
- (integer) retainCount
{
return [self error:"%s should not implement %s",
object_get_class_name (self), sel_get_name(aSel)];
return retainCount;
}
/*
CONVENIENCE METHODS
These methods exist only so that certain methods always work.
*/
- (id) copy
{
return self;
}
-doesNotRecognize:(SEL)aSel
- (id) mutableCopy
{
return [self error:"%s does not recognize %s",
object_get_class_name (self), sel_get_name(aSel)];
return self;
}
-error:(string)aString, ... = #0;
//+(integer)version = #0;
//+setVersion:(integer)aVersion = #0;
//+(integer)streamVersion: (TypedStream*)aStream = #0;
//-read: (TypedStream*)aStream = #0;
//-write: (TypedStream*)aStream = #0;
//-awake = #0;
@end

View file

@ -20,8 +20,8 @@
if (!self || !anOrigin || !aSize)
return NIL;
origin = [anOrigin copy];
size = [aSize copy];
origin = [anOrigin retain];
size = [aSize retain];
return self;
}
@ -64,9 +64,9 @@
return;
if (origin)
[origin free];
[origin release];
origin = [aPoint copy];
origin = [aPoint retain];
}
- (void) setSize: (Size)aSize
@ -75,9 +75,9 @@
return;
if (size)
[size free];
[size release];
size = [aSize copy];
size = [aSize retain];
}
- (void) setRect: (Rect)aRect

77
ruamoko/lib/Stack.r Normal file
View file

@ -0,0 +1,77 @@
/*
Stack.r
A general-purpose stack class
Copyright (C) 2003 Jeff Teunissen <deek@quakeforge.net>
This file is part of the Ruamoko Standard Library.
This library is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or (at
your option) any later version.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#include "Object.h"
#include "ListNode.h"
#include "Stack.h"
@implementation Stack
- (void) removeAllObjects
{
while ([self count] > 0)
[self pop];
}
- (void) addObject: (id)anObject
{
top = [[[ListNode alloc] initWithObject: anObject] setNextNode: top];
stackSize++;
}
- (id) pop
{
local id data;
local id oldTop = NIL;
if (!top)
return NIL;
oldTop = top;
top = [top next];
stackSize--;
data = [[oldTop object] retain];
[oldTop release];
return [data autorelease];
}
- (id) peek
{
return [top object];
}
- (integer) count
{
}
@end