From 0af1004f5cedbcc6b7fa21775629ee67a084a145 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 3 Jan 2011 14:01:46 -0600 Subject: [PATCH] more PART parser work --- new/sch_dir_lib_source.cpp | 8 ++- new/sch_lib.cpp | 100 ++++++++++++++++++++++++------------- new/sch_lib.h | 13 +++-- new/sch_lpid.cpp | 16 +++++- new/sch_lpid.h | 12 +++++ new/sch_part.cpp | 15 ++++-- 6 files changed, 119 insertions(+), 45 deletions(-) diff --git a/new/sch_dir_lib_source.cpp b/new/sch_dir_lib_source.cpp index 042daa2a50..3153eaf62f 100644 --- a/new/sch_dir_lib_source.cpp +++ b/new/sch_dir_lib_source.cpp @@ -459,8 +459,12 @@ void DIR_LIB_SOURCE::GetRevisions( STRINGS* aResults, const STRING& aPartName ) PN_ITER it = partnames.upper_bound( partName +'/' ); PN_ITER end = partnames.lower_bound( partName + char( '/' +1 ) ); - while( it != end ) - aResults->push_back( *it++ ); + for( ; it != end; ++it ) + { + const char* rev = endsWithRev( *it ); + assert( rev ); + aResults->push_back( it->substr( rev - it->c_str() ) ); + } } } diff --git a/new/sch_lib.cpp b/new/sch_lib.cpp index a9c567d998..1c55520103 100644 --- a/new/sch_lib.cpp +++ b/new/sch_lib.cpp @@ -39,13 +39,12 @@ /* -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. +The LIB part cache consists 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 which 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. 1) Only things which are asked for are done. 2) Anything we learn we remember. @@ -54,10 +53,31 @@ right hand side of the map tuple. namespace SCH { -class PART_REVS : public std::map< STRING, PART* > -{ - // @todo provide an integer sort on revN.. strings here. +/** + * Struct LTREV + * is for PART_REVS, and provides a custom way to compare rev STRINGs. + * Namely, the revN[N..] string if present, is collated according to a + * 'higher revision first'. + */ +struct LTREV +{ + bool operator() ( const STRING& s1, const STRING& s2 ) const + { + return RevCmp( s1.c_str(), s2.c_str() ) < 0; + } +}; + + +/** + * Class PART_REVS + * contains the collection of revisions for a particular part name, in the + * form of cached PARTs. The tuple consists of a rev string and a PART pointer. + * The rev string is like "rev1", the PART pointer will be NULL until the PART + * gets loaded, lazily. + */ +class PART_REVS : public std::map< STRING, PART*, LTREV > +{ public: ~PART_REVS() { @@ -68,6 +88,15 @@ public: } }; + +/** + * Class PARTS + * contains the collection of PART_REVS for all PARTs in the lib. + * The tuple consists of a part name and a PART_REVS pointer. + * The part name does not have the revision attached (of course this is understood + * by definition of "part name"). The PART_REVS pointer will be NULL until a client + * askes about the revisions for a part name, so the loading is done lazily. + */ class PARTS : public std::map< STRING, PART_REVS* > { public: @@ -126,7 +155,7 @@ LIB::~LIB() } -const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) +const PART* LIB::lookupPart( const LPID& aLPID ) throw( IO_ERROR ) { if( !parts ) { @@ -137,7 +166,7 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) // insert a PART_REVS for each part name for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it ) { - // D(printf("findPart:%s\n", it->c_str() );) + D(printf("lookupPart:%s\n", it->c_str() );) (*parts)[*it] = new PART_REVS; } } @@ -152,44 +181,46 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) // if the key for parts has no aLPID.GetPartName() the part is not in this lib if( revs ) { - if( revs->size() == 0 ) + if( revs->size() == 0 ) // assume rev list has not been loaded yet { // load all the revisions for this part. source->GetRevisions( &vfetch, aLPID.GetPartName() ); - // creat a PART_REV entry for revision, but leave the PART* NULL + // create a PART_REV entry for each 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() );) + D(printf("lookupPartRev:%s\n", it->c_str() );) (*revs)[*it] = 0; } - } - 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() ); - } - - return result->second; - } + PART_REVS::iterator rev; // 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 + rev = revs->begin(); // sort order has highest rev first - if( !result->second ) // the PART has never been loaded before + if( !rev->second ) // the PART has never been instantiated before { - result->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), result->first ) ); + rev->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), rev->first ) ); } - return result->second; + D(printf("lookupPartLatestRev:%s\n", rev->second->partNameAndRev.c_str() );) + return rev->second; + } + else + { + rev = revs->find( aLPID.GetRevision() ); + + if( rev != revs->end() ) + { + if( !rev->second ) // the PART has never been instantiated before + { + rev->second = new PART( this, aLPID.GetPartNameAndRev() ); + } + return rev->second; + } } } @@ -199,7 +230,7 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR ) PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR ) { - PART* part = (PART*) findPart( aLPID ); + PART* part = (PART*) lookupPart( aLPID ); if( !part ) // part does not exist in this lib { @@ -221,7 +252,8 @@ PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR printf( "\n" ); #endif - SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ ); + // @todo consider changing ReadPart to return a "source" + SWEET_LEXER sw( part->body, wxString::FromUTF8( aLPID.Format().c_str() ) ); part->Parse( &sw, aLibTable ); } diff --git a/new/sch_lib.h b/new/sch_lib.h index 12b7cfa14c..5dc32a2878 100644 --- a/new/sch_lib.h +++ b/new/sch_lib.h @@ -343,14 +343,17 @@ protected: PARTS* parts; /** - * Function findPart - * finds a PART, returns NULL if cannot find. + * Function lookupPart + * looks up a PART, returns NULL if cannot find in source. Does not parse + * the part. Does not even load the part's Sweet string. No ownership + * is given to the PART, it stays in the cache that is this LIB. + * * @throw IO_ERROR if there is some kind of communications error reading * the original list of parts. + * + * @return PART* - the cached PART, or NULL if not found. No ownership transferred. */ - const PART* findPart( const LPID& aLPID ) throw( IO_ERROR ); - - + const PART* lookupPart( const LPID& aLPID ) throw( IO_ERROR ); }; diff --git a/new/sch_lpid.cpp b/new/sch_lpid.cpp index d031dcf877..ef24cdb0f8 100644 --- a/new/sch_lpid.cpp +++ b/new/sch_lpid.cpp @@ -58,6 +58,20 @@ const char* EndsWithRev( const char* start, const char* tail, char separator ) return 0; } +int RevCmp( const char* s1, const char* s2 ) +{ + int r = strncmp( s1, s2, 3 ); + + if( r || strlen(s1)<4 || strlen(s2)<4 ) + { + return r; + } + + int rnum1 = atoi( s1+3 ); + int rnum2 = atoi( s2+3 ); + + return -(rnum1 - rnum2); // swap the sign, higher revs first +} //----------------------------------------- @@ -94,7 +108,7 @@ static int okRevision( const STRING& aField ) { char rev[32]; // C string for speed - if( aField.size() >= 4 && aField.size() <= sizeof(rev)-3 ) + if( aField.size() >= 4 ) { strcpy( rev, "x/" ); strcat( rev, aField.c_str() ); diff --git a/new/sch_lpid.h b/new/sch_lpid.h index 3a20e28c59..c35c5cb3ce 100644 --- a/new/sch_lpid.h +++ b/new/sch_lpid.h @@ -228,4 +228,16 @@ static inline const char* EndsWithRev( const STRING& aPartName, char separator = } +/** + * Function RevCmp + * compares two rev strings in a way like strcmp() except that the highest numbered + * revision is considered first in the sort order. The function probably won't work + * unless you give it two rev strings. + * @param s1 is a rev string like "rev10" + * @param s2 is a rev string like "rev1". + * @return int - either negative, zero, or positive depending on whether the revision + * is greater, equal, or less on the left hand side. + */ +int RevCmp( const char* s1, const char* s2 ); + #endif // SCH_LPID_H_ diff --git a/new/sch_part.cpp b/new/sch_part.cpp index bf9073c022..4f21a5cf73 100644 --- a/new/sch_part.cpp +++ b/new/sch_part.cpp @@ -135,19 +135,28 @@ public: /// @param me = ja mir, the object getting stuffed, from its perspective void parsePart( PART* me ) { - PART_T tok = in->NextTok(); + PART_T tok; +#if 0 // Be flexible regarding the starting point of the stream. // Caller may not have read the first two tokens out of the // stream: T_LEFT and T_part, so ignore them if seen here. // The 1st two tokens T_LEFT and T_part are then optional in the grammar. - if( tok == T_LEFT ) + if( (tok = in->NextTok() ) == T_LEFT ) { if( ( tok = in->NextTok() ) != T_part ) in->Expecting( T_part ); } +#else + // "( part" are not optional + in->NeedLEFT(); + + if( ( tok = in->NextTok() ) != T_part ) + in->Expecting( T_part ); +#endif + in->NeedSYMBOLorNUMBER(); // read in part NAME_HINT, and toss tok = in->NextTok(); @@ -267,7 +276,7 @@ public: contains |= PB(PARSED); - this->contains |= contains; + me->contains |= contains; } };