Commit b065b37a authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

richio improvements, fix dangling open file

parents 2d1a7e09 9ae4e609
Loading
Loading
Loading
Loading
+32 −5
Original line number Diff line number Diff line
@@ -27,14 +27,41 @@
#include <richio.h>
#include <filter_reader.h>

unsigned FILTER_READER::ReadLine() throw( IO_ERROR )

FILTER_READER::FILTER_READER( LINE_READER& aReader ) :
    LINE_READER( 1 ),
    reader( aReader )
{
    unsigned ret;
    // Not using our own line buffer, will be using aReader's.  This changes
    // the meaning of this->line to be merely a pointer to aReader's line, which of course
    // is not owned here.
    delete [] line;

    line = 0;
}


    while( ( ret = reader.ReadLine() ) != 0 )
FILTER_READER::~FILTER_READER()
{
        if( !strchr( "#\n\r", reader[0] ) )
    // Our 'line' points to aReader's, and he will delete that buffer.
    // Prevent subsequent call to ~LINE_READER() from deleting a buffer we do not own.
    line = 0;
}


char* FILTER_READER::ReadLine() throw( IO_ERROR )
{
    char* s;

    while( ( s = reader.ReadLine() ) != NULL )
    {
        if( !strchr( "#\n\r", s[0] ) )
            break;
    }
    return ret;

    line   = reader.Line();
    length = reader.Length();

    return length ? line : NULL;
}
+35 −40
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength )
}


LINE_READER::~LINE_READER()
{
    delete[] line;
}


void LINE_READER::expandCapacity( unsigned newsize )
{
    // length can equal maxLineLength and nothing breaks, there's room for
@@ -89,6 +95,27 @@ void LINE_READER::expandCapacity( unsigned newsize )
}


FILE_LINE_READER::FILE_LINE_READER( const wxString& aFileName,
            unsigned aStartingLineNumber,
            unsigned aMaxLineLength ) throw( IO_ERROR ) :
    LINE_READER( aMaxLineLength ),
    iOwn( true )
{
    fp = wxFopen( aFileName, wxT( "rt" ) );
    if( !fp )
    {
        wxString msg = wxString::Format(
            _( "Unable to open filename '%s' for reading" ), aFileName.GetData() );
        THROW_IO_ERROR( msg );
    }

    setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 );

    source  = aFileName;
    lineNum = aStartingLineNumber;
}


FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
                    bool doOwn,
                    unsigned aStartingLineNumber,
@@ -97,7 +124,7 @@ FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
    iOwn( doOwn ),
    fp( aFile )
{
    if( doOwn )
    if( doOwn && ftell( aFile ) == 0L )
    {
        setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 );
    }
@@ -113,40 +140,8 @@ FILE_LINE_READER::~FILE_LINE_READER()
        fclose( fp );
}

#if 0

// The strlen() will trip on embedded nuls which can come in via bad data files.
// Try an alternate technique below.

unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
{
    length  = 0;
    line[0] = 0;

    // fgets always puts a terminating nul at end of its read.
    while( fgets( line + length, capacity - length, fp ) )
    {
        length += strlen( line + length );

        if( length >= maxLineLength )
            THROW_IO_ERROR( _("Line length exceeded") );

        // a normal line breaks here, once through while loop
        if( length+1 < capacity || line[length-1] == '\n' )
            break;

        expandCapacity( capacity * 2 );
    }

    // lineNum is incremented even if there was no line read, because this
    // leads to better error reporting when we hit an end of file.
    ++lineNum;

    return length;
}

#else
unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
char* FILE_LINE_READER::ReadLine() throw( IO_ERROR )
{
    length = 0;

@@ -175,9 +170,8 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
    // leads to better error reporting when we hit an end of file.
    ++lineNum;

    return length;
    return length ? line : NULL;
}
#endif


STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) :
@@ -203,7 +197,8 @@ STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint
    lineNum = aStartingPoint.lineNum;
}

unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )

char* STRING_LINE_READER::ReadLine() throw( IO_ERROR )
{
    size_t  nlOffset = lines.find( '\n', ndx );

@@ -231,7 +226,7 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )

    line[length] = 0;

    return length;
    return length ? line : NULL;
}


@@ -242,7 +237,7 @@ INPUTSTREAM_LINE_READER::INPUTSTREAM_LINE_READER( wxInputStream* aStream ) :
}


unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR )
char* INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR )
{
    length  = 0;

@@ -272,7 +267,7 @@ unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR )
    // leads to better error reporting when we hit an end of file.
    ++lineNum;

    return length;
    return length ? line : NULL;
}


+3 −1
Original line number Diff line number Diff line
@@ -117,7 +117,9 @@ protected:
    {
        if( reader )
        {
            unsigned len = reader->ReadLine();
            reader->ReadLine();

            unsigned len = reader->Length();

            // start may have changed in ReadLine(), which can resize and
            // relocate reader's line buffer.
+4 −15
Original line number Diff line number Diff line
@@ -45,32 +45,21 @@ public:
     * Constructor ( LINE_READER& )
     * does not take ownership over @a aReader, so will not destroy it.
     */
    FILTER_READER( LINE_READER& aReader ) :
       reader( aReader )
    {
    }
    FILTER_READER( LINE_READER& aReader );

    ~FILTER_READER();

    unsigned ReadLine() throw( IO_ERROR );
    char* ReadLine() throw( IO_ERROR );

    const wxString& GetSource() const
    {
        return reader.GetSource();
    }

    char* Line() const
    {
        return reader.Line();
    }

    unsigned LineNumber() const
    {
        return reader.LineNumber();
    }

    unsigned Length() const
    {
        return reader.Length();
    }
};

#endif // FILTER_READER_H_
+29 −11
Original line number Diff line number Diff line
@@ -227,20 +227,17 @@ public:
     */
    LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );

    virtual ~LINE_READER()
    {
        delete[] line;
    }
    virtual ~LINE_READER();

    /**
     * Function ReadLine
     * reads a line of text into the buffer and increments the line number
     * counter.  If the line is larger than aMaxLineLength passed to the
     * constructor, then an exception is thrown.  The line is nul terminated.
     * @return unsigned - The number of bytes read, 0 at end of file.
     * @return char* - The beginning of the read line, or NULL if EOF.
     * @throw IO_ERROR when a line is too long.
     */
    virtual unsigned ReadLine() throw( IO_ERROR ) = 0;
    virtual char* ReadLine() throw( IO_ERROR ) = 0;

    /**
     * Function GetSource
@@ -258,7 +255,7 @@ public:
     * Function Line
     * returns a pointer to the last line that was read in.
     */
    virtual char* Line() const
    char* Line() const
    {
        return line;
    }
@@ -287,7 +284,7 @@ public:
     * Function Length
     * returns the number of bytes in the last line read from this LINE_READER.
     */
    virtual unsigned Length() const
    unsigned Length() const
    {
        return length;
    }
@@ -308,6 +305,27 @@ protected:

public:

    /**
     * Constructor FILE_LINE_READER
     * takes @a aFileName and the size of the desired line buffer and opens
     * the file and assumes the obligation to close it.
     *
     * @param aFileName is the name of the file to open and to use for error reporting purposes.
     *
     * @param aStartingLineNumber is the initial line number to report on error, and is
     *  accessible here for the case where multiple DSNLEXERs are reading from the
     *  same file in sequence, all from the same open file (with @a doOwn = false).
     *  Internally it is incremented by one after each ReadLine(), so the first
     *  reported line number will always be one greater than what is provided here.
     *
     * @param aMaxLineLength is the number of bytes to use in the line buffer.
     *
     * @throw IO_ERROR if @a aFileName cannot be opened.
     */
    FILE_LINE_READER( const wxString& aFileName,
            unsigned aStartingLineNumber = 0,
            unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ) throw( IO_ERROR );

    /**
     * Constructor FILE_LINE_READER
     * takes an open FILE and the size of the desired line buffer and takes
@@ -333,7 +351,7 @@ public:
     */
    ~FILE_LINE_READER();

    unsigned ReadLine() throw( IO_ERROR );   // see LINE_READER::ReadLine() description
    char* ReadLine() throw( IO_ERROR );   // see LINE_READER::ReadLine() description

    /**
     * Function Rewind
@@ -380,7 +398,7 @@ public:
     */
    STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint );

    unsigned ReadLine() throw( IO_ERROR );    // see LINE_READER::ReadLine() description
    char* ReadLine() throw( IO_ERROR );    // see LINE_READER::ReadLine() description
};


@@ -402,7 +420,7 @@ public:
     */
    INPUTSTREAM_LINE_READER( wxInputStream* aStream );

    unsigned ReadLine() throw( IO_ERROR );    // see LINE_READER::ReadLine() description
    char* ReadLine() throw( IO_ERROR );    // see LINE_READER::ReadLine() description
};


Loading