Changeset 4426


Ignore:
Timestamp:
Oct 5, 2000, 9:27:57 AM (25 years ago)
Author:
bird
Message:

Implemented buffering of read and write in class kFile.

Location:
trunk/tools/common
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/tools/common/kFile.cpp

    r4402 r4426  
    1 /* $Id: kFile.cpp,v 1.6 2000-10-03 05:42:38 bird Exp $
     1/* $Id: kFile.cpp,v 1.7 2000-10-05 07:27:56 bird Exp $
    22 *
    33 * kFile - Simple (for the time being) file class.
     
    8484        offReal = offVirtual;
    8585    }
     86    else
     87        rc = NO_ERROR;
    8688
    8789    return TRUE;
    8890}
     91
     92
     93/**
     94 * Reads data from the file into the buffer from the given file offset.
     95 * @returns Success indicator.
     96 * @param   offFile     File offset to read from.
     97 *                      (If readonly and beyond end of file the offset used
     98 *                       may be addjusted.)
     99 * @author  knut st. osmundsen (knut.stange.osmundsen@mynd.no)
     100 */
     101BOOL kFile::bufferRead(ULONG offFile) throw (int)
     102{
     103    ULONG   cbRead;
     104
     105    /* refresh file status (cbFile) */
     106    if (!refreshFileStatus())
     107        return FALSE;
     108
     109    /* check that the request is valid */
     110    if (offFile > filestatus.cbFile)
     111        return FALSE;
     112
     113    /* commit dirty buffer */
     114    if (fBufferDirty)
     115    {
     116        if (!bufferCommit())
     117            return TRUE;
     118
     119        /* refresh file status (cbFile) */
     120        if (!refreshFileStatus())
     121            return FALSE;
     122    }
     123
     124    /* If readonly file optimize end of file */
     125    if (fReadOnly && cbBuffer + offFile > filestatus.cbFile)
     126        offFile = filestatus.cbFile > cbBuffer ? filestatus.cbFile - cbBuffer : 0UL;
     127
     128    /* need to change file ptr? */
     129    if (offFile != offReal)
     130    {
     131        ULONG ul;
     132        rc = DosSetFilePtr(hFile, offFile, FILE_BEGIN, &ul);
     133        if (rc != NO_ERROR)
     134        {
     135            if (fThrowErrors)
     136                throw ((int)rc);
     137            return FALSE;
     138        }
     139        offReal = offFile;
     140    }
     141
     142    /* read from the file */
     143    cbRead = min(filestatus.cbFile - offFile, cbBuffer);
     144    rc = DosRead(hFile, pachBuffer, cbRead, &cbRead);
     145    if (rc == NO_ERROR)
     146    {
     147        cbBufferValid   = cbRead;
     148        offBuffer       = offFile;
     149        offReal         = offFile + cbRead;
     150        fBufferDirty    = FALSE;
     151    }
     152    else
     153    {
     154        cbBufferValid   = 0;
     155        offBuffer       = ~0UL;
     156        fBufferDirty    = FALSE;
     157        if (fThrowErrors)
     158            throw ((int)rc);
     159        return FALSE;
     160    }
     161
     162    return TRUE;
     163}
     164
     165
     166/**
     167 * Commits the data in the buffer.
     168 * @returns Success indicator.
     169 * @author  knut st. osmundsen (knut.stange.osmundsen@mynd.no)
     170 */
     171BOOL kFile::bufferCommit(void) throw (int)
     172{
     173    ULONG   cbWrote;
     174    ULONG   ul;
     175
     176    /* don't commit clean buffers! */
     177    if (!fBufferDirty)
     178        return TRUE;
     179
     180    /* need to change file ptr? */
     181    if (offBuffer != offReal)
     182    {
     183        rc = DosSetFilePtr(hFile, offBuffer, FILE_BEGIN, &ul);
     184        if (rc != NO_ERROR)
     185        {
     186            if (fThrowErrors)
     187                throw ((int)rc);
     188            return FALSE;
     189        }
     190        offReal = offBuffer;
     191    }
     192
     193    /* write to the file */
     194    rc = DosWrite(hFile, pachBuffer, cbBufferValid, &cbWrote);
     195    fStatusClean = FALSE;
     196    if (rc == NO_ERROR)
     197    {
     198        fBufferDirty = FALSE;
     199        offReal += cbWrote;
     200    }
     201    else
     202    {
     203        DosSetFilePtr(hFile, offReal, FILE_BEGIN, &ul);
     204        if (fThrowErrors)
     205            throw ((int)rc);
     206        return FALSE;
     207    }
     208
     209    return TRUE;
     210}
     211
    89212
    90213/**
     
    107230    pszFilename(NULL),
    108231    hFile(hFile),
    109     fStdDev(TRUE)
     232    fStdDev(TRUE),
     233    pachBuffer(NULL),
     234    cbBufferValid(0UL),
     235    offBuffer(~0UL),
     236    fBufferDirty(FALSE)
    110237{
    111238    if (!refreshFileStatus())
     
    132259    offReal(0),
    133260    pszFilename(NULL),
    134     fStdDev(FALSE)
     261    fStdDev(FALSE),
     262    pachBuffer(NULL),
     263    cbBufferValid(0UL),
     264    offBuffer(~0UL),
     265    fBufferDirty(FALSE)
    135266{
    136267    ULONG   fulOpenFlags;
     
    166297    if (this->pszFilename == NULL)
    167298        throw (ERROR_NOT_ENOUGH_MEMORY);
     299
     300    /* Buffering */
     301    cbBuffer   = (fReadOnly && filestatus.cbFile < 32768) ? filestatus.cbFile : 8192;
     302    pachBuffer = new char[cbBuffer];
     303    if (pachBuffer == NULL)
     304        throw (ERROR_NOT_ENOUGH_MEMORY);
     305    if (fReadOnly && filestatus.cbFile < 32768)
     306    {
     307        if (!bufferRead(0))
     308            throw ((int)rc);
     309    }
    168310}
    169311
     
    174316kFile::~kFile()
    175317{
     318    if (fBufferDirty)
     319        bufferCommit();
     320    if (pachBuffer)
     321        delete pachBuffer;
    176322    DosClose(hFile);
    177323}
     
    186332BOOL            kFile::read(void *pvBuffer, long cbBuffer)
    187333{
    188     if (position())
    189     {
    190         ULONG   cbRead;
     334    ULONG   cbRead;
     335
     336    /* Validate parameters */
     337    if (cbBuffer == 0)
     338        return TRUE;
     339    if (cbBuffer < 0)
     340    {
     341        rc = ERROR_INVALID_PARAMETER;
     342        if (fThrowErrors)
     343            throw ((int)rc);
     344        return FALSE;
     345    }
     346
     347    /* refresh file status (cbFile) */
     348    if (!refreshFileStatus())
     349        return FALSE;
     350
     351    /* check if valid request */
     352    if (    offVirtual > filestatus.cbFile
     353        ||  offVirtual + cbBuffer > filestatus.cbFile
     354        )
     355    {   /* invalid request */
     356        rc = ERROR_NO_DATA;
     357    }
     358    else if (this->cbBufferValid == filestatus.cbFile && offBuffer == 0)
     359    {
     360        /*
     361         * The entire file is buffered
     362         *      Complete the request.
     363         */
     364        memcpy(pvBuffer, &pachBuffer[offVirtual], (size_t)cbBuffer);
     365        offVirtual += cbBuffer;
     366        rc = NO_ERROR;
     367    }
     368    else if (pachBuffer && cbBuffer <= this->cbBuffer)
     369    {   /*
     370         * Buffered read. (request not bigger than the buffer!)
     371         *      Update status (filesize).
     372         *      Check if the request is with the bounds of the file.
     373         *      Not in buffer?
     374         *          Then read more data into buffer.
     375         *      In buffer?
     376         *          Then complete the request.
     377         *
     378         */
     379        while (cbBuffer > 0)
     380        {
     381            /* Part or all in buffer? */
     382            if (pachBuffer != NULL &&
     383                offVirtual >= offBuffer &&
     384                offVirtual < offBuffer + cbBufferValid
     385                )
     386            {   /* copy data from buffer */
     387                cbRead = cbBufferValid - offVirtual + offBuffer;
     388                cbRead = min(cbRead, cbBuffer);
     389                memcpy(pvBuffer, &pachBuffer[offVirtual - offBuffer], (size_t)cbRead);
     390                offVirtual += cbRead;
     391                pvBuffer = (char*)pvBuffer + cbRead;
     392                cbBuffer -= cbRead;
     393            }
     394            else
     395            {
     396                /* read into buffer */
     397                if (!bufferRead(offVirtual))
     398                    return FALSE;
     399            }
     400        }
     401
     402        rc = NO_ERROR;
     403    }
     404    else if (position())
     405    {   /*
     406         * unbuffered read.
     407         */
    191408        rc = DosRead(hFile, pvBuffer, cbBuffer, &cbRead);
    192409        if (rc == NO_ERROR)
    193         {
    194410            offVirtual = offReal += cbRead;
    195             return TRUE;
    196         }
    197     }
    198 
    199     if (fThrowErrors)
    200         throw ((int)rc);
    201     return FALSE;
     411    }
     412
     413    /* check for error and return accordingly */
     414    if (rc)
     415    {
     416        if (fThrowErrors)
     417            throw ((int)rc);
     418        return FALSE;
     419    }
     420    return TRUE;
    202421}
    203422
     
    255474 * @status  partially implemented.
    256475 * @author  knut st. osmundsen (knut.stange.osmundsen@mynd.no)
    257  * @remark  Should implemented buffered read ASAP!
    258476 */
    259477BOOL            kFile::readln(char *pszBuffer, long cchBuffer) throw (int)
    260478{
    261     char    *psz;
    262     long    cbRead = min(max((long)filestatus.cbFile - (long)offVirtual, 0), cchBuffer-1);
     479    long    cbRead;
     480
     481    /* refresh file status (cbFile) */
     482    if (!refreshFileStatus())
     483        return FALSE;
    263484
    264485    /*
    265      * Read full buffer length or remining part of file into the buffer.
    266      * Look for line end.
    267      * Found lineend: cut buffer there and rewind file back to that point (but skipping the newline).
     486     * Buffered read.
     487     *      Calc max read size.
     488     *      Loop buffer by buffer looking for a newline.
    268489     */
    269     if (cbRead == 0 || !read(pszBuffer, cbRead) )
     490    cbRead = min(max((long)filestatus.cbFile - (long)offVirtual, 0), cchBuffer-1);
     491    if (cbRead == 0)
    270492        return FALSE;
    271493
    272     pszBuffer[cbRead] = '\0';
    273 
    274     psz = strpbrk(pszBuffer, "\r\n");
    275     if (psz != NULL)
    276     {
    277         cbRead -= psz - pszBuffer;
    278         if (*psz == '\r')
     494    while (cbRead > 0)
     495    {
     496        char *pszNewLine;
     497        char *pszReturn;
     498        char *pszEnd;
     499        unsigned long cch;
     500
     501        /* read more buffer ? */
     502        if (offVirtual >= offBuffer + cbBufferValid || offVirtual < offBuffer)
     503            if (!bufferRead(offVirtual))
     504                return FALSE;
     505
     506        /* Scan buffer for new line */
     507        pszNewLine = (char*)memchr(&pachBuffer[offVirtual - offBuffer], '\r', (size_t)(cbBufferValid - offVirtual + offBuffer));
     508        pszReturn  = (char*)memchr(&pachBuffer[offVirtual - offBuffer], '\n', (size_t)(cbBufferValid - offVirtual + offBuffer));
     509        if (pszNewLine != NULL || pszReturn != NULL)
    279510        {
    280             if (psz[1] == '\n')
    281                 cbRead -= 2;
     511            pszEnd = pszReturn != NULL && (pszNewLine == NULL || pszReturn < pszNewLine) ?
     512                    pszReturn : pszNewLine;
     513            cch = pszEnd - &pachBuffer[offVirtual - offBuffer];
     514        }
     515        else
     516        {
     517            pszEnd = NULL;
     518            cch = cbBufferValid - offVirtual + offBuffer;
     519        }
     520
     521        /* copy into result buffer */
     522        memcpy(pszBuffer, &pachBuffer[offVirtual - offBuffer], (size_t)cch);
     523        cbRead -= cch;
     524        offVirtual += cch;
     525        pszBuffer += cch;
     526        *pszBuffer = '\0';
     527
     528        /* check for completion */
     529        if (pszEnd != NULL)
     530        {   /* skip newline */
     531            if (pszEnd[0] == '\r')
     532            {
     533                if (cch + 1 > cbBufferValid)
     534                {
     535                    if (bufferRead(offBuffer + cbBufferValid))
     536                        pszEnd = pachBuffer;
     537                }
     538                else
     539                    pszEnd++;
     540                offVirtual += pszEnd != NULL && *pszEnd == '\n'  ? 2 : 1;
     541            }
    282542            else
    283                 cbRead--;
    284         }
    285         else if (*psz == '\n')
    286             cbRead--;
    287 
    288         *psz = '\0';
    289 
    290         return move(-cbRead);
     543                offVirtual++;
     544            return TRUE;
     545        }
    291546    }
    292547
     
    307562    else
    308563    {
    309         if (position())
    310         {
     564        ULONG cbWrite;
     565        ULONG cbAddPost = 0;
     566
     567        /* buffered writes? */
     568        if (pachBuffer != NULL)
     569        {   /* Buffered write!
     570             *      Init buffer if necessary.
     571             *      Check if all fits into current buffer.
     572             *          Update buffer and return.
     573             *      Check if some fits into the current buffer
     574             *          Start - update valid part of the buffer. Commit buffer.
     575             *          End   - update buffer. no write
     576             *          Not   - commit buffer.
     577             */
     578            if (offBuffer == ~0UL)
     579            {   /* Empty buffer at current virtual offset */
     580                cbBufferValid = offVirtual;
     581                offBuffer = 0;
     582            }
     583
     584            if (    offBuffer <= offVirtual
     585                &&  offBuffer + this->cbBuffer > offVirtual + cbBuffer
     586                )
     587            {   /* all fits into the buffer */
     588                memcpy(&pachBuffer[offVirtual - offBuffer], pvBuffer, (size_t)cbBuffer);
     589                fBufferDirty = TRUE;
     590                if (cbBufferValid < offVirtual - offBuffer + cbBuffer)
     591                    cbBufferValid = offVirtual - offBuffer + cbBuffer;
     592                offVirtual += cbBuffer;
     593                return TRUE;
     594            }
     595            else if (   offBuffer <= offVirtual
     596                     && offBuffer + this->cbBufferValid > offVirtual
     597                     )
     598            {   /* start fits into the valid part of the buffer */
     599                cbWrite = this->cbBuffer - (offVirtual - offBuffer);
     600                memcpy(&pachBuffer[offVirtual - offBuffer], pvBuffer, (size_t)cbWrite);
     601                fBufferDirty = TRUE;
     602                if (cbBufferValid < offVirtual - offBuffer + cbWrite)
     603                    cbBufferValid = offVirtual - offBuffer + cbWrite;
     604                pvBuffer = (char*)pvBuffer + cbWrite;
     605                cbBuffer -= cbWrite;
     606                offVirtual += cbWrite;
     607                if (!bufferCommit())
     608                    return FALSE;
     609            }
     610            else if (   offBuffer < offVirtual + cbBuffer
     611                     && offBuffer + this->cbBuffer >= offVirtual + cbBuffer
     612                     )
     613            {   /* end fits into the buffer */
     614                cbWrite = offVirtual + cbBuffer - offBuffer;
     615                memcpy(pachBuffer, &((char*)pvBuffer)[offBuffer - offVirtual], (size_t)cbWrite);
     616                fBufferDirty = TRUE;
     617                if (cbBufferValid < cbWrite)
     618                    cbBufferValid = cbWrite;
     619                cbBuffer -= cbWrite;
     620                cbAddPost = cbWrite;
     621            }
     622            else if (   offVirtual + cbBuffer <= offBuffer
     623                     || offVirtual >= offBuffer + this->cbBufferValid
     624                     )
     625            {   /* don't fit into the buffer at all */
     626                if (!bufferCommit())
     627                    return FALSE;
     628            }
     629
     630            /* Set filepointer. */
     631            if (!position())
     632                return FALSE;
     633
     634            /* Write. */
     635            rc = DosWrite(hFile, pvBuffer, cbBuffer, &cbWrite);
     636            if (rc == NO_ERROR)
     637            {
     638                offVirtual = offReal += cbWrite;
     639                if (cbAddPost == 0)
     640                {   /* no post add; start empty buffer at current virtual offset .*/
     641                    offBuffer = offVirtual;
     642                    cbBufferValid = 0;
     643                    fBufferDirty = FALSE;
     644                }
     645                else
     646                    offVirtual += cbAddPost;
     647                return TRUE;
     648            }
     649        }
     650        else if (position())
     651        {   /* non-buffered write! */
    311652            ULONG   cbWrote;
    312653
     
    314655            if (rc == NO_ERROR)
    315656            {
    316                 fStatusClean = FALSE;
    317657                offVirtual = offReal += cbWrote;
    318658                return TRUE;
     
    358698    /* !QUICK AND DIRTY! */
    359699    char *  psz, * pszEnd;
    360     char *  pszBuffer = (char*)malloc(1024*64); //64KB should normally be enough...
     700    static char    szBuffer[1024*64];   //64KB should normally be enough for anyone...
    361701
    362702    va_start(arg, pszFormat);
    363     pszEnd = vsprintf(pszBuffer, pszFormat, arg) + pszBuffer;
     703    pszEnd = vsprintf(szBuffer, pszFormat, arg) + szBuffer;
    364704    va_end(arg);
    365705
    366706    psz = pszEnd;
    367     while (psz > pszBuffer)
     707    while (psz > szBuffer)
    368708    {
    369709        if (*psz-- == '\n' && *psz != '\r')
     
    375715    }
    376716
    377     write(pszBuffer, pszEnd - pszBuffer);
    378     free(pszBuffer);
     717    write(szBuffer, pszEnd - szBuffer);
    379718
    380719    return (int)(getPos() - offStart);
     
    401740
    402741
    403 
    404742/**
    405743 * Appends the AppendFile to this file.
     
    437775    return *this;
    438776}
    439 
    440777
    441778
     
    501838    if (!refreshFileStatus())
    502839        return FALSE;
    503     offVirtual = filestatus.cbFile; //?? or +1
     840
     841    if (!fReadOnly && pachBuffer && offBuffer != ~0UL && offBuffer + cbBufferValid > filestatus.cbFile)
     842        /* a writable file with buffer might have uncommited data in the buffer. */
     843        offVirtual = offBuffer + cbBufferValid;
     844    else
     845        offVirtual = filestatus.cbFile;
     846
    504847    rc = NO_ERROR;
    505848    return TRUE;
  • TabularUnified trunk/tools/common/kFile.h

    r4402 r4426  
    1 /* $Id: kFile.h,v 1.6 2000-10-03 05:42:38 bird Exp $
     1/* $Id: kFile.h,v 1.7 2000-10-05 07:27:57 bird Exp $
    22 *
    33 * kFile - Simple (for the time being) file class.
     
    3838
    3939    /** @cat Buffering datamembers */
     40    char *          pachBuffer;         /* Pointer to the buffer. NULL if not buffering. */
     41    unsigned long   cbBuffer;           /* Count of allocated bytes. */
     42    unsigned long   offBuffer;          /* Virtual file offset where the buffer starts. */
     43    unsigned long   cbBufferValid;      /* Count of valid bytes in the buffer. */
     44    BOOL            fBufferDirty;       /* Dirty flag. Set when the buffer needs to be committed. */
     45
     46    /** @cat internal buffer methods */
     47    BOOL            bufferRead(ULONG offFile) throw (int);
     48    BOOL            bufferCommit(void) throw (int);
    4049
    4150    /** @cat internal methods for maintaing internal structures. */
  • TabularUnified trunk/tools/common/kFileDef.cpp

    r4424 r4426  
    114114    if (pFile->start())
    115115    {
    116         this->read(pFile);
     116        try
     117        {
     118            this->read(pFile);
     119        }
     120        catch (int err)
     121        {
     122            throw (err);
     123        }
    117124    }
    118125    else
  • TabularUnified trunk/tools/common/makefile.icc

    r4402 r4426  
    1 # $Id: makefile.icc,v 1.12 2000-10-03 05:42:40 bird Exp $
     1# $Id: makefile.icc,v 1.13 2000-10-05 07:27:57 bird Exp $
    22
    33#
     
    5454$(OBJDIR)\commonicc.lib: $(OBJS)
    5555    $(RM) $@
    56     $(ILIB) /nobackup $@ $(OBJS: = +), NUL;
     56    $(ILIB)/quiet /nobackup $@ $(OBJS: = +), NUL;
    5757
    5858# kDump
Note: See TracChangeset for help on using the changeset viewer.