/***** TranscriptManager.m -- recording/archiving object implementation
	NeXTstep Measurement Kit
	by Alex Meyer <ameyer@phoenix.Princeton.EDU>
	for computer science senior thesis
	16 April 1992 -- created
	21 April 1992 -- provided clean interface for cycles of setFile/close
*****/

#import <stdlib.h>
#import <string.h>
#import <objc/typedstream.h>
#import <objc/Storage.h>
#import "TranscriptManager.h"

@implementation TranscriptManager

- init
{
	storage = [Storage alloc];
	[storage initCount:0
		elementSize:sizeof(tmRec)
		description:NULL];
	fileValid = NO;
	return (self);
}


- free
{
	[self close];
	[storage free];
	[super free];
	return (nil);
}


- setFile:(NXAtom)fName
{
	fileValid = YES;
	fileName = fName;
	return (self);
}


- close
{
	unsigned i,num;

	num = [storage count];
	for (i = 0;i < num;++i) {
		tmPtr ptr;

		ptr = (tmPtr) [storage elementAt:i];
		free(ptr->Stats);
	}
	[storage empty];
	fileValid = NO;
	return (self);
}


- load
{
	NXTypedStream *stream;

	if (!(fileValid))
		return (nil);
	stream = NXOpenTypedStreamForFile(fileName,NX_READONLY);
	if (stream) {
		unsigned i,num;

		NXReadType(stream,"i",&num);
		for (i = 0;i < num;++i) {
			tmRec rec;

			NXReadType(stream,"i",&rec.type);
			NXReadType(stream,"%",&rec.key);
			NXReadType(stream,"%",&rec.desc);
			NXReadType(stream,"i",&rec.statsSize);
			rec.Stats = malloc(rec.statsSize);
			NXReadType(stream,rec.desc,rec.Stats);
			[storage addElement:&rec];
		}
		NXCloseTypedStream(stream);
		return (self);
	}
	return (nil);
}


- save
{
	NXTypedStream *stream;

	if (!(fileValid))
		return (nil);
	stream = NXOpenTypedStreamForFile(fileName,NX_WRITEONLY);
	if (stream) {
		unsigned i,num;

		num = [storage count];
		NXWriteType(stream,"i",&num);
		for (i = 0;i < num;++i) {
			tmPtr ptr;

			ptr = (tmPtr) [storage elementAt:i];
			NXWriteType(stream,"i",&ptr->type);
			NXWriteType(stream,"%",&ptr->key);
			NXWriteType(stream,"%",&ptr->desc);
			NXWriteType(stream,"i",&ptr->statsSize);
			NXWriteType(stream,ptr->desc,ptr->Stats);
		}
		NXCloseTypedStream(stream);
		return (self);
	}
	return (nil);
}


- (unsigned)addRecord:(tmPtr)rec
{
	[storage addElement:rec];
	return ([storage count] - 1);
}


- (unsigned)numRecords
{
	return ([storage count]);
}


- copyRecordIndex:(unsigned)ind
	into:(tmPtr)dst;
{
	tmPtr ptr;

	ptr = (tmPtr) [storage elementAt:ind];
	memcpy(dst,ptr,sizeof(*dst));
	return (self);
}


- copyRecordKey:(NXAtom)key
	ofType:(unsigned)type
	into:(tmPtr)dst
	where:(unsigned *)Ind
{
	unsigned i,num;
	tmPtr ptr;

	num = [storage count];
	for (i = 0;i < num;++i) {
		ptr = (tmPtr) [storage elementAt:i];
		if ((ptr->key == key) && (ptr->type == type))
			break;
	}
	if (i < num) {
		memcpy(dst,ptr,sizeof(*dst));
		*Ind = i;
		return (self);
	}
	return (nil);
}


- (BOOL)findIndex:(unsigned *)Ind
	ofKey:(NXAtom)key
	andType:(unsigned)type
{
	unsigned i,num;
	tmPtr ptr;

	num = [storage count];
	for (i = 0;i < num;++i) {
		ptr = (tmPtr) [storage elementAt:i];
		if ((ptr->key == key) && (ptr->type == type)) {
			*Ind = i;
			return (YES);
		}
	}
	return (NO);
}


- copyIndex:(unsigned)ind
	statsFrom:(void *)Stats
{
	tmPtr ptr;

	ptr = (tmPtr) [storage elementAt:ind];
	if (ptr->Stats)
		free(ptr->Stats);
	ptr->Stats = malloc(ptr->statsSize);
	memcpy(ptr->Stats,Stats,ptr->statsSize);
	return (self);
}

@end
