/* Copyright 2003  Alexander V. Diemand

    This file is part of MolTalk.

    MolTalk is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    MolTalk 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with MolTalk; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
 */
 
/* vim: set filetype=objc: */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "FileStream.oh"
#include "String.oh"


@implementation FileStream


-(id)init	//@nodoc
{
	[super init];
	fstream = NULL;
	return self;
}

-(void)dealloc	//@nodoc
{
	if (fstream)
	{
		fclose(fstream);
		fstream = NULL;
	}
	[super dealloc];
}


/*
 *   returns TRUE if stream is not at the end
 */
-(BOOL)ok
{
	if (!fstream)
	{
		return NO;
	} else {
		return !feof(fstream);
	}
}


/*
 *   close this stream
 */
-(void)close
{
	if (fstream)
	{
		fclose(fstream);
		fstream = NULL;
	}
}


/*
 *   read a line from stream up to /len/ length
 */
-(char*)getsBuffer:(char*)buffer len:(int)len
{
	if (!fstream)
	{
		return NULL;
	}
	return fgets(buffer,len+1,fstream);
}


/*
 *   write /buffer/ to stream
 */
-(int)writeBuffer:(char*)buffer len:(int)len
{
	if (!fstream)
	{
		return 0;
	}
	return fwrite(buffer,1,len,fstream);
}


/*
 *   read into /buffer/ up to /len/ length
 */
-(int)readBuffer:(char*)buffer len:(int)len
{
	if (!fstream)
	{
		return 0;
	}
	return fread(buffer,1,len,fstream);
}


/*
 *   write data to stream
 */
-(void)writeData:(NSData*)data
{
	if (!fstream)
	{
		return;
	}
	unsigned int len = [data length];
	unsigned int written = 0;
	while (written < len)
	{
		written += [self writeBuffer:(char*)([data bytes]+written) len:(len-written)];
	}
}


/*
 *   write a string to the stream
 */
-(void)writeString:(NSString*)string
{
	[self writeData: [string data]];
}


/*
 *   write a C string (/const char * /) to the stream
 */
-(void)writeCString:(const char*)string
{
	unsigned int len=strlen(string);
	[self writeData: [NSData dataWithBytes: string length: len]]; 
}


/*
 *   read data from stream up to /len/ length
 */
-(NSData*)readLength:(unsigned int)len
{
	if (!fstream)
	{
		return nil;
	}
	char *buffer = (char*)malloc(len);
	unsigned int bytesread = 0;
	while (bytesread < len)
	{
		bytesread += [self readBuffer:buffer len:len];
		if (![self ok])
		{
			break;
		}
	}
	return [NSData dataWithBytesNoCopy: buffer length: bytesread];
}


/*
 *   read line up to /len/ length
 */
-(NSData*)readLineLength:(unsigned int)len
{
	if (!fstream)
	{
		return nil;
	}
	char *buffer = (char*)malloc(len+3);
	buffer[len+2]='\0';
	if ([self getsBuffer:buffer len:(len+1)] != NULL)
	{
		unsigned int reallength;
		reallength = strlen(buffer);
		return [NSData dataWithBytesNoCopy: buffer length: reallength];
	}
	return nil;
}


/*
 *   read line up to /len/ length and return in string
 */
-(NSString*)readStringLineLength:(unsigned int)len
{
	if (!fstream)
	{
		return nil;
	}
	char buffer[8194];
	if (len>8192)
	{
		len=8192;
	}
	buffer[len+2]='\0';
	if ([self getsBuffer:buffer len:(len+1)] != NULL)
	{
		return [NSString stringWithCString: buffer];
	}
	return nil;
}

#ifdef SAFEENV
+(id)streamSafeFromFile:(NSString*)t_path
{
        NSString *p_path = [NSString stringWithFormat: @"tempfiles/%@",[t_path lastPathComponent]];
        //printf("FileStream_streamSafeFromFile: %s\n",[p_path cString]);
        return [self streamFromFile: p_path];
}
#endif

/*
 *   create a stream from a file in readonly mode
 */
+(id)streamFromFile:(NSString*)path;
{
	FileStream *fs = [FileStream new];
#ifdef WIN32
	fs->fstream = fopen([path cString], "rb");
#else
	fs->fstream = fopen([path cString], "r");
#endif
	return fs;
}

#ifdef SAFEENV
+(id)streamSafeToFile:(NSString*)t_path
{
        NSString *p_path = [NSString stringWithFormat: @"tempfiles/%@",[t_path lastPathComponent]];
        //printf("FileStream_streamSafeToFile: %s\n",[p_path cString]);
        return [self streamToFile: p_path];
}
#endif

/*
 *   create a stream from a file in writeonly mode
 */
+(id)streamToFile:(NSString*)path;
{
	FileStream *fs = [FileStream new];
#ifdef WIN32
	fs->fstream = fopen([path cString], "wb");
#else
	fs->fstream = fopen([path cString], "w");
#endif
	return fs;
}

#ifdef SAFEENV
+(id)streamSafeAppendToFile:(NSString*)t_path
{
        NSString *p_path = [NSString stringWithFormat: @"tempfiles/%@",[t_path lastPathComponent]];
        //printf("FileStream_streamSafeToFile: %s\n",[p_path cString]);
        return [self streamAppendToFile: p_path];
}
#endif

/*
 *   create a stream from a file in append mode
 */
+(id)streamAppendToFile:(NSString*)path;
{
	FileStream *fs = [FileStream new];
#ifdef WIN32
	fs->fstream = fopen([path cString], "ab");
#else
	fs->fstream = fopen([path cString], "a");
#endif
	return fs;
}


@end

