/* fileio.c */
/* １行入出力の基本ルーチン データフォークへの読み書き*/
/* blastのプログラムで使用してテスト済み */
/* FileIO構造体は呼び出し側で実体を作っておくこと*/
#define FILEIO_SRC
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "fileio.h"

static void Str255cpy(unsigned char *dist, unsigned char *src);
static void Str255cat(unsigned char *dist, unsigned char *src);

int SetUpFileIO(short refnum, char perm, FileIO *fio)
{
	fio->refnum = refnum;
	fio->permission = perm;
	fio->pos = 0;
	fio->bsize = 256;		/* ここは、２５６以上なら大差ない */
	fio->rsize = 0;
	fio->buf = (char *)malloc(sizeof(char) * fio->bsize);
	if(fio->buf == NULL){
		return -1;
	}
	return 0;
}

/* FSCloseを呼んだあと、確保したメモリを開放する*/
/* write permissionが設定されているときは、バッファの中を書き込んだあとで */
/* 動作を行う */
int CloseFileIO(FileIO *fio)
{
	OSErr err;

	err = noErr;
	if(fio->permission == fsWrPerm || fio->permission == fsRdWrPerm 
		|| fio->permission == fsRdWrShPerm){
				/* fio_posは実際に書き込まれた領域の１つ先を指している */
				/* 従って、これをそのまま書き出しサイズとすることができる */
		err = FSWrite(fio->refnum, &(fio->pos), fio->buf); 
	}
	free(fio->buf);
	FSClose(fio->refnum);
	return err;
}

/* 改行コードまで、またはlengthで指定された文字数分読み込む */
/* *bufには改行を除去した文字列が返る */
int Read1Line(FileIO *fio, char *buf, long length)
{
	OSErr err;
	char c;
	long i;
	
	if(fio->rsize == 0){   /* まだファイルが読まれていない場合 */
		fio->rsize = fio->bsize;
		err = FSRead(fio->refnum, &(fio->rsize), fio->buf);
		/* error rcheck */
		if(err != noErr){
			if(err == eofErr){
				if(fio->rsize == 0){  /* 何も読まなかった */
					return err;
				}
			}
			else{
				return err;
			}
		}
	}	
	
	i = 0;
	while(i < length-1 ){
		c = *(fio->buf + fio->pos);	/* バッファからの１文字読み出し */
		fio->pos += 1;
		if(fio->pos > fio->rsize -1){	/* 読み込んだサイズを越えた*/
			if(fio->rsize == fio->bsize){	/* まだ全部読んでない可能性がある */
				fio->rsize = fio->bsize;
				err = FSRead(fio->refnum, &(fio->rsize), fio->buf); /* 再度読み込む */
				if(err != noErr){
					if(err == eofErr){		
						if(fio->rsize == 0){	/* ちょうどファイルの終わりだった */
							*(buf + i) = '\0';
							return eofErr;
						}
					}
					else{
						return err;
					}
				}
				/* 正常にいくらか読み込めた場合 */
				fio->pos = 0;	/* バッファ内のカレントポジション変更 */
			}
			else{/* 既に全部読んでいる場合 */
				if(c == CR){
					*(buf + i) = '\0';
					return eofErr;
				}
				else{
					*(buf + i) = c;
					*(buf + i + 1) = '\0';	/*  判定条件がlength-1なので、最後の\0分余裕がある*/
					return eofErr;
				}
			}
		}
		/* 通常の場合のcode check */
		if(c == CR){
			*(buf + i) = '\0';
			return noErr;
		}
		else{
			*(buf + i) = c;
			i++;
		}
	}

	/* 指定された文字数分読み込んだ */
	*(buf + i) = '\0';
	return noErr;
}
		
/* １行書き込み */
/* 改行コードもそのまま書き込む */
/* return error code */
int Write1Line(FileIO *fio, char *buf, long length)
{
	OSErr err;
	char c;
	long i;
	
	i = 0;
	while(i < length-1 ){
		c = *(buf + i);
		if(c == '\n'){		/* streamではないので、変換が必要だ */
			c = CR;
		}
		
		if(c == '\0'){		/* １行分書き出した */
			return noErr;
		}

		*(fio->buf + fio->pos) = c;	/* バッファに書き込む */
		fio->pos += 1;
		i++;

		if(fio->pos >= fio->bsize){	/* バッファがいっぱいになった */
			err = FSWrite(fio->refnum, &(fio->bsize), fio->buf);
			/* error check */
			if(err != noErr){
					return err;
			}
			fio->pos = 0;
		}
	}
	return noErr;
}

/* get date and time information of file */
short GetFileDateTime(FSSpec fss, DateTimeRec *MdDtr, DateTimeRec *CrDtr)
{
	CInfoPBRec cinfo;
	short err;
			
	cinfo.hFileInfo.ioCompletion = 0;
	cinfo.hFileInfo.ioNamePtr = fss.name;
	cinfo.hFileInfo.ioVRefNum = fss.vRefNum;
	cinfo.hFileInfo.ioFDirIndex = 0;
	cinfo.hFileInfo.ioDirID = fss.parID;
	//err = PBGetCatInfo(&cinfo, false);
	err = PBGetCatInfoSync(&cinfo);
	if(err) return err;
	
	SecondsToDate(cinfo.hFileInfo.ioFlMdDat, MdDtr);
	SecondsToDate(cinfo.hFileInfo.ioFlCrDat, CrDtr);
	
	return err;
}

short GetPathName(FSSpec fss, char *path)
{
	CInfoPBRec cinfo;
	Str255 dirName, fullpath;
	short err;
	
	fullpath[0] = 0;
	
	cinfo.hFileInfo.ioNamePtr = dirName;
	cinfo.hFileInfo.ioVRefNum = fss.vRefNum;
	cinfo.hFileInfo.ioFlParID = fss.parID;
	cinfo.hFileInfo.ioFDirIndex = -1;
	
	do{
		cinfo.hFileInfo.ioDirID = cinfo.hFileInfo.ioFlParID;
		//err = PBGetCatInfo(&cinfo, false);
		err = PBGetCatInfoSync(&cinfo);
		Str255cat(dirName, (unsigned char *)"\p:");
		Str255cat(dirName, fullpath);
		Str255cpy(fullpath, dirName);
	}while(cinfo.hFileInfo.ioDirID != fsRtDirID);
	
	strcpy(path, PtoCstr(fullpath));
	
	return 0;
}

static void Str255cpy(unsigned char *dist, unsigned char *src)
{
	short i;
	
	for(i = 0 ; i <= src[0] ; i++){
		dist[i] = src[i];
	}
}

static void Str255cat(unsigned char *dist, unsigned char *src)
{
	short i;

	for(i = 1 ; i <= src[0] ; i++){
		dist[dist[0] + i] = src[i];
	}
	dist[0] += src[0];
}
 