chfile.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 395 行

CPP
395
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <assert.h>
#include <string.h>
#include <errno.h>
#include <wcvector.h>
#include <stdio.h>      // need for seek-whence defines
#include <string.hpp>

#include "chfile.h"
#include "wbrdefs.h"

char *      BadWhenceMessage = "Invalid \"whence\" argument.";
const int   MaxOpenReadFiles = 20;      // maximum # of files open for reading

FileExcept::FileExcept( Action act, int error, const char * fn,
                            const char * msg )
                : _action( act )
                , _error( error )
//---------------------------------------------------------------
// have to make a copy of the messages as they may be destroyed
// during stack unwinding
{
    int len;
    const char * storeMsg = (msg) ? msg : strerror( error );

    len = strlen( fn );
    _fileName = new char[ len + 1 ];
    memcpy( _fileName, fn, len + 1 );

    len = strlen( storeMsg );
    _message = new char[ len + 1 ];
    memcpy( _message, storeMsg, len + 1 );
}

#if 0   // avoid compiler error 28
FileExcept::~FileExcept()
//-----------------------
{
    delete [] _fileName;
    delete [] _message;
}
#endif

// OpenFiles is a list of all of the opened CheckedFiles.  It is statically
// initialized, but to avoid including <wcvector.h> in "chfile.h", the
// class only stores a pointer to the static instance.

static WCPtrOrderedVector<CheckedFile> OpenFiles;
static WCPtrOrderedVector<CheckedFile> * CheckedFile::_openFiles = &OpenFiles;

CheckedFile::CheckedFile( const char * fileName )
                : _openAccess( 0 )
                , _openPermission( 0 )
                , _handle( -1 )
                , _currOffset( -1 )
                , _isOpen( FALSE )
                , _logOpen( FALSE )
//---------------------------------------------------------------------------
{
    int len;

    len = strlen( fileName ) + 1;
    _fileName = new char[ len ];

    memcpy( _fileName, fileName, len );
}


CheckedFile::~CheckedFile()
//-------------------------
{
    if( _logOpen ) {
        close();
    }

    delete [] _fileName;
}

void CheckedFile::setFileName( const char * fileName )
//----------------------------------------------------
{
    int len;

    assert( !_isOpen && !_logOpen );

    delete [] _fileName;

    len = strlen( fileName ) + 1;
    _fileName = new char[ len ];

    memcpy( _fileName, fileName, len );
}


void CheckedFile::open( int access, int permission )
//--------------------------------------------------
{
    CheckedFile * closeIt;    // file to be closed when out of handles

    if( !_isOpen ) {
        _openAccess = access;
        _openPermission = permission;

        while( _openFiles->entries() >= MaxOpenReadFiles ) {
            closeIt = _openFiles->removeLast();
            closeIt->privClose();
        }

        _handle = ::open( _fileName, _openAccess, _openPermission );

        while( _handle == -1 && errno == EMFILE ) {
            if( _openFiles->entries() == 0 ) {
                FileExcept oops( FileExcept::Open, errno, _fileName );
                throw( oops );
            }

            closeIt = _openFiles->removeLast();
            closeIt->privClose();

            _handle = ::open( _fileName, _openAccess, _openPermission );
        }

        if( _handle == -1 ) {   // error other than out of handles
            FileExcept oops( FileExcept::Open, errno, _fileName );
            throw( oops );
        }

        _isOpen = TRUE;
        _logOpen = TRUE;
        _currOffset = 0;
        if( !( _openAccess & O_WRONLY ) ) {
            _openFiles->append( this );
        }
    }
}

void CheckedFile::reOpen()
//------------------------
// re-open a file and seek to the position it
// was closed at.
{
    long newOff;

    CheckedFile::open( _openAccess, _openPermission );
    newOff = ::lseek( _handle, _currOffset, SEEK_SET );

    assert( newOff == _currOffset );
}


void CheckedFile::close()
//-----------------------
{
    assert( _logOpen );

    privClose();

    _logOpen = FALSE;
    _currOffset = -1;
    _handle = -1;
}

void CheckedFile::privClose()
//---------------------------
// close the physical file, logical file stays open
// since privClose is called from a destructor, avoid
// doing a throw in it.
{
    int retVal;

    if( _isOpen ) {
        retVal = ::close( _handle );

        assert( retVal == 0 );

        if( _openAccess & O_RDONLY ) {
            _openFiles->remove( this );
        }
    }

    _isOpen = FALSE;
}


int CheckedFile::read( void * buffer, int len )
//---------------------------------------------
{
    int numRead;

    if( !_isOpen ) {
        reOpen();
    }

    numRead = ::read( _handle, buffer, len );

    if( numRead == -1 ) {
        FileExcept oops( FileExcept::Read, errno, _fileName );
        throw( oops );
    }

    _currOffset += numRead;

    return numRead;
}

void CheckedFile::write( const void * buffer, int len )
//-----------------------------------------------------
{
    int numWritten;

    if( !_isOpen ) {
        reOpen();
    }

    numWritten = ::write( _handle, (void *) buffer, len );  // cast away const

    if( numWritten != len ) {
        FileExcept oops( FileExcept::Write, errno, _fileName );
        throw( oops );
    }

    _currOffset += numWritten;
}

int CheckedFile::readNString( String & str )
//------------------------------------------
// read in a string in the form <uint_16>{<byte>}*
{
    const   BufLen = 255;
    char    buffer[ BufLen + 1 ];
    uint_16 strLen;
    uint_16 amtRead = 0;
    int     maxRead;

    str = "";       // clear string

    read( &strLen, sizeof( uint_16 ) );

    while( amtRead < strLen ) {
        maxRead = minInt( BufLen, strLen - amtRead );
        read( buffer, maxRead );
        buffer[ maxRead ] = '\0';
        str += buffer;
        amtRead += maxRead;
    }

    return strLen;
}

int CheckedFile::writeNString( String & str )
//-------------------------------------------
// write out a string in the form <uint_16>{<byte>}*
{
    uint_16 strLen;

    strLen = (uint_16) str.length();
    write( &strLen, sizeof( uint_16 ) );
    write( (const char *) str, strLen );

    return strLen;
}

void CheckedFile::puts( const char * str )
//----------------------------------------
{
    int len;

    if( str != NULL ) {
        len = strlen( str );
        if( len > 0 ){
            write( str, len );
        }
    }

    write( "\n", 1 );
}


long CheckedFile::seek( long offset, int whence )
//-----------------------------------------------
{
    long newOff;

    if( !_isOpen ) {
        _currOffset = offset;
        reOpen();
    }

    switch( whence ) {
    case SEEK_SET:
        if( offset > _currOffset ) {
            newOff = ::lseek( _handle, offset - _currOffset, SEEK_CUR );
        } else {
            if( offset == _currOffset ) {
                return offset;              // already at right position
            } else {
                newOff = ::lseek( _handle, offset, SEEK_SET );
            }
        }
        break;
    case SEEK_CUR:
    case SEEK_END:
        newOff = ::lseek( _handle, offset, whence );
        break;
    default:
        FileExcept oops( FileExcept::Seek, EINVAL, _fileName, BadWhenceMessage );
        throw( oops );
    }

    if( newOff == -1 ) {
        FileExcept oops( FileExcept::Seek, errno, _fileName );
        throw( oops );
    }

    _currOffset = newOff;
    return newOff;
}

long CheckedFile::tell() const
//----------------------------
{
    return _currOffset;
}

int CheckedFile::fstat( struct stat * buf )
//-----------------------------------------
{
    int retVal;

    if( !_isOpen ) {
        reOpen();
    }

    retVal = ::fstat( _handle, buf );

    if( retVal != 0 ) {
        FileExcept oops( FileExcept::Stat, errno, _fileName );
        throw( oops );
    }

    return retVal;
}

time_t CheckedFile::st_mtime()
//----------------------------
{
    struct stat buf;

    fstat( &buf );

    return buf.st_mtime;
}

off_t CheckedFile::st_size()
//--------------------------
{
    struct stat buf;

    fstat( &buf );

    return buf.st_size;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?