You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

646 lines
21 KiB

10 months ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2010-2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2012 Wayne Stambaugh <stambaughw@gmail.com>
  6. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #ifndef _LIB_TABLE_BASE_H_
  26. #define _LIB_TABLE_BASE_H_
  27. #include <map>
  28. #include <boost/ptr_container/ptr_vector.hpp>
  29. #include <memory>
  30. #include <mutex>
  31. #include <shared_mutex>
  32. #include <project.h>
  33. #include <richio.h>
  34. #include <kicommon.h>
  35. class OUTPUTFORMATTER;
  36. class LIB_TABLE_LEXER;
  37. class LIB_ID;
  38. class LIB_TABLE_ROW;
  39. class LIB_TABLE_GRID;
  40. class LIB_TABLE;
  41. class IO_ERROR;
  42. class wxWindow;
  43. typedef boost::ptr_vector< LIB_TABLE_ROW > LIB_TABLE_ROWS;
  44. typedef LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER;
  45. typedef LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER;
  46. /**
  47. * Allows boost pointer containers to make clones of the data stored in them. Since they
  48. * store pointers the data is cloned. Copying and assigning pointers would cause ownership
  49. * issues if the standard C++ containers were used.
  50. */
  51. KICOMMON_API LIB_TABLE_ROW* new_clone( const LIB_TABLE_ROW& aRow );
  52. /**
  53. * LIB_TABLE_IO abstracts the file I/O operations for the library table
  54. * loading and saving.
  55. *
  56. * Normally, this is file-based-reading, but that's not a requirement.
  57. */
  58. class KICOMMON_API LIB_TABLE_IO
  59. {
  60. public:
  61. virtual ~LIB_TABLE_IO() = default;
  62. /**
  63. * Create a reader for the given URI.
  64. *
  65. * This can return nullptr, for example if the URI is not a file or
  66. * is not readable.
  67. */
  68. virtual std::unique_ptr<LINE_READER> GetReader( const wxString& aURI ) const = 0;
  69. /**
  70. * Check if the given URI is writable.
  71. */
  72. virtual bool CanSaveToUri( const wxString& aURI ) const = 0;
  73. /**
  74. * Compare two URIs for equivalence.
  75. *
  76. * For example, two URIs that point to the same file should be considered equivalent,
  77. * even if they are not string-wise equal (e.g. symlinks)
  78. */
  79. virtual bool UrisAreEquivalent( const wxString& aURI1, const wxString& aURI2 ) const = 0;
  80. /**
  81. * Save the given table to the given URI.
  82. */
  83. virtual std::unique_ptr<OUTPUTFORMATTER> GetWriter( const wxString& aURI ) const = 0;
  84. };
  85. /**
  86. * Implementations of LIB_TABLE_IO for file-based I/O.
  87. *
  88. * This is the default implementation for real usage.
  89. */
  90. class KICOMMON_API FILE_LIB_TABLE_IO : public LIB_TABLE_IO
  91. {
  92. public:
  93. FILE_LIB_TABLE_IO() = default;
  94. std::unique_ptr<LINE_READER> GetReader( const wxString& aURI ) const override;
  95. bool CanSaveToUri( const wxString& aURI ) const override;
  96. bool UrisAreEquivalent( const wxString& aURI1, const wxString& aURI2 ) const override;
  97. std::unique_ptr<OUTPUTFORMATTER> GetWriter( const wxString& aURI ) const override;
  98. };
  99. /**
  100. * Hold a record identifying a library accessed by the appropriate plug in object in the
  101. * #LIB_TABLE. This is an abstract base class from which to derive library specific rows.
  102. */
  103. class KICOMMON_API LIB_TABLE_ROW
  104. {
  105. public:
  106. LIB_TABLE_ROW() :
  107. enabled( true ),
  108. visible( true ),
  109. m_loaded( false ),
  110. m_parent( nullptr )
  111. {
  112. }
  113. virtual ~LIB_TABLE_ROW()
  114. {
  115. }
  116. LIB_TABLE_ROW( const wxString& aNick, const wxString& aURI, const wxString& aOptions,
  117. const wxString& aDescr = wxEmptyString, LIB_TABLE* aParent = nullptr ) :
  118. nickName( aNick ),
  119. description( aDescr ),
  120. enabled( true ),
  121. visible( true ),
  122. m_loaded( false ),
  123. m_parent( aParent )
  124. {
  125. properties.reset();
  126. SetOptions( aOptions );
  127. SetFullURI( aURI );
  128. }
  129. bool operator==( const LIB_TABLE_ROW& r ) const;
  130. bool operator!=( const LIB_TABLE_ROW& r ) const { return !( *this == r ); }
  131. /**
  132. * @return the logical name of this library table row.
  133. */
  134. const wxString& GetNickName() const { return nickName; }
  135. /**
  136. * Change the logical name of this library, useful for an editor.
  137. */
  138. void SetNickName( const wxString& aNickName ) { nickName = aNickName; }
  139. /**
  140. * @return true if the library was loaded without error
  141. */
  142. bool GetIsLoaded() const { return m_loaded; }
  143. /**
  144. * Mark the row as being a loaded library
  145. */
  146. void SetLoaded( bool aLoaded ) { m_loaded = aLoaded; };
  147. /**
  148. * @return the enabled status of this library row
  149. */
  150. bool GetIsEnabled() const { return enabled; }
  151. /**
  152. * Change the enabled status of this library
  153. */
  154. void SetEnabled( bool aEnabled = true ) { enabled = aEnabled; }
  155. bool GetIsVisible() const { return visible; }
  156. void SetVisible( bool aVisible = true ) { visible = aVisible; }
  157. virtual bool Refresh() { return false; }
  158. /**
  159. * Return the type of library represented by this row.
  160. */
  161. virtual const wxString GetType() const = 0;
  162. /**
  163. * Change the type of library represented by this row that must be implemented in the
  164. * derived object to provide the library table row type.
  165. */
  166. virtual void SetType( const wxString& aType ) = 0;
  167. virtual bool SupportsSettingsDialog() const { return false; }
  168. virtual void ShowSettingsDialog( wxWindow* aParent ) const {}
  169. /**
  170. * Return the full location specifying URI for the LIB, either in original UI form or
  171. * in environment variable expanded form.
  172. *
  173. * @param aSubstituted Tells if caller wanted the substituted form, else not.
  174. */
  175. const wxString GetFullURI( bool aSubstituted = false ) const;
  176. /**
  177. * Change the full URI for the library.
  178. */
  179. void SetFullURI( const wxString& aFullURI );
  180. /**
  181. * Return the options string, which may hold a password or anything else needed to
  182. * instantiate the underlying library plugin.
  183. */
  184. const wxString& GetOptions() const { return options; }
  185. /**
  186. * Change the library options strings.
  187. */
  188. void SetOptions( const wxString& aOptions );
  189. /**
  190. * Return the description of the library referenced by this row.
  191. */
  192. const wxString& GetDescr() const { return description; }
  193. /**
  194. * Change the description of the library referenced by this row.
  195. */
  196. void SetDescr( const wxString& aDescr ) { description = aDescr; }
  197. LIB_TABLE* GetParent() const { return m_parent; }
  198. void SetParent( LIB_TABLE* aParent ) { m_parent = aParent; }
  199. std::mutex& GetMutex() { return m_loadMutex; }
  200. /**
  201. * Return the constant #PROPERTIES for this library (#LIB_TABLE_ROW). These are
  202. * the "options" in a table.
  203. */
  204. const std::map<std::string, UTF8>* GetProperties() const { return properties.get(); }
  205. /**
  206. * Serialize this object as utf8 text to an #OUTPUTFORMATTER, and tries to
  207. * make it look good using multiple lines and indentation.
  208. *
  209. * @param out is an #OUTPUTFORMATTER
  210. * @param nestLevel is the indentation level to base all lines of the output.
  211. * Actual indentation will be 2 spaces for each nestLevel.
  212. */
  213. void Format( OUTPUTFORMATTER* out, int nestLevel ) const;
  214. LIB_TABLE_ROW* clone() const
  215. {
  216. return do_clone();
  217. }
  218. protected:
  219. LIB_TABLE_ROW( const LIB_TABLE_ROW& aRow ) :
  220. nickName( aRow.nickName ),
  221. uri_user( aRow.uri_user ),
  222. options( aRow.options ),
  223. description( aRow.description ),
  224. enabled( aRow.enabled ),
  225. visible( aRow.visible ),
  226. m_loaded( aRow.m_loaded ),
  227. m_parent( aRow.m_parent )
  228. {
  229. if( aRow.properties )
  230. properties = std::make_unique<std::map<std::string, UTF8>>( *aRow.properties.get() );
  231. else
  232. properties.reset();
  233. }
  234. void operator=( const LIB_TABLE_ROW& aRow );
  235. private:
  236. virtual LIB_TABLE_ROW* do_clone() const = 0;
  237. void setProperties( std::map<std::string, UTF8>* aProperties );
  238. private:
  239. wxString nickName;
  240. wxString uri_user; ///< what user entered from UI or loaded from disk
  241. wxString options;
  242. wxString description;
  243. bool enabled = true; ///< Whether the LIB_TABLE_ROW is enabled
  244. bool visible = true; ///< Whether the LIB_TABLE_ROW is visible in choosers
  245. bool m_loaded = false; ///< Whether the LIB_TABLE_ROW is loaded
  246. LIB_TABLE* m_parent; ///< Pointer to the table this row lives in (maybe null)
  247. std::unique_ptr<std::map<std::string, UTF8>> properties;
  248. std::mutex m_loadMutex;
  249. };
  250. /**
  251. * Manage #LIB_TABLE_ROW records (rows), and can be searched based on library nickname.
  252. *
  253. * <p>
  254. * This class owns the <b>library table</b>, which is like fstab in concept and maps
  255. * logical library name to the library URI, type, and options. It is heavily based on
  256. * the SWEET parser work done by Dick Hollenbeck and can be seen in new/sch_lib_table.h.
  257. * A library table has the following columns:
  258. * <ul>
  259. * <li> Logical Library Name (Nickname)
  260. * <li> Library Type, used to determine which plugin to load to access the library.
  261. * <li> Library URI. The full URI to the library source, form dependent on Type.
  262. * <li> Options, used for as yet to be defined information such as user names or passwords
  263. * </ul>
  264. * </p>
  265. * <p>
  266. * The Library Type can be one of:
  267. * <ul>
  268. * <li> "file"
  269. * <li> "ftp"
  270. * <li> "http"
  271. * </ul>
  272. * </p>
  273. * <p>
  274. * For now, the Library URI types needed to support the various types can be one of those
  275. * shown below, which are typical of each type:
  276. * <ul>
  277. * <li> "file://C:/mylibdir"
  278. * <li> "ftp://kicad.org/partlib/trunk"
  279. * <li> "http://kicad.org/partlib"
  280. * </ul>
  281. * </p>
  282. * <p>
  283. * The library table is built up from several additive entries (table fragments), and the
  284. * final table is a (conceptual) merging of the table fragments. Two anticipated sources
  285. * of the entries are a personal table saved in the KiCad configuration and a project
  286. * resident table that resides in project file. The project footprint table entries are
  287. * considered a higher priority in the final dynamically assembled library table. An row
  288. * in the project file contribution to the library table takes precedence over the personal
  289. * table if there is a collision of logical library names. Otherwise, the entries simply
  290. * combine without issue to make up the applicable library table.
  291. * </p>
  292. *
  293. * @author Wayne Stambaugh
  294. */
  295. class KICOMMON_API LIB_TABLE : public PROJECT::_ELEM
  296. {
  297. public:
  298. /**
  299. * Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate
  300. * #LIB_TABLE_ROW objects.
  301. *
  302. * @param aLexer is the lexer to parse.
  303. *
  304. * @throw IO_ERROR if an I/O error occurs during parsing.
  305. * @throw PARSER_ERROR if the lexer format to parse is invalid.
  306. * @throw boost::bad_pointer if an any attempt to add an invalid pointer to the
  307. * boost::ptr_vector.
  308. * @throw boost::bad_index if an index outside the row table bounds is accessed.
  309. */
  310. virtual void Parse( LIB_TABLE_LEXER* aLexer ) = 0;
  311. /**
  312. * Generate the table in s-expression format to \a aOutput with an indentation level
  313. * of \a aIndentLevel.
  314. *
  315. * @param aOutput is the #OUTPUTFORMATTER to format the table into.
  316. * @param aIndentLevel is the indentation level (2 spaces) to indent.
  317. *
  318. * @throw IO_ERROR if an I/O error occurs during output.
  319. * @throw boost::interprocess::lock_except if separate process attempt to access the table.
  320. */
  321. virtual void Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const = 0;
  322. /**
  323. * Build a library table by pre-pending this table fragment in front of \a aFallBackTable.
  324. * Loading of this table fragment is done by using Parse().
  325. *
  326. * @param aFallBackTable is another LIB_TABLE which is searched only when
  327. * a row is not found in this table. No ownership is
  328. * taken of aFallBackTable.
  329. * @param aTableIo is the I/O object to use for the table data. nullptr
  330. * means use the default file-based I/O.
  331. */
  332. LIB_TABLE( LIB_TABLE* aFallBackTable = nullptr,
  333. std::unique_ptr<LIB_TABLE_IO> aTableIo = nullptr );
  334. virtual ~LIB_TABLE();
  335. /**
  336. * Compares this table against another.
  337. *
  338. * This compares the row *contents* against each other.
  339. * Any fallback tables are not checked.
  340. */
  341. bool operator==( const LIB_TABLE& r ) const
  342. {
  343. if( m_rows.size() == r.m_rows.size() )
  344. {
  345. unsigned i;
  346. for( i = 0; i < m_rows.size() && m_rows[i] == r.m_rows[i]; ++i )
  347. ;
  348. if( i == m_rows.size() )
  349. return true;
  350. }
  351. return false;
  352. }
  353. bool operator!=( const LIB_TABLE& r ) const { return !( *this == r ); }
  354. /**
  355. * Get the number of rows contained in the table
  356. */
  357. unsigned GetCount() const
  358. {
  359. return m_rows.size();
  360. }
  361. /**
  362. * Get the 'n'th #LIB_TABLE_ROW object
  363. * @param aIndex index of row (must exist: from 0 to GetCount() - 1)
  364. * @return reference to the row
  365. */
  366. LIB_TABLE_ROW& At( unsigned aIndex )
  367. {
  368. return m_rows[aIndex];
  369. }
  370. /**
  371. * @copydoc At()
  372. */
  373. const LIB_TABLE_ROW& At( unsigned aIndex ) const
  374. {
  375. return m_rows[aIndex];
  376. }
  377. /**
  378. * Return true if the table is empty.
  379. *
  380. * @param aIncludeFallback is used to determine if the fallback table should be
  381. * included in the test.
  382. *
  383. * @return true if the footprint library table is empty.
  384. */
  385. bool IsEmpty( bool aIncludeFallback = true );
  386. /**
  387. * @return the library description from @a aNickname, or an empty string
  388. * if @a aNickname does not exist.
  389. */
  390. const wxString GetDescription( const wxString& aNickname );
  391. /**
  392. * Test for the existence of \a aNickname in the library table.
  393. *
  394. * @param aCheckEnabled if true will only return true for enabled libraries
  395. * @return true if a library \a aNickname exists in the table.
  396. */
  397. bool HasLibrary( const wxString& aNickname, bool aCheckEnabled = false ) const;
  398. /**
  399. * Test for the existence of \a aPath in the library table.
  400. *
  401. * @param aCheckEnabled if true will only return true for enabled libraries
  402. * @return true if a library \a aNickname exists in the table.
  403. */
  404. bool HasLibraryWithPath( const wxString& aPath ) const;
  405. /**
  406. * Return the logical library names, all of them that are pertinent to
  407. * a look up done on this LIB_TABLE.
  408. */
  409. std::vector<wxString> GetLogicalLibs();
  410. /**
  411. * Return the full URI of the library mapped to \a aLibNickname.
  412. */
  413. wxString GetFullURI( const wxString& aLibNickname, bool aExpandEnvVars = true ) const;
  414. /**
  415. * Adds \a aRow if it does not already exist or if doReplace is true. If doReplace
  416. * is not true and the key for aRow already exists, the function fails and returns false.
  417. *
  418. * The key for the table is the nickName, and all in this table must be unique.
  419. *
  420. * @param aRow is the new row to insert, or to forcibly add if doReplace is true.
  421. * @param doReplace if true, means insert regardless of whether aRow's key already
  422. * exists. If false, then fail if the key already exists.
  423. *
  424. * @return bool - true if the operation succeeded.
  425. */
  426. bool InsertRow( LIB_TABLE_ROW* aRow, bool doReplace = false );
  427. /**
  428. * Removes a row from the table and frees the pointer
  429. * @param aRow is the row to remove
  430. * @return true if the row was found (and removed)
  431. */
  432. bool RemoveRow( const LIB_TABLE_ROW* aRow );
  433. /**
  434. * Replaces the Nth row with the given new row
  435. * @return true if successful
  436. */
  437. bool ReplaceRow( size_t aIndex, LIB_TABLE_ROW* aRow );
  438. /**
  439. * Moves a row within the table
  440. * @param aIndex is the current index of the row to move
  441. * @param aOffset is the number of positions to move it by in the table
  442. * @return true if the move resulted in a change
  443. */
  444. bool ChangeRowOrder( size_t aIndex, int aOffset );
  445. /**
  446. * Takes ownership of another list of rows; the original list will be freed
  447. */
  448. void TransferRows( LIB_TABLE_ROWS& aRowsList );
  449. /**
  450. * @return a #LIB_TABLE_ROW pointer if \a aURI is found in this table or in any chained
  451. * fallBack table fragments, else NULL.
  452. */
  453. const LIB_TABLE_ROW* FindRowByURI( const wxString& aURI );
  454. /**
  455. * Load the library table using the path defined by \a aFileName aFallBackTable.
  456. *
  457. * @param aFileName contains the full path to the s-expression file.
  458. *
  459. * @throw IO_ERROR if an error occurs attempting to load the footprint library
  460. * table.
  461. */
  462. void Load( const wxString& aFileName );
  463. /**
  464. * Write this library table to \a aFileName in s-expression form.
  465. *
  466. * @param aFileName is the name of the file to write to.
  467. */
  468. void Save( const wxString& aFileName ) const;
  469. /**
  470. * Parses \a aOptionsList and places the result into a #PROPERTIES object which is
  471. * returned. If the options field is empty, then the returned PROPERTIES will be
  472. * a NULL pointer.
  473. *
  474. * <p>
  475. * Typically aOptionsList comes from the "options" field within a LIB_TABLE_ROW and
  476. * the format is simply a comma separated list of name value pairs. e.g.:
  477. * [name1[=value1][|name2[=value2]]] etc. When using the UI to create or edit
  478. * a library table, this formatting is handled for you.
  479. * </p>
  480. */
  481. static std::map<std::string, UTF8>* ParseOptions( const std::string& aOptionsList );
  482. /**
  483. * Returns a list of options from the aProperties parameter.
  484. *
  485. * The name=value pairs will be separated with the '|' character. The =value portion may
  486. * not be present. You might expect something like "name1=value1|name2=value2|flag_me".
  487. * Notice that flag_me does not have a value. This is ok.
  488. *
  489. * @param aProperties is the PROPERTIES to format or NULL. If NULL the returned
  490. * string will be empty.
  491. */
  492. static UTF8 FormatOptions( const std::map<std::string, UTF8>* aProperties );
  493. /**
  494. * Returns the version number (0 if unset)
  495. *
  496. * @return integer version number read from table
  497. */
  498. int GetVersion() const
  499. {
  500. return m_version;
  501. }
  502. protected:
  503. /*
  504. * Do not make this public. It MUST be called with a lock already in place.
  505. */
  506. void clear();
  507. /**
  508. * Return a #LIB_TABLE_ROW if \a aNickname is found in this table or in any chained
  509. * fallBack table fragment, else NULL.
  510. *
  511. * @param aNickname is the name of the library table entry to find.
  512. * @param aCheckIfEnabled is a flag to check if the library table entry is enabled.
  513. * @return a pointer to the #LIB_TABLE_ROW found.
  514. */
  515. LIB_TABLE_ROW* findRow( const wxString& aNickname, bool aCheckIfEnabled = false ) const;
  516. /**
  517. * Performs the mechanics of inserting a row, but without locking or reindexing.
  518. */
  519. bool doInsertRow( LIB_TABLE_ROW* aRow, bool doReplace = false );
  520. /**
  521. * Updates the env vars from older version of KiCad, provided they do not currently
  522. * resolve to anything
  523. *
  524. * @return True if the tables were modified
  525. */
  526. bool migrate();
  527. /*
  528. * Do not make this public. It MUST be called with a lock already in place.
  529. */
  530. void reindex();
  531. protected:
  532. // Injected I/O interface
  533. std::unique_ptr<LIB_TABLE_IO> m_io;
  534. LIB_TABLE* m_fallBack;
  535. /// Versioning to handle importing old tables
  536. mutable int m_version;
  537. /// Owning set of rows.
  538. // TODO: This should really be private; but the lib table grids re-use it
  539. // (without using m_rowsMap).
  540. LIB_TABLE_ROWS m_rows;
  541. /// this is a non-owning index into the LIB_TABLE_ROWS table
  542. std::map<wxString, LIB_TABLE_ROWS_ITER> m_rowsMap;
  543. /// Mutex to protect access to the rows vector
  544. mutable std::shared_mutex m_mutex;
  545. };
  546. #endif // _LIB_TABLE_BASE_H_