28#include <wx/filename.h>
33#include <lib_table_lexer.h>
40using namespace LIB_TABLE_T;
45 const wxFileName fn( aURI );
47 if( !fn.IsOk() || !fn.IsFileReadable() )
50 return std::make_unique<FILE_LINE_READER>( aURI );
55 const wxFileName fn( aURI );
60 return fn.IsFileWritable();
66 if( aURI1.Find(
"://" ) != wxNOT_FOUND )
69 return aURI1 == aURI2;
73 const wxFileName fn1( aURI1 );
74 const wxFileName fn2( aURI2 );
87 const wxFileName fn( aURI );
88 return std::make_unique<FILE_OUTPUTFORMATTER>( aURI );
126 uri.Replace(
'\\',
'/' );
128 wxString extraOptions;
131 extraOptions +=
"(disabled)";
134 extraOptions +=
"(hidden)";
136 out->
Print( nestLevel,
"(lib (name %s)(type %s)(uri %s)(options %s)(descr %s)%s)\n",
139 out->
Quotew( uri ).c_str(),
142 extraOptions.ToStdString().c_str() );
167 m_io(
std::
move( aTableIo ) ), m_fallBack( aFallBackTable ), m_version( 0 )
172 m_io = std::make_unique<FILE_LIB_TABLE_IO>();
210 return wxEmptyString;
229 if( row.GetFullURI() == aPath )
257 std::shared_lock<std::shared_mutex> lock( cur->
m_mutex );
272 for(
const std::pair<const wxString, LIB_TABLE_ROWS_ITER>& entry : cur->
m_rowsMap )
274 wxString legacyLibName = entry.first;
275 legacyLibName.Replace(
" ",
"_" );
277 if( legacyLibName == aNickName )
279 row = &*entry.second;
287 }
while( ( cur = cur->
m_fallBack ) !=
nullptr );
299 for(
unsigned i = 0; i < cur->
m_rows.size(); i++ )
301 const wxString tmp = cur->
m_rows[i].GetFullURI(
true );
303 if(
m_io->UrisAreEquivalent( tmp, aURI ) )
308 }
while( ( cur = cur->
m_fallBack ) !=
nullptr );
319 std::set<wxString> unique;
320 std::vector<wxString> ret;
331 }
while( ( cur = cur->
m_fallBack ) !=
nullptr );
333 ret.reserve( unique.size() );
336 for( std::set< wxString >::const_iterator it = unique.begin(); it!=unique.end(); ++it )
337 ret.push_back( *it );
340 std::sort( ret.begin(), ret.end(),
341 [](
const wxString& lhs,
const wxString& rhs )
343 return StrNumCmp( lhs, rhs, true ) < 0;
352 std::lock_guard<std::shared_mutex> lock(
m_mutex );
370 m_rows.replace( it->second, aRow );
385 std::lock_guard<std::shared_mutex> lock(
m_mutex );
392 if( &*it->second == aRow )
395 m_rows.erase( it->second );
402 for(
int i = (
int)
m_rows.size() - 1; i >= 0; --i )
422 std::lock_guard<std::shared_mutex> lock(
m_mutex );
424 if( aIndex >=
m_rows.size() )
429 m_rows.replace( aIndex, aRow );
437 std::lock_guard<std::shared_mutex> lock(
m_mutex );
439 if( aIndex >=
m_rows.size() )
442 int newPos =
static_cast<int>( aIndex ) + aOffset;
444 if( newPos < 0 || newPos >
static_cast<int>(
m_rows.size() ) - 1 )
447 auto element =
m_rows.release(
m_rows.begin() + aIndex );
449 m_rows.insert(
m_rows.begin() + newPos, element.release() );
458 std::lock_guard<std::shared_mutex> lock(
m_mutex );
461 m_rows.transfer(
m_rows.end(), aRowsList.begin(), aRowsList.end(), aRowsList );
473 it->SetParent(
this );
481 bool table_updated =
false;
485 bool row_updated =
false;
486 wxString uri = row.GetFullURI(
true );
490 row_updated |= ( uri.Replace( wxS(
"${KICAD5_" ), wxS(
"${KICAD7_" ),
false ) > 0 );
491 row_updated |= ( uri.Replace( wxS(
"${KICAD6_" ), wxS(
"${KICAD7_" ), false ) > 0 );
495 row.SetFullURI( uri );
496 table_updated =
true;
500 return table_updated;
506 std::lock_guard<std::shared_mutex> lock(
m_mutex );
509 std::unique_ptr<LINE_READER> reader =
m_io->GetReader( aFileName );
514 LIB_TABLE_LEXER lexer( reader.get() );
528 std::unique_ptr<OUTPUTFORMATTER> sf =
m_io->GetWriter( aFileName );
532 THROW_IO_ERROR( wxString::Format(
_(
"Failed to get writer for %s" ), aFileName ) );
543 if( aOptionsList.size() )
545 const char* cp = &aOptionsList[0];
546 const char* end = cp + aOptionsList.size();
548 std::map<std::string, UTF8> props;
557 while( cp < end && isspace( *cp ) )
563 if( *cp ==
'\\' && cp + 1 < end && cp[1] ==
OPT_SEP )
583 size_t eqNdx = pair.find(
'=' );
585 if( eqNdx != pair.npos )
587 std::string
name = pair.substr( 0, eqNdx );
588 std::string value = pair.substr( eqNdx + 1 );
599 return new std::map<std::string, UTF8>( props );
612 for( std::map<std::string, UTF8>::const_iterator it = aProperties->begin(); it != aProperties->end(); ++it )
614 const std::string&
name = it->first;
616 const UTF8& value = it->second;
628 for( std::string::const_iterator si = value.
begin(); si != value.
end(); ++si )
bool CanSaveToUri(const wxString &aURI) const override
Check if the given URI is writable.
bool UrisAreEquivalent(const wxString &aURI1, const wxString &aURI2) const override
Compare two URIs for equivalence.
std::unique_ptr< LINE_READER > GetReader(const wxString &aURI) const override
Create a reader for the given URI.
std::unique_ptr< OUTPUTFORMATTER > GetWriter(const wxString &aURI) const override
Save the given table to the given URI.
Hold a record identifying a library accessed by the appropriate plug in object in the LIB_TABLE.
void SetFullURI(const wxString &aFullURI)
Change the full URI for the library.
bool visible
Whether the LIB_TABLE_ROW is visible in choosers.
std::unique_ptr< std::map< std::string, UTF8 > > properties
const wxString & GetOptions() const
Return the options string, which may hold a password or anything else needed to instantiate the under...
const wxString & GetDescr() const
Return the description of the library referenced by this row.
wxString uri_user
what user entered from UI or loaded from disk
virtual const wxString GetType() const =0
Return the type of library represented by this row.
void Format(OUTPUTFORMATTER *out, int nestLevel) const
Serialize this object as utf8 text to an OUTPUTFORMATTER, and tries to make it look good using multip...
bool enabled
Whether the LIB_TABLE_ROW is enabled.
void SetParent(LIB_TABLE *aParent)
const wxString & GetNickName() const
const wxString GetFullURI(bool aSubstituted=false) const
Return the full location specifying URI for the LIB, either in original UI form or in environment var...
LIB_TABLE_ROW * clone() const
bool operator==(const LIB_TABLE_ROW &r) const
bool GetIsEnabled() const
void SetOptions(const wxString &aOptions)
Change the library options strings.
void setProperties(std::map< std::string, UTF8 > *aProperties)
bool GetIsVisible() const
Manage LIB_TABLE_ROW records (rows), and can be searched based on library nickname.
bool ReplaceRow(size_t aIndex, LIB_TABLE_ROW *aRow)
Replaces the Nth row with the given new row.
std::shared_mutex m_mutex
Mutex to protect access to the rows vector.
const wxString GetDescription(const wxString &aNickname)
std::vector< wxString > GetLogicalLibs()
Return the logical library names, all of them that are pertinent to a look up done on this LIB_TABLE.
static std::map< std::string, UTF8 > * ParseOptions(const std::string &aOptionsList)
Parses aOptionsList and places the result into a #PROPERTIES object which is returned.
static UTF8 FormatOptions(const std::map< std::string, UTF8 > *aProperties)
Returns a list of options from the aProperties parameter.
std::map< wxString, LIB_TABLE_ROWS_ITER > m_rowsMap
this is a non-owning index into the LIB_TABLE_ROWS table
bool HasLibrary(const wxString &aNickname, bool aCheckEnabled=false) const
Test for the existence of aNickname in the library table.
int m_version
Versioning to handle importing old tables.
bool InsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Adds aRow if it does not already exist or if doReplace is true.
void TransferRows(LIB_TABLE_ROWS &aRowsList)
Takes ownership of another list of rows; the original list will be freed.
LIB_TABLE_ROWS m_rows
Owning set of rows.
bool doInsertRow(LIB_TABLE_ROW *aRow, bool doReplace=false)
Performs the mechanics of inserting a row, but without locking or reindexing.
bool migrate()
Updates the env vars from older version of KiCad, provided they do not currently resolve to anything.
void Load(const wxString &aFileName)
Load the library table using the path defined by aFileName aFallBackTable.
bool HasLibraryWithPath(const wxString &aPath) const
Test for the existence of aPath in the library table.
virtual void Format(OUTPUTFORMATTER *aOutput, int aIndentLevel) const =0
Generate the table in s-expression format to aOutput with an indentation level of aIndentLevel.
bool RemoveRow(const LIB_TABLE_ROW *aRow)
Removes a row from the table and frees the pointer.
LIB_TABLE(LIB_TABLE *aFallBackTable=nullptr, std::unique_ptr< LIB_TABLE_IO > aTableIo=nullptr)
Build a library table by pre-pending this table fragment in front of aFallBackTable.
wxString GetFullURI(const wxString &aLibNickname, bool aExpandEnvVars=true) const
Return the full URI of the library mapped to aLibNickname.
bool IsEmpty(bool aIncludeFallback=true)
Return true if the table is empty.
virtual void Parse(LIB_TABLE_LEXER *aLexer)=0
Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate LIB_TABLE_ROW objec...
std::unique_ptr< LIB_TABLE_IO > m_io
const LIB_TABLE_ROW * FindRowByURI(const wxString &aURI)
bool ChangeRowOrder(size_t aIndex, int aOffset)
Moves a row within the table.
void Save(const wxString &aFileName) const
Write this library table to aFileName in s-expression form.
LIB_TABLE_ROW * findRow(const wxString &aNickname, bool aCheckIfEnabled=false) const
Return a LIB_TABLE_ROW if aNickname is found in this table or in any chained fallBack table fragment,...
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
std::string::const_iterator begin() const
std::string::size_type size() const
std::string::const_iterator end() const
const wxString ExpandEnvVarSubstitutions(const wxString &aString, const PROJECT *aProject)
Replace any environment variable & text variable references with their values.
#define OPT_SEP
options separator character
#define THROW_IO_ERROR(msg)
LIB_TABLE_ROW * new_clone(const LIB_TABLE_ROW &aRow)
Allows boost pointer containers to make clones of the data stored in them.
boost::ptr_vector< LIB_TABLE_ROW > LIB_TABLE_ROWS
LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER
This file contains miscellaneous commonly used macros and functions.
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.