Commit 29e829b7 authored by Dick Hollenbeck's avatar Dick Hollenbeck

new/sch_lpid.*, fix Doxygen errors in /new

parents 85477537 5311dd70
...@@ -220,6 +220,13 @@ extern const unsigned ${result}_keyword_count; ...@@ -220,6 +220,13 @@ extern const unsigned ${result}_keyword_count;
using namespace DSN; // enum ${enum} is in this namespace using namespace DSN; // enum ${enum} is in this namespace
/**
* Classs ${RESULT}_LEXER
* is an automatically generated class using the TokenList2DnsLexer.cmake
* technology, based on keywords provided by file:
* ${inputFile}
*/
class ${RESULT}_LEXER : public DSNLEXER class ${RESULT}_LEXER : public DSNLEXER
{ {
public: public:
......
...@@ -77,6 +77,11 @@ target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} ) ...@@ -77,6 +77,11 @@ target_link_libraries( test_sch_lib_table ${wxWidgets_LIBRARIES} )
add_executable( test_sch_part sch_part.cpp ) add_executable( test_sch_part sch_part.cpp )
target_link_libraries( test_sch_part ${wxWidgets_LIBRARIES} ) 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
...@@ -84,4 +89,3 @@ make_lexer( ...@@ -84,4 +89,3 @@ make_lexer(
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp ${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
ELT_T ELT_T
) )
...@@ -443,4 +443,6 @@ public: ...@@ -443,4 +443,6 @@ public:
} // namespace SCH } // namespace SCH
/// @todo remove endsWithRev() in favor of EndsWithRev(), find home for it.
// EOF // EOF
...@@ -140,6 +140,13 @@ static const char* strrstr( const char* haystack, const char* needle ) ...@@ -140,6 +140,13 @@ static const char* strrstr( const char* haystack, const char* needle )
return ret; return ret;
} }
#if 1 // @todo switch over to EndsWithRev() global
static inline bool isDigit( char c )
{
return c >= '0' && c <= '9';
}
static inline bool isDigit( char c ) static inline bool isDigit( char c )
{ {
...@@ -185,6 +192,8 @@ static inline const char* endsWithRev( const STRING& aPartName, char separator ) ...@@ -185,6 +192,8 @@ static inline const char* endsWithRev( const STRING& aPartName, char separator )
return endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator ); return endsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator );
} }
#endif
// see struct BY_REV // see struct BY_REV
bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const bool BY_REV::operator() ( const STRING& s1, const STRING& s2 ) const
...@@ -587,9 +596,9 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR ) ...@@ -587,9 +596,9 @@ void DIR_LIB_SOURCE::cacheOneDir( const STRING& aCategory ) throw( IO_ERROR )
} }
#if (1 || defined( TEST_DIR_LIB_SOURCE )) && defined(DEBUG) #if 1 && defined(DEBUG)
int main( int argc, char** argv ) void DIR_LIB_SOURCE::Test( int argc, char** argv )
{ {
STRINGS partnames; STRINGS partnames;
STRINGS sweets; STRINGS sweets;
...@@ -601,7 +610,8 @@ int main( int argc, char** argv ) ...@@ -601,7 +610,8 @@ int main( int argc, char** argv )
// DIR_LIB_SOURCE uut( argv[1] ? argv[1] : "", "" ); // DIR_LIB_SOURCE uut( argv[1] ? argv[1] : "", "" );
DIR_LIB_SOURCE uut( argv[1] ? argv[1] : "", "useVersioning" ); DIR_LIB_SOURCE uut( argv[1] ? argv[1] : "", "useVersioning" );
// initially, only the NAME_CACHE sweets and STRING categories are loaded: // show the cached content, only the directory information is cached,
// parts are cached in class LIB, not down here.
uut.Show(); uut.Show();
uut.GetCategoricalPartNames( &partnames, "lions" ); uut.GetCategoricalPartNames( &partnames, "lions" );
...@@ -649,7 +659,12 @@ int main( int argc, char** argv ) ...@@ -649,7 +659,12 @@ int main( int argc, char** argv )
{ {
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) ); printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
} }
}
int main( int argc, char** argv )
{
DIR_LIB_SOURCE::Test( argc, argv );
return 0; return 0;
} }
......
...@@ -132,8 +132,7 @@ class DIR_LIB_SOURCE : public LIB_SOURCE ...@@ -132,8 +132,7 @@ class DIR_LIB_SOURCE : public LIB_SOURCE
*/ */
STRING makeFileName( const STRING& aPartName ); STRING makeFileName( const STRING& aPartName );
//protected: protected:
public:
/** /**
* Constructor DIR_LIB_SOURCE( const STRING& aDirectoryPath ) * Constructor DIR_LIB_SOURCE( const STRING& aDirectoryPath )
...@@ -151,8 +150,7 @@ public: ...@@ -151,8 +150,7 @@ public:
* 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.
*/ */
DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = "" ) DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = "" ) throw( IO_ERROR );
throw( IO_ERROR );
~DIR_LIB_SOURCE(); ~DIR_LIB_SOURCE();
...@@ -187,6 +185,10 @@ public: ...@@ -187,6 +185,10 @@ public:
* will output a debug dump of contents. * will output a debug dump of contents.
*/ */
void Show(); void Show();
public:
static void Test( int argc, char** argv );
#endif #endif
}; };
......
...@@ -25,29 +25,18 @@ ...@@ -25,29 +25,18 @@
#include <sch_lib_table.h> #include <sch_lib_table.h>
#include <sch_lib_table_lexer.h> #include <sch_lib_table_lexer.h>
#include <sch_lpid.h>
#include <set> #include <set>
using namespace std; //using namespace std; // screws up Doxygen
using namespace SCH; using namespace SCH;
LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) : LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) :
fallBack( aFallBackTable ) fallBack( aFallBackTable )
{ {
/* not copying fall back, simply search aFallBackTable separately if "logicalName not found". // not copying fall back, simply search aFallBackTable separately
if( aFallBackTable ) // if "logicalName not found".
{
const ROWS& t = aFallBackTable->rows;
for( ROWS_CITER it = t.begin(); it != t.end(); ++it )
{
// our rows are empty, expect no collisions here
auto_ptr<ROW> row( new ROW( *it->second ) );
row->owner = this;
insert( row );
}
}
*/
} }
...@@ -56,9 +45,9 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) ...@@ -56,9 +45,9 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
/* grammar: /* grammar:
(lib_table (lib_table
(lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
(lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
(lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) (lib (logical LOGICAL)(type TYPE)(full_uri FULL_URI)(options OPTIONS))
) )
note: "(lib_table" has already been read in. note: "(lib_table" has already been read in.
...@@ -66,7 +55,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) ...@@ -66,7 +55,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
ELT_T tok; ELT_T tok;
while( (tok = in->NextTok() ) != T_RIGHT && tok != T_EOF ) while( ( tok = in->NextTok() ) != T_RIGHT && tok != T_EOF )
{ {
// (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS")) // (lib (logical "LOGICAL")(type "TYPE")(full_uri "FULL_URI")(options "OPTIONS"))
...@@ -83,7 +72,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) ...@@ -83,7 +72,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
in->NeedSYMBOLorNUMBER(); in->NeedSYMBOLorNUMBER();
auto_ptr<ROW> row( new ROW( this ) ); std::auto_ptr<ROW> row( new ROW( this ) );
row->SetLogicalName( in->CurText() ); row->SetLogicalName( in->CurText() );
...@@ -127,12 +116,12 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) ...@@ -127,12 +116,12 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
row->SetOptions( in->CurText() ); row->SetOptions( in->CurText() );
in->NeedRIGHT(); in->NeedRIGHT();
in->NeedRIGHT(); // teriminate the (lib..) in->NeedRIGHT(); // terminate the (lib..)
// all logicalNames within this table fragment must be unique, so we do not // all logicalNames within this table fragment must be unique, so we do not
// replace. However a fallBack table can have a conflicting logicalName // use doReplace in InsertRow(). However a fallBack table can have a
// and ours will supercede that one since in FindLib() we search this table // conflicting logicalName and ours will supercede that one since in
// before any fall back. // FindLib() we search this table before any fall back.
if( !InsertRow( row ) ) if( !InsertRow( row ) )
{ {
STRING msg; STRING msg;
...@@ -144,7 +133,6 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR ) ...@@ -144,7 +133,6 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
throw IO_ERROR( msg ); throw IO_ERROR( msg );
} }
} }
return;
} }
...@@ -172,12 +160,13 @@ void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const ...@@ -172,12 +160,13 @@ void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
STRINGS LIB_TABLE::GetLogicalLibs() STRINGS 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 in the fall back table(s). // quietly reject any duplicates, which can happen when encountering a duplicate
set<STRING> unique; // logical lib name from one of the fall back table(s).
STRINGS ret;
const LIB_TABLE* cur = this; std::set<STRING> unique;
STRINGS ret;
const LIB_TABLE* cur = this;
do do
{ {
...@@ -188,8 +177,8 @@ STRINGS LIB_TABLE::GetLogicalLibs() ...@@ -188,8 +177,8 @@ STRINGS LIB_TABLE::GetLogicalLibs()
} while( ( cur = cur->fallBack ) != 0 ); } while( ( cur = cur->fallBack ) != 0 );
// return a sorted, unique set of STRINGS to caller // return a sorted, unique set of logical lib name STRINGS to caller
for( set<STRING>::const_iterator it = unique.begin(); it!=unique.end(); ++it ) for( std::set<STRING>::const_iterator it = unique.begin(); it!=unique.end(); ++it )
ret.push_back( *it ); ret.push_back( *it );
return ret; return ret;
...@@ -228,7 +217,7 @@ const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) const ...@@ -228,7 +217,7 @@ const LIB_TABLE::ROW* LIB_TABLE::FindRow( const STRING& aLogicalName ) const
} }
bool LIB_TABLE::InsertRow( auto_ptr<ROW>& aRow, bool doReplace ) bool LIB_TABLE::InsertRow( std::auto_ptr<ROW>& aRow, bool doReplace )
{ {
// this does not need to be super fast. // this does not need to be super fast.
......
...@@ -41,6 +41,41 @@ class PART; ...@@ -41,6 +41,41 @@ class PART;
* Class LIB_TABLE * Class LIB_TABLE
* holds LIB_TABLE::ROW records, and can be searched in a very high speed * holds LIB_TABLE::ROW records, and can be searched in a very high speed
* way based on logical library name. * way based on logical library name.
* <p>
* This class owns the <b>library table</b>, which is like fstab in concept and maps logical
* library name to library URI, type, and options. It has the following columns:
* <ul>
* <li> Logical Library Name
* <li> Library Type
* <li> Library URI. The full URI to the library source, form dependent on Type.
* <li> Options, used for access, such as password
* </ul>
* <p>
* The Library Type can be one of:
* <ul>
* <li> "dir"
* <li> "schematic" i.e. a parts list from another schematic.
* <li> "subversion"
* <li> "http"
* </ul>
* <p>
* For now, the Library URI types needed to support the various types can be one of those
* shown below, which are typical of each type:
* <ul>
* <li> "file://C:/mylibdir"
* <li> "file://home/user/kicadwork/jtagboard.sch"
* <li> "svn://kicad.org/partlib/trunk"
* <li> "http://kicad.org/partlib"
* </ul>
* <p>
* The applicable library table is built up from several additive rows (table fragments),
* and the final table is a (conceptual) merging of the table fragments. Two
* anticipated sources of the rows are a personal table, and a schematic resident
* table. The schematic resident table rows are considered a higher priority in
* the final dynamically assembled library table. A row in the schematic
* contribution to the library table takes precedence over the personal table
* if there is a collision on logical library name, otherwise the rows simply
* combine without issue to make up the applicable library table.
* *
* @author Dick Hollenbeck * @author Dick Hollenbeck
*/ */
...@@ -168,7 +203,8 @@ public: ...@@ -168,7 +203,8 @@ public:
/** /**
* Constructor LIB_TABLE * Constructor LIB_TABLE
* builds a library table from an s-expression form of the library table. * 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().
* @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.
*/ */
...@@ -176,16 +212,15 @@ public: ...@@ -176,16 +212,15 @@ public:
/** /**
* Function Parse * Function Parse
* fills this object from information in the input stream \a aLexer, which * fills this table fragment from information in the input stream \a aLexer, which
* is a DSNLEXER customized for the grammar needed to describe instances of this object. * is a DSNLEXER customized for the grammar needed to describe instances of this object.
* The entire textual element spec is <br> * The entire textual element spec is <br>
* (lib_table (logical _yourfieldname_)(value _yourvalue_) visible))
* *
* <pre> * <pre>
* (lib_table * (lib_table
* (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) * (lib (logical LOGICAL)(type TYPE)(fullURI FULL_URI)(options OPTIONS))
* (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) * (lib (logical LOGICAL)(type TYPE)(fullURI FULL_URI)(options OPTIONS))
* (lib (logical "LOGICAL")(type "TYPE")(fullURI "FULL_URI")(options "OPTIONS")) * (lib (logical LOGICAL)(type TYPE)(fullURI 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
...@@ -193,7 +228,7 @@ public: ...@@ -193,7 +228,7 @@ public:
* identifying keyword and before the content specifying stuff.<br> * identifying keyword and before the content specifying stuff.<br>
* (lib_table ^ (....) ) * (lib_table ^ (....) )
* *
* @param aSpec is the input token stream of keywords and symbols. * @param aLexer is the input token stream of keywords and symbols.
*/ */
void Parse( SCH_LIB_TABLE_LEXER* aLexer ) throw( IO_ERROR ); void Parse( SCH_LIB_TABLE_LEXER* aLexer ) throw( IO_ERROR );
......
/**
* Function GetPart
* 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
* will find it and load it into its containing LIB, even if that means
* having to load a new LIB as given in the library table.
*/
static PART* SCH_LIBS::GetPart( const LPID& aLogicalPartID ) throw( IO_ERROR )
{
}
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2010-2011 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2010 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef SCH_LIBS_H_
#define SCH_LIBS_H_
#include <sch_lib.h>
/**
* Class LIBS
* houses a handful of functions that manage all the RAM resident LIBs, and
* provide for a global part lookup function, GetPart(), which can be the basis
* of a cross LIB hyperlink.
*/
class LIBS
{
public:
/**
* Function GetPart
* 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
* will find it and load it into its containing LIB, even if that means
* having to load a new LIB as given in the library table.
*/
static PART* GetPart( const LPID& aLogicalPartID ) throw( IO_ERROR );
/**
* Function GetLib
* is first a lookup function and then if needed, a factory function.
* If aLogicalLibraryName has been opened, then return the already opened
* LIB. If not, then instantiate the library and fill the initial
* library PARTs (unparsed) and categories, and add it to LIB::libraries
* for future reference.
*/
static LIB* GetLib( const STRING& aLogicalLibraryName ) throw( IO_ERROR );
/**
* Function GetOpenedLibNames
* returns the logical library names of LIBs that are already opened.
* @see LPID::GetLogicalLibraries()
*/
static STRINGS GetOpendedLogicalLibNames();
/**
* Function CloseLibrary
* closes an open library @a aLibrary and removes it from class LIBS.
*/
static void CloseLibrary( LIB* aLibrary ) throw( IO_ERROR );
private:
/// collection of LIBs, searchable by logical name.
static std::map< STRING, LIB* > libraries; // owns the LIBs.
};
#endif // SCH_LIBS_H_
...@@ -22,15 +22,248 @@ ...@@ -22,15 +22,248 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <cstring>
#include <sch_lpid.h> #include <sch_lpid.h>
using namespace SCH; using namespace SCH;
static inline bool isDigit( char c )
{
return c >= '0' && c <= '9';
}
const char* EndsWithRev( const char* start, const char* tail, char separator )
{
bool sawDigit = false;
while( tail > start && isDigit( *--tail ) )
{
sawDigit = true;
}
// if sawDigit, tail points to the 'v' here.
if( sawDigit && tail-3 >= start )
{
tail -= 3;
if( tail[0]==separator && tail[1]=='r' && tail[2]=='e' && tail[3]=='v' )
{
return tail+1; // omit separator, return "revN[N..]"
}
}
return 0;
}
LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR ) LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
{ {
const char* rev = EndsWithRev( aLPID );
size_t revNdx;
size_t partNdx;
size_t baseNdx;
//=====<revision>=========================================
if( rev )
{
revNdx = rev - aLPID.c_str();
revision = aLPID.substr( revNdx );
--revNdx; // back up to omit the '/' which preceeds the rev
}
else
revNdx = aLPID.size();
//=====<logical>==========================================
if( ( partNdx = aLPID.find( ':' ) ) != aLPID.npos )
{
logical = aLPID.substr( 0, partNdx );
++partNdx; // skip ':'
}
else
partNdx = 0;
//=====<rawName && category>==============================
// "length limited" search:
const char* base = (const char*) memchr( aLPID.c_str() + partNdx, '/', revNdx - partNdx );
if( base )
{
baseNdx = base - aLPID.c_str();
category = aLPID.substr( partNdx, baseNdx - partNdx );
++baseNdx; // skip '/'
}
else
{
baseNdx = partNdx;
}
//=====<baseName>==========================================
baseName = aLPID.substr( baseNdx, revNdx - baseNdx );
}
STRING LPID::GetLogicalLib() const
{
return logical;
}
bool LPID::SetLogicalLib( const STRING& aLogical )
{
if( aLogical.find_first_of( ":/" ) == STRING::npos )
{
logical = aLogical;
return true;
}
return false;
}
STRING LPID::GetCategory() const
{
return category;
}
bool LPID::SetCategory( const STRING& aCategory )
{
if( aCategory.find_first_of( ":/" ) == STRING::npos )
{
category = aCategory;
return true;
}
return false;
}
STRING LPID::GetBaseName() const
{
return baseName;
}
bool LPID::SetBaseName( const STRING& aBaseName )
{
if( aBaseName.find_first_of( ":/" ) == STRING::npos )
{
baseName = aBaseName;
return true;
}
return false;
}
STRING LPID::GetPartName() const
{
STRING ret;
// return [category/]baseName
if( category.size() )
{
ret += category;
ret += '/';
}
ret += baseName;
return ret;
}
STRING LPID::GetRevision() const
{
return revision;
}
bool LPID::SetRevision( const STRING& aRevision )
{
STRING rev;
rev += "x/";
rev += aRevision;
if( EndsWithRev( rev ) )
{
revision = aRevision;
return true;
}
return false;
} }
STRING LPID::GetFullText() const
{
STRING ret;
if( logical.size() )
{
ret += logical;
ret += ':';
}
if( category.size() )
{
ret += category;
ret += '/';
}
ret += baseName;
if( revision.size() )
{
ret += '/';
ret += revision;
}
return ret;
}
#if 1 && defined(DEBUG)
// build this with Debug CMAKE_BUILD_TYPE
void LPID::Test()
{
static const char* lpids[] = {
"me:passives/R/rev0",
"passives/R/rev2",
":passives/R/rev3",
"C/rev22",
"passives/C22",
"R",
"me:R",
// most difficult:
"me:/R/rev0",
"me:R/rev0",
};
for( unsigned i=0; i<sizeof(lpids)/sizeof(lpids[0]); ++i )
{
// test some round tripping
LPID lpid( lpids[i] ); // parse
// format
printf( "input:'%s' full:'%s' base:'%s' partName:'%s' cat:'%s'\n",
lpids[i],
lpid.GetFullText().c_str(),
lpid.GetBaseName().c_str(),
lpid.GetPartName().c_str(),
lpid.GetCategory().c_str()
);
}
}
int main( int argc, char** argv )
{
LPID::Test();
return 0;
}
#endif
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
#ifndef SCH_LPID_H_ #ifndef SCH_LPID_H_
#define SCH_LPID_H_ #define SCH_LPID_H_
//#include <wx/string.h> #include <sch_lib.h> // STRING
/** /**
* Class LPID * Class LPID
...@@ -45,42 +44,7 @@ ...@@ -45,42 +44,7 @@
* <li> "rev6" is the revision number, which is optional. If missing then its * <li> "rev6" is the revision number, which is optional. If missing then its
* delimiter should also not be present. * delimiter should also not be present.
* </ul> * </ul>
* <p> * @author Dick Hollenbeck
* This class owns the <b>library table</b>, which is like fstab in concept and maps logical
* library name to library URI, type, and options. It has the following columns:
* <ul>
* <li> Logical Library Name
* <li> Library Type
* <li> Library URI. The full URI to the library source, form dependent on Type.
* <li> Options, used for access, such as password
* </ul>
* <p>
* For now, the Library Type can be one of:
* <ul>
* <li> "dir"
* <li> "schematic" i.e. a parts list from another schematic.
* <li> "subversion"
* <li> "bazaar"
* <li> "http"
* </ul>
* <p>
* For now, the Library URI types needed to support the various types can be one of those
* shown below, which are typical of each type:
* <ul>
* <li> "file://C:/mylibdir"
* <li> "file://home/user/kicadwork/jtagboard.sch"
* <li> "svn://kicad.org/partlib/trunk"
* <li> "http://kicad.org/partlib"
* </ul>
* <p>
* The applicable library table is built up from several additive rows (table fragments),
* and the final table is a merging of the table fragments. Two anticipated sources of
* the rows are a personal table, and a schematic resident table. The schematic
* resident table rows are considered a higher priority in the final dynamically
* assembled library table. A row in the schematic contribution to the library table
* will take precedence over the personal table if there is a collision on logical
* library name, otherwise the rows simply combine without issue to make up the
* applicable library table.
*/ */
class LPID // aka GUID class LPID // aka GUID
{ {
...@@ -95,12 +59,19 @@ public: ...@@ -95,12 +59,19 @@ public:
LPID( const STRING& aLPID ) throw( PARSE_ERROR ); LPID( const STRING& aLPID ) throw( PARSE_ERROR );
/** /**
* Function GetLogLib * Function GetLogicalLib
* returns the logical library portion of a LPID. There is not Set accessor * returns the logical library portion of a LPID. There is not Set accessor
* 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 GetLogLib() const; STRING GetLogicalLib() const;
/**
* Function SetCategory
* overrides the logical lib name portion of the LPID to @a aLogical, and can be empty.
* @return bool - true unless parameter has ':' or '/' in it.
*/
bool SetLogicalLib( const STRING& aLogical );
/** /**
* Function GetCategory * Function GetCategory
...@@ -113,8 +84,35 @@ public: ...@@ -113,8 +84,35 @@ public:
* Function SetCategory * Function SetCategory
* overrides the category portion of the LPID to @a aCategory and is typically * overrides the category portion of the LPID to @a aCategory and is typically
* either the empty string or a single word like "passives". * either the empty string or a single word like "passives".
* @return bool - true unless parameter has ':' or '/' in it.
*/
bool SetCategory( const STRING& aCategory );
/**
* Function GetBaseName
* returns the part name without the category.
*/
STRING GetBaseName() const;
/**
* Function SetBaseName
* overrides the base name portion of the LPID to @a aBaseName
* @return bool - true unless parameter has ':' or '/' in it.
*/
bool SetBaseName( const STRING& aBaseName );
/**
* Function GetBaseName
* returns the part name, i.e. category/baseName without revision.
*/
STRING GetPartName() const;
/**
* Function SetBaseName
* overrides the part name portion of the LPID to @a aPartName
not really needed, partname is an agreggate anyway, just parse a new one.
void SetPartName( const STRING& aPartName );
*/ */
void SetCategory( const STRING& aCategory );
/** /**
* Function GetRevision * Function GetRevision
...@@ -126,14 +124,43 @@ public: ...@@ -126,14 +124,43 @@ public:
* Function SetRevision * Function SetRevision
* overrides the revision portion of the LPID to @a aRevision and must * overrides the revision portion of the LPID to @a aRevision and must
* be in the form "rev<num>" where "<num>" is "1", "2", etc. * be in the form "rev<num>" where "<num>" is "1", "2", etc.
* @return bool - true unless parameter is not of the form "revN]N..]"
*/ */
void SetRevision( const STRING& aRevision ); bool SetRevision( const STRING& aRevision );
/** /**
* Function GetFullText * Function GetFullText
* returns the full text of the LPID. * returns the full text of the LPID.
*/ */
STRING GetFullText() const; STRING GetFullText() const;
#if defined(DEBUG)
static void Test();
#endif
protected:
STRING logical; ///< logical lib name or empty
STRING category; ///< or empty
STRING baseName; ///< excludes category
STRING revision; ///< "revN[N..]" or empty
}; };
/**
* Function EndsWithRev
* returns a pointer to the final string segment: "revN[N..]" or NULL if none.
* @param start is the beginning of string segment to test, the partname or
* any middle portion of it.
* @param tail is a pointer to the terminating nul, or one past inclusive end of
* segment, i.e. the string segment of interest is [start,tail)
* @param separator is the separating byte, expected: '.' or '/', depending on context.
*/
const char* EndsWithRev( const char* start, const char* tail, char separator = '/' );
static inline const char* EndsWithRev( const STRING& aPartName, char separator = '/' )
{
return EndsWithRev( aPartName.c_str(), aPartName.c_str()+aPartName.size(), separator );
}
#endif // SCH_LPID_H_ #endif // SCH_LPID_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