new/sch_lpid.*, fix Doxygen errors in /new
This commit is contained in:
commit
29e829b7c0
|
@ -220,6 +220,13 @@ extern const unsigned ${result}_keyword_count;
|
|||
|
||||
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
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -77,6 +77,11 @@ 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(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table.keywords
|
||||
|
@ -84,4 +89,3 @@ make_lexer(
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/sch_lib_table_keywords.cpp
|
||||
ELT_T
|
||||
)
|
||||
|
||||
|
|
|
@ -443,4 +443,6 @@ public:
|
|||
} // namespace SCH
|
||||
|
||||
|
||||
/// @todo remove endsWithRev() in favor of EndsWithRev(), find home for it.
|
||||
|
||||
// EOF
|
||||
|
|
|
@ -140,6 +140,13 @@ static const char* strrstr( const char* haystack, const char* needle )
|
|||
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 )
|
||||
{
|
||||
|
@ -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 );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// see struct BY_REV
|
||||
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 )
|
|||
}
|
||||
|
||||
|
||||
#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 sweets;
|
||||
|
@ -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] : "", "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.GetCategoricalPartNames( &partnames, "lions" );
|
||||
|
@ -649,7 +659,12 @@ int main( int argc, char** argv )
|
|||
{
|
||||
printf( "exception: %s\n", (const char*) wxConvertWX2MB( ioe.errorText ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int main( int argc, char** argv )
|
||||
{
|
||||
DIR_LIB_SOURCE::Test( argc, argv );
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -132,8 +132,7 @@ class DIR_LIB_SOURCE : public LIB_SOURCE
|
|||
*/
|
||||
STRING makeFileName( const STRING& aPartName );
|
||||
|
||||
//protected:
|
||||
public:
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Constructor DIR_LIB_SOURCE( const STRING& aDirectoryPath )
|
||||
|
@ -151,8 +150,7 @@ public:
|
|||
* tree, otherwise only a single version of each part is recognized, namely the
|
||||
* one without the ".revN[N..]" trailer.
|
||||
*/
|
||||
DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = "" )
|
||||
throw( IO_ERROR );
|
||||
DIR_LIB_SOURCE( const STRING& aDirectoryPath, const STRING& aOptions = "" ) throw( IO_ERROR );
|
||||
|
||||
~DIR_LIB_SOURCE();
|
||||
|
||||
|
@ -187,6 +185,10 @@ public:
|
|||
* will output a debug dump of contents.
|
||||
*/
|
||||
void Show();
|
||||
|
||||
public:
|
||||
static void Test( int argc, char** argv );
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -25,29 +25,18 @@
|
|||
|
||||
#include <sch_lib_table.h>
|
||||
#include <sch_lib_table_lexer.h>
|
||||
#include <sch_lpid.h>
|
||||
#include <set>
|
||||
|
||||
using namespace std;
|
||||
//using namespace std; // screws up Doxygen
|
||||
using namespace SCH;
|
||||
|
||||
|
||||
LIB_TABLE::LIB_TABLE( LIB_TABLE* aFallBackTable ) :
|
||||
fallBack( aFallBackTable )
|
||||
{
|
||||
/* not copying fall back, simply search aFallBackTable separately if "logicalName not found".
|
||||
if( aFallBackTable )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
*/
|
||||
// not copying fall back, simply search aFallBackTable separately
|
||||
// if "logicalName not found".
|
||||
}
|
||||
|
||||
|
||||
|
@ -56,9 +45,9 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
|||
/* grammar:
|
||||
|
||||
(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.
|
||||
|
@ -66,7 +55,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
|||
|
||||
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"))
|
||||
|
||||
|
@ -83,7 +72,7 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
|||
|
||||
in->NeedSYMBOLorNUMBER();
|
||||
|
||||
auto_ptr<ROW> row( new ROW( this ) );
|
||||
std::auto_ptr<ROW> row( new ROW( this ) );
|
||||
|
||||
row->SetLogicalName( in->CurText() );
|
||||
|
||||
|
@ -127,12 +116,12 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
|||
row->SetOptions( in->CurText() );
|
||||
|
||||
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
|
||||
// replace. However a fallBack table can have a conflicting logicalName
|
||||
// and ours will supercede that one since in FindLib() we search this table
|
||||
// before any fall back.
|
||||
// use doReplace in InsertRow(). However a fallBack table can have a
|
||||
// conflicting logicalName and ours will supercede that one since in
|
||||
// FindLib() we search this table before any fall back.
|
||||
if( !InsertRow( row ) )
|
||||
{
|
||||
STRING msg;
|
||||
|
@ -144,7 +133,6 @@ void LIB_TABLE::Parse( SCH_LIB_TABLE_LEXER* in ) throw( IO_ERROR )
|
|||
throw IO_ERROR( msg );
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -172,12 +160,13 @@ void LIB_TABLE::ROW::Format( OUTPUTFORMATTER* out, int nestLevel ) const
|
|||
|
||||
STRINGS LIB_TABLE::GetLogicalLibs()
|
||||
{
|
||||
// only return unique logical library names. Use std::set::insert() to
|
||||
// quietly reject any duplicates, which can happen in the fall back table(s).
|
||||
set<STRING> unique;
|
||||
STRINGS ret;
|
||||
// Only return unique logical library names. Use std::set::insert() to
|
||||
// quietly reject any duplicates, which can happen when encountering a duplicate
|
||||
// logical lib name from one of the fall back table(s).
|
||||
|
||||
const LIB_TABLE* cur = this;
|
||||
std::set<STRING> unique;
|
||||
STRINGS ret;
|
||||
const LIB_TABLE* cur = this;
|
||||
|
||||
do
|
||||
{
|
||||
|
@ -188,8 +177,8 @@ STRINGS LIB_TABLE::GetLogicalLibs()
|
|||
|
||||
} while( ( cur = cur->fallBack ) != 0 );
|
||||
|
||||
// return a sorted, unique set of STRINGS to caller
|
||||
for( set<STRING>::const_iterator it = unique.begin(); it!=unique.end(); ++it )
|
||||
// return a sorted, unique set of logical lib name STRINGS to caller
|
||||
for( std::set<STRING>::const_iterator it = unique.begin(); it!=unique.end(); ++it )
|
||||
ret.push_back( *it );
|
||||
|
||||
return ret;
|
||||
|
@ -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.
|
||||
|
||||
|
|
|
@ -41,6 +41,41 @@ class PART;
|
|||
* Class LIB_TABLE
|
||||
* holds LIB_TABLE::ROW records, and can be searched in a very high speed
|
||||
* 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
|
||||
*/
|
||||
|
@ -168,7 +203,8 @@ public:
|
|||
|
||||
/**
|
||||
* 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
|
||||
* a record is not found in this table. No ownership is taken of aFallBackTable.
|
||||
*/
|
||||
|
@ -176,16 +212,15 @@ public:
|
|||
|
||||
/**
|
||||
* 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.
|
||||
* The entire textual element spec is <br>
|
||||
* (lib_table (logical _yourfieldname_)(value _yourvalue_) visible))
|
||||
*
|
||||
* <pre>
|
||||
* (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>
|
||||
*
|
||||
* When this function is called, the input token stream given by \a aLexer
|
||||
|
@ -193,7 +228,7 @@ public:
|
|||
* identifying keyword and before the content specifying stuff.<br>
|
||||
* (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 );
|
||||
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* 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 )
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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_
|
237
new/sch_lpid.cpp
237
new/sch_lpid.cpp
|
@ -22,15 +22,248 @@
|
|||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <sch_lpid.h>
|
||||
|
||||
|
||||
using namespace SCH;
|
||||
|
||||
|
||||
LPID::LPID( const STRING& aLPID ) throw( PARSE_ERROR )
|
||||
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 )
|
||||
{
|
||||
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
|
||||
|
|
111
new/sch_lpid.h
111
new/sch_lpid.h
|
@ -25,8 +25,7 @@
|
|||
#ifndef SCH_LPID_H_
|
||||
#define SCH_LPID_H_
|
||||
|
||||
//#include <wx/string.h>
|
||||
|
||||
#include <sch_lib.h> // STRING
|
||||
|
||||
/**
|
||||
* Class LPID
|
||||
|
@ -45,42 +44,7 @@
|
|||
* <li> "rev6" is the revision number, which is optional. If missing then its
|
||||
* delimiter should also not be present.
|
||||
* </ul>
|
||||
* <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>
|
||||
* 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.
|
||||
* @author Dick Hollenbeck
|
||||
*/
|
||||
class LPID // aka GUID
|
||||
{
|
||||
|
@ -95,12 +59,19 @@ public:
|
|||
LPID( const STRING& aLPID ) throw( PARSE_ERROR );
|
||||
|
||||
/**
|
||||
* Function GetLogLib
|
||||
* Function GetLogicalLib
|
||||
* 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
|
||||
* 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
|
||||
|
@ -113,8 +84,35 @@ public:
|
|||
* Function SetCategory
|
||||
* overrides the category portion of the LPID to @a aCategory and is typically
|
||||
* 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
|
||||
|
@ -126,14 +124,43 @@ public:
|
|||
* Function SetRevision
|
||||
* overrides the revision portion of the LPID to @a aRevision and must
|
||||
* 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
|
||||
* returns the full text of the LPID.
|
||||
*/
|
||||
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_
|
||||
|
|
Loading…
Reference in New Issue