Commit 27a02d32 authored by Dick Hollenbeck's avatar Dick Hollenbeck

fully implement nul termination for LINE_READER::ReadLine()

parent c3924e6f
...@@ -86,10 +86,11 @@ void DSNLEXER::PushReader( LINE_READER* aLineReader ) ...@@ -86,10 +86,11 @@ void DSNLEXER::PushReader( LINE_READER* aLineReader )
{ {
readerStack.push_back( aLineReader ); readerStack.push_back( aLineReader );
reader = aLineReader; reader = aLineReader;
start = (char*) (*reader);
// force a new readLine() as first thing. // force a new readLine() as first thing.
limit = start(); limit = start;
next = start(); next = start;
} }
...@@ -101,10 +102,11 @@ bool DSNLEXER::PopReader() ...@@ -101,10 +102,11 @@ bool DSNLEXER::PopReader()
readerStack.pop_back(); readerStack.pop_back();
reader = &readerStack.back(); reader = &readerStack.back();
start = (char*) (*reader);
// force a new readLine() as first thing. // force a new readLine() as first thing.
limit = start(); limit = start;
next = start(); next = start;
return true; return true;
} }
return false; return false;
...@@ -331,7 +333,7 @@ L_read: ...@@ -331,7 +333,7 @@ L_read:
goto exit; goto exit;
} }
cur = start(); cur = start;
// skip leading whitespace // skip leading whitespace
while( cur<limit && isSpace(*cur) ) while( cur<limit && isSpace(*cur) )
...@@ -345,8 +347,8 @@ L_read: ...@@ -345,8 +347,8 @@ L_read:
{ {
// save the entire line, including new line as the current token. // save the entire line, including new line as the current token.
// the '#' character may not be at offset zero. // the '#' character may not be at offset zero.
curText = start(); // entire line is the token curText = start; // entire line is the token
cur = start(); // ensure a good curOffset below cur = start; // ensure a good curOffset below
curTok = DSN_COMMENT; curTok = DSN_COMMENT;
head = limit; // do a readLine() on next call in here. head = limit; // do a readLine() on next call in here.
goto exit; goto exit;
...@@ -414,7 +416,7 @@ L_read: ...@@ -414,7 +416,7 @@ L_read:
like: U2-14 or "U2"-"14" like: U2-14 or "U2"-"14"
This is detectable by a non-space immediately preceeding the dash. 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 = '-'; curText = '-';
curTok = DSN_DASH; curTok = DSN_DASH;
...@@ -535,7 +537,7 @@ L_read: ...@@ -535,7 +537,7 @@ L_read:
exit: // single point of exit, no returns elsewhere please. exit: // single point of exit, no returns elsewhere please.
curOffset = cur - start(); curOffset = cur - start;
next = head; next = head;
......
...@@ -47,8 +47,8 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength ) ...@@ -47,8 +47,8 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength )
capacity = LINE_READER_LINE_INITIAL_SIZE; capacity = LINE_READER_LINE_INITIAL_SIZE;
// but never go above user's aMaxLineLength, and leave space for trailing nul // but never go above user's aMaxLineLength, and leave space for trailing nul
if( capacity > aMaxLineLength-1 ) if( capacity > aMaxLineLength+1 )
capacity = aMaxLineLength-1; capacity = aMaxLineLength+1;
line = new char[capacity]; line = new char[capacity];
...@@ -71,9 +71,10 @@ void LINE_READER::expandCapacity( unsigned newsize ) ...@@ -71,9 +71,10 @@ void LINE_READER::expandCapacity( unsigned newsize )
// resize the buffer, and copy the original data // resize the buffer, and copy the original data
char* bigger = new char[capacity]; char* bigger = new char[capacity];
wxASSERT( capacity >= length ); wxASSERT( capacity >= length+1 );
memcpy( bigger, line, length ); memcpy( bigger, line, length );
bigger[length] = 0;
delete[] line; delete[] line;
line = bigger; line = bigger;
...@@ -102,8 +103,8 @@ unsigned FILE_LINE_READER::ReadLine() throw (IOError) ...@@ -102,8 +103,8 @@ unsigned FILE_LINE_READER::ReadLine() throw (IOError)
if( length == maxLineLength ) if( length == maxLineLength )
throw IOError( _("Line length exceeded") ); throw IOError( _("Line length exceeded") );
// a normal line breaks here, once through // a normal line breaks here, once through while loop
if( length < capacity-1 || line[length-1] == '\n' ) if( length+1 < capacity || line[length-1] == '\n' )
break; break;
expandCapacity( capacity * 2 ); expandCapacity( capacity * 2 );
...@@ -130,12 +131,13 @@ unsigned STRING_LINE_READER::ReadLine() throw (IOError) ...@@ -130,12 +131,13 @@ unsigned STRING_LINE_READER::ReadLine() throw (IOError)
if( length >= maxLineLength ) if( length >= maxLineLength )
throw IOError( _("Line length exceeded") ); throw IOError( _("Line length exceeded") );
if( length > capacity ) if( length+1 > capacity )
expandCapacity( length ); expandCapacity( length+1 );
wxASSERT( ndx + length <= lines.length() ); wxASSERT( ndx + length <= lines.length() );
memcpy( line, &source[ndx], length ); memcpy( line, &source[ndx], length );
line[length] = 0;
++lineNum; ++lineNum;
ndx += length; ndx += length;
......
...@@ -78,6 +78,7 @@ enum DSN_SYNTAX_T { ...@@ -78,6 +78,7 @@ enum DSN_SYNTAX_T {
*/ */
class DSNLEXER class DSNLEXER
{ {
char* start;
char* next; char* next;
char* limit; char* limit;
...@@ -99,20 +100,17 @@ class DSNLEXER ...@@ -99,20 +100,17 @@ class DSNLEXER
const KEYWORD* keywords; const KEYWORD* keywords;
unsigned keywordCount; 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(); void init();
int readLine() throw (IOError) int readLine() throw (IOError)
{ {
unsigned len = reader->ReadLine(); unsigned len = reader->ReadLine();
// set next and limit to start() and start() + len. // start may have changed in ReadLine(), which can resize and
// start() is constant until the next ReadLine(), which could resize and
// relocate reader's line buffer. // relocate reader's line buffer.
next = start(); start = (*reader);
next = start;
limit = next + len; limit = next + len;
return len; return len;
......
...@@ -101,12 +101,12 @@ public: ...@@ -101,12 +101,12 @@ public:
/** /**
* 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 the buffer size, then an exception * counter. If the line is larger than aMaxLineLength passed to the
* is thrown. * constructor, then an exception is thrown. The line is nul terminated.
* @return unsigned - The number of bytes read, 0 at end of file. * @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; virtual unsigned ReadLine() throw( IOError ) = 0;
/** /**
* Function GetSource * Function GetSource
...@@ -160,7 +160,7 @@ class FILE_LINE_READER : public LINE_READER ...@@ -160,7 +160,7 @@ class FILE_LINE_READER : public LINE_READER
{ {
protected: protected:
FILE* fp; ///< I own this file FILE* fp; ///< I own this file
public: public:
...@@ -181,15 +181,7 @@ public: ...@@ -181,15 +181,7 @@ public:
fclose( fp ); fclose( fp );
} }
/** unsigned ReadLine() throw( IOError ); // see LINE_READER::ReadLine() description
* 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);
/** /**
* Function Rewind * Function Rewind
...@@ -217,34 +209,26 @@ protected: ...@@ -217,34 +209,26 @@ protected:
public: 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 * @param aString is a source string consisting of one or more lines
* of text, where multiple lines are separated with a '\n' character. * of text, where multiple lines are separated with a '\n' character.
* The last line does not necessarily need a trailing '\n'. * The last line does not necessarily need a trailing '\n'.
*
* @param aSource describes the source of aString for error reporting purposes * @param aSource describes the source of aString for error reporting purposes
* can be anything meaninful, such as wxT( "cliboard" ). * can be anything meaninful, such as wxT( "cliboard" ).
*/ */
STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : STRING_LINE_READER( const std::string& aString, const wxString& aSource ) :
LINE_READER( 4096 ), LINE_READER( LINE_READER_LINE_DEFAULT_MAX ),
lines( aString ), lines( aString ),
ndx( 0 ) ndx( 0 )
{ {
// Clipboard text should be nice and _use multiple lines_ so that // Clipboard text should be nice and _use multiple lines_ so that
// we can report _line number_ oriented error messages when parsing. // we can report _line number_ oriented error messages when parsing.
// Therefore a line of 4096 characters max seems more than adequate.
source = aSource; source = aSource;
} }
/** unsigned ReadLine() throw(IOError); // see LINE_READER::ReadLine() description
* 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);
}; };
......
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