Commit b065b37a authored by Dick Hollenbeck's avatar Dick Hollenbeck

richio improvements, fix dangling open file

parents 2d1a7e09 9ae4e609
...@@ -27,14 +27,41 @@ ...@@ -27,14 +27,41 @@
#include <richio.h> #include <richio.h>
#include <filter_reader.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;
}
FILTER_READER::~FILTER_READER()
{
// 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;
}
while( ( ret = reader.ReadLine() ) != 0 )
char* FILTER_READER::ReadLine() throw( IO_ERROR )
{
char* s;
while( ( s = reader.ReadLine() ) != NULL )
{ {
if( !strchr( "#\n\r", reader[0] ) ) if( !strchr( "#\n\r", s[0] ) )
break; break;
} }
return ret;
line = reader.Line();
length = reader.Length();
return length ? line : NULL;
} }
...@@ -64,6 +64,12 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength ) ...@@ -64,6 +64,12 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength )
} }
LINE_READER::~LINE_READER()
{
delete[] line;
}
void LINE_READER::expandCapacity( unsigned newsize ) void LINE_READER::expandCapacity( unsigned newsize )
{ {
// length can equal maxLineLength and nothing breaks, there's room for // length can equal maxLineLength and nothing breaks, there's room for
...@@ -89,6 +95,27 @@ void LINE_READER::expandCapacity( unsigned newsize ) ...@@ -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, FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
bool doOwn, bool doOwn,
unsigned aStartingLineNumber, unsigned aStartingLineNumber,
...@@ -97,7 +124,7 @@ FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, ...@@ -97,7 +124,7 @@ FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
iOwn( doOwn ), iOwn( doOwn ),
fp( aFile ) fp( aFile )
{ {
if( doOwn ) if( doOwn && ftell( aFile ) == 0L )
{ {
setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 ); setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 );
} }
...@@ -113,40 +140,8 @@ FILE_LINE_READER::~FILE_LINE_READER() ...@@ -113,40 +140,8 @@ FILE_LINE_READER::~FILE_LINE_READER()
fclose( fp ); 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 char* FILE_LINE_READER::ReadLine() throw( IO_ERROR )
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 )
{ {
length = 0; length = 0;
...@@ -175,9 +170,8 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) ...@@ -175,9 +170,8 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
// leads to better error reporting when we hit an end of file. // leads to better error reporting when we hit an end of file.
++lineNum; ++lineNum;
return length; return length ? line : NULL;
} }
#endif
STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : 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 ...@@ -203,7 +197,8 @@ STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint
lineNum = aStartingPoint.lineNum; 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 ); size_t nlOffset = lines.find( '\n', ndx );
...@@ -231,7 +226,7 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) ...@@ -231,7 +226,7 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR )
line[length] = 0; line[length] = 0;
return length; return length ? line : NULL;
} }
...@@ -242,7 +237,7 @@ INPUTSTREAM_LINE_READER::INPUTSTREAM_LINE_READER( wxInputStream* aStream ) : ...@@ -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; length = 0;
...@@ -272,7 +267,7 @@ unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR ) ...@@ -272,7 +267,7 @@ unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR )
// leads to better error reporting when we hit an end of file. // leads to better error reporting when we hit an end of file.
++lineNum; ++lineNum;
return length; return length ? line : NULL;
} }
......
...@@ -117,7 +117,9 @@ protected: ...@@ -117,7 +117,9 @@ protected:
{ {
if( reader ) if( reader )
{ {
unsigned len = reader->ReadLine(); reader->ReadLine();
unsigned len = reader->Length();
// start may have changed in ReadLine(), which can resize and // start may have changed in ReadLine(), which can resize and
// relocate reader's line buffer. // relocate reader's line buffer.
......
...@@ -45,32 +45,21 @@ public: ...@@ -45,32 +45,21 @@ public:
* Constructor ( LINE_READER& ) * Constructor ( LINE_READER& )
* does not take ownership over @a aReader, so will not destroy it. * does not take ownership over @a aReader, so will not destroy it.
*/ */
FILTER_READER( LINE_READER& aReader ) : FILTER_READER( LINE_READER& aReader );
reader( aReader )
{ ~FILTER_READER();
}
unsigned ReadLine() throw( IO_ERROR ); char* ReadLine() throw( IO_ERROR );
const wxString& GetSource() const const wxString& GetSource() const
{ {
return reader.GetSource(); return reader.GetSource();
} }
char* Line() const
{
return reader.Line();
}
unsigned LineNumber() const unsigned LineNumber() const
{ {
return reader.LineNumber(); return reader.LineNumber();
} }
unsigned Length() const
{
return reader.Length();
}
}; };
#endif // FILTER_READER_H_ #endif // FILTER_READER_H_
...@@ -227,20 +227,17 @@ public: ...@@ -227,20 +227,17 @@ public:
*/ */
LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX );
virtual ~LINE_READER() virtual ~LINE_READER();
{
delete[] line;
}
/** /**
* Function ReadLine * Function ReadLine
* reads a line of text into the buffer and increments the line number * reads a line of text into the buffer and increments the line number
* counter. If the line is larger than aMaxLineLength passed to the * counter. If the line is larger than aMaxLineLength passed to the
* constructor, then an exception is thrown. The line is nul terminated. * 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. * @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 * Function GetSource
...@@ -258,7 +255,7 @@ public: ...@@ -258,7 +255,7 @@ public:
* Function Line * Function Line
* returns a pointer to the last line that was read in. * returns a pointer to the last line that was read in.
*/ */
virtual char* Line() const char* Line() const
{ {
return line; return line;
} }
...@@ -287,7 +284,7 @@ public: ...@@ -287,7 +284,7 @@ public:
* Function Length * Function Length
* returns the number of bytes in the last line read from this LINE_READER. * returns the number of bytes in the last line read from this LINE_READER.
*/ */
virtual unsigned Length() const unsigned Length() const
{ {
return length; return length;
} }
...@@ -308,6 +305,27 @@ protected: ...@@ -308,6 +305,27 @@ protected:
public: 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 * Constructor FILE_LINE_READER
* takes an open FILE and the size of the desired line buffer and takes * takes an open FILE and the size of the desired line buffer and takes
...@@ -333,7 +351,7 @@ public: ...@@ -333,7 +351,7 @@ public:
*/ */
~FILE_LINE_READER(); ~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 * Function Rewind
...@@ -380,7 +398,7 @@ public: ...@@ -380,7 +398,7 @@ public:
*/ */
STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ); 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: ...@@ -402,7 +420,7 @@ public:
*/ */
INPUTSTREAM_LINE_READER( wxInputStream* aStream ); 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
}; };
......
...@@ -222,16 +222,8 @@ void FP_CACHE::Load() ...@@ -222,16 +222,8 @@ void FP_CACHE::Load()
do do
{ {
FILE* fp = wxFopen( fpFileName, wxT( "r" ) );
if( !fp )
{
THROW_IO_ERROR( wxString::Format( _( "cannot open footprint library file '%s'" ),
fpFileName.GetData() ) );
}
// reader now owns fp, will close on exception or return // reader now owns fp, will close on exception or return
FILE_LINE_READER reader( fp, fpFileName ); FILE_LINE_READER reader( fpFileName );
m_owner->m_parser->SetLineReader( &reader ); m_owner->m_parser->SetLineReader( &reader );
...@@ -1551,15 +1543,7 @@ PCB_IO::~PCB_IO() ...@@ -1551,15 +1543,7 @@ PCB_IO::~PCB_IO()
BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties ) BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties )
{ {
wxFFile file( aFileName, wxT("r") ); FILE_LINE_READER reader( aFileName );
if( !file.IsOpened() )
{
wxString msg = wxString::Format( _( "Unable to read file \"%s\"" ), GetChars( aFileName ) );
THROW_IO_ERROR( msg );
}
FILE_LINE_READER reader( file.fp(), aFileName, false /* wxFFile owns fp */ );
m_parser->SetLineReader( &reader ); m_parser->SetLineReader( &reader );
m_parser->SetBoard( aAppendToMe ); m_parser->SetBoard( aAppendToMe );
......
This diff is collapsed.
...@@ -80,15 +80,10 @@ bool NETLIST_READER::ReadOldFmtdNetList( FILE* aFile ) ...@@ -80,15 +80,10 @@ bool NETLIST_READER::ReadOldFmtdNetList( FILE* aFile )
/* First, read the netlist: Build the list of footprints found in netlist /* First, read the netlist: Build the list of footprints found in netlist
*/ */
#ifndef __WXMAC__
// netlineReader dtor will close aFile // netlineReader dtor will close aFile
FILE_LINE_READER netlineReader( aFile, m_netlistFullName ); FILE_LINE_READER netlineReader( aFile, m_netlistFullName );
#else COMPONENT_INFO* curComponent = NULL;
//Seems that the setvbuf call destroys the FILE buffer (already allocated)
//And looses the first 4096 bytes so we set doOwn => false
FILE_LINE_READER netlineReader( aFile, m_netlistFullName, false );
#endif
COMPONENT_INFO *curComponent = NULL;
while( netlineReader.ReadLine() ) while( netlineReader.ReadLine() )
{ {
char* line = StrPurge( netlineReader.Line() ); char* line = StrPurge( netlineReader.Line() );
...@@ -370,25 +365,24 @@ bool NETLIST_READER::SetPadNetName( char* aText ) ...@@ -370,25 +365,24 @@ bool NETLIST_READER::SetPadNetName( char* aText )
*/ */
bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistReader ) bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistReader )
{ {
wxString cmpRef; wxString cmpRef;
COMPONENT_INFO* cmp_info = NULL; COMPONENT_INFO* cmp_info = NULL;
char* line;
while( aNetlistReader.ReadLine() ) while( ( line = aNetlistReader.ReadLine() ) != NULL )
{ {
const char* Line = aNetlistReader.Line(); if( strnicmp( line, "$endlist", 8 ) == 0 ) // end of list for the current component
if( strnicmp( Line, "$endlist", 8 ) == 0 ) // end of list for the current component
{ {
cmp_info = NULL; cmp_info = NULL;
continue; continue;
} }
if( strnicmp( Line, "$endfootprintlist", 4 ) == 0 ) if( strnicmp( line, "$endfootprintlist", 4 ) == 0 )
// End of this section // End of this section
return 0; return 0;
if( strnicmp( Line, "$component", 10 ) == 0 ) // New component reference found if( strnicmp( line, "$component", 10 ) == 0 ) // New component reference found
{ {
cmpRef = FROM_UTF8( Line + 11 ); cmpRef = FROM_UTF8( line + 11 );
cmpRef.Trim( true ); cmpRef.Trim( true );
cmpRef.Trim( false ); cmpRef.Trim( false );
...@@ -405,7 +399,7 @@ bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistR ...@@ -405,7 +399,7 @@ bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistR
else if( cmp_info ) else if( cmp_info )
{ {
// Add new filter to list // Add new filter to list
wxString fp = FROM_UTF8( Line + 1 ); wxString fp = FROM_UTF8( line + 1 );
fp.Trim( false ); fp.Trim( false );
fp.Trim( true ); fp.Trim( true );
cmp_info->m_FootprintFilter.Add( fp ); cmp_info->m_FootprintFilter.Add( fp );
......
...@@ -230,14 +230,9 @@ void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IO_ERROR ) ...@@ -230,14 +230,9 @@ void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IO_ERROR )
void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IO_ERROR ) void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IO_ERROR )
{ {
FILE* fp = wxFopen( filename, wxT("r") ); FILE_LINE_READER reader( filename );
if( !fp ) PushReader( &reader );
{
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
PushReader( new FILE_LINE_READER( fp, filename ) );
if( NextTok() != T_LEFT ) if( NextTok() != T_LEFT )
Expecting( T_LEFT ); Expecting( T_LEFT );
...@@ -248,21 +243,15 @@ void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IO_ERROR ) ...@@ -248,21 +243,15 @@ void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IO_ERROR )
SetPCB( new PCB() ); SetPCB( new PCB() );
doPCB( pcb ); doPCB( pcb );
PopReader();
delete PopReader(); // close fp
} }
void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IO_ERROR ) void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IO_ERROR )
{ {
FILE* fp = wxFopen( filename, wxT("r") ); FILE_LINE_READER reader( filename );
if( !fp )
{
ThrowIOError( _("Unable to open file \"%s\""), GetChars(filename) );
}
PushReader( new FILE_LINE_READER( fp, filename ) ); PushReader( &reader );
if( NextTok() != T_LEFT ) if( NextTok() != T_LEFT )
Expecting( T_LEFT ); Expecting( T_LEFT );
...@@ -274,7 +263,7 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IO_ERROR ) ...@@ -274,7 +263,7 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IO_ERROR )
doSESSION( session ); doSESSION( session );
delete PopReader(); // close fp PopReader();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment