--- np2/common/textfile.c 2005/03/19 18:54:58 1.6 +++ np2/common/textfile.c 2006/12/10 12:45:46 1.10 @@ -1,44 +1,97 @@ #include "compiler.h" -#include "dosio.h" +#include "strres.h" #include "textfile.h" +#if defined(SUPPORT_TEXTCNV) +#include "textcnv.h" +#endif +#if defined(SUPPORT_ARC) +#include "arc.h" +#else +#include "dosio.h" +#endif -typedef struct { - UINT mode; - FILEH fh; - BOOL xendian; -} _TEXTFH, *TEXTFH; +// ---- arc support? -typedef struct { - _TEXTFH tf; +#if defined(SUPPORT_ARC) +#define _FILEH ARCFH +#define _FILEH_INVALID NULL +#define _FSEEK_SET ARCSEEK_SET +#define _file_open_rb arcex_fileopen +#define _file_create arcex_filecreate +#define _file_read arc_fileread +#define _file_write arc_filewrite +#define _file_seek arc_fileseek +#define _file_close arc_fileclose +#else +#define _FILEH FILEH +#define _FILEH_INVALID FILEH_INVALID +#define _FSEEK_SET FSEEK_SET +#define _file_open_rb file_open_rb +#define _file_create file_create +#define _file_read file_read +#define _file_write file_write +#define _file_seek file_seek +#define _file_close file_close +#endif + +enum { + TFMODE_READ = 0x01, + TFMODE_WRITE = 0x02 +}; + +struct _textfile; +typedef struct _textfile _TEXTFILE; +typedef struct _textfile *TEXTFILE; + +typedef BRESULT (*READFN)(TEXTFILE tf, void *buffer, UINT size); + +struct _textfile { + UINT8 mode; + UINT8 width; +#if defined(SUPPORT_TEXTCNV) + UINT8 access; + UINT8 xendian; +#endif + _FILEH fh; + long fpos; UINT8 *buf; UINT bufsize; UINT bufpos; UINT bufrem; -} _TEXTREAD, *TEXTREAD; + READFN readfn; +#if defined(SUPPORT_TEXTCNV) + UINT8 *cnvbuf; + UINT cnvbufsize; + TCTOOEM tooem; + TCFROMOEM fromoem; +#endif +}; -// ---- A +// ---- ReadA -static UINT fillbufferA(TEXTREAD tr) { +static UINT readbufferA(TEXTFILE tf) { UINT rsize; - if (tr->bufrem == 0) { - rsize = file_read(tr->tf.fh, tr->buf, tr->bufsize); - tr->bufpos = 0; - tr->bufrem = 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(tr->bufrem); + return(tf->bufrem); } -static BRESULT readlineA(TEXTREAD tr, void *buffer, UINT size) { +static BRESULT readlineA(TEXTFILE tf, void *buffer, UINT size) { - UINT8 *dst; + char *dst; BOOL crlf; BRESULT ret; - UINT8 c; -const UINT8 *src; + char c; +const char *src; UINT pos; if (size == 0) { @@ -46,7 +99,7 @@ const UINT8 *src; size = 0; } else { - dst = (UINT8 *)buffer; + dst = (char *)buffer; size--; } @@ -54,14 +107,14 @@ const UINT8 *src; ret = FAILURE; c = 0; do { - if (fillbufferA(tr) == 0) { + if (readbufferA(tf) == 0) { break; } ret = SUCCESS; - src = tr->buf; - src += tr->bufpos; + src = (char *)tf->buf; + src += tf->bufpos; pos = 0; - while(posbufrem) { + while(posbufrem) { c = src[pos]; pos++; if ((c == 0x0d) || (c == 0x0a)) { @@ -73,16 +126,16 @@ const UINT8 *src; *dst++ = c; } } - tr->bufpos += pos; - tr->bufrem -= pos; + tf->bufpos += pos; + tf->bufrem -= pos; } while(!crlf); if ((crlf) && (c == 0x0d)) { - if (fillbufferA(tr) != 0) { - src = tr->buf; - src += tr->bufpos; + if (readbufferA(tf) != 0) { + src = (char *)tf->buf; + src += tf->bufpos; if (*src == 0x0a) { - tr->bufpos++; - tr->bufrem--; + tf->bufpos++; + tf->bufrem--; } } } @@ -93,33 +146,30 @@ const UINT8 *src; } -// ---- W +// ---- ReadW -static UINT fillbufferW(TEXTREAD tr) { +static UINT readbufferW(TEXTFILE tf) { UINT rsize; UINT8 *buf; - UINT8 tmp; - if (tr->bufrem == 0) { - buf = tr->buf; - rsize = file_read(tr->tf.fh, buf, tr->bufsize) / 2; - tr->bufpos = 0; - tr->bufrem = rsize / 2; - if (tr->tf.xendian) { - while(rsize) { - tmp = buf[0]; - buf[0] = buf[1]; - buf[1] = tmp; - buf += 2; - rsize--; - } + 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 defined(SUPPORT_TEXTCNV) + if (tf->xendian) { + textcnv_swapendian16(buf, rsize); } +#endif // defined(SUPPORT_TEXTCNV) } - return(tr->bufrem); + return(tf->bufrem); } -static BRESULT readlineW(TEXTREAD tr, void *buffer, UINT size) { +static BRESULT readlineW(TEXTFILE tf, void *buffer, UINT size) { UINT16 *dst; BOOL crlf; @@ -140,14 +190,14 @@ const UINT16 *src; ret = FAILURE; c = 0; do { - if (fillbufferW(tr) == 0) { + if (readbufferW(tf) == 0) { break; } ret = SUCCESS; - src = (UINT16 *)tr->buf; - src += tr->bufpos; + src = (UINT16 *)tf->buf; + src += tf->bufpos; pos = 0; - while(posbufrem) { + while(posbufrem) { c = src[pos]; pos++; if ((c == 0x0d) || (c == 0x0a)) { @@ -159,16 +209,16 @@ const UINT16 *src; *dst++ = c; } } - tr->bufpos += pos; - tr->bufrem -= pos; + tf->bufpos += pos; + tf->bufrem -= pos; } while(!crlf); if ((crlf) && (c == 0x0d)) { - if (fillbufferW(tr) != 0) { - src = (UINT16 *)tr->buf; - src += tr->bufpos; + if (readbufferW(tf) != 0) { + src = (UINT16 *)tf->buf; + src += tf->bufpos; if (*src == 0x0a) { - tr->bufpos++; - tr->bufrem--; + tf->bufpos++; + tf->bufrem--; } } } @@ -179,30 +229,152 @@ const UINT16 *src; } +// ---- read with convert + +#if defined(SUPPORT_TEXTCNV) +static BRESULT readlineAtoOEM(TEXTFILE tf, void *buffer, UINT size) { + + BRESULT ret; + + ret = readlineA(tf, tf->cnvbuf, tf->cnvbufsize); + if (ret == SUCCESS) { + (tf->tooem)(buffer, size, tf->cnvbuf, (UINT)-1); + } + return(ret); +} + +static BRESULT readlineWtoOEM(TEXTFILE tf, void *buffer, UINT size) { + + BRESULT ret; + + ret = readlineW(tf, tf->cnvbuf, tf->cnvbufsize / 2); + if (ret == SUCCESS) { + (tf->tooem)(buffer, size, tf->cnvbuf, (UINT)-1); + } + return(ret); +} +#endif // defined(SUPPORT_TEXTCNV) + + +// ---- write + +static BRESULT flushwritebuffer(TEXTFILE tf) { + + UINT size; + UINT wsize; + + if (tf->bufpos) { + size = tf->bufpos * tf->width; + wsize = _file_write(tf->fh, tf->buf, size); + tf->fpos += wsize; + if (wsize != size) { + return(FAILURE); + } + } + return(SUCCESS); +} + +static BRESULT writebufferA(TEXTFILE tf, const void *buffer, UINT size) { + + BRESULT ret; +const UINT8 *p; + UINT wsize; + + ret = SUCCESS; + p = (UINT8 *)buffer; + while(size) { + wsize = min(size, tf->bufrem); + if (wsize) { + CopyMemory(tf->buf + tf->bufpos, p, wsize); + p += wsize; + size -= wsize; + tf->bufpos += wsize; + tf->bufrem -= wsize; + } + if (tf->bufrem == 0) { + ret = flushwritebuffer(tf); + tf->bufpos = 0; + tf->bufrem = tf->bufsize / sizeof(char); + } + } + return(ret); +} + +static BRESULT writebufferW(TEXTFILE tf, const void *buffer, UINT size) { + + BRESULT ret; +const UINT8 *p; + UINT8 *q; + UINT wsize; + + ret = SUCCESS; + p = (UINT8 *)buffer; + while(size) { + wsize = min(size, tf->bufrem); + if (wsize) { + q = tf->buf + (tf->bufpos * sizeof(UINT16)); + CopyMemory(q, p, wsize * sizeof(UINT16)); +#if defined(SUPPORT_TEXTCNV) + if (tf->xendian) { + textcnv_swapendian16(q, wsize); + } +#endif // defined(SUPPORT_TEXTCNV) + p += wsize * sizeof(UINT16); + size -= wsize; + tf->bufpos += wsize; + tf->bufrem -= wsize; + } + if (tf->bufrem == 0) { + ret = flushwritebuffer(tf); + tf->bufpos = 0; + tf->bufrem = tf->bufsize / sizeof(UINT16); + } + } + return(ret); +} + + // ---- -TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { +static TEXTFILEH registfile(_FILEH fh, UINT buffersize, + const UINT8 *hdr, UINT hdrsize) { - FILEH fh; - UINT8 hdr[4]; - UINT hdrsize; + UINT cnvbufsize; +#if defined(SUPPORT_TEXTCNV) + TCINF inf; +#endif long fpos; - UINT srcwidth; - BOOL xendian; - TEXTREAD ret; + UINT8 width; + READFN readfn; + TEXTFILE ret; buffersize = buffersize & (~3); if (buffersize < 256) { buffersize = 256; } - fh = file_open_rb(filename); - if (fh == FILEH_INVALID) { - goto tfo_err1; + cnvbufsize = 0; +#if defined(SUPPORT_TEXTCNV) + if (textcnv_getinfo(&inf, hdr, hdrsize) == 0) { + return(NULL); + } + fpos = inf.hdrsize; + width = inf.width; + if (inf.width == 1) { + readfn = (inf.tooem != NULL)?readlineAtoOEM:readlineA; + } + else if (inf.width == 2) { + buffersize = buffersize * 2; + readfn = (inf.tooem != NULL)?readlineWtoOEM:readlineW; + } + else { + return(NULL); + } + if ((inf.tooem != NULL) || (inf.fromoem != NULL)) { + cnvbufsize = buffersize; } - hdrsize = file_read(fh, hdr, 4); +#else // defined(SUPPORT_TEXTCNV) fpos = 0; - srcwidth = 1; - xendian = FALSE; + width = 1; if ((hdrsize >= 3) && (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { // UTF-8 @@ -211,69 +383,223 @@ TEXTFILEH textfile_open(const OEMCHAR *f else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { // UCSLE fpos = 2; - srcwidth = 2; + width = 2; #if defined(BYTESEX_BIG) - xendian = TRUE; -#endif + return(NULL); +#endif // defined(BYTESEX_BIG) } else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { // UCS2BE fpos = 2; - srcwidth = 2; + width = 2; #if defined(BYTESEX_LITTLE) - xendian = TRUE; -#endif + return(NULL); +#endif // defined(BYTESEX_LITTLE) } - - if (srcwidth != sizeof(OEMCHAR)) { - goto tfo_err2; + if (width != sizeof(OEMCHAR)) { + return(NULL); } buffersize = buffersize * sizeof(OEMCHAR); + readfn = (width == 2)?readlineW:readlineA; +#endif // defined(SUPPORT_TEXTCNV) - if (file_seek(fh, fpos, FSEEK_SET) != fpos) { - goto tfo_err2; - } - - ret = (TEXTREAD)_MALLOC(sizeof(_TEXTREAD) + buffersize, filename); + ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize + cnvbufsize, + "TEXTFILE"); if (ret == NULL) { - goto tfo_err2; + return(NULL); } - ZeroMemory(ret, sizeof(_TEXTREAD)); - ret->tf.mode = 0; - ret->tf.fh = fh; - ret->tf.xendian = xendian; + ZeroMemory(ret, sizeof(_TEXTFILE)); +// ret->mode = 0; + ret->width = width; + ret->fh = fh; + ret->fpos = fpos; ret->buf = (UINT8 *)(ret + 1); ret->bufsize = buffersize; + ret->readfn = readfn; +#if defined(SUPPORT_TEXTCNV) + ret->access = inf.caps; + ret->xendian = inf.xendian; + ret->cnvbuf = ret->buf + buffersize; + ret->cnvbufsize = cnvbufsize; + ret->tooem = inf.tooem; + ret->fromoem = inf.fromoem; +#endif // defined(SUPPORT_TEXTCNV) return((TEXTFILEH)ret); +} + +static BRESULT flushfile(TEXTFILE tf) { + + BRESULT ret; + long fpos; + UINT size; + UINT wsize; + + ret = SUCCESS; + if (tf->mode & TFMODE_READ) { + fpos = tf->fpos - (tf->bufrem * tf->width); + tf->fpos = _file_seek(tf->fh, fpos, _FSEEK_SET); + if (tf->fpos != fpos) { + ret = FAILURE; + } + } + else if (tf->mode & TFMODE_WRITE) { + if (tf->bufpos) { + size = tf->bufpos * tf->width; + wsize = _file_write(tf->fh, tf->buf, size); + if (wsize != size) { + ret = FAILURE; + } + tf->fpos += wsize; + } + } + else { + fpos = _file_seek(tf->fh, tf->fpos, _FSEEK_SET); + if (tf->fpos != fpos) { + ret = FAILURE; + } + tf->fpos = fpos; + } + tf->mode = 0; + tf->bufpos = 0; + tf->bufrem = 0; + return(ret); +} + + +// ---- + +TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { + + _FILEH fh; + UINT8 hdr[4]; + UINT hdrsize; + TEXTFILEH ret; -tfo_err2: - file_close(fh); + 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_err1: +tfo_err: return(NULL); } -void textfile_close(TEXTFILEH tfh) { +TEXTFILEH textfile_create(const OEMCHAR *filename, UINT buffersize) { - if (tfh) { - file_close(((TEXTFH)tfh)->fh); - _MFREE(tfh); + _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) { - TEXTREAD tr; + TEXTFILE tf; - tr = (TEXTREAD)tfh; - if (tr) { - if (sizeof(OEMCHAR) == 1) { - return(readlineA(tr, buffer, size)); - } - else if (sizeof(OEMCHAR) == 2) { - return(readlineW(tr, buffer, size)); + tf = (TEXTFILE)tfh; + if (tf == NULL) { + return(FAILURE); + } +#if defined(SUPPORT_TEXTCNV) + if (!(tf->access & TEXTCNV_READ)) { + return(FAILURE); + } +#endif // defined(SUPPORT_TEXTCNV) + if (!(tf->mode & TFMODE_READ)) { + flushfile(tf); + tf->mode = TFMODE_READ; + } + return((tf->readfn)(tf, buffer, size)); +} + +BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { + + TEXTFILE tf; +const void *buf; + UINT leng; + + tf = (TEXTFILE)tfh; + if (tf == NULL) { + return(FAILURE); + } +#if defined(SUPPORT_TEXTCNV) + if (!(tf->access & TEXTCNV_WRITE)) { + return(FAILURE); + } +#endif // defined(SUPPORT_TEXTCNV) + if (!(tf->mode & TFMODE_WRITE)) { + flushfile(tf); + tf->mode = TFMODE_WRITE; + } + leng = OEMSTRLEN(buffer); +#if defined(SUPPORT_TEXTCNV) + if (tf->fromoem != NULL) { + leng = (tf->fromoem)(tf->cnvbuf, tf->cnvbufsize / tf->width, + buffer, leng); + buf = tf->cnvbuf; + } + else { + buf = buffer; + } +#else // defined(SUPPORT_TEXTCNV) + buf = buffer; +#endif // defined(SUPPORT_TEXTCNV) + if (tf->width == 1) { + return(writebufferA(tf, buf, leng)); + } + else if (tf->width == 2) { + return(writebufferW(tf, buf, leng)); + } + else { + return(FAILURE); + } +} + +void textfile_close(TEXTFILEH tfh) { + + TEXTFILE tf; + + tf = (TEXTFILE)tfh; + if (tf) { + if (tf->mode & TFMODE_WRITE) { + flushfile(tf); } + _file_close(tf->fh); + _MFREE(tf); } - return(FAILURE); }