Audio plugin host https://kx.studio/carla
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.

749 lines
39KB

  1. //------------------------------------------------------------------------
  2. // Project : SDK Base
  3. // Version : 1.0
  4. //
  5. // Category : Helpers
  6. // Filename : base/source/fstring.h
  7. // Created by : Steinberg, 2008
  8. // Description : String class
  9. //
  10. //-----------------------------------------------------------------------------
  11. // LICENSE
  12. // (c) 2021, Steinberg Media Technologies GmbH, All Rights Reserved
  13. //-----------------------------------------------------------------------------
  14. // Redistribution and use in source and binary forms, with or without modification,
  15. // are permitted provided that the following conditions are met:
  16. //
  17. // * Redistributions of source code must retain the above copyright notice,
  18. // this list of conditions and the following disclaimer.
  19. // * Redistributions in binary form must reproduce the above copyright notice,
  20. // this list of conditions and the following disclaimer in the documentation
  21. // and/or other materials provided with the distribution.
  22. // * Neither the name of the Steinberg Media Technologies nor the names of its
  23. // contributors may be used to endorse or promote products derived from this
  24. // software without specific prior written permission.
  25. //
  26. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  27. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  28. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  29. // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  30. // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  31. // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  33. // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  34. // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  35. // OF THE POSSIBILITY OF SUCH DAMAGE.
  36. //-----------------------------------------------------------------------------
  37. #pragma once
  38. #include "pluginterfaces/base/ftypes.h"
  39. #include "pluginterfaces/base/fstrdefs.h"
  40. #include "pluginterfaces/base/istringresult.h"
  41. #include "pluginterfaces/base/ipersistent.h"
  42. #include "base/source/fobject.h"
  43. #include <cstdarg>
  44. namespace Steinberg {
  45. class FVariant;
  46. class String;
  47. #ifdef UNICODE
  48. static const bool kWideStringDefault = true;
  49. #else
  50. static const bool kWideStringDefault = false;
  51. #endif
  52. static const uint16 kBomUtf16 = 0xFEFF; ///< UTF16 Byte Order Mark
  53. static const char8* const kBomUtf8 = "\xEF\xBB\xBF"; ///< UTF8 Byte Order Mark
  54. static const int32 kBomUtf8Length = 3;
  55. enum MBCodePage
  56. {
  57. kCP_ANSI = 0, ///< Default ANSI codepage.
  58. kCP_MAC_ROMAN = 2, ///< Default Mac codepage.
  59. kCP_ANSI_WEL = 1252, ///< West European Latin Encoding.
  60. kCP_MAC_CEE = 10029, ///< Mac Central European Encoding.
  61. kCP_Utf8 = 65001, ///< UTF8 Encoding.
  62. kCP_ShiftJIS = 932, ///< Shifted Japan Industrial Standard Encoding.
  63. kCP_US_ASCII = 20127, ///< US-ASCII (7-bit).
  64. kCP_Default = kCP_ANSI ///< Default ANSI codepage.
  65. };
  66. enum UnicodeNormalization
  67. {
  68. kUnicodeNormC, ///< Unicode normalization Form C, canonical composition.
  69. kUnicodeNormD, ///< Unicode normalization Form D, canonical decomposition.
  70. kUnicodeNormKC, ///< Unicode normalization form KC, compatibility composition.
  71. kUnicodeNormKD ///< Unicode normalization form KD, compatibility decomposition.
  72. };
  73. //------------------------------------------------------------------------
  74. // Helper functions to create hash codes from string data.
  75. //------------------------------------------------------------------------
  76. extern uint32 hashString8 (const char8* s, uint32 m);
  77. extern uint32 hashString16 (const char16* s, uint32 m);
  78. inline uint32 hashString (const tchar* s, uint32 m)
  79. {
  80. #ifdef UNICODE
  81. return hashString16 (s, m);
  82. #else
  83. return hashString8 (s, m);
  84. #endif
  85. }
  86. //-----------------------------------------------------------------------------
  87. /** Invariant String.
  88. @ingroup adt
  89. A base class which provides methods to work with its
  90. member string. Neither of the operations allows modifying the member string and
  91. that is why all operation are declared as const.
  92. There are operations for access, comparison, find, numbers and conversion.
  93. Almost all operations exist in three versions for char8, char16 and the
  94. polymorphic type tchar. The type tchar can either be char8 or char16 depending
  95. on whether UNICODE is activated or not.*/
  96. //-----------------------------------------------------------------------------
  97. class ConstString
  98. {
  99. public:
  100. //-----------------------------------------------------------------------------
  101. ConstString (const char8* str, int32 length = -1); ///< Assign from string of type char8 (length=-1: all)
  102. ConstString (const char16* str, int32 length = -1); ///< Assign from string of type char16 (length=-1: all)
  103. ConstString (const ConstString& str, int32 offset = 0, int32 length = -1); ///< Copy constructor (length=-1: all).
  104. ConstString (const FVariant& var); ///< Assign a string from FVariant
  105. ConstString ();
  106. virtual ~ConstString () {} ///< Destructor.
  107. // access -----------------------------------------------------------------
  108. virtual int32 length () const {return static_cast<int32> (len);} ///< Return length of string
  109. inline bool isEmpty () const {return buffer == nullptr || len == 0;} ///< Return true if string is empty
  110. operator const char8* () const {return text8 ();} ///< Returns pointer to string of type char8 (no modification allowed)
  111. operator const char16* () const {return text16 ();} ///< Returns pointer to string of type char16(no modification allowed)
  112. inline tchar operator[] (short idx) const {return getChar (static_cast<uint32> (idx));} ///< Returns character at 'idx'
  113. inline tchar operator[] (long idx) const {return getChar (static_cast<uint32> (idx));}
  114. inline tchar operator[] (int idx) const {return getChar (static_cast<uint32> (idx));}
  115. inline tchar operator[] (unsigned short idx) const {return getChar (idx);}
  116. inline tchar operator[] (unsigned long idx) const {return getChar (static_cast<uint32> (idx));}
  117. inline tchar operator[] (unsigned int idx) const {return getChar (idx);}
  118. inline virtual const char8* text8 () const; ///< Returns pointer to string of type char8
  119. inline virtual const char16* text16 () const; ///< Returns pointer to string of type char16
  120. inline virtual const tchar* text () const; ///< Returns pointer to string of type tchar
  121. inline virtual const void* ptr () const {return buffer;} ///< Returns pointer to string of type void
  122. inline virtual char8 getChar8 (uint32 index) const; ///< Returns character of type char16 at 'index'
  123. inline virtual char16 getChar16 (uint32 index) const; ///< Returns character of type char8 at 'index'
  124. inline tchar getChar (uint32 index) const; ///< Returns character of type tchar at 'index'
  125. inline tchar getCharAt (uint32 index) const; ///< Returns character of type tchar at 'index', no conversion!
  126. bool testChar8 (uint32 index, char8 c) const; ///< Returns true if character is equal at position 'index'
  127. bool testChar16 (uint32 index, char16 c) const;
  128. inline bool testChar (uint32 index, char8 c) const {return testChar8 (index, c);}
  129. inline bool testChar (uint32 index, char16 c) const {return testChar16 (index, c);}
  130. bool extract (String& result, uint32 idx, int32 n = -1) const; ///< Get n characters long substring starting at index (n=-1: until end)
  131. int32 copyTo8 (char8* str, uint32 idx = 0, int32 n = -1) const;
  132. int32 copyTo16 (char16* str, uint32 idx = 0, int32 n = -1) const;
  133. int32 copyTo (tchar* str, uint32 idx = 0, int32 n = -1) const;
  134. void copyTo (IStringResult* result) const; ///< Copies whole member string
  135. void copyTo (IString& string) const; ///< Copies whole member string
  136. inline uint32 hash (uint32 tsize) const
  137. {
  138. return isWide ? hashString16 (buffer16, tsize) : hashString8 (buffer8, tsize) ;
  139. }
  140. //-------------------------------------------------------------------------
  141. // compare ----------------------------------------------------------------
  142. enum CompareMode
  143. {
  144. kCaseSensitive, ///< Comparison is done with regard to character's case
  145. kCaseInsensitive ///< Comparison is done without regard to character's case
  146. };
  147. int32 compareAt (uint32 index, const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive) const; ///< Compare n characters of str with n characters of this starting at index (return: see above)
  148. int32 compare (const ConstString& str, int32 n, CompareMode m = kCaseSensitive) const; ///< Compare n characters of str with n characters of this (return: see above)
  149. int32 compare (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Compare all characters of str with this (return: see above)
  150. int32 naturalCompare (const ConstString& str, CompareMode mode = kCaseSensitive) const;
  151. bool startsWith (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this starts with str
  152. bool endsWith (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this ends with str
  153. bool contains (const ConstString& str, CompareMode m = kCaseSensitive) const; ///< Check if this contains str
  154. // static methods
  155. static bool isCharSpace (char8 character); ///< Returns true if character is a space
  156. static bool isCharSpace (char16 character); ///< @copydoc isCharSpace(const char8)
  157. static bool isCharAlpha (char8 character); ///< Returns true if character is an alphabetic character
  158. static bool isCharAlpha (char16 character); ///< @copydoc isCharAlpha(const char8)
  159. static bool isCharAlphaNum (char8 character); ///< Returns true if character is an alphanumeric character
  160. static bool isCharAlphaNum (char16 character); ///< @copydoc isCharAlphaNum(const char8)
  161. static bool isCharDigit (char8 character); ///< Returns true if character is a number
  162. static bool isCharDigit (char16 character); ///< @copydoc isCharDigit(const char8)
  163. static bool isCharAscii (char8 character); ///< Returns true if character is in ASCII range
  164. static bool isCharAscii (char16 character); ///< Returns true if character is in ASCII range
  165. static bool isCharUpper (char8 character);
  166. static bool isCharUpper (char16 character);
  167. static bool isCharLower (char8 character);
  168. static bool isCharLower (char16 character);
  169. //-------------------------------------------------------------------------
  170. /** @name Find first occurrence of n characters of str in this (n=-1: all) ending at endIndex (endIndex = -1: all)*/
  171. ///@{
  172. inline int32 findFirst (const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, str, n, m, endIndex);}
  173. inline int32 findFirst (char8 c, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, c, m, endIndex);}
  174. inline int32 findFirst (char16 c, CompareMode m = kCaseSensitive, int32 endIndex = -1) const {return findNext (0, c, m, endIndex);}
  175. ///@}
  176. /** @name Find next occurrence of n characters of str starting at startIndex in this (n=-1: all) ending at endIndex (endIndex = -1: all)*/
  177. ///@{
  178. int32 findNext (int32 startIndex, const ConstString& str, int32 n = -1, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
  179. int32 findNext (int32 startIndex, char8 c, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
  180. int32 findNext (int32 startIndex, char16 c, CompareMode = kCaseSensitive, int32 endIndex = -1) const;
  181. ///@}
  182. /** @name Find previous occurrence of n characters of str starting at startIndex in this (n=-1: all) */
  183. ///@{
  184. int32 findPrev (int32 startIndex, const ConstString& str, int32 n = -1, CompareMode = kCaseSensitive) const;
  185. int32 findPrev (int32 startIndex, char8 c, CompareMode = kCaseSensitive) const;
  186. int32 findPrev (int32 startIndex, char16 c, CompareMode = kCaseSensitive) const;
  187. ///@}
  188. inline int32 findLast (const ConstString& str, int32 n = -1, CompareMode m = kCaseSensitive) const {return findPrev (-1, str, n, m);} ///< Find last occurrence of n characters of str in this (n=-1: all)
  189. inline int32 findLast (char8 c, CompareMode m = kCaseSensitive) const {return findPrev (-1, c, m);}
  190. inline int32 findLast (char16 c, CompareMode m = kCaseSensitive) const {return findPrev (-1, c, m);}
  191. int32 countOccurences (char8 c, uint32 startIndex, CompareMode = kCaseSensitive) const; ///< Counts occurences of c within this starting at index
  192. int32 countOccurences (char16 c, uint32 startIndex, CompareMode = kCaseSensitive) const;
  193. int32 getFirstDifferent (const ConstString& str, CompareMode = kCaseSensitive) const; ///< Returns position of first different character
  194. //-------------------------------------------------------------------------
  195. // numbers ----------------------------------------------------------------
  196. bool isDigit (uint32 index) const; ///< Returns true if character at position is a digit
  197. bool scanFloat (double& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to double value starting at offset
  198. bool scanInt64 (int64& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to int64 value starting at offset
  199. bool scanUInt64 (uint64& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to uint64 value starting at offset
  200. bool scanInt32 (int32& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to int32 value starting at offset
  201. bool scanUInt32 (uint32& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to uint32 value starting at offset
  202. bool scanHex (uint8& value, uint32 offset = 0, bool scanToEnd = true) const; ///< Converts string to hex/uint8 value starting at offset
  203. int32 getTrailingNumberIndex (uint32 width = 0) const; ///< Returns start index of trailing number
  204. int64 getTrailingNumber (int64 fallback = 0) const; ///< Returns result of scanInt64 or the fallback
  205. int64 getNumber () const; ///< Returns result of scanInt64
  206. // static methods
  207. static bool scanInt64_8 (const char8* text, int64& value, bool scanToEnd = true); ///< Converts string of type char8 to int64 value
  208. static bool scanInt64_16 (const char16* text, int64& value, bool scanToEnd = true); ///< Converts string of type char16 to int64 value
  209. static bool scanInt64 (const tchar* text, int64& value, bool scanToEnd = true); ///< Converts string of type tchar to int64 value
  210. static bool scanUInt64_8 (const char8* text, uint64& value, bool scanToEnd = true); ///< Converts string of type char8 to uint64 value
  211. static bool scanUInt64_16 (const char16* text, uint64& value, bool scanToEnd = true); ///< Converts string of type char16 to uint64 value
  212. static bool scanUInt64 (const tchar* text, uint64& value, bool scanToEnd = true); ///< Converts string of type tchar to uint64 value
  213. static bool scanInt32_8 (const char8* text, int32& value, bool scanToEnd = true); ///< Converts string of type char8 to int32 value
  214. static bool scanInt32_16 (const char16* text, int32& value, bool scanToEnd = true); ///< Converts string of type char16 to int32 value
  215. static bool scanInt32 (const tchar* text, int32& value, bool scanToEnd = true); ///< Converts string of type tchar to int32 value
  216. static bool scanUInt32_8 (const char8* text, uint32& value, bool scanToEnd = true); ///< Converts string of type char8 to int32 value
  217. static bool scanUInt32_16 (const char16* text, uint32& value, bool scanToEnd = true); ///< Converts string of type char16 to int32 value
  218. static bool scanUInt32 (const tchar* text, uint32& value, bool scanToEnd = true); ///< Converts string of type tchar to int32 value
  219. static bool scanHex_8 (const char8* text, uint8& value, bool scanToEnd = true); ///< Converts string of type char8 to hex/unit8 value
  220. static bool scanHex_16 (const char16* text, uint8& value, bool scanToEnd = true); ///< Converts string of type char16 to hex/unit8 value
  221. static bool scanHex (const tchar* text, uint8& value, bool scanToEnd = true); ///< Converts string of type tchar to hex/unit8 value
  222. //-------------------------------------------------------------------------
  223. // conversion -------------------------------------------------------------
  224. void toVariant (FVariant& var) const;
  225. static char8 toLower (char8 c); ///< Converts to lower case
  226. static char8 toUpper (char8 c); ///< Converts to upper case
  227. static char16 toLower (char16 c);
  228. static char16 toUpper (char16 c);
  229. static int32 multiByteToWideString (char16* dest, const char8* source, int32 wcharCount, uint32 sourceCodePage = kCP_Default); ///< If dest is zero, this returns the maximum number of bytes needed to convert source
  230. static int32 wideStringToMultiByte (char8* dest, const char16* source, int32 char8Count, uint32 destCodePage = kCP_Default); ///< If dest is zero, this returns the maximum number of bytes needed to convert source
  231. bool isWideString () const {return isWide != 0;} ///< Returns true if string is wide
  232. bool isAsciiString () const; ///< Checks if all characters in string are in ascii range
  233. bool isNormalized (UnicodeNormalization = kUnicodeNormC); ///< On PC only kUnicodeNormC is working
  234. #if SMTG_OS_MACOS
  235. virtual void* toCFStringRef (uint32 encoding = 0xFFFF, bool mutableCFString = false) const; ///< CFString conversion
  236. #endif
  237. //-------------------------------------------------------------------------
  238. //-----------------------------------------------------------------------------
  239. protected:
  240. union
  241. {
  242. void* buffer;
  243. char8* buffer8;
  244. char16* buffer16;
  245. };
  246. uint32 len : 30;
  247. uint32 isWide : 1;
  248. };
  249. //-----------------------------------------------------------------------------
  250. /** String.
  251. @ingroup adt
  252. Extends class ConstString by operations which allow modifications.
  253. \see ConstString */
  254. //-----------------------------------------------------------------------------
  255. class String : public ConstString
  256. {
  257. public:
  258. //-----------------------------------------------------------------------------
  259. String ();
  260. String (const char8* str, MBCodePage codepage, int32 n = -1, bool isTerminated = true); ///< assign n characters of str and convert to wide string by using the specified codepage
  261. String (const char8* str, int32 n = -1, bool isTerminated = true); ///< assign n characters of str (-1: all)
  262. String (const char16* str, int32 n = -1, bool isTerminated = true); ///< assign n characters of str (-1: all)
  263. String (const String& str, int32 n = -1); ///< assign n characters of str (-1: all)
  264. String (const ConstString& str, int32 n = -1); ///< assign n characters of str (-1: all)
  265. String (const FVariant& var); ///< assign from FVariant
  266. String (IString* str); ///< assign from IString
  267. ~String ();
  268. #if SMTG_CPP11_STDLIBSUPPORT
  269. String (String&& str);
  270. String& operator= (String&& str);
  271. #endif
  272. // access------------------------------------------------------------------
  273. void updateLength (); ///< Call this when the string is truncated outside (not recommended though)
  274. const char8* text8 () const SMTG_OVERRIDE;
  275. const char16* text16 () const SMTG_OVERRIDE;
  276. char8 getChar8 (uint32 index) const SMTG_OVERRIDE;
  277. char16 getChar16 (uint32 index) const SMTG_OVERRIDE;
  278. bool setChar8 (uint32 index, char8 c);
  279. bool setChar16 (uint32 index, char16 c);
  280. inline bool setChar (uint32 index, char8 c) {return setChar8 (index, c);}
  281. inline bool setChar (uint32 index, char16 c) {return setChar16 (index, c);}
  282. //-------------------------------------------------------------------------
  283. // assignment--------------------------------------------------------------
  284. String& operator= (const char8* str) {return assign (str);} ///< Assign from a string of type char8
  285. String& operator= (const char16* str) {return assign (str);}
  286. String& operator= (const ConstString& str) {return assign (str);}
  287. String& operator= (const String& str) {return assign (str);}
  288. String& operator= (char8 c) {return assign (c);}
  289. String& operator= (char16 c) {return assign (c);}
  290. String& assign (const ConstString& str, int32 n = -1); ///< Assign n characters of str (-1: all)
  291. String& assign (const char8* str, int32 n = -1, bool isTerminated = true); ///< Assign n characters of str (-1: all)
  292. String& assign (const char16* str, int32 n = -1, bool isTerminated = true); ///< Assign n characters of str (-1: all)
  293. String& assign (char8 c, int32 n = 1);
  294. String& assign (char16 c, int32 n = 1);
  295. //-------------------------------------------------------------------------
  296. // concat------------------------------------------------------------------
  297. String& append (const ConstString& str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
  298. String& append (const char8* str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
  299. String& append (const char16* str, int32 n = -1); ///< Append n characters of str to this (n=-1: all)
  300. String& append (const char8 c, int32 n = 1); ///< Append char c n times
  301. String& append (const char16 c, int32 n = 1); ///< Append char c n times
  302. String& insertAt (uint32 idx, const ConstString& str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
  303. String& insertAt (uint32 idx, const char8* str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
  304. String& insertAt (uint32 idx, const char16* str, int32 n = -1); ///< Insert n characters of str at position idx (n=-1: all)
  305. String& insertAt (uint32 idx, char8 c) {char8 str[] = {c, 0}; return insertAt (idx, str, 1);}
  306. String& insertAt (uint32 idx, char16 c) {char16 str[] = {c, 0}; return insertAt (idx, str, 1);}
  307. String& operator+= (const String& str) {return append (str);}
  308. String& operator+= (const ConstString& str) {return append (str);}
  309. String& operator+= (const char8* str) {return append (str);}
  310. String& operator+= (const char16* str) {return append (str);}
  311. String& operator+= (const char8 c) {return append (c);}
  312. String& operator+= (const char16 c) {return append (c);}
  313. //-------------------------------------------------------------------------
  314. // replace-----------------------------------------------------------------
  315. String& replace (uint32 idx, int32 n1, const ConstString& str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
  316. String& replace (uint32 idx, int32 n1, const char8* str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
  317. String& replace (uint32 idx, int32 n1, const char16* str, int32 n2 = -1); ///< Replace n1 characters of this (starting at idx) with n2 characters of str (n1,n2=-1: until end)
  318. int32 replace (const char8* toReplace, const char8* toReplaceWith, bool all = false, CompareMode m = kCaseSensitive); ///< Replace find string with replace string - returns number of replacements
  319. int32 replace (const char16* toReplace, const char16* toReplaceWith, bool all = false, CompareMode m = kCaseSensitive); ///< Replace find string with replace string - returns number of replacements
  320. bool replaceChars8 (const char8* toReplace, char8 toReplaceBy); ///< Returns true when any replacement was done
  321. bool replaceChars16 (const char16* toReplace, char16 toReplaceBy);
  322. inline bool replaceChars8 (char8 toReplace, char8 toReplaceBy) {char8 str[] = {toReplace, 0}; return replaceChars8 (str, toReplaceBy);}
  323. inline bool replaceChars16 (char16 toReplace, char16 toReplaceBy) {char16 str[] = {toReplace, 0}; return replaceChars16 (str, toReplaceBy);}
  324. inline bool replaceChars (char8 toReplace, char8 toReplaceBy) {return replaceChars8 (toReplace, toReplaceBy);}
  325. inline bool replaceChars (char16 toReplace, char16 toReplaceBy) {return replaceChars16 (toReplace, toReplaceBy);}
  326. inline bool replaceChars (const char8* toReplace, char8 toReplaceBy) {return replaceChars8 (toReplace, toReplaceBy);}
  327. inline bool replaceChars (const char16* toReplace, char16 toReplaceBy) {return replaceChars16 (toReplace, toReplaceBy);}
  328. //-------------------------------------------------------------------------
  329. // remove------------------------------------------------------------------
  330. String& remove (uint32 index = 0, int32 n = -1); ///< Remove n characters from string starting at index (n=-1: until end)
  331. enum CharGroup {kSpace, kNotAlphaNum, kNotAlpha};
  332. bool trim (CharGroup mode = kSpace); ///< Trim lead/trail.
  333. void removeChars (CharGroup mode = kSpace); ///< Removes all of group.
  334. bool removeChars8 (const char8* which); ///< Remove all occurrences of each char in 'which'
  335. bool removeChars16 (const char16* which); ///< Remove all occurrences of each char in 'which'
  336. inline bool removeChars8 (const char8 which) {char8 str[] = {which, 0}; return removeChars8 (str); }
  337. inline bool removeChars16 (const char16 which) {char16 str[] = {which, 0}; return removeChars16 (str); }
  338. inline bool removeChars (const char8* which) {return removeChars8 (which);}
  339. inline bool removeChars (const char16* which) {return removeChars16 (which);}
  340. inline bool removeChars (const char8 which) {return removeChars8 (which);}
  341. inline bool removeChars (const char16 which) {return removeChars16 (which);}
  342. bool removeSubString (const ConstString& subString, bool allOccurences = true);
  343. //-------------------------------------------------------------------------
  344. // print-------------------------------------------------------------------
  345. String& printf (const char8* format, ...); ///< Print formatted data into string
  346. String& printf (const char16* format, ...); ///< Print formatted data into string
  347. String& vprintf (const char8* format, va_list args);
  348. String& vprintf (const char16* format, va_list args);
  349. //-------------------------------------------------------------------------
  350. // numbers-----------------------------------------------------------------
  351. String& printInt64 (int64 value);
  352. String& printFloat (double value);
  353. /** Increment the trailing number if present else start with minNumber, width specifies the string width format (width 2 for number 3 is 03),
  354. applyOnlyFormat set to true will only format the string to the given width without incrementing the founded trailing number */
  355. bool incrementTrailingNumber (uint32 width = 2, tchar separator = STR (' '), uint32 minNumber = 1, bool applyOnlyFormat = false);
  356. //-------------------------------------------------------------------------
  357. // conversion--------------------------------------------------------------
  358. bool fromVariant (const FVariant& var); ///< Assigns string from FVariant
  359. void toVariant (FVariant& var) const;
  360. bool fromAttributes (IAttributes* a, IAttrID attrID); ///< Assigns string from FAttributes
  361. bool toAttributes (IAttributes* a, IAttrID attrID);
  362. void swapContent (String& s); ///< Swaps ownership of the strings pointed to
  363. void take (String& str); ///< Take ownership of the string of 'str'
  364. void take (void* _buffer, bool wide); ///< Take ownership of buffer
  365. void* pass ();
  366. void passToVariant (FVariant& var); ///< Pass ownership of buffer to Variant - sets Variant ownership
  367. void toLower (uint32 index); ///< Lower case the character.
  368. void toLower (); ///< Lower case the string.
  369. void toUpper (uint32 index); ///< Upper case the character.
  370. void toUpper (); ///< Upper case the string.
  371. unsigned char* toPascalString (unsigned char* buf); ///< Pascal string conversion
  372. const String& fromPascalString (const unsigned char* buf); ///< Pascal string conversion
  373. bool toWideString (uint32 sourceCodePage = kCP_Default); ///< Converts to wide string according to sourceCodePage
  374. bool toMultiByte (uint32 destCodePage = kCP_Default);
  375. void fromUTF8 (const char8* utf8String); ///< Assigns from UTF8 string
  376. bool normalize (UnicodeNormalization = kUnicodeNormC); ///< On PC only kUnicodeNormC is working
  377. #if SMTG_OS_MACOS
  378. virtual bool fromCFStringRef (const void*, uint32 encoding = 0xFFFF); ///< CFString conversion
  379. #endif
  380. //-------------------------------------------------------------------------
  381. //-----------------------------------------------------------------------------
  382. protected:
  383. bool resize (uint32 newSize, bool wide, bool fill = false);
  384. private:
  385. void tryFreeBuffer ();
  386. bool checkToMultiByte (uint32 destCodePage = kCP_Default) const; // to remove debug code from inline - const_cast inside!!!
  387. };
  388. // String concatenation functions.
  389. inline String operator+ (const ConstString& s1, const ConstString& s2) {return String (s1).append (s2);}
  390. inline String operator+ (const ConstString& s1, const char8* s2) {return String (s1).append (s2);}
  391. inline String operator+ (const ConstString& s1, const char16* s2) {return String (s1).append (s2);}
  392. inline String operator+ (const char8* s1, const ConstString& s2) {return String (s1).append (s2);}
  393. inline String operator+ (const char16* s1, const ConstString& s2) {return String (s1).append (s2);}
  394. inline String operator+ (const ConstString& s1, const String& s2) {return String (s1).append (s2);}
  395. inline String operator+ (const String& s1, const ConstString& s2) {return String (s1).append (s2);}
  396. inline String operator+ (const String& s1, const String& s2) {return String (s1).append (s2);}
  397. inline String operator+ (const String& s1, const char8* s2) {return String (s1).append (s2);}
  398. inline String operator+ (const String& s1, const char16* s2) {return String (s1).append (s2);}
  399. inline String operator+ (const char8* s1, const String& s2) {return String (s1).append (s2);}
  400. inline String operator+ (const char16* s1, const String& s2) {return String (s1).append (s2);}
  401. //-----------------------------------------------------------------------------
  402. // ConstString
  403. //-----------------------------------------------------------------------------
  404. inline const tchar* ConstString::text () const
  405. {
  406. #ifdef UNICODE
  407. return text16 ();
  408. #else
  409. return text8 ();
  410. #endif
  411. }
  412. //-----------------------------------------------------------------------------
  413. inline const char8* ConstString::text8 () const
  414. {
  415. return (!isWide && buffer8) ? buffer8: kEmptyString8;
  416. }
  417. //-----------------------------------------------------------------------------
  418. inline const char16* ConstString::text16 () const
  419. {
  420. return (isWide && buffer16) ? buffer16 : kEmptyString16;
  421. }
  422. //-----------------------------------------------------------------------------
  423. inline char8 ConstString::getChar8 (uint32 index) const
  424. {
  425. if (index < len && buffer8 && !isWide)
  426. return buffer8[index];
  427. return 0;
  428. }
  429. //-----------------------------------------------------------------------------
  430. inline char16 ConstString::getChar16 (uint32 index) const
  431. {
  432. if (index < len && buffer16 && isWide)
  433. return buffer16[index];
  434. return 0;
  435. }
  436. //-----------------------------------------------------------------------------
  437. inline tchar ConstString::getChar (uint32 index) const
  438. {
  439. #ifdef UNICODE
  440. return getChar16 (index);
  441. #else
  442. return getChar8 (index);
  443. #endif
  444. }
  445. //-----------------------------------------------------------------------------
  446. inline tchar ConstString::getCharAt (uint32 index) const
  447. {
  448. #ifdef UNICODE
  449. if (isWide)
  450. return getChar16 (index);
  451. #endif
  452. return static_cast<tchar> (getChar8 (index));
  453. }
  454. //-----------------------------------------------------------------------------
  455. inline int64 ConstString::getNumber () const
  456. {
  457. int64 tmp = 0;
  458. scanInt64 (tmp);
  459. return tmp;
  460. }
  461. //-----------------------------------------------------------------------------
  462. inline bool ConstString::scanInt32_8 (const char8* text, int32& value, bool scanToEnd)
  463. {
  464. int64 tmp;
  465. if (scanInt64_8 (text, tmp, scanToEnd))
  466. {
  467. value = (int32)tmp;
  468. return true;
  469. }
  470. return false;
  471. }
  472. //-----------------------------------------------------------------------------
  473. inline bool ConstString::scanInt32_16 (const char16* text, int32& value, bool scanToEnd)
  474. {
  475. int64 tmp;
  476. if (scanInt64_16 (text, tmp, scanToEnd))
  477. {
  478. value = (int32)tmp;
  479. return true;
  480. }
  481. return false;
  482. }
  483. //-----------------------------------------------------------------------------
  484. inline bool ConstString::scanInt32 (const tchar* text, int32& value, bool scanToEnd)
  485. {
  486. int64 tmp;
  487. if (scanInt64 (text, tmp, scanToEnd))
  488. {
  489. value = (int32)tmp;
  490. return true;
  491. }
  492. return false;
  493. }
  494. //-----------------------------------------------------------------------------
  495. inline bool ConstString::scanUInt32_8 (const char8* text, uint32& value, bool scanToEnd)
  496. {
  497. uint64 tmp;
  498. if (scanUInt64_8 (text, tmp, scanToEnd))
  499. {
  500. value = (uint32)tmp;
  501. return true;
  502. }
  503. return false;
  504. }
  505. //-----------------------------------------------------------------------------
  506. inline bool ConstString::scanUInt32_16 (const char16* text, uint32& value, bool scanToEnd)
  507. {
  508. uint64 tmp;
  509. if (scanUInt64_16 (text, tmp, scanToEnd))
  510. {
  511. value = (uint32)tmp;
  512. return true;
  513. }
  514. return false;
  515. }
  516. //-----------------------------------------------------------------------------
  517. inline bool ConstString::scanUInt32 (const tchar* text, uint32& value, bool scanToEnd)
  518. {
  519. uint64 tmp;
  520. if (scanUInt64 (text, tmp, scanToEnd))
  521. {
  522. value = (uint32)tmp;
  523. return true;
  524. }
  525. return false;
  526. }
  527. //-----------------------------------------------------------------------------
  528. inline const char8* String::text8 () const
  529. {
  530. if (isWide && !isEmpty ())
  531. checkToMultiByte (); // this should be avoided, since it can lead to information loss
  532. return ConstString::text8 ();
  533. }
  534. //-----------------------------------------------------------------------------
  535. inline const char16* String::text16 () const
  536. {
  537. if (!isWide && !isEmpty ())
  538. {
  539. const_cast<String&> (*this).toWideString ();
  540. }
  541. return ConstString::text16 ();
  542. }
  543. //-----------------------------------------------------------------------------
  544. inline char8 String::getChar8 (uint32 index) const
  545. {
  546. if (isWide && !isEmpty ())
  547. checkToMultiByte (); // this should be avoided, since it can lead to information loss
  548. return ConstString::getChar8 (index);
  549. }
  550. //-----------------------------------------------------------------------------
  551. inline char16 String::getChar16 (uint32 index) const
  552. {
  553. if (!isWide && !isEmpty ())
  554. {
  555. const_cast<String&> (*this).toWideString ();
  556. }
  557. return ConstString::getChar16 (index);
  558. }
  559. //-----------------------------------------------------------------------------
  560. inline bool operator< (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) < 0) ? true : false;}
  561. inline bool operator<= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) <= 0) ? true : false;}
  562. inline bool operator> (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) > 0) ? true : false;}
  563. inline bool operator>= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) >= 0) ? true : false;}
  564. inline bool operator== (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) == 0) ? true : false;}
  565. inline bool operator!= (const ConstString& s1, const ConstString& s2) {return (s1.compare (s2) != 0) ? true : false;}
  566. inline bool operator< (const ConstString& s1, const char8* s2) {return (s1.compare (s2) < 0) ? true : false;}
  567. inline bool operator<= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) <= 0) ? true : false;}
  568. inline bool operator> (const ConstString& s1, const char8* s2) {return (s1.compare (s2) > 0) ? true : false;}
  569. inline bool operator>= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) >= 0) ? true : false;}
  570. inline bool operator== (const ConstString& s1, const char8* s2) {return (s1.compare (s2) == 0) ? true : false;}
  571. inline bool operator!= (const ConstString& s1, const char8* s2) {return (s1.compare (s2) != 0) ? true : false;}
  572. inline bool operator< (const char8* s1, const ConstString& s2) {return (s2.compare (s1) > 0) ? true : false;}
  573. inline bool operator<= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) >= 0) ? true : false;}
  574. inline bool operator> (const char8* s1, const ConstString& s2) {return (s2.compare (s1) < 0) ? true : false;}
  575. inline bool operator>= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) <= 0) ? true : false;}
  576. inline bool operator== (const char8* s1, const ConstString& s2) {return (s2.compare (s1) == 0) ? true : false;}
  577. inline bool operator!= (const char8* s1, const ConstString& s2) {return (s2.compare (s1) != 0) ? true : false;}
  578. inline bool operator< (const ConstString& s1, const char16* s2) {return (s1.compare (s2) < 0) ? true : false;}
  579. inline bool operator<= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) <= 0) ? true : false;}
  580. inline bool operator> (const ConstString& s1, const char16* s2) {return (s1.compare (s2) > 0) ? true : false;}
  581. inline bool operator>= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) >= 0) ? true : false;}
  582. inline bool operator== (const ConstString& s1, const char16* s2) {return (s1.compare (s2) == 0) ? true : false;}
  583. inline bool operator!= (const ConstString& s1, const char16* s2) {return (s1.compare (s2) != 0) ? true : false;}
  584. inline bool operator< (const char16* s1, const ConstString& s2) {return (s2.compare (s1) > 0) ? true : false;}
  585. inline bool operator<= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) >= 0) ? true : false;}
  586. inline bool operator> (const char16* s1, const ConstString& s2) {return (s2.compare (s1) < 0) ? true : false;}
  587. inline bool operator>= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) <= 0) ? true : false;}
  588. inline bool operator== (const char16* s1, const ConstString& s2) {return (s2.compare (s1) == 0) ? true : false;}
  589. inline bool operator!= (const char16* s1, const ConstString& s2) {return (s2.compare (s1) != 0) ? true : false;}
  590. // The following functions will only work with European Numbers!
  591. // (e.g. Arabic, Tibetan, and Khmer digits are not supported)
  592. extern int32 strnatcmp8 (const char8* s1, const char8* s2, bool caseSensitive = true);
  593. extern int32 strnatcmp16 (const char16* s1, const char16* s2, bool caseSensitive = true);
  594. inline int32 strnatcmp (const tchar* s1, const tchar* s2, bool caseSensitive = true)
  595. {
  596. #ifdef UNICODE
  597. return strnatcmp16 (s1, s2, caseSensitive);
  598. #else
  599. return strnatcmp8 (s1, s2, caseSensitive);
  600. #endif
  601. }
  602. //-----------------------------------------------------------------------------
  603. /** StringObject implements IStringResult and IString methods.
  604. It can therefore be exchanged with other Steinberg objects using one or both of these
  605. interfaces.
  606. \see String, ConstString
  607. */
  608. //-----------------------------------------------------------------------------
  609. class StringObject : public FObject, public String, public IStringResult, public IString
  610. {
  611. public:
  612. //-----------------------------------------------------------------------------
  613. StringObject () {}
  614. StringObject (const char16* str, int32 n = -1, bool isTerminated = true) : String (str, n, isTerminated) {}
  615. StringObject (const char8* str, int32 n = -1, bool isTerminated = true) : String (str, n, isTerminated) {}
  616. StringObject (const StringObject& str, int32 n = -1) : String (str, n) {}
  617. StringObject (const String& str, int32 n = -1) : String (str, n) {}
  618. StringObject (const FVariant& var) : String (var) {}
  619. using String::operator=;
  620. // IStringResult ----------------------------------------------------------
  621. void PLUGIN_API setText (const char8* text) SMTG_OVERRIDE;
  622. //-------------------------------------------------------------------------
  623. // IString-----------------------------------------------------------------
  624. void PLUGIN_API setText8 (const char8* text) SMTG_OVERRIDE;
  625. void PLUGIN_API setText16 (const char16* text) SMTG_OVERRIDE;
  626. const char8* PLUGIN_API getText8 () SMTG_OVERRIDE;
  627. const char16* PLUGIN_API getText16 () SMTG_OVERRIDE;
  628. void PLUGIN_API take (void* s, bool _isWide) SMTG_OVERRIDE;
  629. bool PLUGIN_API isWideString () const SMTG_OVERRIDE;
  630. //-------------------------------------------------------------------------
  631. OBJ_METHODS (StringObject, FObject)
  632. FUNKNOWN_METHODS2 (IStringResult, IString, FObject)
  633. };
  634. //------------------------------------------------------------------------
  635. } // namespace Steinberg