#import "List_Archival.h"

#import <appkit/appkit.h>
#import <objc/objc-runtime.h>

@implementation List(Archival)
static inline char *ClassName() { return "List"; }
static inline long ArchiveVersion()
{
long version;
	version = 1000 * LIST_VERS + 10 * LIST_SUBVERS + LIST_TYPE;
	return version;
}

- (const char *) name
{
	return "List";
}

- initFromTStream:(NXTypedStream *) stream
{
	[self initCount: 0];
	return [self readFromTStream: stream];
}

- readFromTStream:(NXTypedStream *) stream
{
long version;
int objCount;
Class objClass;
Object <ObjectArchival> *obj;
const char *objsClassName, *className;
void *data1 = NULL, *data2 = NULL;

NX_DURING
[self debug: SUPER_DEBUG method: _cmd, "class = %s; superclass = %s\n",
	[[self class] name], [[self superclass] name]];
[self debug: SUPER_DEBUG method: _cmd, "\tinstance = %s\n", ClassName()];

	/* Read the object class name & version */
	NXReadTypes(stream, "*i", &className, &version);
	if( strcmp(className, ClassName()) != 0 )
	{
		NXAllocErrorData(strlen(className)+1, &data1);
		NXAllocErrorData(strlen(ClassName())+1, &data2);
		strcpy(data1, className);
		strcpy(data2, ClassName());
		NX_RAISE(eWrongClassName, data1, data2);
	}

	/* Unarchive this version format */
	switch( version )
	{
		case LIST_VERSION_0:
			NXReadType(stream, "i", &objCount);
			if( objCount <= 0 )
			{
				[self free];
				return nil;
			}
			/* Determine the class of the archived objects */
			NXReadType(stream, "*", &objsClassName);
			objClass = objc_lookUpClass(objsClassName);
			NXAllocErrorData(strlen(objsClassName)+1, &data1);
			strcpy(data1, objsClassName);
			if( objClass == nil )
				NX_RAISE(eUnknownArchiveClass, data1, NULL);
			/* Make sure this class conforms to the ObjectArchival protocol */
			if( [objClass conformsTo:@protocol(ObjectArchival)] == NO )
				NX_RAISE(eNonconformingClass, data1, NULL);
		
			/* Read in the list's objects */
			while( numElements < objCount )
			{
				obj = [[objClass alloc] initFromTStream: stream];
				if( obj == nil )
					NX_RAISE(eObjReadErr, data1, NULL);
				[self addObject: obj];
			}
			break;

		default:
			NXAllocErrorData(strlen([[self class] name])+1, &data1);
			NXAllocErrorData(sizeof(long), &data2);
			strcpy(data1, [[self class] name]);
			*((long *) data2) = version;
			NX_RAISE(eBadObjVersion, data1, data2);
			break;
	}
NX_HANDLER
	NX_RERAISE();
NX_ENDHANDLER

	return self;
}

- writeToTStream:(NXTypedStream *) stream
{
long version;
int element;
id <ObjectArchival> obj;
const char *objsClassName, *className;

NX_DURING
[self debug: SUPER_DEBUG method: _cmd, "class = %s; superclass = %s\n",
	[[self class] name], [[self superclass] name]];
[self debug: SUPER_DEBUG method: _cmd, "\tinstance = %s\n", ClassName()];

	/* First write the class name & version */
	className = ClassName();
	version = ArchiveVersion();
	NXWriteTypes(stream, "*i", &className, &version);

	NXWriteType(stream, "i", &numElements);
	/* Write the class name of the archived objects */
	objsClassName = [[[self objectAt: 0] class] name];
	NXWriteType(stream, "*", &objsClassName);
	/* Write out the list's objects */
	element = 0;
	while( element < numElements )
	{
		obj = [self objectAt: element ++];
		[obj writeToTStream: stream];
	}
NX_HANDLER
	NX_RERAISE();
NX_ENDHANDLER

	return self;
}
@end
/* RCS Information:
	$Author: me $;
	$Date: 93/02/23 02:00:43 $;
	$Source: /usr1/me/NeXTSrc/MyClasses/RCS/List_Archival.m,v $;
	$Revision: 1.1 $;
	$Log:	List_Archival.m,v $
Revision 1.1  93/02/23  02:00:43  me
Begin RCS logging.
;
*/
