diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 67b31af15c..be8944fcba 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,15 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-Mar-3 UPDATE Dick Hollenbeck +================================================================================ +++common + * DSNLEXER now owns an abstract LINE_READER by pointer so that polymorphism + can be used in alternative LINE_READERS. + * Write FILE_LINE_READER and STRING_LINE_READER. The latter can be used + to parse text coming from the clipboard or other string source. + + 2010-Feb-20 UPDATE Dick Hollenbeck ================================================================================ ++common diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp index 14972a8f3e..6bbc91de2e 100644 --- a/common/dsnlexer.cpp +++ b/common/dsnlexer.cpp @@ -51,7 +51,7 @@ static int compare( const void* a1, const void* a2 ) DSNLEXER::DSNLEXER( FILE* aFile, const wxString& aFilename, const KEYWORD* aKeywordTable, unsigned aKeywordCount ) { - reader = new LINE_READER( aFile, 4096 ); + reader = new FILE_LINE_READER( aFile, 4096 ); keywords = aKeywordTable; keywordCount = aKeywordCount; diff --git a/common/richio.cpp b/common/richio.cpp index 3b913b3476..3e8216e548 100644 --- a/common/richio.cpp +++ b/common/richio.cpp @@ -34,9 +34,8 @@ //----------------------------------------------------------- -LINE_READER::LINE_READER( FILE* aFile, unsigned aMaxLineLength ) +LINE_READER::LINE_READER( unsigned aMaxLineLength ) { - fp = aFile; lineNum = 0; maxLineLength = aMaxLineLength; @@ -50,7 +49,14 @@ LINE_READER::LINE_READER( FILE* aFile, unsigned aMaxLineLength ) } -int LINE_READER::ReadLine() throw (IOError) +FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, unsigned aMaxLineLength ) : + LINE_READER( aMaxLineLength ) +{ + fp = aFile; +} + + +int FILE_LINE_READER::ReadLine() throw (IOError) { const char* p = fgets( line, capacity, fp ); @@ -73,6 +79,35 @@ int LINE_READER::ReadLine() throw (IOError) } +int STRING_LINE_READER::ReadLine() throw (IOError) +{ + size_t nlOffset = source.find( '\n', ndx ); + size_t advance; + + if( nlOffset == std::string::npos ) + advance = source.length() - ndx; + else + advance = nlOffset - ndx + 1; // include the newline, so +1 + + if( advance ) + { + if( advance >= maxLineLength ) + throw IOError( _("Line length exceeded") ); + + wxASSERT( ndx + advance <= source.length() ); + + memcpy( line, &source[ndx], advance ); + line[advance] = 0; + + length = advance; + + ++lineNum; + ndx += advance; + } + + return advance; +} + //--------------------------------------------------------- diff --git a/include/richio.h b/include/richio.h index 4951a2c6ea..9fbbffebd2 100644 --- a/include/richio.h +++ b/include/richio.h @@ -70,37 +70,21 @@ struct IOError class LINE_READER { protected: - - FILE* fp; - int lineNum; - unsigned maxLineLength; unsigned length; + int lineNum; char* line; + unsigned maxLineLength; unsigned capacity; + public: + LINE_READER( unsigned aMaxLineLength ); - /** - * Constructor LINE_READER - * takes an open FILE and the size of the desired line buffer. - * @param aFile An open file in "ascii" mode, not binary mode. - * @param aMaxLineLength The number of bytes to use in the line buffer. - */ - LINE_READER( FILE* aFile, unsigned aMaxLineLength ); - - ~LINE_READER() + virtual ~LINE_READER() { delete[] line; } - /* - int CharAt( int aNdx ) - { - if( (unsigned) aNdx < capacity ) - return (char) (unsigned char) line[aNdx]; - return -1; - } - */ /** * Function ReadLine @@ -110,7 +94,7 @@ public: * @return int - The number of bytes read, 0 at end of file. * @throw IOError only when a line is too long. */ - int ReadLine() throw (IOError); + virtual int ReadLine() throw (IOError) = 0; operator char* () { @@ -129,6 +113,72 @@ public: }; +/** + * Class FILE_LINE_READER + * is a LINE_READER that reads from an open file. File must be already open + * so that this class can exist without and UI policy. + */ +class FILE_LINE_READER : public LINE_READER +{ +protected: + + FILE* fp; ///< no ownership, no close on destruction + +public: + + /** + * Constructor LINE_READER + * takes an open FILE and the size of the desired line buffer. + * @param aFile An open file in "ascii" mode, not binary mode. + * @param aMaxLineLength The number of bytes to use in the line buffer. + */ + FILE_LINE_READER( FILE* aFile, unsigned aMaxLineLength ); + + + /** + * 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 int - The number of bytes read, 0 at end of file. + * @throw IOError only when a line is too long. + */ + int ReadLine() throw (IOError); +}; + + +/** + * Class STRING_LINE_READER + * is a LINE_READER that reads from a multiline 8 bit wide std::string + */ +class STRING_LINE_READER : public LINE_READER +{ +protected: + std::string source; + size_t ndx; + +public: + STRING_LINE_READER( const std::string& aString ) : + LINE_READER( 4096 ), + source( 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. + } + + /** + * 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 int - The number of bytes read, 0 at end of file. + * @throw IOError only when a line is too long. + */ + int ReadLine() throw (IOError); +}; + /** * Class OUTPUTFORMATTER