Commit 69801630 authored by Dick Hollenbeck's avatar Dick Hollenbeck

changes

parent 911bde45
...@@ -7,8 +7,8 @@ email address. ...@@ -7,8 +7,8 @@ email address.
2010-Dec-28 UPDATE Dick Hollenbeck <dick@softplc.com> 2010-Dec-28 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
++new: ++new:
Completed a good portion of /new class LIB_TABLE. Completed most of /new class LIB_TABLE.
Starting LPID. Completed all of /new class LPID.
++common: ++common:
Tricked xnode.h into not issuing deprecation warnings. Tricked xnode.h into not issuing deprecation warnings.
++richio: ++richio:
......
...@@ -25,8 +25,10 @@ ...@@ -25,8 +25,10 @@
#ifndef KICAD_EXCEPTIONS_H_ #ifndef KICAD_EXCEPTIONS_H_
#define KICAD_EXCEPTIONS_H_ #define KICAD_EXCEPTIONS_H_
/* Just exceptions /**
*/ * @ingroup exception_types
* @{
*/
#include <wx/string.h> #include <wx/string.h>
...@@ -84,4 +86,7 @@ struct PARSE_ERROR : public IO_ERROR ...@@ -84,4 +86,7 @@ struct PARSE_ERROR : public IO_ERROR
} }
}; };
/** @} exception_types */
#endif // KICAD_EXCEPTIONS_H_ #endif // KICAD_EXCEPTIONS_H_
...@@ -60,28 +60,37 @@ endif() ...@@ -60,28 +60,37 @@ endif()
include_directories( ${CMAKE_CURRENT_SOURCE_DIR} ) include_directories( ${CMAKE_CURRENT_SOURCE_DIR} )
#=====<on standby until unit testing infrastructure>============================
if( false )
add_executable( test_dir_lib_source add_executable( test_dir_lib_source
sch_dir_lib_source.cpp sch_dir_lib_source.cpp
) )
target_link_libraries( test_dir_lib_source ${wxWidgets_LIBRARIES} ) target_link_libraries( test_dir_lib_source ${wxWidgets_LIBRARIES} )
add_executable( test_sch_part sch_part.cpp )
target_link_libraries( test_sch_part ${wxWidgets_LIBRARIES} )
add_executable( test_lpid
sch_lpid.cpp
)
target_link_libraries( test_lpid ${wxWidgets_LIBRARIES} )
endif( false )
#=====</on standby until unit testing infrastructure>===========================
add_executable( test_sch_lib_table add_executable( test_sch_lib_table
sch_lib_table.cpp sch_lib_table.cpp
sch_lib_table_keywords.cpp sch_lib_table_keywords.cpp
sch_lib.cpp sch_lib.cpp
sch_lpid.cpp
sch_dir_lib_source.cpp
${PROJECT_SOURCE_DIR}/common/richio.cpp ${PROJECT_SOURCE_DIR}/common/richio.cpp
${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp ${PROJECT_SOURCE_DIR}/common/dsnlexer.cpp
) )
target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} ) target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} )
add_executable( test_sch_part sch_part.cpp )
target_link_libraries( test_sch_part ${wxWidgets_LIBRARIES} )
add_executable( test_lpid
sch_lpid.cpp
)
target_link_libraries( test_lpid ${wxWidgets_LIBRARIES} )
make_lexer( make_lexer(
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table.keywords ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table.keywords
......
...@@ -329,6 +329,10 @@ is used on the hood ornament. When aResults pointer is passed as an argument, I ...@@ -329,6 +329,10 @@ is used on the hood ornament. When aResults pointer is passed as an argument, I
won't refer to this as 'returning' a value, but rather 'fetching' a result to won't refer to this as 'returning' a value, but rather 'fetching' a result to
distinguish between the two strategies. distinguish between the two strategies.
<p> Functions named as lookupSomething() or LookupSomething() are to be understood
as "find and load if needed". This is different than a simple find operation only, in
that an implied load operation is also done, but only if needed.
@section architecture Architecture @section architecture Architecture
...@@ -337,47 +341,59 @@ LIB_SOURCE. A library source is the backing to a library. The class name for a ...@@ -337,47 +341,59 @@ LIB_SOURCE. A library source is the backing to a library. The class name for a
library in the new design is LIB. library in the new design is LIB.
<p> <p>
Show architecture here. <IMG SRC="../drawing.png" ALT="You should see design architecture here">
<a href="../drawing.png" > Click here to see an architectural drawing.</a>
*/ */
/** /**
* \defgroup string_types STRING Types * @defgroup string_types STRING Types
* Provide some string types for use within the API. * Provide some string types for use within the API.
* @{
*/ */
typedef std::string STRING;
typedef std::dequeue<STRING> STRINGS;
//typedef std::vector<wxString> WSTRINGS;
/**
* @defgroup exception_types Exception Types
* Provide some exception types for use within the API.
*/
const STRING StrEmpty = "";
/** @} string_types STRING Types */
/** /**
* \defgroup exception_types Exception Types * Class HTTP_LIB_SOURCE
* Provide some exception types for use within the API. * implements a LIB_SOURCE to access a remote document root repository using http protocol.
* @{
*/ */
class HTTP_LIB_SOURCE : public LIB_SOURCE
{
friend class LIB_TABLE; ///< constructor the LIB uses these functions.
protected:
/** @} exception_types Exception Types */ /**
* Constructor ( const STRING& aSvnURL )
* sets up a LIB_SOURCE using aSvnURI which points to a subversion
* repository.
* @see LIBS::GetLibrary().
*
* @param aHttpURL is a full URL of a document root repo directory. Example might
* be "http://kicad.org/libs"
*
* @param aOptions is the options string from the library table. It can be any
* string that the LIB_SOURCE can parse and understand, perhaps using comma separation
* between options. Options and their syntax is LIB_SOURCE implementation specific.
*/
HTTP_LIB_SOURCE( const STRING& aHttpURL, const STRING& aOptions ) throws( IO_ERROR );
};
/** /**
* Class SVN_LIB_SOURCE * Class SVN_LIB_SOURCE
* implements a LIB_SOURCE in a subversion repository. * implements a LIB_SOURCE to access a [remote or local] subversion repository
* using subversion client protocol.
*/ */
class SVN_LIB_SOURCE : public LIB_SOURCE class SVN_LIB_SOURCE : public LIB_SOURCE
{ {
friend class LIBS; ///< constructor the LIB uses these functions. friend class LIB_TABLE; ///< constructor the LIB uses these functions.
protected: protected:
...@@ -389,8 +405,12 @@ protected: ...@@ -389,8 +405,12 @@ protected:
* *
* @param aSvnURL is a full URL of a subversion repo directory. Example might * @param aSvnURL is a full URL of a subversion repo directory. Example might
* be "svn://kicad.org/repos/library/trunk" * be "svn://kicad.org/repos/library/trunk"
*
* @param aOptions is the options string from the library table. It can be any
* string that the LIB_SOURCE can parse and understand, perhaps using comma separation
* between options. Options and their syntax is LIB_SOURCE implementation specific.
*/ */
SVN_LIB_SOURCE( const STRING& aSvnURL ) throws( IO_ERROR ); SVN_LIB_SOURCE( const STRING& aSvnURL, const STRING& aOptions ) throws( IO_ERROR );
}; };
...@@ -401,7 +421,7 @@ protected: ...@@ -401,7 +421,7 @@ protected:
*/ */
class SCHEMATIC_LIB_SOURCE : public LIB_SOURCE class SCHEMATIC_LIB_SOURCE : public LIB_SOURCE
{ {
friend class LIBS; ///< constructor the LIB uses these functions. friend class LIB_TABLE; ///< constructor the LIB uses these functions.
protected: protected:
...@@ -414,8 +434,12 @@ protected: ...@@ -414,8 +434,12 @@ protected:
* *
* @param aSchematicFile is a full path and filename. Example: * @param aSchematicFile is a full path and filename. Example:
* "/home/user/kicadproject/design.sch" * "/home/user/kicadproject/design.sch"
*
* @param aOptions is the options string from the library table. It can be any
* string that the LIB_SOURCE can parse and understand, perhaps using comma separation
* between options. Options and their syntax is LIB_SOURCE implementation specific.
*/ */
SCHEMATIC_LIB_SOURCE( const STRING& aSchematicFile ) throws( IO_ERROR ); SCHEMATIC_LIB_SOURCE( const STRING& aSchematicFile, const STRING& aOptions ) throws( IO_ERROR );
}; };
...@@ -445,4 +469,6 @@ public: ...@@ -445,4 +469,6 @@ public:
/// @todo remove endsWithRev() in favor of EndsWithRev(), find home for it. /// @todo remove endsWithRev() in favor of EndsWithRev(), find home for it.
/// @todo add simple unit test infrastructure.
// EOF // EOF
...@@ -590,7 +590,7 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR ) ...@@ -590,7 +590,7 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR )
} }
#if 1 && defined(DEBUG) #if 0 && defined(DEBUG)
void DIR_LIB_SOURCE::Test( int argc, char** argv ) void DIR_LIB_SOURCE::Test( int argc, char** argv )
{ {
......
...@@ -69,7 +69,7 @@ namespace SCH { ...@@ -69,7 +69,7 @@ namespace SCH {
*/ */
class DIR_LIB_SOURCE : public LIB_SOURCE class DIR_LIB_SOURCE : public LIB_SOURCE
{ {
friend class LIBS; ///< LIBS::GetLib() can construct one. friend class LIB_TABLE; ///< constructor is protected, LIB_TABLE can construct
bool useVersioning; ///< use files with extension ".revNNN..", else not bool useVersioning; ///< use files with extension ".revNNN..", else not
...@@ -146,7 +146,7 @@ protected: ...@@ -146,7 +146,7 @@ protected:
* *
* @param aOptions is the options string from the library table, currently * @param aOptions is the options string from the library table, currently
* the only supported option, that this LIB_SOURCE knows about is * the only supported option, that this LIB_SOURCE knows about is
* "userVersioning". If present means support versioning in the directory * "useVersioning". If present means support versioning in the directory
* tree, otherwise only a single version of each part is recognized, namely the * tree, otherwise only a single version of each part is recognized, namely the
* one without the ".revN[N..]" trailer. * one without the ".revN[N..]" trailer.
*/ */
......
...@@ -43,3 +43,24 @@ LIB::~LIB() ...@@ -43,3 +43,24 @@ LIB::~LIB()
delete sink; delete sink;
} }
PART* LIB::LookupPart( const LPID& aLPID ) throw( IO_ERROR )
{
return 0;
}
#if 0 && defined(DEBUG)
void LIB::Test( int argc, char** argv ) throw( IO_ERROR );
{
}
int main( int argc, char** argv )
{
LIB::Test( argc, argv );
return 0;
}
#endif
...@@ -25,27 +25,13 @@ ...@@ -25,27 +25,13 @@
#ifndef SCH_LIB_H_ #ifndef SCH_LIB_H_
#define SCH_LIB_H_ #define SCH_LIB_H_
#include <string> #include <utf8.h>
#include <deque>
#include <kicad_exceptions.h> #include <kicad_exceptions.h>
#ifdef DEBUG
#define D(x) x
#else
#define D(x) // nothing
#endif
typedef std::string STRING;
typedef std::deque<STRING> STRINGS;
typedef STRINGS STRINGS;
extern const STRING StrEmpty;
namespace SCH { namespace SCH {
class LPID;
class PART; class PART;
...@@ -83,7 +69,7 @@ protected: ///< derived classes must implement ...@@ -83,7 +69,7 @@ protected: ///< derived classes must implement
* Function ReadPart * Function ReadPart
* fetches @a aPartName's s-expression into @a aResult after clear()ing aResult. * fetches @a aPartName's s-expression into @a aResult after clear()ing aResult.
*/ */
virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev=StrEmpty ) virtual void ReadPart( STRING* aResult, const STRING& aPartName, const STRING& aRev = "" )
throw( IO_ERROR ) = 0; throw( IO_ERROR ) = 0;
/** /**
...@@ -113,7 +99,7 @@ protected: ///< derived classes must implement ...@@ -113,7 +99,7 @@ protected: ///< derived classes must implement
* *
* @param aResults is a place to put the fetched result, one category per STRING. * @param aResults is a place to put the fetched result, one category per STRING.
*/ */
virtual void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory=StrEmpty ) virtual void GetCategoricalPartNames( STRINGS* aResults, const STRING& aCategory="" )
throw( IO_ERROR ) = 0; throw( IO_ERROR ) = 0;
/** /**
...@@ -186,7 +172,7 @@ protected: ///< derived classes must implement ...@@ -186,7 +172,7 @@ protected: ///< derived classes must implement
* part is done, then LIB::ReloadPart() must be called on this same part * part is done, then LIB::ReloadPart() must be called on this same part
* and all parts that inherit it must be reparsed. * and all parts that inherit it must be reparsed.
* @return STRING - if the LIB_SINK support revision numbering, then return a * @return STRING - if the LIB_SINK support revision numbering, then return a
* evision name that was next in the sequence, e.g. "rev22", else StrEmpty. * revision name that was next in the sequence, e.g. "rev22", else "".
*/ */
virtual STRING WritePart( const STRING& aPartName, const STRING& aSExpression ) virtual STRING WritePart( const STRING& aPartName, const STRING& aSExpression )
throw( IO_ERROR ) = 0; throw( IO_ERROR ) = 0;
...@@ -207,15 +193,15 @@ protected: ...@@ -207,15 +193,15 @@ protected:
*/ */
class LIB class LIB
{ {
friend class LIB_TABLE; ///< the LIB factory is LIB_TABLE friend class LIB_TABLE; ///< protected constructor, LIB_TABLE may construct
protected: // constructor is not public, called from LIBS only. protected: // constructor is not public, called from LIB_TABLE only.
/** /**
* Constructor LIB * Constructor LIB
* is not public and is only called from LIBS::GetLib() * is not public and is only called from class LIB_TABLE
* *
* @param aLogicalLibrary is the name of a well know logical library, and is * @param aLogicalLibrary is the name of a well known logical library, and is
* known because it already exists in the library table. * known because it already exists in the library table.
* *
* @param aSource is an open LIB_SOURCE whose ownership is * @param aSource is an open LIB_SOURCE whose ownership is
...@@ -246,13 +232,20 @@ public: ...@@ -246,13 +232,20 @@ public:
//-----<use delegates: source and sink>--------------------------------- //-----<use delegates: source and sink>---------------------------------
/** /**
* Function GetPart * Function LookupPart
* returns a PART given @a aPartName, such as "passives/R". * returns a PART given @a aPartName, such as "passives/R". No ownership
* @param aPartName is local to this LIB and does not have the logical * is given to the PART, it stays in the cache that is this LIB.
* library name prefixed. *
* @param aLPID is the part to lookup. The logicalLibName can be empty in it
* since yes, we know which LIB is in play.
*
* @return PART* - The desired PART and will never be NULL. No ownership is
* given to caller. PARTs always reside in the cache that is a LIB.
*
* @throw IO_ERROR if the part cannot be found or loaded.
*/ */
const PART* GetPart( const STRING& aPartName ) throw( IO_ERROR ); PART* LookupPart( const LPID& aLPID )
throw( IO_ERROR );
/** /**
* Function ReloadPart * Function ReloadPart
...@@ -273,8 +266,7 @@ public: ...@@ -273,8 +266,7 @@ public:
* creates cache entries for the very same parts if they do not already exist * creates cache entries for the very same parts if they do not already exist
* in this LIB (i.e. cache). * in this LIB (i.e. cache).
*/ */
STRINGS GetCategoricalPartNames( const STRING& aCategory=StrEmpty ) throw( IO_ERROR ); STRINGS GetCategoricalPartNames( const STRING& aCategory = "" ) throw( IO_ERROR );
//-----<.use delegates: source and sink>-------------------------------- //-----<.use delegates: source and sink>--------------------------------
...@@ -317,6 +309,9 @@ public: ...@@ -317,6 +309,9 @@ public:
return STRINGS(); return STRINGS();
} }
#if defined(DEBUG)
static void Test( int argc, char** argv ) throw( IO_ERROR );
#endif
protected: protected:
......
...@@ -22,11 +22,13 @@ ...@@ -22,11 +22,13 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <set>
#include <assert.h>
#include <sch_lib_table.h>
#include <sch_lib_table_lexer.h> #include <sch_lib_table_lexer.h>
#include <sch_lpid.h> #include <sch_lpid.h>
#include <set> #include <sch_lib_table.h>
#include <sch_dir_lib_source.h>
//using namespace std; // screws up Doxygen //using namespace std; // screws up Doxygen
using namespace SCH; using namespace SCH;
...@@ -185,14 +187,99 @@ STRINGS LIB_TABLE::GetLogicalLibs() ...@@ -185,14 +187,99 @@ STRINGS LIB_TABLE::GetLogicalLibs()
} }
PART* LIB_TABLE::GetPart( const LPID& aLogicalPartID ) throw( IO_ERROR ) PART* LIB_TABLE::LookupPart( const LPID& aLogicalPartID, LIB* aLocalLib )
throw( IO_ERROR )
{ {
// need LIPD done. LIB* lib = lookupLib( aLogicalPartID, aLocalLib );
return 0;
return lib->LookupPart( aLogicalPartID );
}
LIB* LIB_TABLE::lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib )
throw( IO_ERROR )
{
if( aLocalLib )
{
return aLocalLib;
}
else
{
const STRING& logName = aLogicalPartID.GetLogicalLib();
if( logName.size() )
{
ROW* row = FindRow( logName );
if( !row )
{
STRING msg = "Unable to find logical lib ";
msg += logName;
throw IO_ERROR( msg );
}
if( !row->lib )
{
loadLib( row );
}
assert( row->lib ); // loadLib() throws if cannot load
return row->lib;
}
else
{
STRING msg = "No logicalLibName in LPID and no localLib";
throw IO_ERROR( msg );
}
}
// return NULL; never get here
}
void LIB_TABLE::loadLib( ROW* aRow ) throw( IO_ERROR )
{
assert( !aRow->lib ); // caller should know better.
const STRING& libType = aRow->GetType();
if( !libType.compare( "dir" ) )
{
// autor_ptr wrap source while we create sink, in case sink throws.
std::auto_ptr<LIB_SOURCE> source(
new DIR_LIB_SOURCE(
aRow->GetFullURI(),
aRow->GetOptions() ) );
/* @todo load LIB_SINK
std::auto_ptr<LIB_SINK> sink(
new DIR_LIB_SINK(
aRow->GetFullURI(),
aRow->GetOptions() ) );
*/
// LIB::LIB( const STRING& aLogicalLibrary, LIB_SOURCE* aSource, LIB_SINK* aSink = NULL );
aRow->lib = new LIB( aRow->GetLogicalName(), source.release(), NULL );
}
else if( !libType.compare( "schematic" ) )
{
// @todo code and load SCHEMATIC_LIB_SOURCE
}
else if( !libType.compare( "subversion" ) )
{
// @todo code and load SVN_LIB_SOURCE
}
else if( !libType.compare( "http" ) )
{
// @todo code and load HTTP_LIB_SOURCE
}
} }
const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) 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. This function is the reason
...@@ -207,7 +294,7 @@ const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) const ...@@ -207,7 +294,7 @@ const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) const
if( it != cur->rows.end() ) if( it != cur->rows.end() )
{ {
// reference: http://myitcorner.com/blog/?p=361 // reference: http://myitcorner.com/blog/?p=361
return (const LIB_TABLE::ROW*) it->second; // found return (LIB_TABLE::ROW*) it->second; // found
} }
// not found, search fall back table(s), if any // not found, search fall back table(s), if any
...@@ -247,7 +334,7 @@ bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace ) ...@@ -247,7 +334,7 @@ bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
} }
#if 1 && defined(DEBUG) #if 0 && defined(DEBUG)
// build this with a Debug CMAKE_BUILD_TYPE // build this with a Debug CMAKE_BUILD_TYPE
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#include <string> #include <string>
#include <boost/ptr_container/ptr_map.hpp> #include <boost/ptr_container/ptr_map.hpp>
#include <sch_lib.h> #include <sch_lib.h>
//#include <sch_lpid.h>
class SCH_LIB_TABLE_LEXER; // outside namespace SCH, since make_lexer() Functions.cmake can't do namespace class SCH_LIB_TABLE_LEXER; // outside namespace SCH, since make_lexer() Functions.cmake can't do namespace
class OUTPUTFORMATTER; class OUTPUTFORMATTER;
...@@ -197,14 +199,14 @@ public: ...@@ -197,14 +199,14 @@ public:
STRING fullURI; STRING fullURI;
STRING options; STRING options;
LIB* lib; LIB* lib; ///< ownership of the loaded LIB is here
}; };
/** /**
* Constructor LIB_TABLE * Constructor 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
* @a aFallBackTable. Loading of this table fragment is done by using Parse(). * @a aFallBackTable. Loading of this table fragment is done by using Parse().
*
* @param aFallBackTable is another LIB_TABLE which is searched only when * @param aFallBackTable is another LIB_TABLE which is searched only when
* a record is not found in this table. No ownership is taken of aFallBackTable. * a record is not found in this table. No ownership is taken of aFallBackTable.
*/ */
...@@ -218,9 +220,9 @@ public: ...@@ -218,9 +220,9 @@ public:
* *
* <pre> * <pre>
* (lib_table * (lib_table
* (lib (logical LOGICAL)(type TYPE)(fullURI FULL_URI)(options OPTIONS)) * (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
* (lib (logical LOGICAL)(type TYPE)(fullURI FULL_URI)(options OPTIONS)) * (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
* (lib (logical LOGICAL)(type TYPE)(fullURI FULL_URI)(options OPTIONS)) * (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
* </pre> * </pre>
* *
* When this function is called, the input token stream given by \a aLexer * When this function is called, the input token stream given by \a aLexer
...@@ -236,6 +238,7 @@ public: ...@@ -236,6 +238,7 @@ public:
* Function Format * Function Format
* serializes this object as utf8 text to an OUTPUTFORMATTER, and tries to * serializes this object as utf8 text to an OUTPUTFORMATTER, and tries to
* make it look good using multiple lines and indentation. * make it look good using multiple lines and indentation.
*
* @param out is an OUTPUTFORMATTER * @param out is an OUTPUTFORMATTER
* @param nestLevel is the indentation level to base all lines of the output. * @param nestLevel is the indentation level to base all lines of the output.
* Actual indentation will be 2 spaces for each nestLevel. * Actual indentation will be 2 spaces for each nestLevel.
...@@ -243,13 +246,26 @@ public: ...@@ -243,13 +246,26 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR ); void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IO_ERROR );
/** /**
* Function GetPart * Function LookupPart
* finds and loads a PART, and parses it. As long as the part is * finds and loads a PART, and parses it. As long as the part is
* accessible in any LIB_SOURCE, opened or not opened, this function * accessible in any LIB_SOURCE, opened or not opened, this function
* will find it and load it into its containing LIB, even if that means * will find it and load it into its containing LIB, even if that means
* having to open a LIB in this table that was not previously opened. * having to open a LIB in this table that was not previously opened.
*
* @param aLogicalPartID holds the partName and may also hold the logicalLibName. If
* logicalLibName is empty, then @a aFallBackLib should not be NULL.
*
* @param aFallBackLib is used only if aLogicalPartID has an empty logicalLibName.
* This is for the case when an LPID has no logicalLibName because the LPID is using
* a partName from the same LIB as was the referring content.
*
* @return PART* - this will never be NULL, and no ownership is transfered because
* all PARTs live in LIBs. You only get to point to them in some LIB. If the PART
* cannot be found, then an exception is thrown.
*
* @throw IO_ERROR if any problem occurs or if the part cannot be found.
*/ */
PART* GetPart( const LPID& aLogicalPartID ) throw( IO_ERROR ); PART* LookupPart( const LPID& aLogicalPartID, LIB* aFallBackLib = NULL ) throw( IO_ERROR );
/** /**
* Function GetLogicalLibs * Function GetLogicalLibs
...@@ -322,12 +338,42 @@ protected: // only a table editor can use these ...@@ -322,12 +338,42 @@ protected: // only a table editor can use these
/** /**
* Function FindRow * Function FindRow
* returns a ROW* if aLogicalName is found in this table or in fallBack, else NULL. * returns a ROW* if aLogicalName is found in this table or in any chained
* fallBack table fragment, else NULL.
*/ */
const ROW* FindRow( const STRING& aLogicalName ) const; ROW* FindRow( const STRING& aLogicalName ) const;
private: private:
/**
* Function lookupLib
* finds or loads a LIB based on @a aLogicalPartID or @a aFallBackLib.
* If the LIB is already loaded then it is returned as is, else it is loaded.
*
* @param aLogicalPartID may hold the logicalLibName. If
* logicalLibName is empty, then @a aLocalLib should not be NULL.
*
* @param aLocalLib is used if not NULL, and should be supplied especiallly if
* aLogicalPartID has an empty logicalLibName. This is for the case when
* a partName must come from the same LIB as the referring content.
* For example, a PART extends another PART in the same LIB and the extends
* LPID has no logical lib name.
*
* @return LIB* - this will never be NULL, and no ownership is transfered because
* all LIBs live in the LIB_TABLEs. You only get to point to them in some LIB_TABLE.
* If the LIB cannot be found, then an exception is thrown.
*
* @throw IO_ERROR if any problem occurs or if the LIB cannot be found or cannot be loaded.
*/
LIB* lookupLib( const LPID& aLogicalPartID, LIB* aLocalLib = NULL ) throw( IO_ERROR );
/**
* Function loadLib
* loads a LIB using information in @a aRow. Call only if LIB not
* already loaded.
*/
void loadLib( ROW* aRow ) throw( IO_ERROR );
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;
......
...@@ -23,8 +23,9 @@ ...@@ -23,8 +23,9 @@
*/ */
#include <cstring> #include <cstring>
#include <wx/wx.h> // _()
#include <sch_lpid.h> #include <sch_lpid.h>
#include <wx/wx.h>
using namespace SCH; using namespace SCH;
...@@ -61,7 +62,8 @@ const char* EndsWithRev( const char* start, const char* tail, char separator ) ...@@ -61,7 +62,8 @@ const char* EndsWithRev( const char* start, const char* tail, char separator )
//----<Policy and field test functions>------------------------------------- //----<Policy and field test functions>-------------------------------------
// These all return -1 on success, or >= 0 if there is an error at a // These all return -1 on success, or >= 0 if there is an error at a
// particular character offset into their respectives arguments. // particular character offset into their respective arguments. If >=0,
// then that return value gives the character offset of the error.
static inline int okLogical( const STRING& aField ) static inline int okLogical( const STRING& aField )
{ {
...@@ -97,7 +99,7 @@ static int okRevision( const STRING& aField ) ...@@ -97,7 +99,7 @@ static int okRevision( const STRING& aField )
strcpy( rev, "x/" ); strcpy( rev, "x/" );
strcat( rev, aField.c_str() ); strcat( rev, aField.c_str() );
if( EndsWithRev( rev ) == rev+2 ) if( EndsWithRev( rev, rev + strlen(rev) ) == rev+2 )
return -1; // success return -1; // success
} }
...@@ -191,7 +193,7 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR ) ...@@ -191,7 +193,7 @@ LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
} }
STRING LPID::GetLogicalLib() const const STRING& LPID::GetLogicalLib() const
{ {
return logical; return logical;
} }
...@@ -208,7 +210,7 @@ int LPID::SetLogicalLib( const STRING& aLogical ) ...@@ -208,7 +210,7 @@ int LPID::SetLogicalLib( const STRING& aLogical )
} }
STRING LPID::GetCategory() const const STRING& LPID::GetCategory() const
{ {
return category; return category;
} }
...@@ -225,7 +227,7 @@ int LPID::SetCategory( const STRING& aCategory ) ...@@ -225,7 +227,7 @@ int LPID::SetCategory( const STRING& aCategory )
} }
STRING LPID::GetBaseName() const const STRING& LPID::GetBaseName() const
{ {
return baseName; return baseName;
} }
...@@ -259,7 +261,7 @@ STRING LPID::GetPartName() const ...@@ -259,7 +261,7 @@ STRING LPID::GetPartName() const
} }
STRING LPID::GetRevision() const const STRING& LPID::GetRevision() const
{ {
return revision; return revision;
} }
......
...@@ -25,14 +25,22 @@ ...@@ -25,14 +25,22 @@
#ifndef SCH_LPID_H_ #ifndef SCH_LPID_H_
#define SCH_LPID_H_ #define SCH_LPID_H_
#include <sch_lib.h> // STRING #include <utf8.h>
#include <kicad_exceptions.h>
namespace SCH {
/** /**
* Class LPID * Class LPID
* (aka GUID) is a Logical Part ID and consists of various portions much like a URI. * (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 * It is a container for the separated portions of a logical part id STRING so they
* sources reside. Its static functions serve as managers of the "library table" to * can be accessed individually. The various portions of an LPID are:
* map logical library names to actual library sources. * logicalLibraryName, category, baseName, and revision. Only the baseName is
* mandatory. There is another construct called "partName" which consists of
* [category/]baseName. That is the category followed by a slash, but only if
* the category is not empty.
* <p>
* partName = [category/]baseName
* <p> * <p>
* Example LPID string: * Example LPID string:
* "kicad:passives/R/rev6". * "kicad:passives/R/rev6".
...@@ -41,8 +49,9 @@ ...@@ -41,8 +49,9 @@
* <li> "kicad" is the logical library name. * <li> "kicad" is the logical library name.
* <li> "passives" is the category. * <li> "passives" is the category.
* <li> "passives/R" is the partname. * <li> "passives/R" is the partname.
* <li> "rev6" is the revision number, which is optional. If missing then its * <li> "rev6" is the revision, which is optional. If missing then its
* delimiter should also not be present. * / delimiter should also not be present. A revision must begin with
* "rev" and be followed by at least one or more decimal digits.
* </ul> * </ul>
* @author Dick Hollenbeck * @author Dick Hollenbeck
*/ */
...@@ -52,7 +61,6 @@ public: ...@@ -52,7 +61,6 @@ public:
LPID(); LPID();
/** /**
* Constructor LPID * Constructor LPID
* takes aLPID string and parses it. A typical LPID string uses a logical * takes aLPID string and parses it. A typical LPID string uses a logical
...@@ -76,7 +84,7 @@ public: ...@@ -76,7 +84,7 @@ public:
* for this portion since it comes from the library table and is considered * for this portion since it comes from the library table and is considered
* read only here. * read only here.
*/ */
STRING GetLogicalLib() const; const STRING& GetLogicalLib() const;
/** /**
* Function SetCategory * Function SetCategory
...@@ -92,7 +100,7 @@ public: ...@@ -92,7 +100,7 @@ public:
* returns the category of this part id, "passives" in the example at the * returns the category of this part id, "passives" in the example at the
* top of the class description. * top of the class description.
*/ */
STRING GetCategory() const; const STRING& GetCategory() const;
/** /**
* Function SetCategory * Function SetCategory
...@@ -108,7 +116,7 @@ public: ...@@ -108,7 +116,7 @@ public:
* Function GetBaseName * Function GetBaseName
* returns the part name without the category. * returns the part name without the category.
*/ */
STRING GetBaseName() const; const STRING& GetBaseName() const;
/** /**
* Function SetBaseName * Function SetBaseName
...@@ -120,7 +128,7 @@ public: ...@@ -120,7 +128,7 @@ public:
int SetBaseName( const STRING& aBaseName ); int SetBaseName( const STRING& aBaseName );
/** /**
* Function GetBaseName * Function GetPartName
* returns the part name, i.e. category/baseName without revision. * returns the part name, i.e. category/baseName without revision.
*/ */
STRING GetPartName() const; STRING GetPartName() const;
...@@ -134,9 +142,9 @@ public: ...@@ -134,9 +142,9 @@ public:
/** /**
* Function GetRevision * Function GetRevision
* returns the revision portion of the LPID or StrEmpty if none. * returns the revision portion of the LPID.
*/ */
STRING GetRevision() const; const STRING& GetRevision() const;
/** /**
* Function SetRevision * Function SetRevision
...@@ -161,10 +169,11 @@ public: ...@@ -161,10 +169,11 @@ public:
protected: protected:
STRING logical; ///< logical lib name or empty STRING logical; ///< logical lib name or empty
STRING category; ///< or empty STRING category; ///< or empty
STRING baseName; ///< excludes category STRING baseName; ///< without category
STRING revision; ///< "revN[N..]" or empty STRING revision; ///< "revN[N..]" or empty
}; };
} // namespace SCH
/** /**
* Function EndsWithRev * Function EndsWithRev
......
...@@ -31,7 +31,7 @@ void PART::Parse( LIB* aLexer ) throw( PARSE_ERROR ) ...@@ -31,7 +31,7 @@ void PART::Parse( LIB* aLexer ) throw( PARSE_ERROR )
} }
#if 1 #if 0 && defined(DEBUG)
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
......
#ifndef UTF8_H_
#define UTF8_H_
#include <string>
#include <deque>
/**
* @ingroup string_types
* @{
*/
/**
* Type STRING
* holds a sequence of 8 bit bytes that represent a sequence
* of variable multi-byte international characters, with unspecified encoding.
*/
typedef std::string STRING;
/**
* Type STRING_UTF8
* holds a UTF8 encoded sequence of 8 bit bytes that represent a sequence
* of variable multi-byte international characters. UTF8 is the chosen encoding
* for all Kicad data files so that they can be transported from one nation to another
* without ambiguity. Data files are those where Kicad controls the content.
* This is not the same thing as filenames, which are not file content.
* Filenames may be encoded on disk using an encoding chosen by the host operating
* system. Nonetheless, Kicad data file _content_ is always UTF8 encoded, regardless
* of host operating system.
* STRING_UTF is UTF8 encoded, by definition.
*/
typedef STRING STRING_UTF8;
/**
* Type STRINGS_UTF8
* is an "array like" list of STRING_UTF8s
*/
typedef std::deque<STRING> STRINGS_UTF8;
typedef std::deque<STRING> STRINGS;
/** @} string_types */
// @todo this does not belong here
#ifndef D
#ifdef DEBUG
#define D(x) x
#else
#define D(x) // nothing
#endif
#endif
#endif // UTF8_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment