*) 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
|
||||
* strips the upper bits of the int to ensure the value passed to C++ %isspace() is
|
||||
* in the range of 0-255
|
||||
* tests for whitespace. Our whitespace, by our definition, is a subset of ASCII,
|
||||
* 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
|
||||
// isspace( int value ) works fine under Linux,
|
||||
// but seems use only a 7 bits value under mingw, in comparisons.
|
||||
// (for instance 0xA0 is seen as 0x20)
|
||||
// So we need to test if the value is ASCII ( <= 127) and a space ( ' ', \t, \n ... )
|
||||
// and not just a space:
|
||||
return ( (unsigned) cc <= 127 ) && ::isspace( cc );
|
||||
if( cc <= ' ' )
|
||||
{
|
||||
switch( cc )
|
||||
{
|
||||
case ' ':
|
||||
case '\n':
|
||||
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 ),
|
||||
fp( aFile )
|
||||
{
|
||||
if( doOwn )
|
||||
{
|
||||
setvbuf( fp, NULL, _IOFBF, BUFSIZ * 8 );
|
||||
}
|
||||
|
||||
source = aFileName;
|
||||
lineNum = aStartingLineNumber;
|
||||
}
|
||||
|
@ -101,6 +106,10 @@ 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 )
|
||||
{
|
||||
|
@ -129,6 +138,40 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR )
|
|||
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 ) :
|
||||
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
|
||||
|
|
Loading…
Reference in New Issue