Commit 0dc4d9c1 authored by Dick Hollenbeck's avatar Dick Hollenbeck Committed by Wayne Stambaugh
Browse files

Commit Dick's changes to the FP_LIB_TABLE object.

parent 012fa536
Loading
Loading
Loading
Loading
+46 −51
Original line number Original line Diff line number Diff line
/*
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 *
 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2010-12 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
 * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
 *
 *
@@ -39,7 +39,7 @@ FP_LIB_TABLE::FP_LIB_TABLE( FP_LIB_TABLE* aFallBackTable ) :
    fallBack( aFallBackTable )
    fallBack( aFallBackTable )
{
{
    // not copying fall back, simply search aFallBackTable separately
    // not copying fall back, simply search aFallBackTable separately
    // if "logicalName not found".
    // if "nickName not found".
}
}




@@ -68,9 +68,9 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR


        in->NeedSYMBOLorNUMBER();
        in->NeedSYMBOLorNUMBER();


        std::auto_ptr<ROW> row( new ROW( this ) );
        ROW     row( this );


        row->SetLogicalName( in->CurText() );
        row.SetNickName( in->FromUTF8() );


        in->NeedRIGHT();
        in->NeedRIGHT();


@@ -82,7 +82,7 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR


        in->NeedSYMBOLorNUMBER();
        in->NeedSYMBOLorNUMBER();


        row->SetType( in->CurText() );
        row.SetType( in->FromUTF8() );


        in->NeedRIGHT();
        in->NeedRIGHT();


@@ -94,7 +94,7 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR


        in->NeedSYMBOLorNUMBER();
        in->NeedSYMBOLorNUMBER();


        row->SetFullURI( in->CurText() );
        row.SetFullURI( in->FromUTF8() );


        in->NeedRIGHT();
        in->NeedRIGHT();


@@ -106,23 +106,21 @@ void FP_LIB_TABLE::Parse( FP_LIB_TABLE_LEXER* in ) throw( IO_ERROR, PARSE_ERROR


        in->NeedSYMBOLorNUMBER();
        in->NeedSYMBOLorNUMBER();


        row->SetOptions( in->CurText() );
        row.SetOptions( in->FromUTF8() );


        in->NeedRIGHT();
        in->NeedRIGHT();
        in->NeedRIGHT();            // terminate the (lib..)
        in->NeedRIGHT();            // terminate the (lib..)


        // all logicalNames within this table fragment must be unique, so we do not
        // all nickNames within this table fragment must be unique, so we do not
        // use doReplace in InsertRow().  However a fallBack table can have a
        // use doReplace in InsertRow().  However a fallBack table can have a
        // conflicting logicalName and ours will supercede that one since in
        // conflicting nickName and ours will supercede that one since in
        // FindLib() we search this table before any fall back.
        // FindLib() we search this table before any fall back.
        if( !InsertRow( row ) )
        if( !InsertRow( row ) )
        {
        {
            std::string msg;
            wxString msg = wxString::Format(

                                _( "'%s' is a duplicate footprint library nickName" ),
            msg += '\'';
                                GetChars( row.nickName )
            msg += row->logicalName;
                                );
            msg += '\'';
            msg += " is a duplicate logical footprint library name";
            THROW_IO_ERROR( msg );
            THROW_IO_ERROR( msg );
        }
        }
    }
    }
@@ -135,7 +133,7 @@ void FP_LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const
    out->Print( nestLevel, "(fp_lib_table\n" );
    out->Print( nestLevel, "(fp_lib_table\n" );


    for( ROWS_CITER it = rows.begin();  it != rows.end();  ++it )
    for( ROWS_CITER it = rows.begin();  it != rows.end();  ++it )
        it->second->Format( out, nestLevel+1 );
        it->Format( out, nestLevel+1 );


    out->Print( nestLevel, ")\n" );
    out->Print( nestLevel, ")\n" );
}
}
@@ -144,48 +142,50 @@ void FP_LIB_TABLE::Format( OUTPUTFORMATTER* out, int nestLevel ) const
void FP_LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
void FP_LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
    throw( IO_ERROR )
    throw( IO_ERROR )
{
{
    out->Print( nestLevel, "(lib (logical %s)(type %s)(full_uri %s)(options %s))\n",
    out->Print( nestLevel, "(lib (name %s)(type %s)(full_uri %s)(options %s))\n",
                out->Quotes( logicalName ).c_str(),
                out->Quotew( nickName ).c_str(),
                out->Quotes( type ).c_str(),
                out->Quotew( type ).c_str(),
                out->Quotes( uri ).c_str(),
                out->Quotew( uri ).c_str(),
                out->Quotes( options ).c_str() );
                out->Quotew( options ).c_str()
                );
}
}




std::vector<std::string> FP_LIB_TABLE::GetLogicalLibs()
std::vector<wxString> FP_LIB_TABLE::GetLogicalLibs()
{
{
    // Only return unique logical library names.  Use std::set::insert() to
    // Only return unique logical library names.  Use std::set::insert() to
    // quietly reject any duplicates, which can happen when encountering a duplicate
    // quietly reject any duplicates, which can happen when encountering a duplicate
    // logical lib name from one of the fall back table(s).
    // nickname from one of the fall back table(s).


    std::set<std::string>      unique;
    std::set<wxString>          unique;
    std::vector<std::string>   ret;
    std::vector<wxString>       ret;
    const FP_LIB_TABLE*         cur = this;
    const FP_LIB_TABLE*         cur = this;


    do
    do
    {
    {
        for( ROWS_CITER it = cur->rows.begin();  it!=cur->rows.end();  ++it )
        for( ROWS_CITER it = cur->rows.begin();  it!=cur->rows.end();  ++it )
        {
        {
            unique.insert( it->second->logicalName );
            unique.insert( it->nickName );
        }
        }


    } while( ( cur = cur->fallBack ) != 0 );
    } while( ( cur = cur->fallBack ) != 0 );


    // return a sorted, unique set of logical lib name std::vector<std::string> to caller
    // return a sorted, unique set of nicknames in a std::vector<wxString> to caller
    for( std::set<std::string>::const_iterator it = unique.begin();  it!=unique.end();  ++it )
    for( std::set<wxString>::const_iterator it = unique.begin();  it!=unique.end();  ++it )
        ret.push_back( *it );
        ret.push_back( *it );


    return ret;
    return ret;
}
}




#if 0       // will need PLUGIN_RELEASER.
MODULE* FP_LIB_TABLE::LookupFootprint( const FP_LIB_ID& aFootprintId )
MODULE* FP_LIB_TABLE::LookupFootprint( const FP_LIB_ID& aFootprintId )
    throw( IO_ERROR )
    throw( IO_ERROR )
{
{
    PLUGIN* plugin = lookupLib( aFootprintId );
    PLUGIN* plugin = lookupLib( aFootprintId );


    return plugin->FootprintLoad( wxString( aFootprintId.GetBaseName().c_str() ),
    return plugin->FootprintLoad( FROM_UTF8( aFootprintId.GetBaseName().c_str() ),
                                  wxString( aFootprintId.GetLogicalLib().c_str() ) );
                                  FROM_UTF8( aFootprintId.GetLogicalLib().c_str() ) );
}
}




@@ -254,24 +254,22 @@ void FP_LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
        THROW_IO_ERROR( msg );
        THROW_IO_ERROR( msg );
    }
    }
}
}
#endif




FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const std::string& aLogicalName ) const
FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const wxString& aNickName ) const
{
{
    // this function must be *super* fast, so therefore should not instantiate
    // this function must be *super* fast, so therefore should not instantiate
    // anything which would require using the heap.  This function is the reason
    // anything which would require using the heap.
    // ptr_map<> was used instead of ptr_set<>, which would have required
    // instantiating a ROW just to find a ROW.
    const FP_LIB_TABLE* cur = this;
    const FP_LIB_TABLE* cur = this;


    do
    do
    {
    {
        ROWS_CITER  it = cur->rows.find( aLogicalName );
        INDEX_CITER  it = cur->nickIndex.find( aNickName );


        if( it != cur->rows.end() )
        if( it != cur->nickIndex.end() )
        {
        {
            // reference: http://myitcorner.com/blog/?p=361
            return (FP_LIB_TABLE::ROW*) &cur->rows[it->second];  // found
            return (FP_LIB_TABLE::ROW*) it->second;  // found
        }
        }


        // not found, search fall back table(s), if any
        // not found, search fall back table(s), if any
@@ -281,29 +279,26 @@ FP_LIB_TABLE::ROW* FP_LIB_TABLE::FindRow( const std::string& aLogicalName ) cons
}
}




bool FP_LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
bool FP_LIB_TABLE::InsertRow( const ROW& aRow, bool doReplace )
{
{
    // this does not need to be super fast.
    // this does not need to be super fast.


    ROWS_CITER it = rows.find( aRow->logicalName );
    INDEX_CITER it = nickIndex.find( aRow.nickName );


    if( it == rows.end() )
    if( it == nickIndex.end() )
    {
    {
        // be careful here, key is needed because aRow can be
        rows.push_back( aRow );
        // release()ed before logicalName is captured.
        nickIndex.insert( INDEX_VALUE( aRow.nickName, rows.size() - 1 ) );
        const std::string& key = aRow->logicalName;
        rows.insert( key, aRow );
        return true;
        return true;
    }
    }


    if( doReplace )
    if( doReplace )
    {
    {
        rows.erase( aRow->logicalName );
        int ndx = it->second;


        // be careful here, key is needed because aRow can be
        rows[ndx] = aRow;
        // release()ed before logicalName is captured.
        nickIndex.erase( aRow.nickName );
        const std::string&   key = aRow->logicalName;
        nickIndex.insert( INDEX_VALUE( aRow.nickName, ndx ) );
        rows.insert( key, aRow );
        return true;
        return true;
    }
    }


+113 −42
Original line number Original line Diff line number Diff line
/*
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 *
 * Copyright (C) 2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2010-12 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2012 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
 * Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
 *
 *
@@ -26,10 +26,13 @@
#ifndef _FP_LIB_TABLE_H_
#ifndef _FP_LIB_TABLE_H_
#define _FP_LIB_TABLE_H_
#define _FP_LIB_TABLE_H_


#include <macros.h>


#include <fp_lib_id.h>
#include <vector>
#include <map>


#include <boost/ptr_container/ptr_map.hpp>
#include <wx/grid.h>
#include <fp_lib_id.h>




class OUTPUTFORMATTER;
class OUTPUTFORMATTER;
@@ -78,7 +81,7 @@ class MODULE;
 *
 *
 * @author Wayne Stambaugh
 * @author Wayne Stambaugh
 */
 */
class FP_LIB_TABLE
class FP_LIB_TABLE : public wxGridTableBase
{
{
public:
public:


@@ -94,19 +97,19 @@ public:
    public:
    public:


        /**
        /**
         * Function GetLogicalName
         * Function GetNickName
         * returns the logical name of this library table row.
         * returns the short name of this library table row.
         */
         */
        const std::string& GetLogicalName() const
        const wxString& GetNickName() const
        {
        {
            return logicalName;
            return nickName;
        }
        }


        /**
        /**
         * Function GetType
         * Function GetType
         * returns the type of LIB represented by this record.
         * returns the type of LIB represented by this record.
         */
         */
        const std::string& GetType() const
        const wxString& GetType() const
        {
        {
            return type;
            return type;
        }
        }
@@ -115,7 +118,7 @@ public:
         * Function GetFullURI
         * Function GetFullURI
         * returns the full location specifying URI for the LIB.
         * returns the full location specifying URI for the LIB.
         */
         */
        const std::string& GetFullURI() const
        const wxString& GetFullURI() const
        {
        {
            return uri;
            return uri;
        }
        }
@@ -125,14 +128,14 @@ public:
         * returns the options string, which may hold a password or anything else needed to
         * returns the options string, which may hold a password or anything else needed to
         * instantiate the underlying LIB_SOURCE.
         * instantiate the underlying LIB_SOURCE.
         */
         */
        const std::string& GetOptions() const
        const wxString& GetOptions() const
        {
        {
            return options;
            return options;
        }
        }


        ~ROW()
        ~ROW()
        {
        {
            delete lib;
            // delete lib;
        }
        }


        /**
        /**
@@ -149,24 +152,24 @@ public:
    protected:
    protected:


        ROW( FP_LIB_TABLE* aOwner ) :
        ROW( FP_LIB_TABLE* aOwner ) :
            owner( aOwner ),
            owner( aOwner )
            lib( 0 )
            // lib( 0 )
        {}
        {}


        /**
        /**
         * Function SetLogicalName
         * Function SetNickName
         * changes the logical name of this library, useful for an editor.
         * changes the logical name of this library, useful for an editor.
         */
         */
        void SetLogicalName( const std::string& aLogicalName )
        void SetNickName( const wxString& aNickName )
        {
        {
            logicalName = aLogicalName;
            nickName = aNickName;
        }
        }


        /**
        /**
         * Function SetType
         * Function SetType
         * changes the type represented by this record.
         * changes the type represented by this record.
         */
         */
        void SetType( const std::string& aType )
        void SetType( const wxString& aType )
        {
        {
            type = aType;
            type = aType;
        }
        }
@@ -175,7 +178,7 @@ public:
         * Function SetFullURI
         * Function SetFullURI
         * changes the full URI for the library, useful from a library table editor.
         * changes the full URI for the library, useful from a library table editor.
         */
         */
        void SetFullURI( const std::string& aFullURI )
        void SetFullURI( const wxString& aFullURI )
        {
        {
            uri = aFullURI;
            uri = aFullURI;
        }
        }
@@ -185,21 +188,24 @@ public:
         * changes the options string for this record, and is useful from
         * changes the options string for this record, and is useful from
         * the library table editor.
         * the library table editor.
         */
         */
        void SetOptions( const std::string& aOptions )
        void SetOptions( const wxString& aOptions )
        {
        {
            options = aOptions;
            options = aOptions;
        }
        }


    private:
    private:
        FP_LIB_TABLE*   owner;
        FP_LIB_TABLE*   owner;
        std::string    logicalName;
        wxString        nickName;
        std::string    type;
        wxString        type;
        std::string    uri;
        wxString        uri;
        std::string    options;
        wxString        options;


        /*
        PLUGIN*         lib;        ///< ownership of the loaded LIB is here
        PLUGIN*         lib;        ///< ownership of the loaded LIB is here
        */
    };
    };



    /**
    /**
     * Constructor FP_LIB_TABLE
     * Constructor FP_LIB_TABLE
     * builds a library table by pre-pending this table fragment in front of
     * builds a library table by pre-pending this table fragment in front of
@@ -246,6 +252,7 @@ public:
     */
     */
    void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR );
    void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR );


#if 0
    /**
    /**
     * Function LookupPart
     * Function LookupPart
     * finds and loads a MODULE, and parses it.  As long as the part is
     * finds and loads a MODULE, and parses it.  As long as the part is
@@ -262,25 +269,76 @@ public:
     * @throw IO_ERROR if any problem occurs or if the footprint cannot be found.
     * @throw IO_ERROR if any problem occurs or if the footprint cannot be found.
     */
     */
    MODULE* LookupFootprint( const FP_LIB_ID& aFootprintId ) throw( IO_ERROR );
    MODULE* LookupFootprint( const FP_LIB_ID& aFootprintId ) throw( IO_ERROR );
#endif



    /**
    /**
     * Function GetLogicalLibs
     * Function GetLogicalLibs
     * returns the logical library names, all of them that are pertinent to
     * returns the logical library names, all of them that are pertinent to
     * a lookup done on this FP_LIB_TABLE.
     * a lookup done on this FP_LIB_TABLE.
     */
     */
    std::vector<std::string> GetLogicalLibs();
    std::vector<wxString> GetLogicalLibs();


    //-----<wxGridTableBase overloads>-------------------------------------------

    int         GetNumberRows () { return rows.size(); }
    int         GetNumberCols () { return 4; }

    wxString    GetValue( int aRow, int aCol )
    {
        if( unsigned( aRow ) < rows.size() )
        {
            const ROW&  r  = rows[aRow];

            switch( aCol )
            {
            case 0:     return r.GetNickName();
            case 1:     return r.GetType();
            case 2:     return r.GetFullURI();
            case 3:     return r.GetOptions();
            default:
                ;       // fall thru to wxEmptyString
            }
        }

        return wxEmptyString;
    }

    void    SetValue( int aRow, int aCol, const wxString &aValue )
    {
        if( aCol == 0 )
        {
            // when the nickname is changed, there's careful work to do, including
            // ensuring uniqueness of the nickname.
        }
        else if( unsigned( aRow ) < rows.size() )
        {
            ROW&  r  = rows[aRow];

            switch( aCol )
            {
            case 1:     return r.SetType( aValue  );
            case 2:     return r.SetFullURI( aValue );
            case 3:     return r.SetOptions( aValue );
            }
        }
    }

    //-----</wxGridTableBase overloads>------------------------------------------



    //----<read accessors>----------------------------------------------------
    //----<read accessors>----------------------------------------------------
    // the returning of a const std::string* tells if not found, but might be too
    // the returning of a const wxString* tells if not found, but might be too
    // promiscuous?
    // promiscuous?


    /**
    /**
     * Function GetURI
     * Function GetURI
     * returns the full library path from a logical library name.
     * returns the full library path from a logical library name.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @return const std::string* - or NULL if not found.
     * @return const wxString* - or NULL if not found.
     */
     */
    const std::string* GetURI( const std::string& aLogicalLibraryName ) const
    const wxString* GetURI( const wxString& aLogicalLibraryName ) const
    {
    {
        const ROW* row = FindRow( aLogicalLibraryName );
        const ROW* row = FindRow( aLogicalLibraryName );
        return row ? &row->uri : 0;
        return row ? &row->uri : 0;
@@ -290,9 +348,9 @@ public:
     * Function GetType
     * Function GetType
     * returns the type of a logical library.
     * returns the type of a logical library.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @return const std::string* - or NULL if not found.
     * @return const wxString* - or NULL if not found.
     */
     */
    const std::string* GetType( const std::string& aLogicalLibraryName ) const
    const wxString* GetType( const wxString& aLogicalLibraryName ) const
    {
    {
        const ROW* row = FindRow( aLogicalLibraryName );
        const ROW* row = FindRow( aLogicalLibraryName );
        return row ? &row->type : 0;
        return row ? &row->type : 0;
@@ -302,9 +360,9 @@ public:
     * Function GetLibOptions
     * Function GetLibOptions
     * returns the options string for \a aLogicalLibraryName.
     * returns the options string for \a aLogicalLibraryName.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @param aLogicalLibraryName is the short name for the library of interest.
     * @return const std::string* - or NULL if not found.
     * @return const wxString* - or NULL if not found.
     */
     */
    const std::string* GetLibOptions( const std::string& aLogicalLibraryName ) const
    const wxString* GetLibOptions( const wxString& aLogicalLibraryName ) const
    {
    {
        const ROW* row = FindRow( aLogicalLibraryName );
        const ROW* row = FindRow( aLogicalLibraryName );
        return row ? &row->options : 0;
        return row ? &row->options : 0;
@@ -324,23 +382,24 @@ protected: // only a table editor can use these
     * Function InsertRow
     * Function InsertRow
     * adds aRow if it does not already exist or if doReplace is true.  If doReplace
     * adds aRow if it does not already exist or if doReplace is true.  If doReplace
     * is not true and the key for aRow already exists, the function fails and returns false.
     * is not true and the key for aRow already exists, the function fails and returns false.
     * The key for the table is the logicalName, and all in this table must be unique.
     * The key for the table is the nickName, and all in this table must be unique.
     * @param aRow is the new row to insert, or to forcibly add if doReplace is true.
     * @param aRow is the new row to insert, or to forcibly add if doReplace is true.
     * @param doReplace if true, means insert regardless of whether aRow's key already
     * @param doReplace if true, means insert regardless of whether aRow's key already
     *  exists.  If false, then fail if the key already exists.
     *  exists.  If false, then fail if the key already exists.
     * @return bool - true if the operation succeeded.
     * @return bool - true if the operation succeeded.
     */
     */
    bool InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace = false );
    bool InsertRow( const ROW& aRow, bool doReplace = false );


    /**
    /**
     * Function FindRow
     * Function FindRow
     * returns a #ROW* if aLogicalName is found in this table or in any chained
     * returns a #ROW* if aNickName is found in this table or in any chained
     * fallBack table fragment, else NULL.
     * fallBack table fragment, else NULL.
     */
     */
    ROW* FindRow( const std::string& aLogicalName ) const;
    ROW* FindRow( const wxString& aNickName ) const;


private:
private:


#if 0   // lets see what we need.
    /**
    /**
     * Function lookupLib
     * Function lookupLib
     * finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
     * finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
@@ -367,12 +426,24 @@ private:
     * already loaded.
     * already loaded.
     */
     */
    void loadLib( ROW* aRow ) throw( IO_ERROR );
    void loadLib( ROW* aRow ) throw( IO_ERROR );
#endif


    typedef boost::ptr_map<std::string, ROW>    ROWS;
    typedef std::vector<ROW>            ROWS;
    typedef ROWS::iterator              ROWS_ITER;
    typedef ROWS::iterator              ROWS_ITER;
    typedef ROWS::const_iterator        ROWS_CITER;
    typedef ROWS::const_iterator        ROWS_CITER;


    ROWS           rows;
    ROWS           rows;

    /// this is a non-owning index into the ROWS table
    typedef std::map<wxString,int>      INDEX;              // "int" is std::vector array index
    typedef INDEX::iterator             INDEX_ITER;
    typedef INDEX::const_iterator       INDEX_CITER;
    typedef INDEX::value_type           INDEX_VALUE;


    /// the particular key is the nickName within each row.
    INDEX           nickIndex;

    FP_LIB_TABLE*  fallBack;
    FP_LIB_TABLE*  fallBack;
};
};