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) 2010-2020 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 26 #ifndef _LIB_ID_H_ 27 #define _LIB_ID_H_ 28 29 #include <richio.h> 30 #include <utf8.h> 31 32 /** 33 * A logical library item identifier and consists of various portions much like a URI. 34 * 35 * It consists of of triad of the library nickname, the name of the item in the library, 36 * and an optional revision of the item. This is a generic library identifier that can be 37 * used for any type of library that contains multiple named items such as footprint or 38 * symbol libraries. 39 * 40 * Example LIB_ID string: 41 * "smt:R_0805/rev0". 42 * 43 * - "smt" is the logical library name used to look up library information saved in the #LIB_TABLE. 44 * - "R" is the name of the item within the library. 45 * - "rev0" is the revision, which is optional. If missing then its delimiter should also not 46 * be present. A revision must begin with "rev" and be followed by at least one or more 47 * decimal digits. 48 * 49 * @author Dick Hollenbeck 50 */ 51 class LIB_ID 52 { 53 public: LIB_ID()54 LIB_ID() {} 55 56 // NOTE: don't define any constructors which call Parse() on their arguments. We want it 57 // to be obvious to callers that parsing is involved (and that valid IDs are guaranteed in 58 // the presence of disallowed characters, malformed ids, etc.). 59 60 /** 61 * This LIB_ID ctor is a special version which ignores the parsing due to symbol 62 * names allowing '/' as a valid character. This was causing the symbol names to 63 * be truncated at the first occurrence of '/' in the symbol name. 64 * 65 * @param aLibraryName is the library name used to look up the library item in the #LIB_TABLE. 66 * @param aItemName is the name of the library item which is not parsed by the standard 67 * LIB_ID::Parse() function. 68 */ 69 LIB_ID( const wxString& aLibraryName, const wxString& aItemName ); 70 71 /** 72 * Parse LIB_ID with the information from @a aId. 73 * 74 * A typical LIB_ID string consists of a library nickname followed by a library item name. 75 * e.g.: "smt:R_0805", or 76 * e.g.: "mylib:R_0805", or 77 * e.g.: "ttl:7400" 78 * 79 * @param aId is the string to populate the #LIB_ID object. 80 * @param aFix indicates invalid chars should be replaced with '_'. 81 * 82 * @return minus 1 (i.e. -1) means success, >= 0 indicates the character offset into 83 * aId at which an error was detected. 84 */ 85 int Parse( const UTF8& aId, bool aFix = false ); 86 87 /** 88 * Return the logical library name portion of a LIB_ID. 89 */ GetLibNickname()90 const UTF8& GetLibNickname() const { return m_libraryName; } 91 92 /** 93 * Override the logical library name portion of the LIB_ID to @a aNickname. 94 * 95 * @return int - minus 1 (i.e. -1) means success, >= 0 indicates the character offset 96 * into the parameter at which an error was detected, usually because it 97 * contained '/' or ':'. 98 */ 99 int SetLibNickname( const UTF8& aNickname ); 100 101 /** 102 * @return the library item name, i.e. footprintName, in UTF8. 103 */ GetLibItemName()104 const UTF8& GetLibItemName() const { return m_itemName; } 105 106 /** 107 * Get strings for display messages in dialogs. 108 * 109 * Equivalent to m_itemName.wx_str(), but more explicit when building a Unicode string 110 * in messages. 111 * 112 * @return the library item name, i.e. footprintName in a wxString (UTF16 or 32). 113 */ GetUniStringLibItemName()114 const wxString GetUniStringLibItemName() const { return m_itemName.wx_str(); } 115 116 /** 117 * Override the library item name portion of the LIB_ID to @a aLibItemName 118 * 119 * @return int - minus 1 (i.e. -1) means success, >= 0 indicates the character offset 120 * into the parameter at which an error was detected, usually because it 121 * contained '/'. 122 */ 123 int SetLibItemName( const UTF8& aLibItemName ); 124 125 /** 126 * @return the fully formatted text of the LIB_ID in a UTF8 string. 127 */ 128 UTF8 Format() const; 129 130 /** 131 * @return the fully formatted text of the LIB_ID in a wxString (UTF16 or UTF32), 132 * suitable to display the LIB_ID in dialogs. 133 */ GetUniStringLibId()134 wxString GetUniStringLibId() const 135 { 136 return Format().wx_str(); 137 } 138 139 /** 140 * @return a string in the proper format as an LIB_ID for a combination of 141 * aLibraryName, aLibItemName, and aRevision. 142 * 143 * @throw PARSE_ERROR if any of the pieces are illegal. 144 */ 145 static UTF8 Format( const UTF8& aLibraryName, const UTF8& aLibItemName ); 146 147 /** 148 * Check if this LID_ID is valid. 149 * 150 * A valid #LIB_ID must have both the library nickname and the library item name defined. 151 * The revision field is optional. 152 * 153 * @note A return value of true does not indicated that the #LIB_ID is a valid #LIB_TABLE 154 * entry. 155 * 156 * @return true is the #LIB_ID is valid. 157 * 158 */ IsValid()159 bool IsValid() const 160 { 161 return !m_libraryName.empty() && !m_itemName.empty(); 162 } 163 164 /** 165 * @return true if the #LIB_ID only has the #m_itemName name defined. 166 */ IsLegacy()167 bool IsLegacy() const 168 { 169 return m_libraryName.empty() && !m_itemName.empty(); 170 } 171 172 /** 173 * Clear the contents of the library nickname, library entry name, and revision strings. 174 */ 175 void clear(); 176 177 /** 178 * @return a boolean true value if the LIB_ID is empty. Otherwise return false. 179 */ empty()180 bool empty() const 181 { 182 return m_libraryName.empty() && m_itemName.empty(); 183 } 184 185 /** 186 * Compare the contents of LIB_ID objects by performing a std::string comparison of the 187 * library nickname, library entry name, and revision strings respectively. 188 * 189 * @param aLibId is the LIB_ID to compare against. 190 * @return -1 if less than \a aLibId, 1 if greater than \a aLibId, and 0 if equal to \a aLibId. 191 */ 192 int compare( const LIB_ID& aLibId ) const; 193 194 bool operator < ( const LIB_ID& aLibId ) const { return this->compare( aLibId ) < 0; } 195 bool operator > ( const LIB_ID& aLibId ) const { return this->compare( aLibId ) > 0; } 196 bool operator ==( const LIB_ID& aLibId ) const { return this->compare( aLibId ) == 0; } 197 bool operator !=( const LIB_ID& aLibId ) const { return !(*this == aLibId); } 198 199 /** 200 * Examine \a aLibItemName for invalid #LIB_ID item name characters. 201 * 202 * @param aLibItemName is the #LIB_ID name to test for illegal characters. 203 * @return offset of first illegal character otherwise -1. 204 */ 205 static int HasIllegalChars( const UTF8& aLibItemName ); 206 207 /** 208 * Replace illegal #LIB_ID item name characters with underscores '_'. 209 * 210 * @param aLibItemName is the #LIB_ID item name to replace illegal characters. 211 * @param aLib True if we are checking library names, false if we are checking item names 212 * @return the corrected version of \a aLibItemName. 213 */ 214 static UTF8 FixIllegalChars( const UTF8& aLibItemName, bool aLib ); 215 216 /** 217 * Looks for characters that are illegal in library nicknames. 218 * 219 * @param aLibraryName is the logical library name to be tested. 220 * @return Invalid character found in the name or 0 is the name is valid. 221 */ 222 static unsigned FindIllegalLibraryNameChar( const UTF8& aLibraryName ); 223 224 protected: 225 /** 226 * Tests whether a Unicode character is a legal LIB_ID item name character. 227 * 228 * The criteria for legal LIB_ID character is as follows: 229 * - For both symbol and footprint names, neither '/' or ':' are legal. They are 230 * reserved characters used by #LIB_ID::Parse. 231 * - Spaces are allowed in footprint names as they are a legal filename character 232 * on all operating systems. 233 * - Spaces are not allowed in symbol names since symbol names are not quoted in the 234 * schematic or symbol library file formats. 235 * - Spaces are allowed in footprint library nicknames as they are quoted in the 236 * footprint library table file format. 237 * - Spaces are now also allowed in symbol library nicknames since they are quoted in 238 * the new symbol library sexpr file format. 239 * - Illegal file name characters are not allowed in footprint names since the file 240 * name is the footprint name. 241 * - Illegal file name characters except '/' are allowed in symbol names since the 242 * name is not the file name. 243 * 244 * 245 * @note @a aUniChar is expected to be a 32 bit Unicode character, not a UTF8 char, that use 246 * a variable length coding value. 247 */ 248 static bool isLegalChar( unsigned aUniChar ); 249 250 /** 251 * Tests whether a Unicode character is a legal LIB_ID library nickname character 252 * 253 * @note @a aUniChar is expected to be a 32 bit Unicode character, not a UTF8 char, that use 254 * a variable length coding value. 255 */ 256 static bool isLegalLibraryNameChar( unsigned aUniChar ); 257 258 UTF8 m_libraryName; ///< The nickname of the library or empty. 259 UTF8 m_itemName; ///< The name of the entry in the logical library. 260 }; 261 262 263 #endif // _LIB_ID_H_ 264