--- np2/common/textfile.c 2005/03/20 06:09:16 1.7 +++ np2/common/textfile.c 2005/05/15 20:18:31 1.9 @@ -1,7 +1,10 @@ #include "compiler.h" #include "strres.h" -#include "dosio.h" #include "textfile.h" +#if defined(SUPPORT_TEXTCNV) +#include "textcnv.h" +#endif +#include "dosio.h" enum { @@ -9,97 +12,38 @@ enum { TFMODE_WRITE = 0x02 }; -typedef struct { +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 srcwidth; UINT8 xendian; +#endif FILEH fh; long fpos; - void *buf; + UINT8 *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; + READFN readfn; +#if defined(SUPPORT_TEXTCNV) + UINT8 *cnvbuf; + UINT cnvbufsize; + TCTOOEM tooem; + TCFROMOEM fromoem; #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 +// ---- ReadA -static UINT fillbufferA(TEXTFILE tf) { +static UINT readbufferA(TEXTFILE tf) { UINT rsize; @@ -135,7 +79,7 @@ const char *src; ret = FAILURE; c = 0; do { - if (fillbufferA(tf) == 0) { + if (readbufferA(tf) == 0) { break; } ret = SUCCESS; @@ -158,7 +102,7 @@ const char *src; tf->bufrem -= pos; } while(!crlf); if ((crlf) && (c == 0x0d)) { - if (fillbufferA(tf) != 0) { + if (readbufferA(tf) != 0) { src = (char *)tf->buf; src += tf->bufpos; if (*src == 0x0a) { @@ -174,13 +118,12 @@ const char *src; } -// ---- W +// ---- ReadW -static UINT fillbufferW(TEXTFILE tf) { +static UINT readbufferW(TEXTFILE tf) { UINT rsize; UINT8 *buf; - UINT8 tmp; if (tf->bufrem == 0) { buf = tf->buf; @@ -189,15 +132,11 @@ static UINT fillbufferW(TEXTFILE tf) { tf->fpos += rsize * sizeof(UINT16); tf->bufpos = 0; tf->bufrem = rsize; +#if defined(SUPPORT_TEXTCNV) if (tf->xendian) { - while(rsize) { - tmp = buf[0]; - buf[0] = buf[1]; - buf[1] = tmp; - buf += 2; - rsize--; - } + textcnv_swapendian16(buf, rsize); } +#endif // defined(SUPPORT_TEXTCNV) } return(tf->bufrem); } @@ -223,7 +162,7 @@ const UINT16 *src; ret = FAILURE; c = 0; do { - if (fillbufferW(tf) == 0) { + if (readbufferW(tf) == 0) { break; } ret = SUCCESS; @@ -246,7 +185,7 @@ const UINT16 *src; tf->bufrem -= pos; } while(!crlf); if ((crlf) && (c == 0x0d)) { - if (fillbufferW(tf) != 0) { + if (readbufferW(tf) != 0) { src = (UINT16 *)tf->buf; src += tf->bufpos; if (*src == 0x0a) { @@ -262,6 +201,243 @@ 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); +} + + +// ---- + +static TEXTFILEH registfile(FILEH fh, UINT buffersize, + const UINT8 *hdr, UINT hdrsize) { + + UINT cnvbufsize; +#if defined(SUPPORT_TEXTCNV) + TCINF inf; +#endif + long fpos; + UINT8 width; + READFN readfn; + TEXTFILE ret; + + buffersize = buffersize & (~3); + if (buffersize < 256) { + buffersize = 256; + } + 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; + } +#else // defined(SUPPORT_TEXTCNV) + fpos = 0; + width = 1; + 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; + width = 2; +#if defined(BYTESEX_BIG) + return(NULL); +#endif // defined(BYTESEX_BIG) + } + else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { + // UCS2BE + fpos = 2; + width = 2; +#if defined(BYTESEX_LITTLE) + return(NULL); +#endif // defined(BYTESEX_LITTLE) + } + if (width != sizeof(OEMCHAR)) { + return(NULL); + } + buffersize = buffersize * sizeof(OEMCHAR); + readfn = (width == 2)?readlineW:readlineA; +#endif // defined(SUPPORT_TEXTCNV) + + ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize + cnvbufsize, + "TEXTFILE"); + if (ret == NULL) { + return(NULL); + } + 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) { @@ -327,49 +503,75 @@ BRESULT textfile_read(TEXTFILEH tfh, OEM 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)); - } + 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(FAILURE); + return((tf->readfn)(tf, buffer, size)); } BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { TEXTFILE tf; +const void *buf; 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); - } + 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); } - return(FAILURE); } void textfile_close(TEXTFILEH tfh) { - if (tfh) { - file_close(((TEXTFILE)tfh)->fh); - _MFREE(tfh); + TEXTFILE tf; + + tf = (TEXTFILE)tfh; + if (tf) { + if (tf->mode & TFMODE_WRITE) { + flushfile(tf); + } + file_close(tf->fh); + _MFREE(tf); } }