File:  [RetroPC.NET] / np2 / common / textfile.c
Revision 1.7: download - view: text, annotated - select for diffs
Sun Mar 20 15:09:16 2005 JST (20 years, 7 months ago) by yui
Branches: MAIN
CVS tags: HEAD
fix support UCS2 (T.Yui)

#include	"compiler.h"
#include	"strres.h"
#include	"dosio.h"
#include	"textfile.h"


enum {
	TFMODE_READ		= 0x01,
	TFMODE_WRITE	= 0x02
};

typedef struct {
	UINT8	mode;
	UINT8	access;
	UINT8	srcwidth;
	UINT8	xendian;
	FILEH	fh;
	long	fpos;
	void	*buf;
	UINT	bufsize;
	UINT	bufpos;
	UINT	bufrem;
} _TEXTFILE, *TEXTFILE;


static TEXTFILEH registfile(FILEH fh, UINT buffersize,
											const UINT8 *hdr, UINT hdrsize) {

	long		fpos;
	UINT8		srcwidth;
	UINT8		xendian;
	TEXTFILE	ret;

	buffersize = buffersize & (~3);
	if (buffersize < 256) {
		buffersize = 256;
	}
	fpos = 0;
	srcwidth = 1;
	xendian = FALSE;
	if ((hdrsize >= 3) &&
		(hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) {
		// UTF-8
		fpos = 3;
	}
	else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) {
		// UCSLE
		fpos = 2;
		srcwidth = 2;
#if defined(BYTESEX_BIG)
		xendian = TRUE;
#endif
	}
	else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) {
		// UCS2BE
		fpos = 2;
		srcwidth = 2;
#if defined(BYTESEX_LITTLE)
		xendian = TRUE;
#endif
	}

	if (srcwidth != sizeof(OEMCHAR)) {
		return(NULL);
	}
	buffersize = buffersize * sizeof(OEMCHAR);

	ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize, "TEXTFILE");
	if (ret == NULL) {
		return(NULL);
	}
	ZeroMemory(ret, sizeof(_TEXTFILE));
//	ret->mode = 0;
	ret->srcwidth = srcwidth;
	ret->xendian = xendian;
	ret->fh = fh;
	ret->fpos = fpos;
	ret->buf = (UINT8 *)(ret + 1);
	ret->bufsize = buffersize;
	return((TEXTFILEH)ret);
}

static BRESULT flushfile(TEXTFILE tf) {

	if (tf->mode & TFMODE_READ) {
		tf->fpos -= tf->bufrem * tf->srcwidth;
	}
	tf->mode = 0;
	tf->bufpos = 0;
	tf->bufrem = 0;
	if (file_seek(tf->fh, tf->fpos, FSEEK_SET) == tf->fpos) {
		return(SUCCESS);
	}
	else {
		return(FAILURE);
	}
}


// ---- A

static UINT fillbufferA(TEXTFILE tf) {

	UINT	rsize;

	if (tf->bufrem == 0) {
		rsize = file_read(tf->fh, tf->buf, tf->bufsize);
		rsize = rsize / sizeof(char);
		tf->fpos += rsize * sizeof(char);
		tf->bufpos = 0;
		tf->bufrem = rsize;
	}
	return(tf->bufrem);
}

static BRESULT readlineA(TEXTFILE tf, void *buffer, UINT size) {

	char	*dst;
	BOOL	crlf;
	BRESULT	ret;
	char	c;
const char	*src;
	UINT	pos;

	if (size == 0) {
		dst = NULL;
		size = 0;
	}
	else {
		dst = (char *)buffer;
		size--;
	}

	crlf = FALSE;
	ret = FAILURE;
	c = 0;
	do {
		if (fillbufferA(tf) == 0) {
			break;
		}
		ret = SUCCESS;
		src = (char *)tf->buf;
		src += tf->bufpos;
		pos = 0;
		while(pos<tf->bufrem) {
			c = src[pos];
			pos++;
			if ((c == 0x0d) || (c == 0x0a)) {
				crlf = TRUE;
				break;
			}
			if (size) {
				size--;
				*dst++ = c;
			}
		}
		tf->bufpos += pos;
		tf->bufrem -= pos;
	} while(!crlf);
	if ((crlf) && (c == 0x0d)) {
		if (fillbufferA(tf) != 0) {
			src = (char *)tf->buf;
			src += tf->bufpos;
			if (*src == 0x0a) {
				tf->bufpos++;
				tf->bufrem--;
			}
		}
	}
	if (dst) {
		*dst = '\0';
	}
	return(ret);
}


// ---- W

static UINT fillbufferW(TEXTFILE tf) {

	UINT	rsize;
	UINT8	*buf;
	UINT8	tmp;

	if (tf->bufrem == 0) {
		buf = tf->buf;
		rsize = file_read(tf->fh, buf, tf->bufsize);
		rsize = rsize / sizeof(UINT16);
		tf->fpos += rsize * sizeof(UINT16);
		tf->bufpos = 0;
		tf->bufrem = rsize;
		if (tf->xendian) {
			while(rsize) {
				tmp = buf[0];
				buf[0] = buf[1];
				buf[1] = tmp;
				buf += 2;
				rsize--;
			}
		}
	}
	return(tf->bufrem);
}

static BRESULT readlineW(TEXTFILE tf, void *buffer, UINT size) {

	UINT16		*dst;
	BOOL		crlf;
	BRESULT		ret;
	UINT16		c;
const UINT16	*src;
	UINT		pos;

	if (size == 0) {
		dst = NULL;
		size = 0;
	}
	else {
		dst = (UINT16 *)buffer;
		size--;
	}
	crlf = FALSE;
	ret = FAILURE;
	c = 0;
	do {
		if (fillbufferW(tf) == 0) {
			break;
		}
		ret = SUCCESS;
		src = (UINT16 *)tf->buf;
		src += tf->bufpos;
		pos = 0;
		while(pos<tf->bufrem) {
			c = src[pos];
			pos++;
			if ((c == 0x0d) || (c == 0x0a)) {
				crlf = TRUE;
				break;
			}
			if (size) {
				size--;
				*dst++ = c;
			}
		}
		tf->bufpos += pos;
		tf->bufrem -= pos;
	} while(!crlf);
	if ((crlf) && (c == 0x0d)) {
		if (fillbufferW(tf) != 0) {
			src = (UINT16 *)tf->buf;
			src += tf->bufpos;
			if (*src == 0x0a) {
				tf->bufpos++;
				tf->bufrem--;
			}
		}
	}
	if (dst) {
		*dst = '\0';
	}
	return(ret);
}


// ----

TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) {

	FILEH		fh;
	UINT8		hdr[4];
	UINT		hdrsize;
	TEXTFILEH	ret;

	fh = file_open_rb(filename);
	if (fh == FILEH_INVALID) {
		goto tfo_err;
	}
	hdrsize = file_read(fh, hdr, sizeof(hdr));
	ret = registfile(fh, buffersize, hdr, hdrsize);
	if (ret) {
		return(ret);
	}
	file_close(fh);

tfo_err:
	return(NULL);
}

TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize) {

	FILEH		fh;
const UINT8		*hdr;
	UINT		hdrsize;
	TEXTFILEH	ret;

	fh = file_create(filename);
	if (fh == FILEH_INVALID) {
		goto tfc_err1;
	}
#if defined(OSLANG_UTF8)
	hdr = str_utf8;
	hdrsize = sizeof(str_utf8);
#elif defined(OSLANG_UCS2) 
	hdr = (UINT8 *)str_ucs2;
	hdrsize = sizeof(str_ucs2);
#else
	hdr = NULL;
	hdrsize = 0;
#endif
	if ((hdrsize) && (file_write(fh, hdr, hdrsize) != hdrsize)) {
		goto tfc_err2;
	}
	ret = registfile(fh, buffersize, hdr, hdrsize);
	if (ret) {
		return(ret);
	}

tfc_err2:
	file_close(fh);

tfc_err1:
	return(NULL);
}

BRESULT textfile_read(TEXTFILEH tfh, OEMCHAR *buffer, UINT size) {

	TEXTFILE	tf;

	tf = (TEXTFILE)tfh;
	if (tf) {
		if (!(tf->mode & TFMODE_READ)) {
			flushfile(tf);
			tf->mode = TFMODE_READ;
		}
		if (sizeof(OEMCHAR) == 1) {
			return(readlineA(tf, buffer, size));
		}
		else if (sizeof(OEMCHAR) == 2) {
			return(readlineW(tf, buffer, size));
		}
	}
	return(FAILURE);
}

BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) {

	TEXTFILE	tf;
	UINT		leng;
	UINT		wsize;

	tf = (TEXTFILE)tfh;
	if (tf) {
		if (!(tf->mode & TFMODE_WRITE)) {
			flushfile(tf);
			tf->mode = TFMODE_WRITE;
		}
		leng = OEMSTRLEN(buffer);
		leng = leng * sizeof(OEMCHAR);
		wsize = file_write(tf->fh, buffer, leng);
		tf->fpos += wsize;
		if (wsize == leng) {
			return(SUCCESS);
		}
	}
	return(FAILURE);
}

void textfile_close(TEXTFILEH tfh) {

	if (tfh) {
		file_close(((TEXTFILE)tfh)->fh);
		_MFREE(tfh);
	}
}


RetroPC.NET-CVS <cvs@retropc.net>