fully implement nul termination for LINE_READER::ReadLine()

This commit is contained in:
Dick Hollenbeck 2010-10-21 08:21:32 -05:00
parent c3924e6fc9
commit 27a02d3226
4 changed files with 35 additions and 49 deletions

View File

@ -86,10 +86,11 @@ void DSNLEXER::PushReader( LINE_READER* aLineReader )
{
readerStack.push_back( aLineReader );
reader = aLineReader;
start = (char*) (*reader);
// force a new readLine() as first thing.
limit = start();
next = start();
limit = start;
next = start;
}
@ -101,10 +102,11 @@ bool DSNLEXER::PopReader()
readerStack.pop_back();
reader = &readerStack.back();
start = (char*) (*reader);
// force a new readLine() as first thing.
limit = start();
next = start();
limit = start;
next = start;
return true;
}
return false;
@ -331,7 +333,7 @@ L_read:
goto exit;
}
cur = start();
cur = start;
// skip leading whitespace
while( cur<limit && isSpace(*cur) )
@ -345,8 +347,8 @@ L_read:
{
// save the entire line, including new line as the current token.
// the '#' character may not be at offset zero.
curText = start(); // entire line is the token
cur = start(); // ensure a good curOffset below
curText = start; // entire line is the token
cur = start; // ensure a good curOffset below
curTok = DSN_COMMENT;
head = limit; // do a readLine() on next call in here.
goto exit;
@ -414,7 +416,7 @@ L_read:
like: U2-14 or "U2"-"14"
This is detectable by a non-space immediately preceeding the dash.
*/
if( *cur == '-' && cur>start() && !isSpace( cur[-1] ) )
if( *cur == '-' && cur>start && !isSpace( cur[-1] ) )
{
curText = '-';
curTok = DSN_DASH;
@ -535,7 +537,7 @@ L_read:
exit: // single point of exit, no returns elsewhere please.
curOffset = cur - start();
curOffset = cur - start;
next = head;

View File

@ -47,8 +47,8 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength )
capacity = LINE_READER_LINE_INITIAL_SIZE;
// but never go above user's aMaxLineLength, and leave space for trailing nul
if( capacity > aMaxLineLength-1 )
capacity = aMaxLineLength-1;
if( capacity > aMaxLineLength+1 )
capacity = aMaxLineLength+1;
line = new char[capacity];
@ -71,9 +71,10 @@ void LINE_READER::expandCapacity( unsigned newsize )
// resize the buffer, and copy the original data
char* bigger = new char[capacity];
wxASSERT( capacity >= length );
wxASSERT( capacity >= length+1 );
memcpy( bigger, line, length );
bigger[length] = 0;
delete[] line;
line = bigger;
@ -102,8 +103,8 @@ unsigned FILE_LINE_READER::ReadLine() throw (IOError)
if( length == maxLineLength )
throw IOError( _("Line length exceeded") );
// a normal line breaks here, once through
if( length < capacity-1 || line[length-1] == '\n' )
// a normal line breaks here, once through while loop
if( length+1 < capacity || line[length-1] == '\n' )
break;
expandCapacity( capacity * 2 );
@ -130,12 +131,13 @@ unsigned STRING_LINE_READER::ReadLine() throw (IOError)
if( length >= maxLineLength )
throw IOError( _("Line length exceeded") );
if( length > capacity )
expandCapacity( length );
if( length+1 > capacity )
expandCapacity( length+1 );
wxASSERT( ndx + length <= lines.length() );
memcpy( line, &source[ndx], length );
line[length] = 0;
++lineNum;
ndx += length;

View File

@ -78,6 +78,7 @@ enum DSN_SYNTAX_T {
*/
class DSNLEXER
{
char* start;
char* next;
char* limit;
@ -99,20 +100,17 @@ class DSNLEXER
const KEYWORD* keywords;
unsigned keywordCount;
/// Use casting char* operator to get start of line, which is dynamic since reader
/// can be resizing its buffer at each reader->ReadLine() only.
char* start() const { return (char*) (*reader); }
void init();
int readLine() throw (IOError)
{
unsigned len = reader->ReadLine();
// set next and limit to start() and start() + len.
// start() is constant until the next ReadLine(), which could resize and
// start may have changed in ReadLine(), which can resize and
// relocate reader's line buffer.
next = start();
start = (*reader);
next = start;
limit = next + len;
return len;

View File

@ -101,10 +101,10 @@ public:
/**
* Function ReadLine
* reads a line of text into the buffer and increments the line number
* counter. If the line is larger than the buffer size, then an exception
* is thrown.
* 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.
* @throw IOError only when a line is too long.
* @throw IOError when a line is too long.
*/
virtual unsigned ReadLine() throw( IOError ) = 0;
@ -181,15 +181,7 @@ public:
fclose( fp );
}
/**
* Function ReadLine
* reads a line of text into the buffer and increments the line number
* counter. If the line is larger than the buffer size, then an exception
* is thrown.
* @return unsigned - The number of bytes read, 0 at end of file.
* @throw IOError only when a line is too long.
*/
unsigned ReadLine() throw (IOError);
unsigned ReadLine() throw( IOError ); // see LINE_READER::ReadLine() description
/**
* Function Rewind
@ -217,34 +209,26 @@ protected:
public:
/**
* Constructor STRING_LINE_READER( const std::string& aString )
* Constructor STRING_LINE_READER( const std::string&, const wxString& )
*
* @param aString is a source string consisting of one or more lines
* of text, where multiple lines are separated with a '\n' character.
* The last line does not necessarily need a trailing '\n'.
*
* @param aSource describes the source of aString for error reporting purposes
* can be anything meaninful, such as wxT( "cliboard" ).
*/
STRING_LINE_READER( const std::string& aString, const wxString& aSource ) :
LINE_READER( 4096 ),
LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
lines( aString ),
ndx( 0 )
{
// Clipboard text should be nice and _use multiple lines_ so that
// we can report _line number_ oriented error messages when parsing.
// Therefore a line of 4096 characters max seems more than adequate.
source = aSource;
}
/**
* Function ReadLine
* reads a line of text into the buffer and increments the line number
* counter. If the line is larger than the buffer size, then an exception
* is thrown.
* @return unsigned - The number of bytes read, 0 at end of file.
* @throw IOError only when a line is too long.
*/
unsigned ReadLine() throw (IOError);
unsigned ReadLine() throw(IOError); // see LINE_READER::ReadLine() description
};