Str.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. //
  2. // Copyright (c) 2008-2020 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Container/Vector.h"
  24. #include <cstdarg>
  25. #include <cstring>
  26. #include <cctype>
  27. namespace Urho3D
  28. {
  29. static const int CONVERSION_BUFFER_LENGTH = 128;
  30. static const int MATRIX_CONVERSION_BUFFER_LENGTH = 256;
  31. class WString;
  32. class StringHash;
  33. template <class T, class U> class HashMap;
  34. /// Map of strings.
  35. using StringMap = HashMap<StringHash, String>;
  36. /// %String class.
  37. class URHO3D_API String
  38. {
  39. public:
  40. using Iterator = RandomAccessIterator<char>;
  41. using ConstIterator = RandomAccessConstIterator<char>;
  42. /// Construct empty.
  43. String() noexcept :
  44. length_(0),
  45. capacity_(0),
  46. buffer_(&endZero)
  47. {
  48. }
  49. /// Construct from another string.
  50. String(const String& str) :
  51. length_(0),
  52. capacity_(0),
  53. buffer_(&endZero)
  54. {
  55. *this = str;
  56. }
  57. /// Move-construct from another string.
  58. String(String && str) noexcept :
  59. length_(0),
  60. capacity_(0),
  61. buffer_(&endZero)
  62. {
  63. Swap(str);
  64. }
  65. /// Construct from a C string.
  66. String(const char* str) : // NOLINT(google-explicit-constructor)
  67. length_(0),
  68. capacity_(0),
  69. buffer_(&endZero)
  70. {
  71. *this = str;
  72. }
  73. /// Construct from a C string.
  74. String(char* str) : // NOLINT(google-explicit-constructor)
  75. length_(0),
  76. capacity_(0),
  77. buffer_(&endZero)
  78. {
  79. *this = (const char*)str;
  80. }
  81. /// Construct from a char array and length.
  82. String(const char* str, unsigned length) :
  83. length_(0),
  84. capacity_(0),
  85. buffer_(&endZero)
  86. {
  87. Resize(length);
  88. CopyChars(buffer_, str, length);
  89. }
  90. /// Construct from a null-terminated wide character array.
  91. explicit String(const wchar_t* str) :
  92. length_(0),
  93. capacity_(0),
  94. buffer_(&endZero)
  95. {
  96. SetUTF8FromWChar(str);
  97. }
  98. /// Construct from a null-terminated wide character array.
  99. explicit String(wchar_t* str) :
  100. length_(0),
  101. capacity_(0),
  102. buffer_(&endZero)
  103. {
  104. SetUTF8FromWChar(str);
  105. }
  106. /// Construct from a wide character string.
  107. explicit String(const WString& str);
  108. /// Construct from an integer.
  109. explicit String(int value);
  110. /// Construct from a short integer.
  111. explicit String(short value);
  112. /// Construct from a long integer.
  113. explicit String(long value);
  114. /// Construct from a long long integer.
  115. explicit String(long long value);
  116. /// Construct from an unsigned integer.
  117. explicit String(unsigned value);
  118. /// Construct from an unsigned short integer.
  119. explicit String(unsigned short value);
  120. /// Construct from an unsigned long integer.
  121. explicit String(unsigned long value);
  122. /// Construct from an unsigned long long integer.
  123. explicit String(unsigned long long value);
  124. /// Construct from a float.
  125. explicit String(float value);
  126. /// Construct from a double.
  127. explicit String(double value);
  128. /// Construct from a bool.
  129. explicit String(bool value);
  130. /// Construct from a character.
  131. explicit String(char value);
  132. /// Construct from a character and fill length.
  133. explicit String(char value, unsigned length);
  134. /// Construct from a convertible value.
  135. template <class T> explicit String(const T& value) :
  136. length_(0),
  137. capacity_(0),
  138. buffer_(&endZero)
  139. {
  140. *this = value.ToString();
  141. }
  142. /// Destruct.
  143. ~String()
  144. {
  145. if (capacity_)
  146. delete[] buffer_;
  147. }
  148. /// Assign a string.
  149. String& operator =(const String& rhs)
  150. {
  151. if (&rhs != this)
  152. {
  153. Resize(rhs.length_);
  154. CopyChars(buffer_, rhs.buffer_, rhs.length_);
  155. }
  156. return *this;
  157. }
  158. /// Move-assign a string.
  159. String& operator =(String && rhs) noexcept
  160. {
  161. assert(&rhs != this);
  162. Swap(rhs);
  163. return *this;
  164. }
  165. /// Assign a C string.
  166. String& operator =(const char* rhs)
  167. {
  168. unsigned rhsLength = CStringLength(rhs);
  169. Resize(rhsLength);
  170. CopyChars(buffer_, rhs, rhsLength);
  171. return *this;
  172. }
  173. /// Add-assign a string.
  174. String& operator +=(const String& rhs)
  175. {
  176. unsigned oldLength = length_;
  177. Resize(length_ + rhs.length_);
  178. CopyChars(buffer_ + oldLength, rhs.buffer_, rhs.length_);
  179. return *this;
  180. }
  181. /// Add-assign a C string.
  182. String& operator +=(const char* rhs)
  183. {
  184. unsigned rhsLength = CStringLength(rhs);
  185. unsigned oldLength = length_;
  186. Resize(length_ + rhsLength);
  187. CopyChars(buffer_ + oldLength, rhs, rhsLength);
  188. return *this;
  189. }
  190. /// Add-assign a character.
  191. String& operator +=(char rhs)
  192. {
  193. unsigned oldLength = length_;
  194. Resize(length_ + 1);
  195. buffer_[oldLength] = rhs;
  196. return *this;
  197. }
  198. /// Add-assign (concatenate as string) an integer.
  199. String& operator +=(int rhs);
  200. /// Add-assign (concatenate as string) a short integer.
  201. String& operator +=(short rhs);
  202. /// Add-assign (concatenate as string) a long integer.
  203. String& operator +=(long rhs);
  204. /// Add-assign (concatenate as string) a long long integer.
  205. String& operator +=(long long rhs);
  206. /// Add-assign (concatenate as string) an unsigned integer.
  207. String& operator +=(unsigned rhs);
  208. /// Add-assign (concatenate as string) a short unsigned integer.
  209. String& operator +=(unsigned short rhs);
  210. /// Add-assign (concatenate as string) a long unsigned integer.
  211. String& operator +=(unsigned long rhs);
  212. /// Add-assign (concatenate as string) a long long unsigned integer.
  213. String& operator +=(unsigned long long rhs);
  214. /// Add-assign (concatenate as string) a float.
  215. String& operator +=(float rhs);
  216. /// Add-assign (concatenate as string) a bool.
  217. String& operator +=(bool rhs);
  218. /// Add-assign (concatenate as string) an arbitrary type.
  219. template <class T> String& operator +=(const T& rhs) { return *this += rhs.ToString(); }
  220. /// Add a string.
  221. String operator +(const String& rhs) const
  222. {
  223. String ret;
  224. ret.Resize(length_ + rhs.length_);
  225. CopyChars(ret.buffer_, buffer_, length_);
  226. CopyChars(ret.buffer_ + length_, rhs.buffer_, rhs.length_);
  227. return ret;
  228. }
  229. /// Add a C string.
  230. String operator +(const char* rhs) const
  231. {
  232. unsigned rhsLength = CStringLength(rhs);
  233. String ret;
  234. ret.Resize(length_ + rhsLength);
  235. CopyChars(ret.buffer_, buffer_, length_);
  236. CopyChars(ret.buffer_ + length_, rhs, rhsLength);
  237. return ret;
  238. }
  239. /// Test for equality with another string.
  240. bool operator ==(const String& rhs) const { return strcmp(CString(), rhs.CString()) == 0; }
  241. /// Test for inequality with another string.
  242. bool operator !=(const String& rhs) const { return strcmp(CString(), rhs.CString()) != 0; }
  243. /// Test if string is less than another string.
  244. bool operator <(const String& rhs) const { return strcmp(CString(), rhs.CString()) < 0; }
  245. /// Test if string is greater than another string.
  246. bool operator >(const String& rhs) const { return strcmp(CString(), rhs.CString()) > 0; }
  247. /// Test for equality with a C string.
  248. bool operator ==(const char* rhs) const { return strcmp(CString(), rhs) == 0; }
  249. /// Test for inequality with a C string.
  250. bool operator !=(const char* rhs) const { return strcmp(CString(), rhs) != 0; }
  251. /// Test if string is less than a C string.
  252. bool operator <(const char* rhs) const { return strcmp(CString(), rhs) < 0; }
  253. /// Test if string is greater than a C string.
  254. bool operator >(const char* rhs) const { return strcmp(CString(), rhs) > 0; }
  255. /// Return char at index.
  256. char& operator [](unsigned index)
  257. {
  258. assert(index < length_);
  259. return buffer_[index];
  260. }
  261. /// Return const char at index.
  262. const char& operator [](unsigned index) const
  263. {
  264. assert(index < length_);
  265. return buffer_[index];
  266. }
  267. /// Return char at index.
  268. char& At(unsigned index)
  269. {
  270. assert(index < length_);
  271. return buffer_[index];
  272. }
  273. /// Return const char at index.
  274. const char& At(unsigned index) const
  275. {
  276. assert(index < length_);
  277. return buffer_[index];
  278. }
  279. /// Replace all occurrences of a character.
  280. void Replace(char replaceThis, char replaceWith, bool caseSensitive = true);
  281. /// Replace all occurrences of a string.
  282. void Replace(const String& replaceThis, const String& replaceWith, bool caseSensitive = true);
  283. /// Replace a substring.
  284. void Replace(unsigned pos, unsigned length, const String& replaceWith);
  285. /// Replace a substring with a C string.
  286. void Replace(unsigned pos, unsigned length, const char* replaceWith);
  287. /// Replace a substring by iterators.
  288. Iterator Replace(const Iterator& start, const Iterator& end, const String& replaceWith);
  289. /// Return a string with all occurrences of a character replaced.
  290. String Replaced(char replaceThis, char replaceWith, bool caseSensitive = true) const;
  291. /// Return a string with all occurrences of a string replaced.
  292. String Replaced(const String& replaceThis, const String& replaceWith, bool caseSensitive = true) const;
  293. /// Append a string.
  294. String& Append(const String& str);
  295. /// Append a C string.
  296. String& Append(const char* str);
  297. /// Append a character.
  298. String& Append(char c);
  299. /// Append characters.
  300. String& Append(const char* str, unsigned length);
  301. /// Insert a string.
  302. void Insert(unsigned pos, const String& str);
  303. /// Insert a character.
  304. void Insert(unsigned pos, char c);
  305. /// Insert a string by iterator.
  306. Iterator Insert(const Iterator& dest, const String& str);
  307. /// Insert a string partially by iterators.
  308. Iterator Insert(const Iterator& dest, const Iterator& start, const Iterator& end);
  309. /// Insert a character by iterator.
  310. Iterator Insert(const Iterator& dest, char c);
  311. /// Erase a substring.
  312. void Erase(unsigned pos, unsigned length = 1);
  313. /// Erase a character by iterator.
  314. Iterator Erase(const Iterator& it);
  315. /// Erase a substring by iterators.
  316. Iterator Erase(const Iterator& start, const Iterator& end);
  317. /// Resize the string.
  318. void Resize(unsigned newLength);
  319. /// Set new capacity.
  320. void Reserve(unsigned newCapacity);
  321. /// Reallocate so that no extra memory is used.
  322. void Compact();
  323. /// Clear the string.
  324. void Clear();
  325. /// Swap with another string.
  326. void Swap(String& str);
  327. /// Return iterator to the beginning.
  328. Iterator Begin() { return Iterator(buffer_); }
  329. /// Return const iterator to the beginning.
  330. ConstIterator Begin() const { return ConstIterator(buffer_); }
  331. /// Return iterator to the end.
  332. Iterator End() { return Iterator(buffer_ + length_); }
  333. /// Return const iterator to the end.
  334. ConstIterator End() const { return ConstIterator(buffer_ + length_); }
  335. /// Return first char, or 0 if empty.
  336. char Front() const { return buffer_[0]; }
  337. /// Return last char, or 0 if empty.
  338. char Back() const { return length_ ? buffer_[length_ - 1] : buffer_[0]; }
  339. /// Return a substring from position to end.
  340. String Substring(unsigned pos) const;
  341. /// Return a substring with length from position.
  342. String Substring(unsigned pos, unsigned length) const;
  343. /// Return string with whitespace trimmed from the beginning and the end.
  344. String Trimmed() const;
  345. /// Return string in uppercase.
  346. String ToUpper() const;
  347. /// Return string in lowercase.
  348. String ToLower() const;
  349. /// Return substrings split by a separator char. By default don't return empty strings.
  350. Vector<String> Split(char separator, bool keepEmptyStrings = false) const;
  351. /// Join substrings with a 'glue' string.
  352. void Join(const Vector<String>& subStrings, const String& glue);
  353. /// Return index to the first occurrence of a string, or NPOS if not found.
  354. unsigned Find(const String& str, unsigned startPos = 0, bool caseSensitive = true) const;
  355. /// Return index to the first occurrence of a character, or NPOS if not found.
  356. unsigned Find(char c, unsigned startPos = 0, bool caseSensitive = true) const;
  357. /// Return index to the last occurrence of a string, or NPOS if not found.
  358. unsigned FindLast(const String& str, unsigned startPos = NPOS, bool caseSensitive = true) const;
  359. /// Return index to the last occurrence of a character, or NPOS if not found.
  360. unsigned FindLast(char c, unsigned startPos = NPOS, bool caseSensitive = true) const;
  361. /// Return whether starts with a string.
  362. bool StartsWith(const String& str, bool caseSensitive = true) const;
  363. /// Return whether ends with a string.
  364. bool EndsWith(const String& str, bool caseSensitive = true) const;
  365. /// Return the C string.
  366. const char* CString() const { return buffer_; }
  367. /// Return length.
  368. unsigned Length() const { return length_; }
  369. /// Return buffer capacity.
  370. unsigned Capacity() const { return capacity_; }
  371. /// Return whether the string is empty.
  372. bool Empty() const { return length_ == 0; }
  373. /// Return comparison result with a string.
  374. int Compare(const String& str, bool caseSensitive = true) const;
  375. /// Return comparison result with a C string.
  376. int Compare(const char* str, bool caseSensitive = true) const;
  377. /// Return whether contains a specific occurrence of a string.
  378. bool Contains(const String& str, bool caseSensitive = true) const { return Find(str, 0, caseSensitive) != NPOS; }
  379. /// Return whether contains a specific character.
  380. bool Contains(char c, bool caseSensitive = true) const { return Find(c, 0, caseSensitive) != NPOS; }
  381. /// Construct UTF8 content from Latin1.
  382. void SetUTF8FromLatin1(const char* str);
  383. /// Construct UTF8 content from wide characters.
  384. void SetUTF8FromWChar(const wchar_t* str);
  385. /// Calculate number of characters in UTF8 content.
  386. unsigned LengthUTF8() const;
  387. /// Return byte offset to char in UTF8 content.
  388. unsigned ByteOffsetUTF8(unsigned index) const;
  389. /// Return next Unicode character from UTF8 content and increase byte offset.
  390. unsigned NextUTF8Char(unsigned& byteOffset) const;
  391. /// Return Unicode character at index from UTF8 content.
  392. unsigned AtUTF8(unsigned index) const;
  393. /// Replace Unicode character at index from UTF8 content.
  394. void ReplaceUTF8(unsigned index, unsigned unicodeChar);
  395. /// Append Unicode character at the end as UTF8.
  396. String& AppendUTF8(unsigned unicodeChar);
  397. /// Return a UTF8 substring from position to end.
  398. String SubstringUTF8(unsigned pos) const;
  399. /// Return a UTF8 substring with length from position.
  400. String SubstringUTF8(unsigned pos, unsigned length) const;
  401. /// Return hash value for HashSet & HashMap.
  402. unsigned ToHash() const
  403. {
  404. unsigned hash = 0;
  405. const char* ptr = buffer_;
  406. while (*ptr)
  407. {
  408. hash = *ptr + (hash << 6u) + (hash << 16u) - hash;
  409. ++ptr;
  410. }
  411. return hash;
  412. }
  413. /// Return substrings split by a separator char. By default don't return empty strings.
  414. static Vector<String> Split(const char* str, char separator, bool keepEmptyStrings = false);
  415. /// Return a string by joining substrings with a 'glue' string.
  416. static String Joined(const Vector<String>& subStrings, const String& glue);
  417. /// Encode Unicode character to UTF8. Pointer will be incremented.
  418. static void EncodeUTF8(char*& dest, unsigned unicodeChar);
  419. /// Decode Unicode character from UTF8. Pointer will be incremented.
  420. static unsigned DecodeUTF8(const char*& src);
  421. #ifdef _WIN32
  422. /// Encode Unicode character to UTF16. Pointer will be incremented.
  423. static void EncodeUTF16(wchar_t*& dest, unsigned unicodeChar);
  424. /// Decode Unicode character from UTF16. Pointer will be incremented.
  425. static unsigned DecodeUTF16(const wchar_t*& src);
  426. #endif
  427. /// Return length of a C string.
  428. static unsigned CStringLength(const char* str) { return str ? (unsigned)strlen(str) : 0; }
  429. /// Append to string using formatting.
  430. String& AppendWithFormat(const char* formatString, ...);
  431. /// Append to string using variable arguments.
  432. String& AppendWithFormatArgs(const char* formatString, va_list args);
  433. /// Compare two C strings.
  434. static int Compare(const char* lhs, const char* rhs, bool caseSensitive);
  435. /// Position for "not found".
  436. static const unsigned NPOS = 0xffffffff;
  437. /// Initial dynamic allocation size.
  438. static const unsigned MIN_CAPACITY = 8;
  439. /// Empty string.
  440. static const String EMPTY;
  441. private:
  442. /// Move a range of characters within the string.
  443. void MoveRange(unsigned dest, unsigned src, unsigned count)
  444. {
  445. if (count)
  446. memmove(buffer_ + dest, buffer_ + src, count);
  447. }
  448. /// Copy chars from one buffer to another.
  449. static void CopyChars(char* dest, const char* src, unsigned count)
  450. {
  451. #ifdef _MSC_VER
  452. if (count)
  453. memcpy(dest, src, count);
  454. #else
  455. char* end = dest + count;
  456. while (dest != end)
  457. {
  458. *dest = *src;
  459. ++dest;
  460. ++src;
  461. }
  462. #endif
  463. }
  464. /// Replace a substring with another substring.
  465. void Replace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength);
  466. /// String length.
  467. unsigned length_;
  468. /// Capacity, zero if buffer not allocated.
  469. unsigned capacity_;
  470. /// String buffer, point to &endZero if buffer is not allocated.
  471. char* buffer_;
  472. /// End zero for empty strings.
  473. static char endZero;
  474. };
  475. /// Add a string to a C string.
  476. inline String operator +(const char* lhs, const String& rhs)
  477. {
  478. String ret(lhs);
  479. ret += rhs;
  480. return ret;
  481. }
  482. /// Add a string to a wide char C string.
  483. inline String operator +(const wchar_t* lhs, const String& rhs)
  484. {
  485. String ret(lhs);
  486. ret += rhs;
  487. return ret;
  488. }
  489. /// Wide character string. Only meant for converting from String and passing to the operating system where necessary.
  490. class URHO3D_API WString
  491. {
  492. public:
  493. /// Construct empty.
  494. WString();
  495. /// Construct from a string.
  496. explicit WString(const String& str);
  497. /// Destruct.
  498. ~WString();
  499. /// Return char at index.
  500. wchar_t& operator [](unsigned index)
  501. {
  502. assert(index < length_);
  503. return buffer_[index];
  504. }
  505. /// Return const char at index.
  506. const wchar_t& operator [](unsigned index) const
  507. {
  508. assert(index < length_);
  509. return buffer_[index];
  510. }
  511. /// Return char at index.
  512. wchar_t& At(unsigned index)
  513. {
  514. assert(index < length_);
  515. return buffer_[index];
  516. }
  517. /// Return const char at index.
  518. const wchar_t& At(unsigned index) const
  519. {
  520. assert(index < length_);
  521. return buffer_[index];
  522. }
  523. /// Resize the string.
  524. void Resize(unsigned newLength);
  525. /// Return whether the string is empty.
  526. bool Empty() const { return length_ == 0; }
  527. /// Return length.
  528. unsigned Length() const { return length_; }
  529. /// Return character data.
  530. const wchar_t* CString() const { return buffer_; }
  531. private:
  532. /// String length.
  533. unsigned length_;
  534. /// String buffer, null if not allocated.
  535. wchar_t* buffer_;
  536. };
  537. }