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.

521 lines
17 KiB

  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 (C) 2012-2017 KiCad Developers, see change_log.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/noncopyable.hpp>
  29. #include <boost/ptr_container/ptr_vector.hpp>
  30. #include <memory>
  31. #include <project.h>
  32. #include <properties.h>
  33. #include <richio.h>
  34. #define FP_LATE_ENVVAR 1 ///< late=1/early=0 environment variable expansion
  35. class OUTPUTFORMATTER;
  36. class LIB_TABLE_LEXER;
  37. class LIB_ID;
  38. class LIB_TABLE_ROW;
  39. class LIB_TABLE_GRID;
  40. class IO_ERROR;
  41. typedef boost::ptr_vector< LIB_TABLE_ROW > LIB_TABLE_ROWS;
  42. typedef LIB_TABLE_ROWS::iterator LIB_TABLE_ROWS_ITER;
  43. typedef LIB_TABLE_ROWS::const_iterator LIB_TABLE_ROWS_CITER;
  44. /**
  45. * Allows boost pointer containers to make clones of the data stored in them. Since they
  46. * store pointers the data is cloned. Copying and assigning pointers would cause ownership
  47. * issues if the standard C++ containers were used.
  48. */
  49. LIB_TABLE_ROW* new_clone( const LIB_TABLE_ROW& aRow );
  50. /**
  51. * Hold a record identifying a library accessed by the appropriate plug in object in the
  52. * #LIB_TABLE. This is an abstract base class from which to derive library specific rows.
  53. */
  54. class LIB_TABLE_ROW : boost::noncopyable
  55. {
  56. public:
  57. LIB_TABLE_ROW()
  58. {
  59. }
  60. virtual ~LIB_TABLE_ROW()
  61. {
  62. }
  63. LIB_TABLE_ROW( const wxString& aNick, const wxString& aURI, const wxString& aOptions,
  64. const wxString& aDescr = wxEmptyString ) :
  65. nickName( aNick ),
  66. description( aDescr ),
  67. enabled( true )
  68. {
  69. properties.reset();
  70. SetOptions( aOptions );
  71. SetFullURI( aURI );
  72. }
  73. bool operator==( const LIB_TABLE_ROW& r ) const;
  74. bool operator!=( const LIB_TABLE_ROW& r ) const { return !( *this == r ); }
  75. /**
  76. * @return the logical name of this library table row.
  77. */
  78. const wxString& GetNickName() const { return nickName; }
  79. /**
  80. * Change the logical name of this library, useful for an editor.
  81. */
  82. void SetNickName( const wxString& aNickName ) { nickName = aNickName; }
  83. /**
  84. * @return the enabled status of this library row
  85. */
  86. bool GetIsEnabled() const { return enabled; }
  87. /**
  88. * Change the enabled status of this library
  89. */
  90. void SetEnabled( bool aEnabled = true ) { enabled = aEnabled; }
  91. /**
  92. * Return the type of library represented by this row.
  93. */
  94. virtual const wxString GetType() const = 0;
  95. /**
  96. * Change the type of library represented by this row that must be implemented in the
  97. * derived object to provide the library table row type.
  98. */
  99. virtual void SetType( const wxString& aType ) = 0;
  100. /**
  101. * Return the full location specifying URI for the LIB, either in original UI form or
  102. * in environment variable expanded form.
  103. *
  104. * @param aSubstituted Tells if caller wanted the substituted form, else not.
  105. */
  106. const wxString GetFullURI( bool aSubstituted = false ) const;
  107. /**
  108. * Change the full URI for the library.
  109. */
  110. void SetFullURI( const wxString& aFullURI );
  111. /**
  112. * Return the options string, which may hold a password or anything else needed to
  113. * instantiate the underlying library plugin.
  114. */
  115. const wxString& GetOptions() const { return options; }
  116. /**
  117. * Change the library options strings.
  118. */
  119. void SetOptions( const wxString& aOptions );
  120. /**
  121. * Return the description of the library referenced by this row.
  122. */
  123. const wxString& GetDescr() const { return description; }
  124. /**
  125. * Change the description of the library referenced by this row.
  126. */
  127. void SetDescr( const wxString& aDescr ) { description = aDescr; }
  128. /**
  129. * Return the constant #PROPERTIES for this library (#LIB_TABLE_ROW). These are
  130. * the "options" in a table.
  131. */
  132. const PROPERTIES* GetProperties() const { return properties.get(); }
  133. /**
  134. * Serialize this object as utf8 text to an #OUTPUTFORMATTER, and tries to
  135. * make it look good using multiple lines and indentation.
  136. *
  137. * @param out is an #OUTPUTFORMATTER
  138. * @param nestLevel is the indentation level to base all lines of the output.
  139. * Actual indentation will be 2 spaces for each nestLevel.
  140. */
  141. void Format( OUTPUTFORMATTER* out, int nestLevel ) const;
  142. LIB_TABLE_ROW* clone() const
  143. {
  144. return do_clone();
  145. }
  146. protected:
  147. LIB_TABLE_ROW( const LIB_TABLE_ROW& aRow ) :
  148. nickName( aRow.nickName ),
  149. uri_user( aRow.uri_user ),
  150. #if !FP_LATE_ENVVAR
  151. uri_expanded( aRow.uri_expanded ),
  152. #endif
  153. options( aRow.options ),
  154. description( aRow.description ),
  155. enabled( aRow.enabled )
  156. {
  157. if( aRow.properties )
  158. properties = std::make_unique<PROPERTIES>( *aRow.properties.get() );
  159. else
  160. properties.reset();
  161. }
  162. void operator=( const LIB_TABLE_ROW& aRow );
  163. private:
  164. virtual LIB_TABLE_ROW* do_clone() const = 0;
  165. void setProperties( PROPERTIES* aProperties );
  166. wxString nickName;
  167. wxString uri_user; ///< what user entered from UI or loaded from disk
  168. #if !FP_LATE_ENVVAR
  169. wxString uri_expanded; ///< from ExpandSubstitutions()
  170. #endif
  171. wxString options;
  172. wxString description;
  173. bool enabled = true; ///< Whether the LIB_TABLE_ROW is enabled
  174. std::unique_ptr< PROPERTIES > properties;
  175. };
  176. /**
  177. * Manage #LIB_TABLE_ROW records (rows), and can be searched based on library nickname.
  178. *
  179. * <p>
  180. * This class owns the <b>library table</b>, which is like fstab in concept and maps
  181. * logical library name to the library URI, type, and options. It is heavily based on
  182. * the SWEET parser work done by Dick Hollenbeck and can be seen in new/sch_lib_table.h.
  183. * A library table has the following columns:
  184. * <ul>
  185. * <li> Logical Library Name (Nickname)
  186. * <li> Library Type, used to determine which plugin to load to access the library.
  187. * <li> Library URI. The full URI to the library source, form dependent on Type.
  188. * <li> Options, used for as yet to be defined information such as user names or passwords
  189. * </ul>
  190. * </p>
  191. * <p>
  192. * The Library Type can be one of:
  193. * <ul>
  194. * <li> "file"
  195. * <li> "ftp"
  196. * <li> "http"
  197. * </ul>
  198. * </p>
  199. * <p>
  200. * For now, the Library URI types needed to support the various types can be one of those
  201. * shown below, which are typical of each type:
  202. * <ul>
  203. * <li> "file://C:/mylibdir"
  204. * <li> "ftp://kicad.org/partlib/trunk"
  205. * <li> "http://kicad.org/partlib"
  206. * </ul>
  207. * </p>
  208. * <p>
  209. * The library table is built up from several additive entries (table fragments), and the
  210. * final table is a (conceptual) merging of the table fragments. Two anticipated sources
  211. * of the entries are a personal table saved in the KiCad configuration and a project
  212. * resident table that resides in project file. The project footprint table entries are
  213. * considered a higher priority in the final dynamically assembled library table. An row
  214. * in the project file contribution to the library table takes precedence over the personal
  215. * table if there is a collision of logical library names. Otherwise, the entries simply
  216. * combine without issue to make up the applicable library table.
  217. * </p>
  218. *
  219. * @author Wayne Stambaugh
  220. */
  221. class LIB_TABLE : public PROJECT::_ELEM
  222. {
  223. friend class PANEL_FP_LIB_TABLE;
  224. friend class LIB_TABLE_GRID;
  225. public:
  226. /**
  227. * Parse the #LIB_TABLE_LEXER s-expression library table format into the appropriate
  228. * #LIB_TABLE_ROW objects.
  229. *
  230. * @param aLexer is the lexer to parse.
  231. *
  232. * @throw IO_ERROR if an I/O error occurs during parsing.
  233. * @throw PARSER_ERROR if the lexer format to parse is invalid.
  234. * @throw boost::bad_pointer if an any attempt to add an invalid pointer to the
  235. * boost::ptr_vector.
  236. * @throw boost::bad_index if an index outside the row table bounds is accessed.
  237. */
  238. virtual void Parse( LIB_TABLE_LEXER* aLexer ) = 0;
  239. /**
  240. * Generate the table in s-expression format to \a aOutput with an indention level
  241. * of \a aIndentLevel.
  242. *
  243. * @param aOutput is the #OUTPUTFORMATTER to format the table into.
  244. * @param aIndentLevel is the indentation level (2 spaces) to indent.
  245. *
  246. * @throw IO_ERROR if an I/O error occurs during output.
  247. * @throw boost::interprocess::lock_except if separate process attempt to access the table.
  248. */
  249. virtual void Format( OUTPUTFORMATTER* aOutput, int aIndentLevel ) const = 0;
  250. /**
  251. * Build a library table by pre-pending this table fragment in front of \a aFallBackTable.
  252. * Loading of this table fragment is done by using Parse().
  253. *
  254. * @param aFallBackTable is another LIB_TABLE which is searched only when
  255. * a row is not found in this table. No ownership is
  256. * taken of aFallBackTable.
  257. */
  258. LIB_TABLE( LIB_TABLE* aFallBackTable = nullptr );
  259. virtual ~LIB_TABLE();
  260. /// Delete all rows.
  261. void Clear()
  262. {
  263. rows.clear();
  264. nickIndex.clear();
  265. }
  266. /**
  267. * Compares this table against another.
  268. *
  269. * This compares the row *contents* against each other.
  270. * Any fallback tables are not checked.
  271. */
  272. bool operator==( const LIB_TABLE& r ) const
  273. {
  274. if( rows.size() == r.rows.size() )
  275. {
  276. unsigned i;
  277. for( i = 0; i < rows.size() && rows[i] == r.rows[i]; ++i )
  278. ;
  279. if( i == rows.size() )
  280. return true;
  281. }
  282. return false;
  283. }
  284. bool operator!=( const LIB_TABLE& r ) const { return !( *this == r ); }
  285. /**
  286. * Get the number of rows contained in the table
  287. */
  288. unsigned GetCount() const
  289. {
  290. return rows.size();
  291. }
  292. /**
  293. * Get the 'n'th #LIB_TABLE_ROW object
  294. * @param aIndex index of row (must exist: from 0 to GetCount() - 1)
  295. * @return reference to the row
  296. */
  297. LIB_TABLE_ROW& At( unsigned aIndex )
  298. {
  299. return rows[aIndex];
  300. }
  301. /**
  302. * @copydoc At()
  303. */
  304. const LIB_TABLE_ROW& At( unsigned aIndex ) const
  305. {
  306. return rows[aIndex];
  307. }
  308. /**
  309. * Return true if the table is empty.
  310. *
  311. * @param aIncludeFallback is used to determine if the fallback table should be
  312. * included in the test.
  313. *
  314. * @return true if the footprint library table is empty.
  315. */
  316. bool IsEmpty( bool aIncludeFallback = true );
  317. /**
  318. * @return the library description from @a aNickname, or an empty string
  319. * if @a aNickname does not exist.
  320. */
  321. const wxString GetDescription( const wxString& aNickname );
  322. /**
  323. * Test for the existence of \a aNickname in the library table.
  324. *
  325. * @param aCheckEnabled if true will only return true for enabled libraries
  326. * @return true if a library \a aNickname exists in the table.
  327. */
  328. bool HasLibrary( const wxString& aNickname, bool aCheckEnabled = false ) const;
  329. /**
  330. * Return the logical library names, all of them that are pertinent to
  331. * a look up done on this LIB_TABLE.
  332. */
  333. std::vector<wxString> GetLogicalLibs();
  334. /**
  335. * Return the full URI of the library mapped to \a aLibNickname.
  336. */
  337. wxString GetFullURI( const wxString& aLibNickname, bool aExpandEnvVars = true ) const;
  338. /**
  339. * Adds \a aRow if it does not already exist or if doReplace is true. If doReplace
  340. * is not true and the key for aRow already exists, the function fails and returns false.
  341. *
  342. * The key for the table is the nickName, and all in this table must be unique.
  343. *
  344. * @param aRow is the new row to insert, or to forcibly add if doReplace is true.
  345. * @param doReplace if true, means insert regardless of whether aRow's key already
  346. * exists. If false, then fail if the key already exists.
  347. *
  348. * @return bool - true if the operation succeeded.
  349. */
  350. bool InsertRow( LIB_TABLE_ROW* aRow, bool doReplace = false );
  351. /**
  352. * Removes a row from the table.
  353. * @param aRow is the row to remove
  354. * @return true if the row was found (and removed)
  355. */
  356. bool RemoveRow( LIB_TABLE_ROW* aRow )
  357. {
  358. for( auto iter = rows.begin(); iter != rows.end(); ++iter )
  359. {
  360. if( *iter == *aRow )
  361. {
  362. rows.erase( iter, iter + 1 );
  363. return true;
  364. }
  365. }
  366. return false;
  367. }
  368. /**
  369. * @return a #LIB_TABLE_ROW pointer if \a aURI is found in this table or in any chained
  370. * fallBack table fragments, else NULL.
  371. */
  372. const LIB_TABLE_ROW* FindRowByURI( const wxString& aURI );
  373. /**
  374. * Load the library table using the path defined by \a aFileName aFallBackTable.
  375. *
  376. * @param aFileName contains the full path to the s-expression file.
  377. *
  378. * @throw IO_ERROR if an error occurs attempting to load the footprint library
  379. * table.
  380. */
  381. void Load( const wxString& aFileName );
  382. /**
  383. * Write this library table to \a aFileName in s-expression form.
  384. *
  385. * @param aFileName is the name of the file to write to.
  386. */
  387. void Save( const wxString& aFileName ) const;
  388. /**
  389. * Parses \a aOptionsList and places the result into a #PROPERTIES object which is
  390. * returned. If the options field is empty, then the returned PROPERTIES will be
  391. * a NULL pointer.
  392. *
  393. * <p>
  394. * Typically aOptionsList comes from the "options" field within a LIB_TABLE_ROW and
  395. * the format is simply a comma separated list of name value pairs. e.g.:
  396. * [name1[=value1][|name2[=value2]]] etc. When using the UI to create or edit
  397. * a library table, this formatting is handled for you.
  398. * </p>
  399. */
  400. static PROPERTIES* ParseOptions( const std::string& aOptionsList );
  401. /**
  402. * Returns a list of options from the aProperties parameter.
  403. *
  404. * The name=value pairs will be separated with the '|' character. The =value portion may
  405. * not be present. You might expect something like "name1=value1|name2=value2|flag_me".
  406. * Notice that flag_me does not have a value. This is ok.
  407. *
  408. * @param aProperties is the PROPERTIES to format or NULL. If NULL the returned
  409. * string will be empty.
  410. */
  411. static UTF8 FormatOptions( const PROPERTIES* aProperties );
  412. protected:
  413. /**
  414. * Return a #LIB_TABLE_ROW if \a aNickname is found in this table or in any chained
  415. * fallBack table fragment, else NULL.
  416. */
  417. LIB_TABLE_ROW* findRow( const wxString& aNickname ) const;
  418. LIB_TABLE_ROW* findRow( const wxString& aNickname );
  419. void reindex()
  420. {
  421. nickIndex.clear();
  422. for( LIB_TABLE_ROWS_ITER it = rows.begin(); it != rows.end(); ++it )
  423. nickIndex.insert( INDEX_VALUE( it->GetNickName(), it - rows.begin() ) );
  424. }
  425. void ensureIndex()
  426. {
  427. // The dialog lib table editor may not maintain the nickIndex.
  428. // Lazy indexing may be required. To handle lazy indexing, we must enforce
  429. // that "nickIndex" is either empty or accurate, but never inaccurate.
  430. if( !nickIndex.size() )
  431. reindex();
  432. }
  433. LIB_TABLE_ROWS rows;
  434. /// this is a non-owning index into the LIB_TABLE_ROWS table
  435. typedef std::map<wxString,int> INDEX; // "int" is std::vector array index
  436. typedef INDEX::iterator INDEX_ITER;
  437. typedef INDEX::const_iterator INDEX_CITER;
  438. typedef INDEX::value_type INDEX_VALUE;
  439. /// this particular key is the nickName within each row.
  440. INDEX nickIndex;
  441. LIB_TABLE* fallBack;
  442. };
  443. #endif // _LIB_TABLE_BASE_H_