Loading common/dsnlexer.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -65,7 +65,7 @@ DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, keywords( aKeywordTable ), keywords( aKeywordTable ), keywordCount( aKeywordCount ) keywordCount( aKeywordCount ) { { FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename, 4096 ); FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename ); PushReader( fileReader ); PushReader( fileReader ); init(); init(); } } Loading common/richio.cpp +37 −2 Original line number Original line Diff line number Diff line Loading @@ -82,11 +82,23 @@ void LINE_READER::expandCapacity( unsigned newsize ) } } FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength ) : FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn, unsigned aStartingLineNumber, unsigned aMaxLineLength ) : LINE_READER( aMaxLineLength ), LINE_READER( aMaxLineLength ), iOwn( doOwn ), fp( aFile ) fp( aFile ) { { source = aFileName; source = aFileName; lineNum = aStartingLineNumber; } FILE_LINE_READER::~FILE_LINE_READER() { if( iOwn && fp ) fclose( fp ); } } Loading Loading @@ -117,6 +129,29 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) } } STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : 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. source = aSource; } STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ) : LINE_READER( LINE_READER_LINE_DEFAULT_MAX ), lines( aStartingPoint.lines ), ndx( aStartingPoint.ndx ) { // since we are keeping the same "source" name, for error reporting purposes // we need to have the same notion of line number and offset. source = aStartingPoint.source; lineNum = aStartingPoint.lineNum; } unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) { { size_t nlOffset = lines.find( '\n', ndx ); size_t nlOffset = lines.find( '\n', ndx ); Loading include/richio.h +28 −19 Original line number Original line Diff line number Diff line Loading @@ -53,7 +53,7 @@ class LINE_READER { { protected: protected: unsigned length; ///< no. bytes in line before trailing nul. unsigned length; ///< no. bytes in line before trailing nul. int lineNum; unsigned lineNum; char* line; ///< the read line of UTF8 text char* line; ///< the read line of UTF8 text unsigned capacity; ///< no. bytes allocated for line. unsigned capacity; ///< no. bytes allocated for line. Loading Loading @@ -115,7 +115,7 @@ public: * returns the line number of the last line read from this LINE_READER. Lines * returns the line number of the last line read from this LINE_READER. Lines * start from 1. * start from 1. */ */ int LineNumber() const unsigned LineNumber() const { { return lineNum; return lineNum; } } Loading @@ -140,7 +140,8 @@ class FILE_LINE_READER : public LINE_READER { { protected: protected: FILE* fp; ///< I own this file bool iOwn; ///< if I own the file, I'll promise to close it, else not. FILE* fp; ///< I may own this file, but might not. public: public: Loading @@ -151,15 +152,23 @@ public: * * * @param aFile is an open file. * @param aFile is an open file. * @param aFileName is the name of the file for error reporting purposes. * @param aFileName is the name of the file for error reporting purposes. * @param doOwn if true, means I should close the open file, else not. * @param aStartingLineNumber is the initial line number to report on error, and is * accessible here for the case where multiple DSNLEXERs are reading from the * same file in sequence, all from the same open file (with @a doOwn = false). * Internally it is incremented by one after each ReadLine(), so the first * reported line number will always be one greater than what is provided here. * @param aMaxLineLength is the number of bytes to use in the line buffer. * @param aMaxLineLength is the number of bytes to use in the line buffer. */ */ FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn = true, unsigned aStartingLineNumber = 0, unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); ~FILE_LINE_READER() /** { * Destructor if( fp ) * may or may not close the open file, depending on @a doOwn in constructor. fclose( fp ); */ } ~FILE_LINE_READER(); unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description Loading Loading @@ -198,15 +207,15 @@ public: * @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( "clipboard" ). * can be anything meaninful, such as wxT( "clipboard" ). */ */ STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : STRING_LINE_READER( const std::string& aString, const wxString& aSource ); LINE_READER( LINE_READER_LINE_DEFAULT_MAX ), lines( aString ), /** ndx( 0 ) * Constructor STRING_LINE_READER( const STRING_LINE_READER& ) { * allows for a continuation of the reading of a stream started by another // Clipboard text should be nice and _use multiple lines_ so that * STRING_LINE_READER. Any stream offset and source name are used from // we can report _line number_ oriented error messages when parsing. * @a aStartingPoint. source = aSource; */ } STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ); unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description }; }; Loading new/design.h +0 −152 Original line number Original line Diff line number Diff line Loading @@ -371,158 +371,6 @@ const STRING StrEmpty = ""; /** @} exception_types Exception Types */ /** @} exception_types Exception Types */ /** * Class LPID (aka GUID) * is a Logical Part ID and consists of various portions much like a URI. It * relies heavily on a logical library name to hide where actual physical library * sources reside. Its static functions serve as managers of the "library table" to * map logical library names to actual library sources. * <p> * Example LPID string: * "kicad:passives/R/rev6". * <p> * <ul> * <li> "kicad" is the logical library name. * <li> "passives" is the category. * <li> "passives/R" is the partname. * <li> "rev6" is the revision number, which is optional. If missing then its * delimiter should also not be present. * </ul> * <p> * This class owns the <b>library table</b>, which is like fstab in concept and maps logical * library name to library URI, type, and options. It has the following columns: * <ul> * <li> Logical Library Name * <li> Library Type * <li> Library URI. The full URI to the library source, form dependent on Type. * <li> Options, used for access, such as password * </ul> * <p> * For now, the Library Type can be one of: * <ul> * <li> "dir" * <li> "schematic" i.e. a parts list from another schematic. * <li> "subversion" * <li> "bazaar" * <li> "http" * </ul> * <p> * For now, the Library URI types needed to support the various types can be one of those * shown below, which are typical of each type: * <ul> * <li> "file://C:/mylibdir" * <li> "file://home/user/kicadwork/jtagboard.sch" * <li> "svn://kicad.org/partlib/trunk" * <li> "http://kicad.org/partlib" * </ul> * <p> * The applicable library table is built up from several additive rows (table fragments), * and the final table is a merging of the table fragments. Two anticipated sources of * the rows are a personal table, and a schematic resident table. The schematic * resident table rows are considered a higher priority in the final dynamically * assembled library table. A row in the schematic contribution to the library table * will take precedence over the personal table if there is a collision on logical * library name, otherwise the rows simply combine without issue to make up the * applicable library table. */ class LPID // aka GUID { public: /** * Constructor LPID * takes aLPID string and parses it. A typical LPID string uses a logical * library name followed by a part name. * e.g.: "kicad:passives/R/rev2", or * e.g.: "mylib:R33" */ LPID( const STRING& aLPID ) throw( PARSE_ERROR ); /** * Function GetLogLib * returns the logical library portion of a LPID. There is not Set accessor * for this portion since it comes from the library table and is considered * read only here. */ STRING GetLogLib() const; /** * Function GetCategory * returns the category of this part id, "passives" in the example at the * top of the class description. */ STRING GetCategory() const; /** * Function SetCategory * overrides the category portion of the LPID to @a aCategory and is typically * either the empty string or a single word like "passives". */ void SetCategory( const STRING& aCategory ); /** * Function GetRevision * returns the revision portion of the LPID or StrEmpty if none. */ STRING GetRevision() const; /** * Function SetRevision * overrides the revision portion of the LPID to @a aRevision and must * be in the form "rev<num>" where "<num>" is "1", "2", etc. */ void SetRevision( const STRING& aRevision ); /** * Function GetFullText * returns the full text of the LPID. */ STRING GetFullText() const; //-----<statics>----------------------------------------------------- /** * Function GetLogicalLibraries * returns the logical library names, all of them that are in the * library table. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRINGS GetLogicalLibraries( SCHEMATIC* aSchematic=NULL ); /** * Function GetLibraryURI * returns the full library path from a logical library name. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetLibraryURI( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; /** * Function GetLibraryType * returns the type of a logical library. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetLibraryType( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; /** * Function GetOptions * returns the options string for \a aLogicalLibraryName. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetPassword( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; }; /** /** * Class SVN_LIB_SOURCE * Class SVN_LIB_SOURCE * implements a LIB_SOURCE in a subversion repository. * implements a LIB_SOURCE in a subversion repository. Loading new/sch_lib_table.cpp +111 −15 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,10 @@ using namespace std; using namespace SCH; using namespace SCH; LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) : fallBack( aFallBackTable ) { { /* not copying fall back, simply search it separately if "logicalName not found". if( aFallBackTable ) if( aFallBackTable ) { { const ROWS& t = aFallBackTable->rows; const ROWS& t = aFallBackTable->rows; Loading @@ -39,12 +41,12 @@ LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) for( ROWS_CITER it = t.begin(); it != t.end(); ++it ) for( ROWS_CITER it = t.begin(); it != t.end(); ++it ) { { // our rows are empty, expect no collisions here // our rows are empty, expect no collisions here auto_ptr<ROW> row( new ROW( *it ) ); auto_ptr<ROW> row( new ROW( *it->second ) ); row->owner = this; row->owner = this; rows.insert( row.release() ); insert( row ); } } } } */ } } Loading Loading @@ -126,18 +128,89 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) in->NeedRIGHT(); in->NeedRIGHT(); in->NeedRIGHT(); // teriminate the (lib..) in->NeedRIGHT(); // teriminate the (lib..) rows.insert( row.release() ); // all logicalNames within this table fragment must be unique, so we do not // replace. However a fallBack table can have a conflicting logicalName // and ours will supercede that one since in findLib() we search this table // before any fall back. if( !InsertLib( row ) ) { char buf[300]; snprintf( buf, sizeof(buf), "'%s' is a duplicate logical lib name", row->logicalName.c_str() ); throw IO_ERROR( buf ); } } } return; return; } } #if 1 void LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ) { out->Print( nestLevel, "(lib_table\n" ); for( ROWS_CITER it = rows.begin(); it != rows.end(); ++it ) it->second->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); } int main( int argc, char** argv ) void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ) { out->Print( nestLevel, "(lib (logical \"%s\")(type \"%s\")(full_uri \"%s\")(options \"%s\"))\n", logicalName.c_str(), libType.c_str(), fullURI.c_str(), options.c_str() ); } const LIB_TABLE::ROW* LIB_TABLE::FindLib( const STRING& aLogicalName ) { // this function must be *super* fast, so therefore should not instantiate // anything which would require using the heap. This function is the reason // ptr_map<> was used instead of ptr_set<>, which would have required // instantiating a ROW just to find a ROW. ROWS_CITER it = rows.find( aLogicalName ); if( it != rows.end() ) { // reference: http://myitcorner.com/blog/?p=361 return (const LIB_TABLE::ROW*) it->second; // found } // not found, search fall back table if( fallBack ) return fallBack->FindLib( aLogicalName ); return 0; // not found } bool LIB_TABLE::InsertLib( auto_ptr<ROW>& aRow, bool doReplace ) { ROWS_ITER it = rows.find( aRow->logicalName ); if( doReplace || it == rows.end() ) { // be careful here, key is needed because aRow can be // release()ed before logicalName is captured. const STRING& key = aRow->logicalName; rows.insert( key, aRow ); return true; } return false; } #if 1 && defined(DEBUG) // build this with a Debug CMAKE_BUILD_TYPE void LIB_TABLE::Test() { { // the null string is not really a legal DSN token since any double quotes // the null string is not really a legal DSN token since any double quotes // as assumed to be a single quote. To pass an empty string, we pass " " // are assumed to be a single quote. To pass an empty string, we pass " " // to (options " ") // to (options " ") SCH_LIB_TABLE_LEXER slr( SCH_LIB_TABLE_LEXER slr( "(lib_table \n" "(lib_table \n" Loading @@ -148,16 +221,14 @@ int main( int argc, char** argv ) wxT( "inline text" ) // source wxT( "inline text" ) // source ); ); LIB_TABLE lib_table; // read the "( lib_table" pair of tokens try try { { // read the "( lib_table" pair of tokens slr.NextTok(); slr.NextTok(); slr.NextTok(); slr.NextTok(); lib_table.Parse( &slr ); // parse the rest of input to slr Parse( &slr ); } } catch( std::exception& ex ) catch( std::exception& ex ) Loading @@ -167,11 +238,36 @@ int main( int argc, char** argv ) catch( IO_ERROR ioe ) catch( IO_ERROR ioe ) { { printf( "caught\n" ); printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); } } lib_table.Show(); STRING_FORMATTER sf; Format( &sf, 0 ); printf( "test 'Parse() <-> Format()' round tripping:\n" ); printf( "%s", sf.GetString().c_str() ); printf( "\ntest a lookup of 'www':\n" ); sf.Clear(); const LIB_TABLE::ROW* www = FindLib( "www" ); if( www ) { // found, print it just to prove it. www->Format( &sf, 1 ); printf( "%s", sf.GetString().c_str() ); } else printf( "not found\n" ); } int main( int argc, char** argv ) { LIB_TABLE lib_table; lib_table.Test(); return 0; return 0; } } Loading Loading
common/dsnlexer.cpp +1 −1 Original line number Original line Diff line number Diff line Loading @@ -65,7 +65,7 @@ DSNLEXER::DSNLEXER( const KEYWORD* aKeywordTable, unsigned aKeywordCount, keywords( aKeywordTable ), keywords( aKeywordTable ), keywordCount( aKeywordCount ) keywordCount( aKeywordCount ) { { FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename, 4096 ); FILE_LINE_READER* fileReader = new FILE_LINE_READER( aFile, aFilename ); PushReader( fileReader ); PushReader( fileReader ); init(); init(); } } Loading
common/richio.cpp +37 −2 Original line number Original line Diff line number Diff line Loading @@ -82,11 +82,23 @@ void LINE_READER::expandCapacity( unsigned newsize ) } } FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength ) : FILE_LINE_READER::FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn, unsigned aStartingLineNumber, unsigned aMaxLineLength ) : LINE_READER( aMaxLineLength ), LINE_READER( aMaxLineLength ), iOwn( doOwn ), fp( aFile ) fp( aFile ) { { source = aFileName; source = aFileName; lineNum = aStartingLineNumber; } FILE_LINE_READER::~FILE_LINE_READER() { if( iOwn && fp ) fclose( fp ); } } Loading Loading @@ -117,6 +129,29 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) } } STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : 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. source = aSource; } STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ) : LINE_READER( LINE_READER_LINE_DEFAULT_MAX ), lines( aStartingPoint.lines ), ndx( aStartingPoint.ndx ) { // since we are keeping the same "source" name, for error reporting purposes // we need to have the same notion of line number and offset. source = aStartingPoint.source; lineNum = aStartingPoint.lineNum; } unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) { { size_t nlOffset = lines.find( '\n', ndx ); size_t nlOffset = lines.find( '\n', ndx ); Loading
include/richio.h +28 −19 Original line number Original line Diff line number Diff line Loading @@ -53,7 +53,7 @@ class LINE_READER { { protected: protected: unsigned length; ///< no. bytes in line before trailing nul. unsigned length; ///< no. bytes in line before trailing nul. int lineNum; unsigned lineNum; char* line; ///< the read line of UTF8 text char* line; ///< the read line of UTF8 text unsigned capacity; ///< no. bytes allocated for line. unsigned capacity; ///< no. bytes allocated for line. Loading Loading @@ -115,7 +115,7 @@ public: * returns the line number of the last line read from this LINE_READER. Lines * returns the line number of the last line read from this LINE_READER. Lines * start from 1. * start from 1. */ */ int LineNumber() const unsigned LineNumber() const { { return lineNum; return lineNum; } } Loading @@ -140,7 +140,8 @@ class FILE_LINE_READER : public LINE_READER { { protected: protected: FILE* fp; ///< I own this file bool iOwn; ///< if I own the file, I'll promise to close it, else not. FILE* fp; ///< I may own this file, but might not. public: public: Loading @@ -151,15 +152,23 @@ public: * * * @param aFile is an open file. * @param aFile is an open file. * @param aFileName is the name of the file for error reporting purposes. * @param aFileName is the name of the file for error reporting purposes. * @param doOwn if true, means I should close the open file, else not. * @param aStartingLineNumber is the initial line number to report on error, and is * accessible here for the case where multiple DSNLEXERs are reading from the * same file in sequence, all from the same open file (with @a doOwn = false). * Internally it is incremented by one after each ReadLine(), so the first * reported line number will always be one greater than what is provided here. * @param aMaxLineLength is the number of bytes to use in the line buffer. * @param aMaxLineLength is the number of bytes to use in the line buffer. */ */ FILE_LINE_READER( FILE* aFile, const wxString& aFileName, unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); FILE_LINE_READER( FILE* aFile, const wxString& aFileName, bool doOwn = true, unsigned aStartingLineNumber = 0, unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); ~FILE_LINE_READER() /** { * Destructor if( fp ) * may or may not close the open file, depending on @a doOwn in constructor. fclose( fp ); */ } ~FILE_LINE_READER(); unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description Loading Loading @@ -198,15 +207,15 @@ public: * @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( "clipboard" ). * can be anything meaninful, such as wxT( "clipboard" ). */ */ STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : STRING_LINE_READER( const std::string& aString, const wxString& aSource ); LINE_READER( LINE_READER_LINE_DEFAULT_MAX ), lines( aString ), /** ndx( 0 ) * Constructor STRING_LINE_READER( const STRING_LINE_READER& ) { * allows for a continuation of the reading of a stream started by another // Clipboard text should be nice and _use multiple lines_ so that * STRING_LINE_READER. Any stream offset and source name are used from // we can report _line number_ oriented error messages when parsing. * @a aStartingPoint. source = aSource; */ } STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ); unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description }; }; Loading
new/design.h +0 −152 Original line number Original line Diff line number Diff line Loading @@ -371,158 +371,6 @@ const STRING StrEmpty = ""; /** @} exception_types Exception Types */ /** @} exception_types Exception Types */ /** * Class LPID (aka GUID) * is a Logical Part ID and consists of various portions much like a URI. It * relies heavily on a logical library name to hide where actual physical library * sources reside. Its static functions serve as managers of the "library table" to * map logical library names to actual library sources. * <p> * Example LPID string: * "kicad:passives/R/rev6". * <p> * <ul> * <li> "kicad" is the logical library name. * <li> "passives" is the category. * <li> "passives/R" is the partname. * <li> "rev6" is the revision number, which is optional. If missing then its * delimiter should also not be present. * </ul> * <p> * This class owns the <b>library table</b>, which is like fstab in concept and maps logical * library name to library URI, type, and options. It has the following columns: * <ul> * <li> Logical Library Name * <li> Library Type * <li> Library URI. The full URI to the library source, form dependent on Type. * <li> Options, used for access, such as password * </ul> * <p> * For now, the Library Type can be one of: * <ul> * <li> "dir" * <li> "schematic" i.e. a parts list from another schematic. * <li> "subversion" * <li> "bazaar" * <li> "http" * </ul> * <p> * For now, the Library URI types needed to support the various types can be one of those * shown below, which are typical of each type: * <ul> * <li> "file://C:/mylibdir" * <li> "file://home/user/kicadwork/jtagboard.sch" * <li> "svn://kicad.org/partlib/trunk" * <li> "http://kicad.org/partlib" * </ul> * <p> * The applicable library table is built up from several additive rows (table fragments), * and the final table is a merging of the table fragments. Two anticipated sources of * the rows are a personal table, and a schematic resident table. The schematic * resident table rows are considered a higher priority in the final dynamically * assembled library table. A row in the schematic contribution to the library table * will take precedence over the personal table if there is a collision on logical * library name, otherwise the rows simply combine without issue to make up the * applicable library table. */ class LPID // aka GUID { public: /** * Constructor LPID * takes aLPID string and parses it. A typical LPID string uses a logical * library name followed by a part name. * e.g.: "kicad:passives/R/rev2", or * e.g.: "mylib:R33" */ LPID( const STRING& aLPID ) throw( PARSE_ERROR ); /** * Function GetLogLib * returns the logical library portion of a LPID. There is not Set accessor * for this portion since it comes from the library table and is considered * read only here. */ STRING GetLogLib() const; /** * Function GetCategory * returns the category of this part id, "passives" in the example at the * top of the class description. */ STRING GetCategory() const; /** * Function SetCategory * overrides the category portion of the LPID to @a aCategory and is typically * either the empty string or a single word like "passives". */ void SetCategory( const STRING& aCategory ); /** * Function GetRevision * returns the revision portion of the LPID or StrEmpty if none. */ STRING GetRevision() const; /** * Function SetRevision * overrides the revision portion of the LPID to @a aRevision and must * be in the form "rev<num>" where "<num>" is "1", "2", etc. */ void SetRevision( const STRING& aRevision ); /** * Function GetFullText * returns the full text of the LPID. */ STRING GetFullText() const; //-----<statics>----------------------------------------------------- /** * Function GetLogicalLibraries * returns the logical library names, all of them that are in the * library table. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRINGS GetLogicalLibraries( SCHEMATIC* aSchematic=NULL ); /** * Function GetLibraryURI * returns the full library path from a logical library name. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetLibraryURI( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; /** * Function GetLibraryType * returns the type of a logical library. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetLibraryType( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; /** * Function GetOptions * returns the options string for \a aLogicalLibraryName. * @param aLogicalLibraryName is the short name for the library of interest. * @param aSchematic provides access to the full library table inclusive * of the schematic contribution, or may be NULL to exclude the schematic rows. */ static STRING GetPassword( const STRING& aLogicalLibraryName, SCHEMATIC* aSchematic=NULL ) const; }; /** /** * Class SVN_LIB_SOURCE * Class SVN_LIB_SOURCE * implements a LIB_SOURCE in a subversion repository. * implements a LIB_SOURCE in a subversion repository. Loading
new/sch_lib_table.cpp +111 −15 Original line number Original line Diff line number Diff line Loading @@ -30,8 +30,10 @@ using namespace std; using namespace SCH; using namespace SCH; LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) : fallBack( aFallBackTable ) { { /* not copying fall back, simply search it separately if "logicalName not found". if( aFallBackTable ) if( aFallBackTable ) { { const ROWS& t = aFallBackTable->rows; const ROWS& t = aFallBackTable->rows; Loading @@ -39,12 +41,12 @@ LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) for( ROWS_CITER it = t.begin(); it != t.end(); ++it ) for( ROWS_CITER it = t.begin(); it != t.end(); ++it ) { { // our rows are empty, expect no collisions here // our rows are empty, expect no collisions here auto_ptr<ROW> row( new ROW( *it ) ); auto_ptr<ROW> row( new ROW( *it->second ) ); row->owner = this; row->owner = this; rows.insert( row.release() ); insert( row ); } } } } */ } } Loading Loading @@ -126,18 +128,89 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) in->NeedRIGHT(); in->NeedRIGHT(); in->NeedRIGHT(); // teriminate the (lib..) in->NeedRIGHT(); // teriminate the (lib..) rows.insert( row.release() ); // all logicalNames within this table fragment must be unique, so we do not // replace. However a fallBack table can have a conflicting logicalName // and ours will supercede that one since in findLib() we search this table // before any fall back. if( !InsertLib( row ) ) { char buf[300]; snprintf( buf, sizeof(buf), "'%s' is a duplicate logical lib name", row->logicalName.c_str() ); throw IO_ERROR( buf ); } } } return; return; } } #if 1 void LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ) { out->Print( nestLevel, "(lib_table\n" ); for( ROWS_CITER it = rows.begin(); it != rows.end(); ++it ) it->second->Format( out, nestLevel+1 ); out->Print( nestLevel, ")\n" ); } int main( int argc, char** argv ) void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ) { out->Print( nestLevel, "(lib (logical \"%s\")(type \"%s\")(full_uri \"%s\")(options \"%s\"))\n", logicalName.c_str(), libType.c_str(), fullURI.c_str(), options.c_str() ); } const LIB_TABLE::ROW* LIB_TABLE::FindLib( const STRING& aLogicalName ) { // this function must be *super* fast, so therefore should not instantiate // anything which would require using the heap. This function is the reason // ptr_map<> was used instead of ptr_set<>, which would have required // instantiating a ROW just to find a ROW. ROWS_CITER it = rows.find( aLogicalName ); if( it != rows.end() ) { // reference: http://myitcorner.com/blog/?p=361 return (const LIB_TABLE::ROW*) it->second; // found } // not found, search fall back table if( fallBack ) return fallBack->FindLib( aLogicalName ); return 0; // not found } bool LIB_TABLE::InsertLib( auto_ptr<ROW>& aRow, bool doReplace ) { ROWS_ITER it = rows.find( aRow->logicalName ); if( doReplace || it == rows.end() ) { // be careful here, key is needed because aRow can be // release()ed before logicalName is captured. const STRING& key = aRow->logicalName; rows.insert( key, aRow ); return true; } return false; } #if 1 && defined(DEBUG) // build this with a Debug CMAKE_BUILD_TYPE void LIB_TABLE::Test() { { // the null string is not really a legal DSN token since any double quotes // the null string is not really a legal DSN token since any double quotes // as assumed to be a single quote. To pass an empty string, we pass " " // are assumed to be a single quote. To pass an empty string, we pass " " // to (options " ") // to (options " ") SCH_LIB_TABLE_LEXER slr( SCH_LIB_TABLE_LEXER slr( "(lib_table \n" "(lib_table \n" Loading @@ -148,16 +221,14 @@ int main( int argc, char** argv ) wxT( "inline text" ) // source wxT( "inline text" ) // source ); ); LIB_TABLE lib_table; // read the "( lib_table" pair of tokens try try { { // read the "( lib_table" pair of tokens slr.NextTok(); slr.NextTok(); slr.NextTok(); slr.NextTok(); lib_table.Parse( &slr ); // parse the rest of input to slr Parse( &slr ); } } catch( std::exception& ex ) catch( std::exception& ex ) Loading @@ -167,11 +238,36 @@ int main( int argc, char** argv ) catch( IO_ERROR ioe ) catch( IO_ERROR ioe ) { { printf( "caught\n" ); printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); } } lib_table.Show(); STRING_FORMATTER sf; Format( &sf, 0 ); printf( "test 'Parse() <-> Format()' round tripping:\n" ); printf( "%s", sf.GetString().c_str() ); printf( "\ntest a lookup of 'www':\n" ); sf.Clear(); const LIB_TABLE::ROW* www = FindLib( "www" ); if( www ) { // found, print it just to prove it. www->Format( &sf, 1 ); printf( "%s", sf.GetString().c_str() ); } else printf( "not found\n" ); } int main( int argc, char** argv ) { LIB_TABLE lib_table; lib_table.Test(); return 0; return 0; } } Loading