Commit 41637b36 authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

commit

parent 0a3830b6
Loading
Loading
Loading
Loading
+29 −4
Original line number Original line Diff line number Diff line
@@ -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();


@@ -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 );


@@ -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++ );
    }
    }
}
}
+2 −4
Original line number Original line Diff line number Diff line
@@ -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 )
    {
    {
+160 −16
Original line number Original line Diff line number Diff line
@@ -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 )
{
{
}
}


@@ -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' )
@@ -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;
+28 −6
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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
@@ -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;
};
};




+0 −1
Original line number Original line Diff line number Diff line
@@ -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