LCOV - code coverage report
Current view: top level - src - mfile.h (source / functions) Hit Total Coverage
Test: test_coverage.info Lines: 25 44 56.8 %
Date: 2017-06-21 14:32:49 Functions: 3 4 75.0 %

          Line data    Source code
       1             : //////////////////////////////////////////////////////////////////////
       2             : //
       3             : //  FILE:       mfile.h
       4             : //              MFile class
       5             : //
       6             : //  Part of:    Scid (Shane's Chess Information Database)
       7             : //  Version:    2.0
       8             : //
       9             : //  Notice:     Copyright (c) 2000  Shane Hudson.  All rights reserved.
      10             : //
      11             : //  Author:     Shane Hudson (sgh@users.sourceforge.net)
      12             : //
      13             : //////////////////////////////////////////////////////////////////////
      14             : 
      15             : 
      16             : // An MFile is a file that can be a regular file, or memory-only with
      17             : // no actual file on any device.
      18             : // In addition, an MFile can decode its contents from a GZip (.gz) file
      19             : // and will hopefully in future also be able to extract the contents of
      20             : // all files in a Zip file, as if they were in one large plain file.
      21             : 
      22             : 
      23             : #ifndef SCID_MFILE_H
      24             : #define SCID_MFILE_H
      25             : 
      26             : #include "common.h"
      27             : #include <stdio.h>
      28             : 
      29             : #ifdef ZLIB
      30             :         #include <zlib.h>
      31             :         inline bool gzable() { return true; }
      32             : #else
      33             :         // If the zlib compression library is NOT used, create dummy inline
      34             :         // functions to replace those used in zlib, which saves wrapping every
      35             :         // zlib function call with #ifndef conditions.
      36             :         inline bool gzable() { return false; }
      37             :         typedef void * gzFile;
      38             :         inline gzFile gzopen (const char*, const char*) { return 0; }
      39             :         inline int gzputc (gzFile, int c) { return c; }
      40             :         inline int gzgetc (gzFile) { return -1; }
      41             :         inline int gzread (gzFile, unsigned char*, int) { return 0; }
      42             :         inline int gzeof (gzFile) { return 1; }
      43             :         inline int gzseek (gzFile, int, int) { return 0; }
      44             :         inline int gzclose (gzFile) { return 0; }
      45             : #endif
      46             : 
      47             : 
      48             : enum mfileT {
      49             :     MFILE_REGULAR = 0, MFILE_MEMORY, MFILE_GZIP, MFILE_ZIP, MFILE_SEQREAD
      50             : };
      51             : 
      52             : class MFile
      53             : {
      54             :   private:
      55             :     static const int SEQREADBUFSIZE = 64 * 1024;
      56             :     FILE *      Handle;         // For regular files.
      57             :     gzFile      GzHandle;       // For Gzip files.
      58             :     fileModeT   FileMode;
      59             :     mfileT      Type;
      60             :     char *      FileName;
      61             :     uint        Capacity;
      62             :     uint        Location;
      63             :     uint        SeqReadLocation;
      64             :     byte *      Data;
      65             :     byte *      CurrentPtr;
      66             :     // The next few fields are used to improve I/O speed on Gzip files, by
      67             :     // avoiding doing a gzgetc() every character, since the zlib file gzio.c
      68             :     // simply does a (relatively slow) gzread() for each gzgetc().
      69             :     byte *      GzBuffer;
      70             :     int         GzBuffer_Avail;
      71             :     byte *      GzBuffer_Current;
      72             : 
      73             :     void Init();
      74             :     void Extend();
      75             :     int  FillGzBuffer();
      76             : 
      77             :   public:
      78          13 :     MFile() { Init(); }
      79          26 :     ~MFile() {
      80          13 :         if (Handle != NULL) fclose (Handle);
      81             :         if (GzHandle != NULL) gzclose (GzHandle);
      82          13 :         if (Data != NULL) delete[] Data;
      83          13 :         if (GzBuffer != NULL) delete[] GzBuffer;
      84          13 :         if (FileName != NULL) delete[] FileName;
      85          13 :     }
      86             : 
      87             :     errorT Create (const char * name, fileModeT fmode);
      88             :     errorT Open  (const char * name, fileModeT fmode);
      89             :     errorT Seek (uint position);
      90             :     errorT Flush ();
      91             :     inline bool EndOfFile();
      92             : 
      93             :     errorT        WriteNBytes (const char * str, uint length);
      94             :     errorT        ReadNBytes (char * str, uint length);
      95             :     inline errorT WriteOneByte (byte value);
      96             :     errorT        WriteTwoBytes (uint value);
      97             :     errorT        WriteThreeBytes (uint value);
      98             :     errorT        WriteFourBytes (uint value);
      99             :     inline int    ReadOneByte ();
     100             :     uint          ReadTwoBytes ();
     101             :     uint          ReadThreeBytes ();
     102             :     uint          ReadFourBytes ();
     103             : 
     104             :     const char * GetFileName () { return (FileName == NULL ? "" : FileName); }
     105             : };
     106             : 
     107             : inline bool
     108       20020 : MFile::EndOfFile ()
     109             : {
     110       20020 :     switch (Type) {
     111             :     case MFILE_MEMORY:
     112             :     case MFILE_SEQREAD:
     113       20010 :         return (Location >= Capacity);
     114             :     case MFILE_REGULAR:
     115          10 :         return feof(Handle);
     116             :     case MFILE_GZIP:
     117           0 :         if (GzBuffer_Avail > 0) { return 0; }
     118           0 :         return gzeof(GzHandle);
     119             :     default:
     120             :         return false;
     121             :     }
     122             : }
     123             : 
     124             : inline errorT
     125           0 : MFile::WriteOneByte (byte value)
     126             : {
     127           0 :     ASSERT (FileMode != FMODE_ReadOnly);
     128           0 :     if (Type == MFILE_MEMORY) {
     129           0 :         if (Location >= Capacity) { Extend(); }
     130           0 :         *CurrentPtr++ = value;
     131           0 :         Location++;
     132           0 :         return OK;
     133             :     }
     134           0 :     if (Type == MFILE_SEQREAD) Seek(Location);
     135           0 :     Location++;
     136           0 :     if (Type == MFILE_GZIP) {
     137             :         return (gzputc(GzHandle, value) == EOF) ? ERROR_FileWrite : OK;
     138             :     }
     139           0 :     return (putc(value, Handle) == EOF) ? ERROR_FileWrite : OK;
     140             : }
     141             : 
     142             : inline int
     143    47032237 : MFile::ReadOneByte ()
     144             : {
     145    47032237 :     ASSERT (FileMode != FMODE_WriteOnly);
     146    47032237 :     if (Type == MFILE_MEMORY || Type == MFILE_SEQREAD) {
     147    47032232 :         if (Location >= Capacity) { return EOF; }
     148    47032232 :         if (Location == SeqReadLocation && Type == MFILE_SEQREAD) {
     149        1438 :             SeqReadLocation += fread(Data, 1, SEQREADBUFSIZE, Handle);
     150         719 :             CurrentPtr = Data;
     151             :         }
     152    47032232 :         byte value = *CurrentPtr;
     153    47032232 :         Location++;
     154    47032232 :         CurrentPtr++;
     155    47032232 :         return (int) value;
     156             :     }
     157           5 :     Location++;
     158           5 :     if (Type == MFILE_GZIP) {
     159           0 :         if (GzBuffer_Avail <= 0) {
     160           0 :             return FillGzBuffer();
     161             :         }
     162           0 :         GzBuffer_Avail--;
     163           0 :         int retval = *GzBuffer_Current;
     164           0 :         GzBuffer_Current++;
     165           0 :         return retval;
     166             :     }
     167           5 :     return  getc(Handle);
     168             : }
     169             : 
     170             : #endif  // SCID_MFILE_H
     171             : 

Generated by: LCOV version 1.12