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.

527 lines
17 KiB

4 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. #ifndef STRING_UTILS_H
  24. #define STRING_UTILS_H
  25. #include <algorithm>
  26. #include <string>
  27. #include <vector>
  28. #include <wx/string.h>
  29. #include <wx/filename.h>
  30. #include <kicommon.h>
  31. void ConvertMarkdown2Html( const wxString& aMarkdownInput, wxString& aHtmlOutput );
  32. /**
  33. * Convert the old `~...~` overbar notation to the new `~{...}` one.
  34. */
  35. KICOMMON_API wxString ConvertToNewOverbarNotation( const wxString& aOldStr );
  36. /**
  37. * Convert curly quotes and em/en dashes to straight quotes and dashes.
  38. *
  39. * @return true if any characters required conversion.
  40. */
  41. KICOMMON_API bool ConvertSmartQuotesAndDashes( wxString* aString );
  42. /**
  43. * Escape/Unescape routines to safely encode reserved-characters in various contexts.
  44. */
  45. enum ESCAPE_CONTEXT
  46. {
  47. CTX_NETNAME,
  48. CTX_LIBID,
  49. CTX_LEGACY_LIBID,
  50. CTX_IPC,
  51. CTX_QUOTED_STR,
  52. CTX_JS_STR,
  53. CTX_LINE,
  54. CTX_CSV,
  55. CTX_FILENAME,
  56. CTX_NO_SPACE // to replace spaces in names that do not accept spaces
  57. };
  58. /**
  59. * The Escape/Unescape routines use HTML-entity-reference-style encoding to handle
  60. * characters which are:
  61. * (a) not legal in filenames
  62. * (b) used as control characters in LIB_IDs
  63. * (c) used to delineate hierarchical paths
  64. */
  65. KICOMMON_API wxString EscapeString( const wxString& aSource, ESCAPE_CONTEXT aContext );
  66. KICOMMON_API wxString UnescapeString( const wxString& aSource );
  67. /**
  68. * Remove markup (such as overbar or subscript) that we can't render to menu items.
  69. */
  70. KICOMMON_API wxString PrettyPrintForMenu( const wxString& aString );
  71. /**
  72. * Capitalize the first letter in each word.
  73. */
  74. KICOMMON_API wxString TitleCaps( const wxString& aString );
  75. /**
  76. * Capitalize only the first word.
  77. */
  78. KICOMMON_API wxString InitialCaps( const wxString& aString );
  79. /**
  80. * Copy bytes from @a aSource delimited string segment to @a aDest buffer.
  81. *
  82. * The extracted string will be null terminated even if truncation is necessary
  83. * because aDestSize was not large enough.
  84. *
  85. * @param aDest is the destination byte buffer.
  86. * @param aSource is the source bytes as a C string.
  87. * @param aDestSize is the size of the destination byte buffer.
  88. * @return the number of bytes read from source, which may be more than the number copied,
  89. * due to escaping of double quotes and the escape byte itself.
  90. * @deprecated should use the one which fetches a wxString, below.
  91. */
  92. KICOMMON_API int ReadDelimitedText( char* aDest, const char* aSource, int aDestSize );
  93. /**
  94. * Copy bytes from @a aSource delimited string segment to @a aDest wxString.
  95. *
  96. * @param aDest is the destination wxString.
  97. * @param aSource is the source C string holding utf8 encoded bytes.
  98. * @return the number of bytes read from source, which may be more than the number copied,
  99. * due to escaping of double quotes and the escape byte itself.
  100. */
  101. KICOMMON_API int ReadDelimitedText( wxString* aDest, const char* aSource );
  102. /**
  103. * Return an 8 bit UTF8 string given aString in Unicode form.
  104. *
  105. * Any double quoted or back slashes are prefixed with a '\\' byte and the form
  106. * of this UTF8 byte string is compatible with function ReadDelimitedText().
  107. *
  108. * @param aString is the input string to convert.
  109. * @return the escaped input text, without the wrapping double quotes.
  110. */
  111. KICOMMON_API std::string EscapedUTF8( const wxString& aString );
  112. /**
  113. * Return a new wxString escaped for embedding in HTML.
  114. */
  115. KICOMMON_API wxString EscapeHTML( const wxString& aString );
  116. /**
  117. * Return a new wxString unescaped from HTML format.
  118. */
  119. KICOMMON_API wxString UnescapeHTML( const wxString& aString );
  120. /**
  121. * Removes HTML tags from a string.
  122. *
  123. * Do not use for filtering potentially malicious inputs and rendering as HTML
  124. * without escaping.
  125. */
  126. KICOMMON_API wxString RemoveHTMLTags( const wxString& aInput );
  127. /**
  128. * Wraps links in HTML <a href=""></a> tags.
  129. */
  130. KICOMMON_API wxString LinkifyHTML( wxString aStr );
  131. /**
  132. * Performs a URL sniff-test on a string.
  133. */
  134. KICOMMON_API bool IsURL( wxString aStr );
  135. /**
  136. * Read one line line from \a aFile.
  137. *
  138. * @return a pointer the first useful line read by eliminating blank lines and comments.
  139. */
  140. KICOMMON_API char* GetLine( FILE* aFile, char* Line, int* LineNum = nullptr, int SizeLine = 255 );
  141. /**
  142. * Return true if the string is empty or contains only whitespace.
  143. */
  144. KICOMMON_API bool NoPrintableChars( const wxString& aString );
  145. /**
  146. * Return the number of printable (ie: non-formatting) chars. Used to approximate rendered
  147. * text size when speed is more important than accuracy.
  148. */
  149. KICOMMON_API int PrintableCharCount( const wxString& aString );
  150. /**
  151. * Remove leading and training spaces, tabs and end of line chars in \a text
  152. *
  153. * @return a pointer on the first n char in text
  154. */
  155. KICOMMON_API char* StrPurge( char* text );
  156. /**
  157. * @return a string giving the current date and time.
  158. */
  159. KICOMMON_API wxString GetISO8601CurrentDateTime();
  160. /**
  161. * Compare two strings with alphanumerical content.
  162. *
  163. * This function is equivalent to strncmp() or strncasecmp() if \a aIgnoreCase is true
  164. * except that strings containing numbers are compared by their integer value not
  165. * by their ASCII code. In other words U10 would be greater than U2.
  166. *
  167. * @param aString1 A wxString reference to the reference string.
  168. * @param aString2 A wxString reference to the comparison string.
  169. * @param aIgnoreCase Use true to make the comparison case insensitive.
  170. * @return An integer value of -1 if \a aString1 is less than \a aString2, 0 if
  171. * \a aString1 is equal to \a aString2, or 1 if \a aString1 is greater
  172. * than \a aString2.
  173. */
  174. KICOMMON_API int StrNumCmp( const wxString& aString1, const wxString& aString2,
  175. bool aIgnoreCase = false );
  176. enum class CASE_SENSITIVITY
  177. {
  178. SENSITIVE,
  179. INSENSITIVE
  180. };
  181. /**
  182. * Sort a container of wxString objects, in place, using the StrNumCmp() function.
  183. */
  184. template <typename T>
  185. inline void StrNumSort( T& aList, CASE_SENSITIVITY aCaseSensitivity )
  186. {
  187. std::sort( aList.begin(), aList.end(),
  188. [aCaseSensitivity]( const wxString& lhs, const wxString& rhs )
  189. {
  190. return StrNumCmp( lhs, rhs, aCaseSensitivity == CASE_SENSITIVITY::INSENSITIVE ) < 0;
  191. } );
  192. }
  193. /**
  194. * Compare a string against wild card (* and ?) pattern using the usual rules.
  195. *
  196. * @return true if pattern matched otherwise false.
  197. */
  198. KICOMMON_API bool WildCompareString( const wxString& pattern,
  199. const wxString& string_to_tst,
  200. bool case_sensitive = true );
  201. /**
  202. * Compare strings like the strcmp function but handle numbers and modifiers within the
  203. * string text correctly for sorting. eg. 1mF > 55uF
  204. *
  205. * @return -1 if first string is less than the second, 0 if the strings are equal, or
  206. * 1 if the first string is greater than the second.
  207. */
  208. KICOMMON_API int ValueStringCompare( const wxString& strFWord, const wxString& strSWord );
  209. /**
  210. * Break a string into three parts: he alphabetic preamble, the numeric part, and any
  211. * alphabetic ending.
  212. *
  213. * For example C10A is split to C 10 A
  214. */
  215. KICOMMON_API int SplitString( const wxString& strToSplit,
  216. wxString* strBeginning,
  217. wxString* strDigits,
  218. wxString* strEnd );
  219. /**
  220. * Gets the trailing int, if any, from a string.
  221. *
  222. * @param aStr the string to check.
  223. * @return the trailing int or 0 if none found.
  224. */
  225. KICOMMON_API int GetTrailingInt( const wxString& aStr );
  226. /**
  227. * @return a wxString object containing the illegal file name characters for all platforms.
  228. */
  229. KICOMMON_API wxString GetIllegalFileNameWxChars();
  230. /**
  231. * Checks if a full filename is valid, i.e. does not contains illegal chars
  232. * path separators are allowed
  233. * @return true if OK.
  234. */
  235. KICOMMON_API bool IsFullFileNameValid( const wxString& aFullFilename );
  236. /**
  237. * Checks \a aName for illegal file name characters.
  238. *
  239. * The Windows (DOS) file system forbidden characters already include the forbidden file
  240. * name characters for both Posix and OSX systems. The characters \/?*|"\<\> are illegal
  241. * and are replaced with %xx where xx the hexadecimal equivalent of the replaced character.
  242. * This replacement may not be as elegant as using an underscore ('_') or hyphen ('-') but
  243. * it guarantees that there will be no naming conflicts when fixing footprint library names.
  244. * however, if aReplaceChar is given, it will replace the illegal chars
  245. *
  246. * @param aName is a point to a std::string object containing the footprint name to verify.
  247. * @param aReplaceChar (if not 0) is the replacement char.
  248. * @return true if any characters have been replaced in \a aName.
  249. */
  250. KICOMMON_API bool ReplaceIllegalFileNameChars( std::string& aName, int aReplaceChar = 0 );
  251. KICOMMON_API bool ReplaceIllegalFileNameChars( wxString& aName, int aReplaceChar = 0 );
  252. /**
  253. * A helper for sorting strings from the rear.
  254. *
  255. * Useful for things like 3D model names where they tend to be largely repetitious at the front.
  256. */
  257. struct rsort_wxString
  258. {
  259. bool operator() ( const wxString& strA, const wxString& strB ) const
  260. {
  261. wxString::const_reverse_iterator sA = strA.rbegin();
  262. wxString::const_reverse_iterator eA = strA.rend();
  263. wxString::const_reverse_iterator sB = strB.rbegin();
  264. wxString::const_reverse_iterator eB = strB.rend();
  265. if( strA.empty() )
  266. {
  267. if( strB.empty() )
  268. return false;
  269. // note: this rule implies that a null string is first in the sort order
  270. return true;
  271. }
  272. if( strB.empty() )
  273. return false;
  274. while( sA != eA && sB != eB )
  275. {
  276. if( ( *sA ) == ( *sB ) )
  277. {
  278. ++sA;
  279. ++sB;
  280. continue;
  281. }
  282. if( ( *sA ) < ( *sB ) )
  283. return true;
  284. else
  285. return false;
  286. }
  287. if( sB == eB )
  288. return false;
  289. return true;
  290. }
  291. };
  292. /**
  293. * Split the input string into a vector of output strings
  294. *
  295. * @note Multiple delimiters are considered to be separate records with empty strings
  296. *
  297. * @param aStr Input string with 0 or more delimiters.
  298. * @param aDelim The string of delimiter. Multiple characters here denote alternate delimiters.
  299. * @return a vector of strings
  300. */
  301. static inline std::vector<std::string> split( const std::string& aStr, const std::string& aDelim )
  302. {
  303. size_t pos = 0;
  304. size_t last_pos = 0;
  305. size_t len;
  306. std::vector<std::string> tokens;
  307. while( pos < aStr.size() )
  308. {
  309. pos = aStr.find_first_of( aDelim, last_pos );
  310. if( pos == std::string::npos )
  311. pos = aStr.size();
  312. len = pos - last_pos;
  313. tokens.push_back( aStr.substr( last_pos, len ) );
  314. last_pos = pos + 1;
  315. }
  316. return tokens;
  317. }
  318. /// Utility to build comma separated lists in messages
  319. inline void AccumulateDescription( wxString& aDesc, const wxString& aItem )
  320. {
  321. if( !aDesc.IsEmpty() )
  322. aDesc << wxT( ", " );
  323. aDesc << aItem;
  324. }
  325. /**
  326. * Build a comma-separated list from a collection of wxStrings.
  327. * (e.g. std::vector, wxArrayString, etc).
  328. */
  329. template <typename T>
  330. inline void AccumulateDescriptions( wxString& aDesc, const T& aItemCollection )
  331. {
  332. for( const auto& item : aItemCollection )
  333. AccumulateDescription( aDesc, item );
  334. }
  335. template <typename T>
  336. inline wxString AccumulateDescriptions( const T& aItemCollection )
  337. {
  338. wxString desc;
  339. AccumulateDescriptions( desc, aItemCollection );
  340. return desc;
  341. }
  342. /**
  343. * Split \a aString to a string list separated at \a aSplitter.
  344. *
  345. * @param aText is the text to split.
  346. * @param aStrings will contain the split lines.
  347. * @param aSplitter is the 'split' character.
  348. */
  349. KICOMMON_API void wxStringSplit( const wxString& aText, wxArrayString& aStrings, wxChar aSplitter );
  350. /**
  351. * Remove trailing zeros from a string containing a converted float number.
  352. *
  353. * The trailing zeros are removed if the mantissa has more than \a aTrailingZeroAllowed
  354. * digits and some trailing zeros.
  355. */
  356. KICOMMON_API void StripTrailingZeros( wxString& aStringValue, unsigned aTrailingZeroAllowed = 1 );
  357. /**
  358. * Print a float number without using scientific notation and no trailing 0
  359. * We want to avoid scientific notation in S-expr files (not easy to read)
  360. * for floating numbers.
  361. *
  362. * We cannot always just use the %g or the %f format to print a fp number
  363. * this helper function uses the %f format when needed, or %g when %f is
  364. * not well working and then removes trailing 0
  365. */
  366. KICOMMON_API std::string UIDouble2Str( double aValue );
  367. /**
  368. * Print a float number without using scientific notation and no trailing 0
  369. * This function is intended in uses to write to file, it ignores locale
  370. *
  371. * We cannot always just use the %g or the %f format to print a fp number
  372. * this helper function uses the %f format when needed, or %g when %f is
  373. * not well working and then removes trailing 0
  374. */
  375. KICOMMON_API std::string FormatDouble2Str( double aValue );
  376. /**
  377. * Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
  378. *
  379. * wxstring is a wxString, not a wxT() or _(). The scope of the return value
  380. * is very limited and volatile, but can be used with printf() style functions well.
  381. *
  382. * @note Trying to convert it to a function is tricky because of the type of the
  383. * parameter!
  384. */
  385. #define TO_UTF8( wxstring ) ( (const char*) ( wxstring ).utf8_str() )
  386. /**
  387. * Convert an expected UTF8 encoded std::string to a wxString.
  388. * If fails, try to convert using current locale
  389. * If still fails, return the initial string (can be already a converted string)
  390. */
  391. KICOMMON_API wxString From_UTF8( const std::string& aString );
  392. KICOMMON_API wxString From_UTF8( const char* cstring );
  393. /**
  394. * Normalize file path \a aFileUri to URI convention.
  395. *
  396. * Unfortunately none of the wxWidgets objects results in acceptable file URIs which breaks
  397. * PDF plotting URI links. This is an attempt to normalize Windows local file paths to a
  398. * URI that PDF readers that can run JavaScript can handle.
  399. *
  400. * @note This does not expand environment or user variables. Variable expansion should be
  401. * performed before calling. If \a aFileUri does not begin with 'file://', \a aFileUri
  402. * returned unchanged.
  403. *
  404. * @param aFileUri is the string to be normalized.
  405. * @return the normalized string.
  406. */
  407. KICOMMON_API wxString NormalizeFileUri( const wxString& aFileUri );
  408. /**
  409. * Expand stacked pin notation like [1,2,3], [1-4], [A1-A4], or [AA1-AA3,AB4,CD12-CD14]
  410. * into individual pin numbers, supporting both numeric and alphanumeric pin prefixes.
  411. *
  412. * Examples:
  413. * "[1,2,3]" -> {"1", "2", "3"}
  414. * "[1-4]" -> {"1", "2", "3", "4"}
  415. * "[A1-A3]" -> {"A1", "A2", "A3"}
  416. * "[AA1-AA3,AB4]" -> {"AA1", "AA2", "AA3", "AB4"}
  417. * "5" -> {"5"} (non-bracketed pins returned as-is)
  418. *
  419. * @param aPinName is the pin name to expand (may or may not use stacked notation)
  420. * @param aValid is optionally set to indicate whether the notation was valid
  421. * @return vector of individual pin numbers
  422. */
  423. KICOMMON_API std::vector<wxString> ExpandStackedPinNotation( const wxString& aPinName,
  424. bool* aValid = nullptr );
  425. /**
  426. * Count the number of pins represented by stacked pin notation without allocating strings.
  427. *
  428. * This is a fast alternative to ExpandStackedPinNotation().size() for cases where only
  429. * the count is needed.
  430. *
  431. * @param aPinName is the pin name to count (may or may not use stacked notation)
  432. * @param aValid is optionally set to indicate whether the notation was valid
  433. * @return count of individual pins represented (always >= 1)
  434. */
  435. KICOMMON_API int CountStackedPinNotation( const wxString& aPinName, bool* aValid = nullptr );
  436. KICOMMON_API wxString GetDefaultVariantName();
  437. KICOMMON_API int SortVariantNames( const wxString& aLhs, const wxString& aRhs );
  438. struct LOAD_MESSAGE;
  439. /**
  440. * Parse library load error messages, extracting user-facing information while
  441. * stripping internal code locations.
  442. *
  443. * @param aErrorString is the raw error string from GetLibraryLoadErrors()
  444. * @param aSeverity is the severity to assign to all extracted messages
  445. * @return vector of LOAD_MESSAGE with cleaned error text
  446. */
  447. KICOMMON_API std::vector<LOAD_MESSAGE> ExtractLibraryLoadErrors( const wxString& aErrorString,
  448. int aSeverity );
  449. #endif // STRING_UTILS_H