*) Use fgetc() technique to avoid strlen() in FILE_LINE_READER::ReadLine(),
which was having difficulty with embedded nuls in files coming from PCAD. *) Make dsnlexer.cpp's isSpace() treat nuls as whitespace.
This commit is contained in:
parent
44c25d14ec
commit
56796a950c
|
@ -369,18 +369,25 @@ int DSNLEXER::NeedNUMBER( const char* aExpectation ) throw( IO_ERROR )
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function isSpace
|
* Function isSpace
|
||||||
* strips the upper bits of the int to ensure the value passed to C++ %isspace() is
|
* tests for whitespace. Our whitespace, by our definition, is a subset of ASCII,
|
||||||
* in the range of 0-255
|
* i.e. no bytes with MSB on can be considered whitespace, since they are likely part
|
||||||
|
* of a multibyte UTF8 character.
|
||||||
*/
|
*/
|
||||||
static inline bool isSpace( int cc )
|
static bool isSpace( int cc )
|
||||||
{
|
{
|
||||||
// Warning: we are using UTF8 char, so values are coded from 0x01 to 0xFF
|
if( cc <= ' ' )
|
||||||
// isspace( int value ) works fine under Linux,
|
{
|
||||||
// but seems use only a 7 bits value under mingw, in comparisons.
|
switch( cc )
|
||||||
// (for instance 0xA0 is seen as 0x20)
|
{
|
||||||
// So we need to test if the value is ASCII ( <= 127) and a space ( ' ', \t, \n ... )
|
case ' ':
|
||||||
// and not just a space:
|
case '\n':
|
||||||
return ( (unsigned) cc <= 127 ) && ::isspace( cc );
|
case '\r':
|
||||||
|
case '\t':
|
||||||
|
case '\0': // PCAD s-expression files have this.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,11 @@ FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName,
|
||||||
iOwn( doOwn ),
|
iOwn( doOwn ),
|
||||||
fp( aFile )
|
fp( aFile )
|
||||||
{
|
{
|
||||||
|
if( doOwn )
|
||||||
|
{
|
||||||
|
setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 );
|
||||||
|
}
|
||||||
|
|
||||||
source = aFileName;
|
source = aFileName;
|
||||||
lineNum = aStartingLineNumber;
|
lineNum = aStartingLineNumber;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +106,10 @@ 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 )
|
unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
{
|
{
|
||||||
|
@ -129,6 +138,40 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
||||||
|
{
|
||||||
|
length = 0;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
if( length >= maxLineLength )
|
||||||
|
THROW_IO_ERROR( _( "Maximum line length exceeded" ) );
|
||||||
|
|
||||||
|
if( length >= capacity )
|
||||||
|
expandCapacity( capacity * 2 );
|
||||||
|
|
||||||
|
// faster, POSIX compatible fgetc(), no locking.
|
||||||
|
int cc = getc_unlocked( fp );
|
||||||
|
if( cc == EOF )
|
||||||
|
break;
|
||||||
|
|
||||||
|
line[ length++ ] = (char) cc;
|
||||||
|
|
||||||
|
if( cc == '\n' )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
line[ length ] = 0;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
#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 ) :
|
||||||
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
||||||
|
|
Loading…
Reference in New Issue