|
|
| version 1.1, 2003/10/16 17:57:10 | version 1.6, 2005/03/19 18:54:58 |
|---|---|
| Line 3 | Line 3 |
| #include "textfile.h" | #include "textfile.h" |
| TEXTFILEH textfile_open(const char *filename, UINT buffersize) { | typedef struct { |
| UINT mode; | |
| FILEH fh; | |
| BOOL xendian; | |
| } _TEXTFH, *TEXTFH; | |
| typedef struct { | |
| _TEXTFH tf; | |
| UINT8 *buf; | |
| UINT bufsize; | |
| UINT bufpos; | |
| UINT bufrem; | |
| } _TEXTREAD, *TEXTREAD; | |
| FILEH fh; | |
| TEXTFILEH ret; | |
| if (buffersize < 256) { | // ---- A |
| buffersize = 256; | |
| } | static UINT fillbufferA(TEXTREAD tr) { |
| fh = file_open(filename); | |
| if (fh != FILEH_INVALID) { | UINT rsize; |
| ret = (TEXTFILEH)_MALLOC(sizeof(_TEXTFILE) + buffersize, filename); | |
| if (ret) { | if (tr->bufrem == 0) { |
| ZeroMemory(ret, sizeof(_TEXTFILE) + buffersize); | rsize = file_read(tr->tf.fh, tr->buf, tr->bufsize); |
| ret->fh = (void *)fh; | tr->bufpos = 0; |
| ret->buffersize = buffersize; | tr->bufrem = rsize; |
| return(ret); | |
| } | |
| file_close(fh); | |
| } | } |
| return(NULL); | return(tr->bufrem); |
| } | } |
| static BRESULT readlineA(TEXTREAD tr, void *buffer, UINT size) { | |
| void textfile_close(TEXTFILEH fh) { | UINT8 *dst; |
| BOOL crlf; | |
| BRESULT ret; | |
| UINT8 c; | |
| const UINT8 *src; | |
| UINT pos; | |
| if (size == 0) { | |
| dst = NULL; | |
| size = 0; | |
| } | |
| else { | |
| dst = (UINT8 *)buffer; | |
| size--; | |
| } | |
| if (fh) { | crlf = FALSE; |
| file_close((FILEH)fh->fh); | ret = FAILURE; |
| _MFREE(fh); | c = 0; |
| do { | |
| if (fillbufferA(tr) == 0) { | |
| break; | |
| } | |
| ret = SUCCESS; | |
| src = tr->buf; | |
| src += tr->bufpos; | |
| pos = 0; | |
| while(pos<tr->bufrem) { | |
| c = src[pos]; | |
| pos++; | |
| if ((c == 0x0d) || (c == 0x0a)) { | |
| crlf = TRUE; | |
| break; | |
| } | |
| if (size) { | |
| size--; | |
| *dst++ = c; | |
| } | |
| } | |
| tr->bufpos += pos; | |
| tr->bufrem -= pos; | |
| } while(!crlf); | |
| if ((crlf) && (c == 0x0d)) { | |
| if (fillbufferA(tr) != 0) { | |
| src = tr->buf; | |
| src += tr->bufpos; | |
| if (*src == 0x0a) { | |
| tr->bufpos++; | |
| tr->bufrem--; | |
| } | |
| } | |
| } | |
| if (dst) { | |
| *dst = '\0'; | |
| } | } |
| return(ret); | |
| } | } |
| static BOOL getnextstring(TEXTFILEH fh) { | // ---- W |
| static UINT fillbufferW(TEXTREAD tr) { | |
| UINT rsize; | UINT rsize; |
| UINT8 *buf; | |
| UINT8 tmp; | |
| if (!fh) { | if (tr->bufrem == 0) { |
| return(FAILURE); | buf = tr->buf; |
| } | rsize = file_read(tr->tf.fh, buf, tr->bufsize) / 2; |
| if (file_seek((FILEH)fh->fh, fh->fhpos, 0) != fh->fhpos) { | tr->bufpos = 0; |
| return(FAILURE); | tr->bufrem = rsize / 2; |
| } | if (tr->tf.xendian) { |
| rsize = file_read((FILEH)fh->fh, fh + 1, fh->buffersize); | while(rsize) { |
| if (rsize == (UINT)-1) { | tmp = buf[0]; |
| return(FAILURE); | buf[0] = buf[1]; |
| buf[1] = tmp; | |
| buf += 2; | |
| rsize--; | |
| } | |
| } | |
| } | } |
| fh->fhpos += rsize; | return(tr->bufrem); |
| fh->pos = 0; | |
| fh->remain = rsize; | |
| return(SUCCESS); | |
| } | } |
| static BRESULT readlineW(TEXTREAD tr, void *buffer, UINT size) { | |
| BOOL textfile_read(TEXTFILEH fh, char *buffer, UINT size) { | UINT16 *dst; |
| BOOL crlf; | |
| char c = '\0'; | BRESULT ret; |
| char *p; | UINT16 c; |
| BOOL crlf; | const UINT16 *src; |
| BOOL ret = FAILURE; | UINT pos; |
| if ((fh) && (size > 0)) { | if (size == 0) { |
| dst = NULL; | |
| size = 0; | |
| } | |
| else { | |
| dst = (UINT16 *)buffer; | |
| size--; | size--; |
| crlf = FALSE; | } |
| do { | crlf = FALSE; |
| if ((!fh->remain) && (getnextstring(fh))) { | ret = FAILURE; |
| return(FAILURE); | c = 0; |
| } | do { |
| if (!fh->remain) { | if (fillbufferW(tr) == 0) { |
| break; | |
| } | |
| ret = SUCCESS; | |
| src = (UINT16 *)tr->buf; | |
| src += tr->bufpos; | |
| pos = 0; | |
| while(pos<tr->bufrem) { | |
| c = src[pos]; | |
| pos++; | |
| if ((c == 0x0d) || (c == 0x0a)) { | |
| crlf = TRUE; | |
| break; | break; |
| } | } |
| ret = SUCCESS; | if (size) { |
| p = (char *)(fh + 1); | |
| p += fh->pos; | |
| while((fh->remain) && (size)) { | |
| c = *p++; | |
| fh->pos++; | |
| fh->remain--; | |
| if ((c == 0x0d) || (c == 0x0a)) { | |
| crlf = TRUE; | |
| break; | |
| } | |
| *buffer++ = c; | |
| size--; | size--; |
| *dst++ = c; | |
| } | } |
| if (!crlf) { | } |
| while((fh->remain) && (size)) { | tr->bufpos += pos; |
| c = *p++; | tr->bufrem -= pos; |
| fh->pos++; | } while(!crlf); |
| fh->remain--; | if ((crlf) && (c == 0x0d)) { |
| if ((c == 0x0d) || (c == 0x0a)) { | if (fillbufferW(tr) != 0) { |
| crlf = TRUE; | src = (UINT16 *)tr->buf; |
| break; | src += tr->bufpos; |
| } | if (*src == 0x0a) { |
| } | tr->bufpos++; |
| } | tr->bufrem--; |
| } while(!crlf); | |
| if ((crlf) && (c == 0x0d)) { | |
| if ((!fh->remain) && (getnextstring(fh))) { | |
| return(FAILURE); | |
| } | |
| if (fh->remain) { | |
| p = (char *)(fh + 1); | |
| p += fh->pos; | |
| if (*p == 0x0a) { | |
| fh->pos++; | |
| fh->remain--; | |
| } | |
| } | } |
| } | } |
| *buffer = '\0'; | } |
| if (dst) { | |
| *dst = '\0'; | |
| } | } |
| return(ret); | return(ret); |
| } | } |
| // ---- | |
| TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { | |
| FILEH fh; | |
| UINT8 hdr[4]; | |
| UINT hdrsize; | |
| long fpos; | |
| UINT srcwidth; | |
| BOOL xendian; | |
| TEXTREAD ret; | |
| buffersize = buffersize & (~3); | |
| if (buffersize < 256) { | |
| buffersize = 256; | |
| } | |
| fh = file_open_rb(filename); | |
| if (fh == FILEH_INVALID) { | |
| goto tfo_err1; | |
| } | |
| hdrsize = file_read(fh, hdr, 4); | |
| 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)) { | |
| goto tfo_err2; | |
| } | |
| buffersize = buffersize * sizeof(OEMCHAR); | |
| if (file_seek(fh, fpos, FSEEK_SET) != fpos) { | |
| goto tfo_err2; | |
| } | |
| ret = (TEXTREAD)_MALLOC(sizeof(_TEXTREAD) + buffersize, filename); | |
| if (ret == NULL) { | |
| goto tfo_err2; | |
| } | |
| ZeroMemory(ret, sizeof(_TEXTREAD)); | |
| ret->tf.mode = 0; | |
| ret->tf.fh = fh; | |
| ret->tf.xendian = xendian; | |
| ret->buf = (UINT8 *)(ret + 1); | |
| ret->bufsize = buffersize; | |
| return((TEXTFILEH)ret); | |
| tfo_err2: | |
| file_close(fh); | |
| tfo_err1: | |
| return(NULL); | |
| } | |
| void textfile_close(TEXTFILEH tfh) { | |
| if (tfh) { | |
| file_close(((TEXTFH)tfh)->fh); | |
| _MFREE(tfh); | |
| } | |
| } | |
| BRESULT textfile_read(TEXTFILEH tfh, OEMCHAR *buffer, UINT size) { | |
| TEXTREAD tr; | |
| tr = (TEXTREAD)tfh; | |
| if (tr) { | |
| if (sizeof(OEMCHAR) == 1) { | |
| return(readlineA(tr, buffer, size)); | |
| } | |
| else if (sizeof(OEMCHAR) == 2) { | |
| return(readlineW(tr, buffer, size)); | |
| } | |
| } | |
| return(FAILURE); | |
| } | |