CoreString.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #pragma once
  24. #include "Iterator.h"
  25. #include "Swap.h"
  26. #include <cstring>
  27. #include <ctype.h>
  28. /// String class
  29. class String
  30. {
  31. public:
  32. typedef RandomAccessIterator<char> Iterator;
  33. typedef RandomAccessConstIterator<char> ConstIterator;
  34. /// Construct empty
  35. String() :
  36. length_(0),
  37. capacity_(0),
  38. buffer_(&endZero)
  39. {
  40. }
  41. /// Construct from another string
  42. String(const String& str) :
  43. length_(0),
  44. capacity_(0),
  45. buffer_(&endZero)
  46. {
  47. *this = str;
  48. }
  49. /// Construct from a C string
  50. explicit String(const char* str) :
  51. length_(0),
  52. capacity_(0),
  53. buffer_(&endZero)
  54. {
  55. *this = str;
  56. }
  57. /// Destruct
  58. ~String()
  59. {
  60. if (capacity_)
  61. delete[] buffer_;
  62. }
  63. /// Assign a string
  64. String& operator = (const String& rhs)
  65. {
  66. Resize(rhs.length_);
  67. CopyChars(buffer_, rhs.buffer_, rhs.length_);
  68. return *this;
  69. }
  70. /// Assign a C string
  71. String& operator = (const char* rhs)
  72. {
  73. unsigned rhsLength = GetCStringLength(rhs);
  74. Resize(rhsLength);
  75. CopyChars(buffer_, rhs, rhsLength);
  76. return *this;
  77. }
  78. /// Add-assign a string
  79. String& operator += (const String& rhs)
  80. {
  81. if (rhs.length_)
  82. {
  83. unsigned oldLength = length_;
  84. Resize(length_ + rhs.length_);
  85. CopyChars(buffer_ + oldLength, rhs.buffer_, rhs.length_);
  86. }
  87. return *this;
  88. }
  89. /// Add-assign a C string
  90. String& operator += (const char* rhs)
  91. {
  92. unsigned rhsLength = GetCStringLength(rhs);
  93. if (rhsLength)
  94. {
  95. unsigned oldLength = length_;
  96. Resize(length_ + rhsLength);
  97. CopyChars(buffer_ + oldLength, rhs, rhsLength);
  98. }
  99. return *this;
  100. }
  101. /// Add-assign a character
  102. String& operator += (char rhs)
  103. {
  104. unsigned oldLength = length_;
  105. Resize(length_ + 1);
  106. buffer_[oldLength] = rhs;
  107. return *this;
  108. }
  109. /// Add a string
  110. String operator + (const String& rhs) const
  111. {
  112. String ret;
  113. ret.Resize(length_ + rhs.length_);
  114. CopyChars(ret.buffer_, buffer_, length_);
  115. CopyChars(ret.buffer_ + length_, rhs.buffer_, rhs.length_);
  116. return ret;
  117. }
  118. /// Add a C string
  119. String operator + (const char* rhs) const
  120. {
  121. if (!rhs)
  122. return String(*this);
  123. unsigned rhsLength = strlen(rhs);
  124. if (!rhsLength)
  125. return String(*this);
  126. String ret;
  127. ret.Resize(length_ + rhsLength);
  128. CopyChars(ret.buffer_, buffer_, length_);
  129. CopyChars(ret.buffer_ + length_, rhs, rhsLength);
  130. return ret;
  131. }
  132. /// Add a character
  133. String operator + (char rhs) const
  134. {
  135. String ret(*this);
  136. ret += rhs;
  137. return ret;
  138. }
  139. /// Test for equality
  140. bool operator == (const String& rhs) const
  141. {
  142. if (rhs.length_ != length_)
  143. return false;
  144. for (unsigned i = 0; i < length_; ++i)
  145. {
  146. if (buffer_[i] != rhs.buffer_[i])
  147. return false;
  148. }
  149. return true;
  150. }
  151. /// Test for inequality with another string
  152. bool operator != (const String& rhs) const
  153. {
  154. if (rhs.length_ != length_)
  155. return true;
  156. for (unsigned i = 0; i < length_; ++i)
  157. {
  158. if (buffer_[i] != rhs.buffer_[i])
  159. return true;
  160. }
  161. return false;
  162. }
  163. /// Test if string is less than another string
  164. bool operator < (const String& rhs) const
  165. {
  166. for (unsigned i = 0; (i < length_) && (i < rhs.length_); ++i)
  167. {
  168. if (buffer_[i] < rhs.buffer_[i])
  169. return true;
  170. if (buffer_[i] > rhs.buffer_[i])
  171. return false;
  172. }
  173. return length_ < rhs.length_;
  174. }
  175. /// Test if string is greater than another string
  176. bool operator > (const String& rhs) const
  177. {
  178. for (unsigned i = 0; (i < length_) && (i < rhs.length_); ++i)
  179. {
  180. if (buffer_[i] > rhs.buffer_[i])
  181. return true;
  182. if (buffer_[i] < rhs.buffer_[i])
  183. return false;
  184. }
  185. return length_ > rhs.length_;
  186. }
  187. /// Return char at index
  188. char& operator [] (unsigned pos) { return buffer_[pos]; }
  189. /// Return const char at index
  190. const char& operator [] (unsigned pos) const { return buffer_[pos]; }
  191. /// Replace all occurrences of a character
  192. void Replace(char replaceThis, char replaceWith);
  193. /// Replace all occurrences of a string
  194. void Replace(const String& replaceThis, const String& replaceWith);
  195. /// Replace a substring
  196. void Replace(unsigned pos, unsigned length, const String& replaceWith);
  197. /// Replace a substring using iterators
  198. Iterator Replace(const Iterator& start, const Iterator& end, const String& replaceWith);
  199. /// Insert a string
  200. void Insert(unsigned pos, const String& str);
  201. /// Insert a character
  202. void Insert(unsigned pos, char c);
  203. /// Insert a string using an iterator
  204. Iterator Insert(const Iterator& dest, const String& str);
  205. /// Insert a string partially using iterators
  206. Iterator Insert(const Iterator& dest, const Iterator& start, const Iterator& end);
  207. /// Insert a character using an iterator
  208. Iterator Insert(const Iterator& dest, char c);
  209. /// Erase a substring
  210. void Erase(unsigned pos, unsigned length = 1);
  211. /// Erase a character using an iterator
  212. Iterator Erase(const Iterator& it);
  213. /// Erase a substring using iterators
  214. Iterator Erase(const Iterator& start, const Iterator& end);
  215. /// Resize the string
  216. void Resize(unsigned newLength);
  217. /// Set new capacity
  218. void Reserve(unsigned newCapacity);
  219. /// Reallocate so that no extra memory is used
  220. void Compact();
  221. /// Clear the string
  222. void Clear();
  223. /// Swap with another string
  224. void Swap(String& str);
  225. /// Return iterator to the beginning
  226. Iterator Begin() { return Iterator(buffer_); }
  227. /// Return const iterator to the beginning
  228. ConstIterator Begin() const { return ConstIterator(buffer_); }
  229. /// Return iterator to the end
  230. Iterator End() { return Iterator(buffer_ + length_); }
  231. /// Return const iterator to the end
  232. ConstIterator End() const { return ConstIterator(buffer_ + length_); }
  233. /// Return a substring from position to end
  234. String Substring(unsigned pos) const;
  235. /// Return a substring with length from position
  236. String Substring(unsigned pos, unsigned length) const;
  237. /// Return string with whitespace trimmed from the beginning and the end
  238. String Trim() const;
  239. /// Return string in uppercase
  240. String ToUpper() const;
  241. /// Return string in lowercase
  242. String ToLower() const;
  243. /// Find the first occurrence of a string, or NPOS if not found
  244. unsigned Find(const String& str, unsigned startPos = 0) const;
  245. /// Find the first occurrence of a character, or NPOS if not found
  246. unsigned Find(char c, unsigned startPos = 0) const;
  247. /// Find the last occurrence of a string, or NPOS if not found
  248. unsigned FindLast(const String& str) const;
  249. /// Find the last occurrence of a character, or NPOS if not found
  250. unsigned FindLast(char c) const;
  251. /// Return the C string
  252. const char* CString() const { return buffer_; }
  253. /// Return length
  254. unsigned Length() const { return length_; }
  255. /// Return buffer capacity
  256. unsigned Capacity() const { return capacity_; }
  257. /// Return whether the string is empty
  258. bool Empty() const { return length_ == 0; }
  259. /// Position for "not found"
  260. static const unsigned NPOS = 0xffffffff;
  261. /// Initial dynamic allocation size
  262. static const unsigned MIN_CAPACITY = 8;
  263. private:
  264. /// Move a range of characters within the string
  265. void MoveRange(unsigned dest, unsigned src, unsigned count)
  266. {
  267. if (count)
  268. memmove(buffer_ + dest, buffer_ + src, count);
  269. }
  270. /// Copy chars from one buffer to another
  271. static void CopyChars(char* dest, const char* src, unsigned count)
  272. {
  273. #ifdef _MSC_VER
  274. if (count)
  275. memcpy(dest, src, count);
  276. #else
  277. char* end = dest + count;
  278. while (dest != end)
  279. {
  280. *dest = *src;
  281. ++dest;
  282. ++src;
  283. }
  284. #endif
  285. }
  286. /// Return length of a C string
  287. static unsigned GetCStringLength(const char* str)
  288. {
  289. if (!str)
  290. return 0;
  291. #ifdef _MSC_VER
  292. return strlen(str);
  293. #else
  294. const char* ptr = str;
  295. while (*ptr)
  296. ++ptr;
  297. return ptr - str;
  298. #endif
  299. }
  300. /// Replace a substring with another substring
  301. void Replace(unsigned pos, unsigned length, const char* srcStart, unsigned srcLength);
  302. /// String length
  303. unsigned length_;
  304. /// Capacity, zero if buffer not allocated
  305. unsigned capacity_;
  306. /// String buffer, null if not allocated
  307. char* buffer_;
  308. /// End zero for empty strings
  309. static char endZero;
  310. };
  311. /// Add a string to a C string
  312. inline String operator + (const char* lhs, const String& rhs)
  313. {
  314. String ret(lhs);
  315. ret += rhs;
  316. return ret;
  317. }