Back to index

lightning-sunbird  0.9+nobinonly
Typedefs | Functions
nr_bufio.h File Reference
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef struct BufioFileStruct

Functions

BufioFile * bufio_Open (const char *name, const char *mode)
 like fopen() this routine takes native filenames, not NSPR names.
int bufio_Close (BufioFile *file)
 close the buffered file and destroy BufioFile struct
int bufio_Seek (BufioFile *file, PRInt32 offset, int whence)
 change the logical position in the file.
PRUint32 bufio_Read (BufioFile *file, char *dest, PRUint32 count)
PRUint32 bufio_Write (BufioFile *file, const char *src, PRUint32 count)
 Buffered writes.
PRInt32 bufio_Tell (BufioFile *file)
 like ftell() returns the current position in the file, or -1 for error
int bufio_Flush (BufioFile *file)
int bufio_SetBufferSize (BufioFile *file, int bufsize)

Typedef Documentation

typedef struct BufioFileStruct

Definition at line 52 of file nr_bufio.h.


Function Documentation

int bufio_Close ( BufioFile *  file)

close the buffered file and destroy BufioFile struct

Definition at line 241 of file nr_bufio.c.

{
    int retval = -1;

    if ( file )
    {
        if ( file->bufdirty )
            _bufio_flushBuf( file );

        retval = fclose( file->fd );

        if ( file->data )
            PR_Free( file->data );

        PR_DELETE( file );
#if DEBUG_dougt
        printf(" --- > Buffered registry read fs hits (%d)\n", num_reads);
#endif
    }

    return retval;
}

Here is the call graph for this function:

int bufio_Flush ( BufioFile *  file)

Definition at line 607 of file nr_bufio.c.

{
    if ( file->bufdirty )
        _bufio_flushBuf( file );
    
    return fflush(file->fd);
}

Here is the call graph for this function:

BufioFile* bufio_Open ( const char *  name,
const char *  mode 
)

like fopen() this routine takes native filenames, not NSPR names.

Definition at line 154 of file nr_bufio.c.

{
    FILE        *fd;
    BufioFile   *file = NULL;

#ifdef XP_OS2
    fd = os2_fileopen( name, mode );
#else
    fd = fopen( name, mode );
#endif
    
    if ( fd )
    {
        /* file opened successfully, initialize the bufio structure */

        file = PR_NEWZAP( BufioFile );
        if ( file )
        {
            file->fd = fd;
            file->bufsize = BUFIO_BUFSIZE_DEFAULT;  /* set the default buffer size */

            file->data = (char*)PR_Malloc( file->bufsize );
            if ( file->data )
            {
                /* get file size to finish initialization of bufio */
                if ( !fseek( fd, 0, SEEK_END ) )
                {
                    file->fsize = ftell( fd );

                    file->readOnly = strcmp(mode,XP_FILE_READ) == 0 || 
                                     strcmp(mode,XP_FILE_READ_BIN) == 0;
                }
                else
                {
                    PR_Free( file->data );
                    PR_DELETE( file );
                }
            }
            else
                PR_DELETE( file );
        }

        /* close file if we couldn't create BufioFile */
        if (!file)
        {
            fclose( fd );
            PR_SetError( PR_OUT_OF_MEMORY_ERROR, 0 );
        }
    }
    else
    {
        /* couldn't open file. Figure out why and set NSPR errors */
        
        switch (errno)
        {
            /* file not found */
#if defined(XP_MAC) || defined(XP_MACOSX)
            case fnfErr:
#else
            case ENOENT:
#endif
                PR_SetError(PR_FILE_NOT_FOUND_ERROR,0);
                break;

            /* file in use */
#if defined(XP_MAC) || defined(XP_MACOSX)
            case opWrErr:
#else
            case EACCES:
#endif
                PR_SetError(PR_NO_ACCESS_RIGHTS_ERROR,0);
                break;

            default:
                PR_SetError(PR_UNKNOWN_ERROR,0);
                break;
        }
    }

    return file;
}

Here is the call graph for this function:

PRUint32 bufio_Read ( BufioFile *  file,
char *  dest,
PRUint32  count 
)

Definition at line 310 of file nr_bufio.c.

{
    PRInt32     startOffset;
    PRInt32     endOffset;
    PRInt32     leftover;
    PRUint32    bytesCopied;
    PRUint32    bytesRead;
    PRUint32    retcount = 0;

    /* sanity check arguments */
    if ( !file || !dest || count == 0 || file->fpos >= file->fsize )
        return 0;

    /* Adjust amount to read if we're near EOF */
    if ( (file->fpos + count) > (PRUint32)file->fsize )
        count = file->fsize - file->fpos;


    /* figure out how much of the data we want is already buffered */

    startOffset = file->fpos - file->datastart;
    endOffset = startOffset + count;

    if ( startOffset >= 0 && startOffset < file->datasize )
    {
        /* The beginning of what we want is in the buffer  */
        /* so copy as much as is available of what we want */

        if ( endOffset <= file->datasize )
            bytesCopied = count;
        else
            bytesCopied = file->datasize - startOffset;

        memcpy( dest, file->data + startOffset, bytesCopied );
        retcount = bytesCopied;
        file->fpos += bytesCopied;
#ifdef DEBUG_dveditzbuf
        file->reads++;
#endif

        /* Was that all we wanted, or do we need to get more? */

        leftover = count - bytesCopied;
        PR_ASSERT( leftover >= 0 );     /* negative left? something's wrong! */

        if ( leftover )
        {
            /* need data that's not in the buffer */

            /* if what's left fits in a buffer then load the buffer with the */
            /* new area before giving the data, otherwise just read right    */
            /* into the user's dest buffer */

            if ( _bufio_loadBuf( file, leftover ) )
            {
                startOffset = file->fpos - file->datastart;

                /* we may not have been able to load as much as we wanted */
                if ( startOffset > file->datasize )
                    bytesRead = 0;
                else if ( startOffset+leftover <= file->datasize )
                    bytesRead = leftover;
                else
                    bytesRead = file->datasize - startOffset;

                if ( bytesRead )
                {
                    memcpy( dest+bytesCopied, file->data+startOffset, bytesRead );
                    file->fpos += bytesRead;
                    retcount += bytesRead;
#ifdef DEBUG_dveditzbuf
                    file->reads++;
#endif
                }
            }
            else 
            {
                /* we need more than we could load into a buffer, so */
                /* skip buffering and just read the data directly    */

                if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
                {
#if DEBUG_dougt
                    ++num_reads;
#endif
                    bytesRead = fread(dest+bytesCopied, 1, leftover, file->fd);
                    file->fpos += bytesRead;
                    retcount += bytesRead;
                }
                else 
                {
                    /* XXX seek failed, couldn't load more data -- help! */
                    /* should we call PR_SetError() ? */
                }
            }
        }
    }
    else
    {
        /* range doesn't start in the loaded buffer but it might end there */
        if ( endOffset > 0 && endOffset <= file->datasize )
            bytesCopied = endOffset;
        else
            bytesCopied = 0;

        leftover = count - bytesCopied;

        if ( bytesCopied )
        {
            /* the tail end of the range we want is already buffered */
            /* first copy the buffered data to the dest area         */
            memcpy( dest+leftover, file->data, bytesCopied );
#ifdef DEBUG_dveditzbuf
            file->reads++;
#endif
        }
            
        /* now pick up the part that's not already in the buffer */

        if ( _bufio_loadBuf( file, leftover ) )
        {
            /* we were able to load some data */
            startOffset = file->fpos - file->datastart;

            /* we may not have been able to read as much as we wanted */
            if ( startOffset > file->datasize )
                bytesRead = 0;
            else if ( startOffset+leftover <= file->datasize )
                bytesRead = leftover;
            else
                bytesRead = file->datasize - startOffset;

            if ( bytesRead )
            {
                memcpy( dest, file->data+startOffset, bytesRead );
#ifdef DEBUG_dveditzbuf
                file->reads++;
#endif
            }
        }
        else
        {
            /* leftover data doesn't fit so skip buffering */
            if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
            {
                bytesRead = fread(dest, 1, leftover, file->fd);
#if DEBUG_dougt
                ++num_reads;
#endif        
            }
            else
                bytesRead = 0;
        }

        /* if we couldn't read all the leftover, don't tell caller */
        /* about the tail end we copied from the first buffer      */
        if ( bytesRead == (PRUint32)leftover )
            retcount = bytesCopied + bytesRead;
        else
            retcount = bytesRead;

        file->fpos += retcount;
    }

    return retcount;
}

Here is the call graph for this function:

int bufio_Seek ( BufioFile *  file,
PRInt32  offset,
int  whence 
)

change the logical position in the file.

Equivalent to fseek()

Definition at line 269 of file nr_bufio.c.

{
    if (!file)
        return -1;

    switch(whence) 
    {
      case SEEK_SET:
           file->fpos = offset;
           break;
         case SEEK_END:
           file->fpos = file->fsize + offset;
           break;
         case SEEK_CUR:
           file->fpos = file->fpos + offset;
           break;
         default:
           return -1;
    }

    if ( file->fpos < 0 ) 
        file->fpos = 0;

    return 0;
}
int bufio_SetBufferSize ( BufioFile *  file,
int  bufsize 
)

Definition at line 719 of file nr_bufio.c.

{
    char    *newBuffer;
    int     retVal = -1;

    PR_ASSERT(file);
    if (!file)
        return retVal;

    if (bufsize == -1)
        bufsize = BUFIO_BUFSIZE_DEFAULT;
    if (bufsize == file->bufsize)
        return bufsize;

    newBuffer = (char*)PR_Malloc( bufsize );
    if (newBuffer)
    {
        /* if the buffer's dirty make sure we successfully flush it */
        if ( file->bufdirty && _bufio_flushBuf(file) != 0 )
        {
            PR_Free( newBuffer );
            return -1;
        }


        file->bufsize = bufsize;
        if ( file->data )
            PR_Free( file->data );
        file->data = newBuffer;
        file->datasize = 0;
        file->datastart = 0;
        retVal = bufsize;
    }
 
    return retVal;
}

Here is the call graph for this function:

PRInt32 bufio_Tell ( BufioFile *  file)

like ftell() returns the current position in the file, or -1 for error

Definition at line 300 of file nr_bufio.c.

{
    if (file)
        return file->fpos;
    else
        return -1;
}
PRUint32 bufio_Write ( BufioFile *  file,
const char *  src,
PRUint32  count 
)

Buffered writes.

Definition at line 482 of file nr_bufio.c.

{
    const char* newsrc;
    PRInt32  startOffset;
    PRInt32  endOffset;
    PRUint32 leftover;
    PRUint32 retcount = 0;
    PRUint32 bytesWritten = 0;
    PRUint32 bytesCopied = 0;

    /* sanity check arguments */
    if ( !file || !src || count == 0 || file->readOnly )
        return 0;

    /* Write to the current buffer if we can, otherwise load a new buffer */

    startOffset = file->fpos - file->datastart;
    endOffset = startOffset + count;

    if ( startOffset >= 0 && startOffset <  file->bufsize )
    {
        /* the area we want to write starts in the buffer */

        if ( endOffset <= file->bufsize )
            bytesCopied = count;
        else
            bytesCopied = file->bufsize - startOffset;

        memcpy( file->data + startOffset, src, bytesCopied );
        file->bufdirty = PR_TRUE;
        endOffset = startOffset + bytesCopied;
        file->dirtystart = PR_MIN( startOffset, file->dirtystart );
        file->dirtyend   = PR_MAX( endOffset,   file->dirtyend );
#ifdef DEBUG_dveditzbuf
        file->writes++;
#endif

        if ( endOffset > file->datasize )
            file->datasize = endOffset;

        retcount = bytesCopied;
        file->fpos += bytesCopied;

        /* was that all we had to write, or is there more? */
        leftover = count - bytesCopied;
        newsrc = src+bytesCopied;
    }
    else
    {
        /* range doesn't start in the loaded buffer but it might end there */
        if ( endOffset > 0 && endOffset <= file->bufsize )
            bytesCopied = endOffset;
        else
            bytesCopied = 0;

        leftover = count - bytesCopied;
        newsrc = src;

        if ( bytesCopied )
        {
            /* the tail end of the write range is already in the buffer */
            memcpy( file->data, src+leftover, bytesCopied );
            file->bufdirty      = PR_TRUE;
            file->dirtystart    = 0;
            file->dirtyend      = PR_MAX( endOffset, file->dirtyend );
#ifdef DEBUG_dveditzbuf
            file->writes++;
#endif

            if ( endOffset > file->datasize )
                file->datasize = endOffset;
        }
    }

    /* if we only wrote part of the request pick up the leftovers */
    if ( leftover )
    {
        /* load the buffer with the new range, if possible */
        if ( _bufio_loadBuf( file, leftover ) )
        {
            startOffset = file->fpos - file->datastart;
            endOffset   = startOffset + leftover;

            memcpy( file->data+startOffset, newsrc, leftover );
            file->bufdirty      = PR_TRUE;
            file->dirtystart    = startOffset;
            file->dirtyend      = endOffset;
#ifdef DEBUG_dveditzbuf
            file->writes++;
#endif
            if ( endOffset > file->datasize )
                file->datasize = endOffset;

            bytesWritten = leftover;
        }
        else
        {
            /* request didn't fit in a buffer, write directly */
            if ( fseek( file->fd, file->fpos, SEEK_SET ) == 0 )
                bytesWritten = fwrite( newsrc, 1, leftover, file->fd );
            else
                bytesWritten = 0; /* seek failed! */
        }

        if ( retcount )
        {
            /* we already counted the first part we wrote */
            retcount    += bytesWritten;
            file->fpos  += bytesWritten;
        }
        else
        {
            retcount    = bytesCopied + bytesWritten;
            file->fpos  += retcount;
        }
    }

    if ( file->fpos > file->fsize )
        file->fsize = file->fpos;
    
    return retcount;
}

Here is the call graph for this function: