Loading new/sch_dir_lib_source.cpp +29 −4 Original line number Original line Diff line number Diff line Loading @@ -400,7 +400,7 @@ DIR_LIB_SOURCE::~DIR_LIB_SOURCE() void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory ) void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory ) throw( IO_ERROR ) throw( IO_ERROR ) { { PN_ITER limit = aCategory.size() ? PN_ITER end = aCategory.size() ? partnames.lower_bound( aCategory + char( '/' + 1 ) ) : partnames.lower_bound( aCategory + char( '/' + 1 ) ) : partnames.end(); partnames.end(); Loading @@ -414,7 +414,7 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a { { STRING partName; STRING partName; while( it != limit ) while( it != end ) { { const char* rev = endsWithRev( *it ); const char* rev = endsWithRev( *it ); Loading @@ -434,7 +434,32 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a else else { { while( it != limit ) while( it != end ) aResults->push_back( *it++ ); } } void DIR_LIB_SOURCE::GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) { aResults->clear(); if( useVersioning ) { STRING partName; const char* rev = endsWithRev( aPartName ); if( rev ) // partName is substring which omits the rev and the separator partName.assign( aPartName, 0, rev - aPartName.c_str() - 1 ); else partName = aPartName; PN_ITER it = partnames.upper_bound( partName +'/' ); PN_ITER end = partnames.lower_bound( partName + char( '/' +1 ) ); while( it != end ) aResults->push_back( *it++ ); aResults->push_back( *it++ ); } } } } Loading new/sch_dir_lib_source.h +2 −4 Original line number Original line Diff line number Diff line Loading @@ -174,10 +174,8 @@ protected: void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = "" ) void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = "" ) throw( IO_ERROR ); throw( IO_ERROR ); void GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) void GetRevisions( STRINGS* aResults, const STRING& aPartName ) { throw( IO_ERROR ); // @todo } void FindParts( STRINGS* aResults, const STRING& aQuery ) throw( IO_ERROR ) void FindParts( STRINGS* aResults, const STRING& aQuery ) throw( IO_ERROR ) { { Loading new/sch_lib.cpp +160 −16 Original line number Original line Diff line number Diff line Loading @@ -25,19 +25,95 @@ #include <memory> // std::auto_ptr #include <memory> // std::auto_ptr #include <wx/string.h> #include <wx/string.h> #include <sch_lib.h> #include <sch_lib.h> #include <sch_lpid.h> #include <sch_lpid.h> #include <sch_part.h> #include <sch_part.h> #include <sweet_lexer.h> #include <sweet_lexer.h> #include <sch_lib_table.h> #include <sch_lib_table.h> #if 1 #include <map> /* The LIB part cache consist of a std::map of partnames without revisions at the top level. Each top level map entry can point to another std::map which it owns and holds all the revisions for that part name. At any point in the tree, there can be NULL pointers which allow for lazy loading, including the very top most root pointer itself, which is PARTS* parts. We use the key to hold the partName at one level, and revision at the deeper nested level, and that key information may not be present within right hand side of the map tuple. 1) Only things which are asked for are done. 2) Anything we learn we remember. */ namespace SCH { class PART_REVS : public std::map< STRING, PART* > { // @todo provide an integer sort on revN.. strings here. public: ~PART_REVS() { for( iterator it = begin(); it != end(); ++it ) { delete it->second; // second may be NULL, no problem } } }; class PARTS : public std::map< STRING, PART_REVS* > { public: ~PARTS() { for( iterator it = begin(); it != end(); ++it ) { delete it->second; // second may be NULL, no problem } } }; } // namespace SCH #else // was nothing but grief: #include <boost/ptr_container/ptr_map.hpp> namespace SCH { /// PARTS' key is revision, like "rev12", PART pointer may be null until loaded. typedef boost::ptr_map< STRING, boost::nullable<PART> > PARTS; typedef PARTS::iterator PARTS_ITER; typedef PARTS::const_iterator PARTS_CITER; /// PART_REVS' key is part name, w/o rev, PART pointer may be null until loaded. typedef boost::ptr_map< STRING, boost::nullable<PARTS> > PART_REVS; typedef PART_REVS::iterator PART_REVS_ITER; typedef PART_REVS::const_iterator PART_REVS_CITER; } // namespace SCH #endif using namespace SCH; using namespace SCH; LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink ) : LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink ) : name( aLogicalLibrary ), logicalName( aLogicalLibrary ), source( aSource ), source( aSource ), sink( aSink ) sink( aSink ), cachedCategories( false ), parts( 0 ) { { } } Loading @@ -46,25 +122,99 @@ LIB::~LIB() { { delete source; delete source; delete sink; delete sink; delete parts; } } PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR ) const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) { if( !parts ) { { PART* part; parts = new PARTS; // If part not already cached source->GetCategoricalPartNames( &vfetch ); if( 1 /* @todo test cache */ ) // insert a PART_REVS for each part name for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it ) { { // load it. // D(printf("findPart:%s\n", it->c_str() );) (*parts)[*it] = new PART_REVS; } } // load all the revisions for this part name, only if it has any PARTS::iterator pi = parts->find( aLPID.GetPartName() ); PART_REVS* revs = pi != parts->end() ? pi->second : NULL; // D(printf("revs:%p partName:%s\n", revs, aLPID.GetPartName().c_str() );) // if the key for parts has no aLPID.GetPartName() the part is not in this lib if( revs ) { if( revs->size() == 0 ) { // load all the revisions for this part. source->GetRevisions( &vfetch, aLPID.GetPartName() ); // creat a PART_REV entry for revision, but leave the PART* NULL for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it ) { // D(printf("findPartRev:%s\n", it->c_str() );) (*revs)[*it] = 0; } part = new PART( this, aLPID.GetPartName(), aLPID.GetRevision() ); } PART_REVS::iterator result = revs->find( aLPID.GetPartNameAndRev() ); if( result != revs->end() ) { if( !result->second ) // the PART has never been loaded before { result->second = new PART( this, aLPID.GetPartNameAndRev() ); } std::auto_ptr<PART> wrapped( part ); return result->second; } // If caller did not say what revision, find the highest numbered one and return that. // Otherwise he knew what he wanted specifically, and we do not have it. if( !aLPID.GetRevision().size() && revs->size() ) { result = revs->begin(); // sort order has highest rev first if( !result->second ) // the PART has never been loaded before { result->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), result->first ) ); } return result->second; } } return 0; // no such part name in this lib } PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR ) { PART* part = (PART*) findPart( aLPID ); if( !part ) // part does not exist in this lib { wxString msg = wxString::Format( _("part '%s' not found in lib %s" ), wxString::FromUTF8( aLPID.GetPartNameAndRev().c_str() ).GetData(), wxString::FromUTF8( logicalName.c_str() ).GetData() ); THROW_IO_ERROR( msg ); } if( part->body.empty() ) { // load body source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() ); source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() ); #if defined(DEBUG) #if 0 && defined(DEBUG) const STRING& body = part->body; const STRING& body = part->body; printf( "body: %s", body.c_str() ); printf( "body: %s", body.c_str() ); if( !body.size() || body[body.size()-1] != '\n' ) if( !body.size() || body[body.size()-1] != '\n' ) Loading @@ -74,12 +224,6 @@ PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ ); SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ ); part->Parse( &sw, aLibTable ); part->Parse( &sw, aLibTable ); // stuff the part into this LIBs cache: // @todo wrapped.release(); } } return part; return part; Loading new/sch_lib.h +28 −6 Original line number Original line Diff line number Diff line Loading @@ -105,7 +105,9 @@ protected: ///< derived classes must implement /** /** * Function GetRevisions * Function GetRevisions * fetches all revisions for @a aPartName into @a aResults. Revisions are strings * fetches all revisions for @a aPartName into @a aResults. Revisions are strings * like "rev12", "rev279", and are library source agnostic. These * like "rev12", "rev279", and are library source agnostic. These do not have to be * in a contiguous order, but the first 3 characters must be "rev" and subsequent * characters must consist of at least one decimal digit. */ */ virtual void GetRevisions( STRINGS* aResults, const STRING& aPartName ) virtual void GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) = 0; throw( IO_ERROR ) = 0; Loading Loading @@ -183,6 +185,9 @@ protected: }; }; class PARTS; /** /** * Class LIB * Class LIB * is a cache of parts, and because the LIB_SOURCE is abstracted, there * is a cache of parts, and because the LIB_SOURCE is abstracted, there Loading Loading @@ -321,14 +326,31 @@ protected: STR_UTF fetch; // scratch, used to fetch things, grows to worst case size. STR_UTF fetch; // scratch, used to fetch things, grows to worst case size. STR_UTFS vfetch; // scratch, used to fetch things. STR_UTFS vfetch; // scratch, used to fetch things. STRING name; STRING logicalName; LIB_SOURCE* source; LIB_SOURCE* source; LIB_SINK* sink; LIB_SINK* sink; // STRING libraryURI; STRINGS categories; STRINGS categories; bool cachedCategories; /// < is true only after reading categories /** parts are in various states of readiness: * 1) not even loaded (if cachedParts is false) * 2) present, but without member 'body' having been read() yet. * 3) body has been read, but not parsed yet. * 4) parsed and inheritance if any has been applied. */ PARTS* parts; /** * Function findPart * finds a PART, returns NULL if cannot find. * @throw IO_ERROR if there is some kind of communications error reading * the original list of parts. */ const PART* findPart( const LPID& aLPID ) throw( IO_ERROR ); // PARTS parts; }; }; Loading new/sch_lib_table.h +0 −1 Original line number Original line Diff line number Diff line Loading @@ -375,7 +375,6 @@ private: typedef boost::ptr_map<STRING, ROW> ROWS; typedef boost::ptr_map<STRING, ROW> ROWS; typedef ROWS::iterator ROWS_ITER; typedef ROWS::iterator ROWS_ITER; typedef ROWS::const_iterator ROWS_CITER; typedef ROWS::const_iterator ROWS_CITER; // typedef std::pair<ROWS_ITER, bool> ROW_PAIR; ROWS rows; ROWS rows; LIB_TABLE* fallBack; LIB_TABLE* fallBack; Loading Loading
new/sch_dir_lib_source.cpp +29 −4 Original line number Original line Diff line number Diff line Loading @@ -400,7 +400,7 @@ DIR_LIB_SOURCE::~DIR_LIB_SOURCE() void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory ) void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory ) throw( IO_ERROR ) throw( IO_ERROR ) { { PN_ITER limit = aCategory.size() ? PN_ITER end = aCategory.size() ? partnames.lower_bound( aCategory + char( '/' + 1 ) ) : partnames.lower_bound( aCategory + char( '/' + 1 ) ) : partnames.end(); partnames.end(); Loading @@ -414,7 +414,7 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a { { STRING partName; STRING partName; while( it != limit ) while( it != end ) { { const char* rev = endsWithRev( *it ); const char* rev = endsWithRev( *it ); Loading @@ -434,7 +434,32 @@ void DIR_LIB_SOURCE::GetCategoricalPartNames( STRINGS* aResults, const STRING& a else else { { while( it != limit ) while( it != end ) aResults->push_back( *it++ ); } } void DIR_LIB_SOURCE::GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) { aResults->clear(); if( useVersioning ) { STRING partName; const char* rev = endsWithRev( aPartName ); if( rev ) // partName is substring which omits the rev and the separator partName.assign( aPartName, 0, rev - aPartName.c_str() - 1 ); else partName = aPartName; PN_ITER it = partnames.upper_bound( partName +'/' ); PN_ITER end = partnames.lower_bound( partName + char( '/' +1 ) ); while( it != end ) aResults->push_back( *it++ ); aResults->push_back( *it++ ); } } } } Loading
new/sch_dir_lib_source.h +2 −4 Original line number Original line Diff line number Diff line Loading @@ -174,10 +174,8 @@ protected: void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = "" ) void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory = "" ) throw( IO_ERROR ); throw( IO_ERROR ); void GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) void GetRevisions( STRINGS* aResults, const STRING& aPartName ) { throw( IO_ERROR ); // @todo } void FindParts( STRINGS* aResults, const STRING& aQuery ) throw( IO_ERROR ) void FindParts( STRINGS* aResults, const STRING& aQuery ) throw( IO_ERROR ) { { Loading
new/sch_lib.cpp +160 −16 Original line number Original line Diff line number Diff line Loading @@ -25,19 +25,95 @@ #include <memory> // std::auto_ptr #include <memory> // std::auto_ptr #include <wx/string.h> #include <wx/string.h> #include <sch_lib.h> #include <sch_lib.h> #include <sch_lpid.h> #include <sch_lpid.h> #include <sch_part.h> #include <sch_part.h> #include <sweet_lexer.h> #include <sweet_lexer.h> #include <sch_lib_table.h> #include <sch_lib_table.h> #if 1 #include <map> /* The LIB part cache consist of a std::map of partnames without revisions at the top level. Each top level map entry can point to another std::map which it owns and holds all the revisions for that part name. At any point in the tree, there can be NULL pointers which allow for lazy loading, including the very top most root pointer itself, which is PARTS* parts. We use the key to hold the partName at one level, and revision at the deeper nested level, and that key information may not be present within right hand side of the map tuple. 1) Only things which are asked for are done. 2) Anything we learn we remember. */ namespace SCH { class PART_REVS : public std::map< STRING, PART* > { // @todo provide an integer sort on revN.. strings here. public: ~PART_REVS() { for( iterator it = begin(); it != end(); ++it ) { delete it->second; // second may be NULL, no problem } } }; class PARTS : public std::map< STRING, PART_REVS* > { public: ~PARTS() { for( iterator it = begin(); it != end(); ++it ) { delete it->second; // second may be NULL, no problem } } }; } // namespace SCH #else // was nothing but grief: #include <boost/ptr_container/ptr_map.hpp> namespace SCH { /// PARTS' key is revision, like "rev12", PART pointer may be null until loaded. typedef boost::ptr_map< STRING, boost::nullable<PART> > PARTS; typedef PARTS::iterator PARTS_ITER; typedef PARTS::const_iterator PARTS_CITER; /// PART_REVS' key is part name, w/o rev, PART pointer may be null until loaded. typedef boost::ptr_map< STRING, boost::nullable<PARTS> > PART_REVS; typedef PART_REVS::iterator PART_REVS_ITER; typedef PART_REVS::const_iterator PART_REVS_CITER; } // namespace SCH #endif using namespace SCH; using namespace SCH; LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink ) : LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink ) : name( aLogicalLibrary ), logicalName( aLogicalLibrary ), source( aSource ), source( aSource ), sink( aSink ) sink( aSink ), cachedCategories( false ), parts( 0 ) { { } } Loading @@ -46,25 +122,99 @@ LIB::~LIB() { { delete source; delete source; delete sink; delete sink; delete parts; } } PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR ) const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) { if( !parts ) { { PART* part; parts = new PARTS; // If part not already cached source->GetCategoricalPartNames( &vfetch ); if( 1 /* @todo test cache */ ) // insert a PART_REVS for each part name for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it ) { { // load it. // D(printf("findPart:%s\n", it->c_str() );) (*parts)[*it] = new PART_REVS; } } // load all the revisions for this part name, only if it has any PARTS::iterator pi = parts->find( aLPID.GetPartName() ); PART_REVS* revs = pi != parts->end() ? pi->second : NULL; // D(printf("revs:%p partName:%s\n", revs, aLPID.GetPartName().c_str() );) // if the key for parts has no aLPID.GetPartName() the part is not in this lib if( revs ) { if( revs->size() == 0 ) { // load all the revisions for this part. source->GetRevisions( &vfetch, aLPID.GetPartName() ); // creat a PART_REV entry for revision, but leave the PART* NULL for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it ) { // D(printf("findPartRev:%s\n", it->c_str() );) (*revs)[*it] = 0; } part = new PART( this, aLPID.GetPartName(), aLPID.GetRevision() ); } PART_REVS::iterator result = revs->find( aLPID.GetPartNameAndRev() ); if( result != revs->end() ) { if( !result->second ) // the PART has never been loaded before { result->second = new PART( this, aLPID.GetPartNameAndRev() ); } std::auto_ptr<PART> wrapped( part ); return result->second; } // If caller did not say what revision, find the highest numbered one and return that. // Otherwise he knew what he wanted specifically, and we do not have it. if( !aLPID.GetRevision().size() && revs->size() ) { result = revs->begin(); // sort order has highest rev first if( !result->second ) // the PART has never been loaded before { result->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), result->first ) ); } return result->second; } } return 0; // no such part name in this lib } PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR ) { PART* part = (PART*) findPart( aLPID ); if( !part ) // part does not exist in this lib { wxString msg = wxString::Format( _("part '%s' not found in lib %s" ), wxString::FromUTF8( aLPID.GetPartNameAndRev().c_str() ).GetData(), wxString::FromUTF8( logicalName.c_str() ).GetData() ); THROW_IO_ERROR( msg ); } if( part->body.empty() ) { // load body source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() ); source->ReadPart( &part->body, aLPID.GetPartName(), aLPID.GetRevision() ); #if defined(DEBUG) #if 0 && defined(DEBUG) const STRING& body = part->body; const STRING& body = part->body; printf( "body: %s", body.c_str() ); printf( "body: %s", body.c_str() ); if( !body.size() || body[body.size()-1] != '\n' ) if( !body.size() || body[body.size()-1] != '\n' ) Loading @@ -74,12 +224,6 @@ PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ ); SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ ); part->Parse( &sw, aLibTable ); part->Parse( &sw, aLibTable ); // stuff the part into this LIBs cache: // @todo wrapped.release(); } } return part; return part; Loading
new/sch_lib.h +28 −6 Original line number Original line Diff line number Diff line Loading @@ -105,7 +105,9 @@ protected: ///< derived classes must implement /** /** * Function GetRevisions * Function GetRevisions * fetches all revisions for @a aPartName into @a aResults. Revisions are strings * fetches all revisions for @a aPartName into @a aResults. Revisions are strings * like "rev12", "rev279", and are library source agnostic. These * like "rev12", "rev279", and are library source agnostic. These do not have to be * in a contiguous order, but the first 3 characters must be "rev" and subsequent * characters must consist of at least one decimal digit. */ */ virtual void GetRevisions( STRINGS* aResults, const STRING& aPartName ) virtual void GetRevisions( STRINGS* aResults, const STRING& aPartName ) throw( IO_ERROR ) = 0; throw( IO_ERROR ) = 0; Loading Loading @@ -183,6 +185,9 @@ protected: }; }; class PARTS; /** /** * Class LIB * Class LIB * is a cache of parts, and because the LIB_SOURCE is abstracted, there * is a cache of parts, and because the LIB_SOURCE is abstracted, there Loading Loading @@ -321,14 +326,31 @@ protected: STR_UTF fetch; // scratch, used to fetch things, grows to worst case size. STR_UTF fetch; // scratch, used to fetch things, grows to worst case size. STR_UTFS vfetch; // scratch, used to fetch things. STR_UTFS vfetch; // scratch, used to fetch things. STRING name; STRING logicalName; LIB_SOURCE* source; LIB_SOURCE* source; LIB_SINK* sink; LIB_SINK* sink; // STRING libraryURI; STRINGS categories; STRINGS categories; bool cachedCategories; /// < is true only after reading categories /** parts are in various states of readiness: * 1) not even loaded (if cachedParts is false) * 2) present, but without member 'body' having been read() yet. * 3) body has been read, but not parsed yet. * 4) parsed and inheritance if any has been applied. */ PARTS* parts; /** * Function findPart * finds a PART, returns NULL if cannot find. * @throw IO_ERROR if there is some kind of communications error reading * the original list of parts. */ const PART* findPart( const LPID& aLPID ) throw( IO_ERROR ); // PARTS parts; }; }; Loading
new/sch_lib_table.h +0 −1 Original line number Original line Diff line number Diff line Loading @@ -375,7 +375,6 @@ private: typedef boost::ptr_map<STRING, ROW> ROWS; typedef boost::ptr_map<STRING, ROW> ROWS; typedef ROWS::iterator ROWS_ITER; typedef ROWS::iterator ROWS_ITER; typedef ROWS::const_iterator ROWS_CITER; typedef ROWS::const_iterator ROWS_CITER; // typedef std::pair<ROWS_ITER, bool> ROW_PAIR; ROWS rows; ROWS rows; LIB_TABLE* fallBack; LIB_TABLE* fallBack; Loading