Diff for /np2/common/textfile.c between versions 1.7 and 1.8

version 1.7, 2005/03/20 06:09:16 version 1.8, 2005/04/01 15:35:49
Line 1 Line 1
 #include        "compiler.h"  #include        "compiler.h"
 #include        "strres.h"  #include        "strres.h"
 #include        "dosio.h"  
 #include        "textfile.h"  #include        "textfile.h"
   #if defined(SUPPORT_TEXTCNV)
   #include        "textcnv.h"
   #endif
   #include        "dosio.h"
   
   
 enum {  enum {
Line 9  enum { Line 12  enum {
         TFMODE_WRITE    = 0x02          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   mode;
           UINT8   width;
   #if defined(SUPPORT_TEXTCNV)
         UINT8   access;          UINT8   access;
         UINT8   srcwidth;  
         UINT8   xendian;          UINT8   xendian;
   #endif
         FILEH   fh;          FILEH   fh;
         long    fpos;          long    fpos;
         void    *buf;          UINT8   *buf;
         UINT    bufsize;          UINT    bufsize;
         UINT    bufpos;          UINT    bufpos;
         UINT    bufrem;          UINT    bufrem;
 } _TEXTFILE, *TEXTFILE;          READFN  readfn;
   #if defined(SUPPORT_TEXTCNV)
           UINT8           *cnvbuf;
 static TEXTFILEH registfile(FILEH fh, UINT buffersize,          UINT            cnvbufsize;
                                                                                         const UINT8 *hdr, UINT hdrsize) {          TCTOOEM         tooem;
           TCFROMOEM       fromoem;
         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  #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;          UINT    rsize;
   
Line 135  const char *src; Line 79  const char *src;
         ret = FAILURE;          ret = FAILURE;
         c = 0;          c = 0;
         do {          do {
                 if (fillbufferA(tf) == 0) {                  if (readbufferA(tf) == 0) {
                         break;                          break;
                 }                  }
                 ret = SUCCESS;                  ret = SUCCESS;
Line 158  const char *src; Line 102  const char *src;
                 tf->bufrem -= pos;                  tf->bufrem -= pos;
         } while(!crlf);          } while(!crlf);
         if ((crlf) && (c == 0x0d)) {          if ((crlf) && (c == 0x0d)) {
                 if (fillbufferA(tf) != 0) {                  if (readbufferA(tf) != 0) {
                         src = (char *)tf->buf;                          src = (char *)tf->buf;
                         src += tf->bufpos;                          src += tf->bufpos;
                         if (*src == 0x0a) {                          if (*src == 0x0a) {
Line 174  const char *src; Line 118  const char *src;
 }  }
   
   
 // ---- W  // ---- ReadW
   
 static UINT fillbufferW(TEXTFILE tf) {  static UINT readbufferW(TEXTFILE tf) {
   
         UINT    rsize;          UINT    rsize;
         UINT8   *buf;          UINT8   *buf;
         UINT8   tmp;  
   
         if (tf->bufrem == 0) {          if (tf->bufrem == 0) {
                 buf = tf->buf;                  buf = tf->buf;
Line 189  static UINT fillbufferW(TEXTFILE tf) { Line 132  static UINT fillbufferW(TEXTFILE tf) {
                 tf->fpos += rsize * sizeof(UINT16);                  tf->fpos += rsize * sizeof(UINT16);
                 tf->bufpos = 0;                  tf->bufpos = 0;
                 tf->bufrem = rsize;                  tf->bufrem = rsize;
   #if defined(SUPPORT_TEXTCNV)
                 if (tf->xendian) {                  if (tf->xendian) {
                         while(rsize) {                          textcnv_swapendian16(buf, rsize);
                                 tmp = buf[0];  
                                 buf[0] = buf[1];  
                                 buf[1] = tmp;  
                                 buf += 2;  
                                 rsize--;  
                         }  
                 }                  }
   #endif  // defined(SUPPORT_TEXTCNV)
         }          }
         return(tf->bufrem);          return(tf->bufrem);
 }  }
Line 223  const UINT16 *src; Line 162  const UINT16 *src;
         ret = FAILURE;          ret = FAILURE;
         c = 0;          c = 0;
         do {          do {
                 if (fillbufferW(tf) == 0) {                  if (readbufferW(tf) == 0) {
                         break;                          break;
                 }                  }
                 ret = SUCCESS;                  ret = SUCCESS;
Line 246  const UINT16 *src; Line 185  const UINT16 *src;
                 tf->bufrem -= pos;                  tf->bufrem -= pos;
         } while(!crlf);          } while(!crlf);
         if ((crlf) && (c == 0x0d)) {          if ((crlf) && (c == 0x0d)) {
                 if (fillbufferW(tf) != 0) {                  if (readbufferW(tf) != 0) {
                         src = (UINT16 *)tf->buf;                          src = (UINT16 *)tf->buf;
                         src += tf->bufpos;                          src += tf->bufpos;
                         if (*src == 0x0a) {                          if (*src == 0x0a) {
Line 262  const UINT16 *src; Line 201  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 = (char *)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) {  TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) {
Line 327  BRESULT textfile_read(TEXTFILEH tfh, OEM Line 503  BRESULT textfile_read(TEXTFILEH tfh, OEM
         TEXTFILE        tf;          TEXTFILE        tf;
   
         tf = (TEXTFILE)tfh;          tf = (TEXTFILE)tfh;
         if (tf) {          if (tf == NULL) {
                 if (!(tf->mode & TFMODE_READ)) {                  return(FAILURE);
                         flushfile(tf);          }
                         tf->mode = TFMODE_READ;  #if defined(SUPPORT_TEXTCNV)
                 }          if (!(tf->access & TEXTCNV_READ)) {
                 if (sizeof(OEMCHAR) == 1) {                  return(FAILURE);
                         return(readlineA(tf, buffer, size));          }
                 }  #endif  // defined(SUPPORT_TEXTCNV)
                 else if (sizeof(OEMCHAR) == 2) {          if (!(tf->mode & TFMODE_READ)) {
                         return(readlineW(tf, buffer, size));                  flushfile(tf);
                 }                  tf->mode = TFMODE_READ;
         }          }
         return(FAILURE);          return((tf->readfn)(tf, buffer, size));
 }  }
   
 BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) {  BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) {
   
         TEXTFILE        tf;          TEXTFILE        tf;
   const void              *buf;
         UINT            leng;          UINT            leng;
         UINT            wsize;  
   
         tf = (TEXTFILE)tfh;          tf = (TEXTFILE)tfh;
         if (tf) {          if (tf == NULL) {
                 if (!(tf->mode & TFMODE_WRITE)) {                  return(FAILURE);
                         flushfile(tf);          }
                         tf->mode = TFMODE_WRITE;  #if defined(SUPPORT_TEXTCNV)
                 }          if (!(tf->access & TEXTCNV_WRITE)) {
                 leng = OEMSTRLEN(buffer);                  return(FAILURE);
                 leng = leng * sizeof(OEMCHAR);          }
                 wsize = file_write(tf->fh, buffer, leng);  #endif  // defined(SUPPORT_TEXTCNV)
                 tf->fpos += wsize;          if (!(tf->mode & TFMODE_WRITE)) {
                 if (wsize == leng) {                  flushfile(tf);
                         return(SUCCESS);                  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) {  void textfile_close(TEXTFILEH tfh) {
   
         if (tfh) {          TEXTFILE        tf;
                 file_close(((TEXTFILE)tfh)->fh);  
                 _MFREE(tfh);          tf = (TEXTFILE)tfh;
           if (tf) {
                   if (tf->mode & TFMODE_WRITE) {
                           flushfile(tf);
                   }
                   file_close(tf->fh);
                   _MFREE(tf);
         }          }
 }  }
   

Removed from v.1.7  
changed lines
  Added in v.1.8


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