Diff for /np2/common/textfile.c between versions 1.5 and 1.9

version 1.5, 2005/03/18 09:23:10 version 1.9, 2005/05/15 20:18:31
Line 1 Line 1
 #include        "compiler.h"  #include        "compiler.h"
 #include        "dosio.h"  #include        "strres.h"
 #include        "textfile.h"  #include        "textfile.h"
   #if defined(SUPPORT_TEXTCNV)
   #include        "textcnv.h"
   #endif
   #include        "dosio.h"
   
   
 static BRESULT getnextstrings(TEXTFILEH fh) {  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;
           READFN  readfn;
   #if defined(SUPPORT_TEXTCNV)
           UINT8           *cnvbuf;
           UINT            cnvbufsize;
           TCTOOEM         tooem;
           TCFROMOEM       fromoem;
   #endif
   };
   
   
   // ---- ReadA
   
   static UINT readbufferA(TEXTFILE tf) {
   
         UINT    rsize;          UINT    rsize;
   
         if (!fh) {          if (tf->bufrem == 0) {
                 return(FAILURE);                  rsize = file_read(tf->fh, tf->buf, tf->bufsize);
                   rsize = rsize / sizeof(char);
                   tf->fpos += rsize * sizeof(char);
                   tf->bufpos = 0;
                   tf->bufrem = rsize;
         }          }
         if (file_seek((FILEH)fh->fh, fh->fhpos, 0) != fh->fhpos) {          return(tf->bufrem);
                 return(FAILURE);  }
   
   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;
         }          }
         rsize = file_read((FILEH)fh->fh, fh + 1, fh->buffersize);          else {
         if (rsize == (UINT)-1) {                  dst = (char *)buffer;
                 return(FAILURE);                  size--;
           }
   
           crlf = FALSE;
           ret = FAILURE;
           c = 0;
           do {
                   if (readbufferA(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 (readbufferA(tf) != 0) {
                           src = (char *)tf->buf;
                           src += tf->bufpos;
                           if (*src == 0x0a) {
                                   tf->bufpos++;
                                   tf->bufrem--;
                           }
                   }
           }
           if (dst) {
                   *dst = '\0';
           }
           return(ret);
   }
   
   
   // ---- ReadW
   
   static UINT readbufferW(TEXTFILE tf) {
   
           UINT    rsize;
           UINT8   *buf;
   
           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(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 (readbufferW(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 (readbufferW(tf) != 0) {
                           src = (UINT16 *)tf->buf;
                           src += tf->bufpos;
                           if (*src == 0x0a) {
                                   tf->bufpos++;
                                   tf->bufrem--;
                           }
                   }
           }
           if (dst) {
                   *dst = '\0';
           }
           return(ret);
   }
   
   
   // ---- 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);
                   }
         }          }
         fh->fhpos += rsize;  
         fh->pos = 0;  
         fh->remain = rsize;  
         return(SUCCESS);          return(SUCCESS);
 }  }
   
 TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) {  static BRESULT writebufferA(TEXTFILE tf, const void *buffer, UINT size) {
   
         FILEH           fh;          BRESULT ret;
         TEXTFILEH       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) {          if (buffersize < 256) {
                 buffersize = 256;                  buffersize = 256;
         }          }
         fh = file_open(filename);          cnvbufsize = 0;
         if (fh == FILEH_INVALID) {  #if defined(SUPPORT_TEXTCNV)
                 goto tfo_err1;          if (textcnv_getinfo(&inf, hdr, hdrsize) == 0) {
                   return(NULL);
         }          }
         ret = (TEXTFILEH)_MALLOC(sizeof(_TEXTFILE) + buffersize, filename);          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) {          if (ret == NULL) {
                 goto tfo_err2;                  return(NULL);
         }          }
         ZeroMemory(ret, sizeof(_TEXTFILE) + buffersize);          ZeroMemory(ret, sizeof(_TEXTFILE));
         ret->fh = (long)fh;  //      ret->mode = 0;
         ret->buffersize = buffersize;          ret->width = width;
 #if defined(OSLANG_UTF8)          ret->fh = fh;
         getnextstrings(ret);          ret->fpos = fpos;
         if (ret->remain >= 3) {          ret->buf = (UINT8 *)(ret + 1);
                 char *ptr;          ret->bufsize = buffersize;
                 ptr = ((char *)(ret + 1)) + ret->pos;          ret->readfn = readfn;
                 if ((ptr[0] == (char)0xef) &&  #if defined(SUPPORT_TEXTCNV)
                         (ptr[1] == (char)0xbb) &&          ret->access = inf.caps;
                         (ptr[2] == (char)0xbf)) {          ret->xendian = inf.xendian;
                         ret->pos += 3;          ret->cnvbuf = ret->buf + buffersize;
                         ret->remain -= 3;          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;
                 }                  }
         }          }
 #endif          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);          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_err2:  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);          file_close(fh);
   
 tfo_err1:  tfc_err1:
         return(NULL);          return(NULL);
 }  }
   
 void textfile_close(TEXTFILEH fh) {  BRESULT textfile_read(TEXTFILEH tfh, OEMCHAR *buffer, UINT size) {
   
         if (fh) {          TEXTFILE        tf;
                 file_close((FILEH)fh->fh);  
                 _MFREE(fh);          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_read(TEXTFILEH fh, OEMCHAR *buffer, UINT size) {  BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) {
   
         char    c = '\0';          TEXTFILE        tf;
         char    *p;  const void              *buf;
         BOOL    crlf;          UINT            leng;
         BRESULT ret = FAILURE;  
   
         if ((fh) && (size > 0)) {          tf = (TEXTFILE)tfh;
                 size--;          if (tf == NULL) {
                 crlf = FALSE;                  return(FAILURE);
                 do {          }
                         if ((!fh->remain) && (getnextstrings(fh))) {  #if defined(SUPPORT_TEXTCNV)
                                 return(FAILURE);          if (!(tf->access & TEXTCNV_WRITE)) {
                         }                  return(FAILURE);
                         if (!fh->remain) {          }
                                 break;  #endif  // defined(SUPPORT_TEXTCNV)
                         }          if (!(tf->mode & TFMODE_WRITE)) {
                         ret = SUCCESS;                  flushfile(tf);
                         p = (char *)(fh + 1);                  tf->mode = TFMODE_WRITE;
                         p += fh->pos;          }
                         while((fh->remain) && (size)) {          leng = OEMSTRLEN(buffer);
                                 c = *p++;  #if defined(SUPPORT_TEXTCNV)
                                 fh->pos++;          if (tf->fromoem != NULL) {
                                 fh->remain--;                  leng = (tf->fromoem)(tf->cnvbuf, tf->cnvbufsize / tf->width,
                                 if ((c == 0x0d) || (c == 0x0a)) {                                                                                                                                  buffer, leng);
                                         crlf = TRUE;                  buf = tf->cnvbuf;
                                         break;          }
                                 }          else {
                                 *buffer++ = c;                  buf = buffer;
                                 size--;          }
                         }  #else   // defined(SUPPORT_TEXTCNV)
                         if (!crlf) {          buf = buffer;
                                 while((fh->remain) && (size)) {  #endif  // defined(SUPPORT_TEXTCNV)
                                         c = *p++;          if (tf->width == 1) {
                                         fh->pos++;                  return(writebufferA(tf, buf, leng));
                                         fh->remain--;          }
                                         if ((c == 0x0d) || (c == 0x0a)) {          else if (tf->width == 2) {
                                                 crlf = TRUE;                  return(writebufferW(tf, buf, leng));
                                                 break;          }
                                         }          else {
                                 }                  return(FAILURE);
                         }          }
                 } while(!crlf);  }
                 if ((crlf) && (c == 0x0d)) {  
                         if ((!fh->remain) && (getnextstrings(fh))) {  void textfile_close(TEXTFILEH tfh) {
                                 return(FAILURE);  
                         }          TEXTFILE        tf;
                         if (fh->remain) {  
                                 p = (char *)(fh + 1);          tf = (TEXTFILE)tfh;
                                 p += fh->pos;          if (tf) {
                                 if (*p == 0x0a) {                  if (tf->mode & TFMODE_WRITE) {
                                         fh->pos++;                          flushfile(tf);
                                         fh->remain--;  
                                 }  
                         }  
                 }                  }
                 *buffer = '\0';                  file_close(tf->fh);
                   _MFREE(tf);
         }          }
         return(ret);  
 }  }
   

Removed from v.1.5  
changed lines
  Added in v.1.9


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