StringBase.inl 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. /*
  2. * This source file is part of libRocket, the HTML/CSS Interface Middleware
  3. *
  4. * For the latest information, see http://www.librocket.com
  5. *
  6. * Copyright (c) 2008-2010 CodePoint Ltd, Shift Technology Ltd
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. *
  26. */
  27. template< typename T >
  28. StringBase< T >::StringBase()
  29. {
  30. string_id = 0;
  31. length = 0;
  32. value = (T*)StringStorage::empty_string;
  33. }
  34. template< typename T >
  35. StringBase< T >::StringBase(const StringBase< T >& copy)
  36. {
  37. string_id = 0;
  38. length = 0;
  39. value = (T*)StringStorage::empty_string;
  40. *this = copy;
  41. }
  42. template< typename T >
  43. StringBase< T >::StringBase(const T* string)
  44. {
  45. string_id = 0;
  46. length = 0;
  47. value = (T*)StringStorage::empty_string;
  48. *this = string;
  49. }
  50. template< typename T >
  51. StringBase< T >::StringBase(const T* string_start, const T* string_end)
  52. {
  53. string_id = 0;
  54. length = (string_end - string_start);
  55. if (length == 0)
  56. {
  57. value = (T*)StringStorage::empty_string;
  58. }
  59. else
  60. {
  61. value = (T*)StringStorage::ReallocString(NULL, 0, length, sizeof(T));
  62. Copy(value, string_start, length, true);
  63. }
  64. }
  65. template< typename T >
  66. StringBase< T >::StringBase(size_type count, const T character)
  67. {
  68. string_id = 0;
  69. length = count;
  70. value = (T*)StringStorage::ReallocString(NULL, 0, length, sizeof(T));
  71. for (size_type i = 0; i < length; i++)
  72. value[i] = character;
  73. value[length] = 0;
  74. }
  75. template< typename T >
  76. StringBase< T >::StringBase(size_type ROCKET_UNUSED(max_length), const T* ROCKET_UNUSED(fmt), ...)
  77. {
  78. string_id = 0;
  79. length = 0;
  80. value = (T*)StringStorage::empty_string;
  81. // Can't implement this at the base level, requires template specialisation
  82. ROCKET_ERRORMSG("Not implemented.");
  83. }
  84. template< typename T >
  85. StringBase< T >::~StringBase()
  86. {
  87. Release();
  88. }
  89. template< typename T >
  90. bool StringBase< T >::Empty() const
  91. {
  92. return length == 0;
  93. }
  94. template< typename T >
  95. void StringBase< T >::Clear()
  96. {
  97. Release();
  98. length = 0;
  99. string_id = 0;
  100. value = (T*)StringStorage::empty_string;
  101. }
  102. template< typename T >
  103. typename StringBase< T >::size_type StringBase< T >::Length() const
  104. {
  105. return length;
  106. }
  107. template< typename T >
  108. const T* StringBase< T >::CString() const
  109. {
  110. return value;
  111. }
  112. template< typename T >
  113. typename StringBase< T >::size_type StringBase< T >::Find(const T* find, size_type offset) const
  114. {
  115. return _Find(find, GetLength(find), offset);
  116. }
  117. template< typename T >
  118. typename StringBase< T >::size_type StringBase< T >::Find(const StringBase< T >& find, size_type offset) const
  119. {
  120. return _Find(find.CString(), find.Length(), offset);
  121. }
  122. template< typename T >
  123. typename StringBase< T >::size_type StringBase< T >::RFind(const T* find, size_type offset) const
  124. {
  125. return _RFind(find, GetLength(find), offset);
  126. }
  127. template< typename T >
  128. typename StringBase< T >::size_type StringBase< T >::RFind(const StringBase< T >& find, size_type offset) const
  129. {
  130. return _RFind(find.CString(), find.Length(), offset);
  131. }
  132. template< typename T >
  133. StringBase< T > StringBase< T >::Replace(const T* find, const T* replace) const
  134. {
  135. return _Replace(find, GetLength(find), replace, GetLength(replace));
  136. }
  137. template< typename T >
  138. StringBase< T > StringBase< T >::Replace(const StringBase< T >& find, const StringBase< T >& replace) const
  139. {
  140. return _Replace(find.CString(), find.Length(), replace.CString(), replace.Length());
  141. }
  142. template< typename T >
  143. StringBase< T > StringBase< T >::Substring(size_type start, size_type count) const
  144. {
  145. // Ensure we're not going of bounds
  146. if (count > length - start)
  147. count = length - start;
  148. if (start > length)
  149. count = 0;
  150. return StringBase< T >(&value[start], &value[start + count]);
  151. }
  152. template< typename T >
  153. StringBase< T >& StringBase< T >::Append(const T* append, size_type count)
  154. {
  155. return _Append(append, GetLength(append), count);
  156. }
  157. template< typename T >
  158. StringBase< T >& StringBase< T >::Append(const StringBase< T >& append, size_type count)
  159. {
  160. return _Append(append.CString(), append.Length(), count);
  161. }
  162. template< typename T >
  163. StringBase< T >& StringBase< T >::Append(const T& append)
  164. {
  165. T buffer[2] = { append, 0 };
  166. return (*this += buffer);
  167. }
  168. template< typename T >
  169. StringBase< T >& StringBase< T >::Assign(const T* assign, size_type count)
  170. {
  171. size_type assign_length = GetLength(assign);
  172. return _Assign(assign, count > assign_length ? assign_length : count);
  173. }
  174. template< typename T >
  175. StringBase< T >& StringBase< T >::Assign(const T* assign, const T* end)
  176. {
  177. return _Assign(assign, end - assign);
  178. }
  179. template< typename T >
  180. StringBase< T >& StringBase< T >::Assign(const StringBase< T >& assign, size_type count)
  181. {
  182. if (count == npos)
  183. {
  184. // We can do the complete assignment really fast as we're
  185. // just reference counting
  186. *this = assign;
  187. }
  188. else
  189. {
  190. // Do a normal (slow) assign
  191. Assign(assign.CString(), count);
  192. }
  193. return *this;
  194. }
  195. // Insert a string into this string
  196. template< typename T >
  197. void StringBase< T >::Insert(size_type index, const T* insert, size_type count)
  198. {
  199. return _Insert(index, insert, GetLength(insert), count);
  200. }
  201. // Insert a string into this string
  202. template< typename T >
  203. void StringBase< T >::Insert(size_type index, const StringBase< T >& insert, size_type count)
  204. {
  205. return _Insert(index, insert.CString(), insert.Length(), count);
  206. }
  207. // Insert a character into this string
  208. template< typename T >
  209. void StringBase< T >::Insert(size_type index, const T& insert)
  210. {
  211. return _Insert(index, &insert, 1, 1);
  212. }
  213. /// Erase characters from this string
  214. template< typename T >
  215. void StringBase< T >::Erase(size_type index, size_type count)
  216. {
  217. if (index >= length)
  218. return;
  219. if (count == npos)
  220. {
  221. Resize(index);
  222. }
  223. else
  224. {
  225. size_type erase_amount = count < length - index ? count : length - index;
  226. Modify(length);
  227. Copy(&value[index], &value[index + erase_amount], length - index - erase_amount, true);
  228. length -= erase_amount;
  229. if (length == 0)
  230. Clear();
  231. }
  232. }
  233. template< typename T >
  234. int StringBase< T >::FormatString(size_type ROCKET_UNUSED(max_length), const T* ROCKET_UNUSED(fmt), ...)
  235. {
  236. ROCKET_ERRORMSG("Not implemented.");
  237. return -1;
  238. }
  239. template< typename T >
  240. void StringBase< T >::Resize(size_type new_length)
  241. {
  242. Modify(new_length, true);
  243. length = new_length;
  244. if (length == 0)
  245. Clear();
  246. }
  247. // Create a lowercase version of the string
  248. template< typename T >
  249. StringBase< T > StringBase< T >::ToLower() const
  250. {
  251. // Loop through the string, looking for an uppercase character
  252. size_t copy_index = npos;
  253. for (size_t i = 0; i < length; i++)
  254. {
  255. if (value[i] >= 'A' && value[i] <= 'Z')
  256. {
  257. copy_index = i;
  258. break;
  259. }
  260. }
  261. // If theres no lowercase letters, simply copy us direct
  262. if (copy_index == npos)
  263. return StringBase< T >(*this);
  264. StringBase< T > lowercase(CString(), CString() + copy_index);
  265. // Otherwise trawl through the rest of the letters
  266. for (size_t i = copy_index; i < length; i++)
  267. {
  268. if (value[i] >= 'A' && value[i] <= 'Z')
  269. lowercase.Append((T)(value[i] + ('a' - 'A')));
  270. else
  271. lowercase.Append(value[i]);
  272. }
  273. return lowercase;
  274. }
  275. // Create a lowercase version of the string
  276. template< typename T >
  277. StringBase< T > StringBase< T >::ToUpper() const
  278. {
  279. // Loop through the string, looking for an uppercase character
  280. size_t copy_index = npos;
  281. for (size_t i = 0; i < length; i++)
  282. {
  283. if (value[i] >= 'a' && value[i] <= 'z')
  284. {
  285. copy_index = i;
  286. break;
  287. }
  288. }
  289. // If theres no lowercase letters, simply copy us direct
  290. if (copy_index == npos)
  291. return StringBase< T >(*this);
  292. StringBase< T > uppercase(CString(), CString() + copy_index);
  293. // Otherwise trawl through the rest of the letters
  294. for (size_t i = copy_index; i < length; i++)
  295. {
  296. if (value[i] >= 'a' && value[i] <= 'z')
  297. uppercase.Append((T)(value[i] - ('a' - 'A')));
  298. else
  299. uppercase.Append(value[i]);
  300. }
  301. return uppercase;
  302. }
  303. template< typename T >
  304. bool StringBase< T >::operator==(const T* compare) const
  305. {
  306. size_type index = 0;
  307. while (compare[index] && value[index] && compare[index] == value[index])
  308. index++;
  309. return index == length && compare[index] == 0;
  310. }
  311. template< typename T >
  312. bool StringBase< T >::operator==(const StringBase< T >& compare) const
  313. {
  314. AddStorage();
  315. compare.AddStorage();
  316. return compare.string_id == string_id;
  317. }
  318. template< typename T >
  319. bool StringBase< T >::operator!=(const T* compare) const
  320. {
  321. return !(*this == compare);
  322. }
  323. template< typename T >
  324. bool StringBase< T >::operator!=(const StringBase< T >& compare) const
  325. {
  326. return !(*this == compare);
  327. }
  328. template< typename T >
  329. bool StringBase< T >::operator<(const T* compare) const
  330. {
  331. size_type index = 0;
  332. while (index < length && compare[index] && compare[index] == value[index])
  333. index++;
  334. // Check if we reached the end of the string
  335. if (index < length)
  336. {
  337. // If we didn't check if we reached the end of
  338. // the string we're comparing against, if so
  339. // then we're not less than
  340. if (compare[index] == 0)
  341. return false;
  342. // Check the character at index
  343. return value[index] < compare[index];
  344. }
  345. else
  346. {
  347. // We reached the end of our string,
  348. // if the string we're comparing with still
  349. // has data, then we're smaller
  350. if (compare[index] != 0)
  351. return true;
  352. }
  353. return false;
  354. }
  355. template< typename T >
  356. bool StringBase< T >::operator<(const StringBase< T >& compare) const
  357. {
  358. return *this < compare.CString();
  359. }
  360. template< typename T >
  361. StringBase< T >& StringBase< T >::operator=(const T* assign)
  362. {
  363. return Assign(assign);
  364. }
  365. template< typename T >
  366. StringBase< T >& StringBase< T >::operator=(const StringBase< T >& assign)
  367. {
  368. assign.AddStorage();
  369. StringStorage::AddReference(assign.string_id);
  370. Release();
  371. string_id = assign.string_id;
  372. value = assign.value;
  373. length = assign.length;
  374. return *this;
  375. }
  376. template< typename T >
  377. StringBase< T > StringBase< T >::operator+(const T* add) const
  378. {
  379. StringBase< T > combined(*this);
  380. combined.Append(add);
  381. return combined;
  382. }
  383. template< typename T >
  384. StringBase< T > StringBase< T >::operator+(const StringBase< T >& add) const
  385. {
  386. StringBase< T > combined(*this);
  387. combined.Append(add);
  388. return combined;
  389. }
  390. template< typename T >
  391. StringBase< T >& StringBase< T >::operator+=(const T* add)
  392. {
  393. return Append(add);
  394. }
  395. template< typename T >
  396. StringBase< T >& StringBase< T >::operator+=(const StringBase< T >& add)
  397. {
  398. return Append(add.CString());
  399. }
  400. template< typename T >
  401. StringBase< T >& StringBase< T >::operator+=(const T& add)
  402. {
  403. return Append(add);
  404. }
  405. template< typename T >
  406. const T& StringBase< T >::operator[](size_type index) const
  407. {
  408. ROCKET_ASSERT(index < length);
  409. return value[index];
  410. }
  411. template< typename T >
  412. T& StringBase< T >::operator[](size_type index)
  413. {
  414. ROCKET_ASSERT(index < length);
  415. return value[index];
  416. }
  417. template< typename T >
  418. typename StringBase< T >::size_type StringBase< T >::GetLength(const T* string) const
  419. {
  420. const T* ptr = string;
  421. while (*ptr)
  422. {
  423. ptr++;
  424. }
  425. return ptr - string;
  426. }
  427. template< typename T >
  428. void StringBase< T >::AddStorage() const
  429. {
  430. if (string_id > 0 || value == (T*)StringStorage::empty_string)
  431. return;
  432. const char* str = (const char*)value;
  433. string_id = StringStorage::AddString(str, length, sizeof(T));
  434. value = (T*)str;
  435. }
  436. template< typename T >
  437. void StringBase< T >::Modify(size_type new_size, bool shrink)
  438. {
  439. T* new_value = value;
  440. if (string_id > 0)
  441. {
  442. // If the string is in storage, we have to allocate a new buffer
  443. // and copy the string into the new buffer (including NULL)
  444. // Its up to the calling function to release it from storage when the
  445. // modifcations are done
  446. new_value = (T*)StringStorage::ReallocString(NULL, 0, new_size, sizeof(T));
  447. Copy(new_value, value, new_size > length ? length : new_size, true);
  448. // Release the old string value and assign the newly-allocated value as this string's value.
  449. Release();
  450. value = new_value;
  451. }
  452. else
  453. {
  454. // If we're not in storage and we're growing, do a realloc, otherwise we'll stay the same size
  455. if (new_size > length)
  456. {
  457. new_value = (T*)StringStorage::ReallocString((char*)value, length, new_size, sizeof(T));
  458. value = new_value;
  459. }
  460. else if (new_size < length && shrink)
  461. {
  462. new_value = (T*)StringStorage::ReallocString(NULL, 0, new_size, sizeof(T));
  463. Copy(new_value, value, new_size, true);
  464. // Release the old value and assign the newly-allocated value as this string's value.
  465. Release();
  466. value = new_value;
  467. }
  468. }
  469. }
  470. template< typename T >
  471. void StringBase< T >::Copy(T* target, const T* src, size_type length, bool terminate) const
  472. {
  473. // Copy values
  474. for (size_type i = 0; i < length; i++)
  475. {
  476. *target++ = *src++;
  477. }
  478. if (terminate)
  479. {
  480. *target++ = 0;
  481. }
  482. }
  483. template< typename T >
  484. void StringBase< T >::Release() const
  485. {
  486. // If theres a valid string id remove the reference
  487. // otherwise ask the storage to release our local buffer
  488. if (string_id > 0)
  489. {
  490. StringStorage::RemoveReference(string_id);
  491. string_id = 0;
  492. }
  493. else if (value != (T*)StringStorage::empty_string)
  494. {
  495. StringStorage::ReleaseString((char*)value, length);
  496. }
  497. }
  498. template< typename T >
  499. typename StringBase< T >::size_type StringBase< T >::_Find(const T* find, size_type find_length, size_type offset) const
  500. {
  501. size_type needle_index = 0;
  502. size_type haystack_index = offset;
  503. // If the find length is greater than the string we have, it can't be here
  504. if (find_length > length)
  505. return npos;
  506. // While there's still data in the haystack loop
  507. while (value[haystack_index])
  508. {
  509. // If the current haystack posize_typeer plus needle offset matches,
  510. // advance the needle index
  511. if (value[haystack_index + needle_index] == find[needle_index])
  512. {
  513. needle_index++;
  514. // If we reach the end of the search term, return the current haystack index
  515. if (needle_index == find_length)
  516. return haystack_index;
  517. }
  518. else
  519. {
  520. // Advance haystack index by one and reset needle index.
  521. haystack_index++;
  522. needle_index = 0;
  523. }
  524. }
  525. return npos;
  526. }
  527. template< typename T >
  528. typename StringBase< T >::size_type StringBase< T >::_RFind(const T* find, size_type find_length, size_type offset) const
  529. {
  530. ROCKET_ASSERT(find_length > 0);
  531. size_type needle_index = 0;
  532. size_type haystack_index = (offset < length ? offset : length) - find_length;
  533. // If the find length is greater than the string we have, it can't be here
  534. if (find_length > length)
  535. return npos;
  536. // While theres still data in the haystack loop
  537. for (;;)
  538. {
  539. // If the current haystack index plus needle offset matches,
  540. // advance the needle index
  541. if (value[haystack_index + needle_index] == find[needle_index])
  542. {
  543. needle_index++;
  544. // If we reach the end of the search term, return the current haystack index
  545. if (find[needle_index] == 0)
  546. return haystack_index;
  547. }
  548. else
  549. {
  550. if (haystack_index == 0)
  551. return npos;
  552. // Advance haystack index backwards
  553. haystack_index--;
  554. needle_index = 0;
  555. }
  556. }
  557. }
  558. template< typename T >
  559. StringBase< T > StringBase< T >::_Replace(const T* find, size_type find_length, const T* replace, size_type replace_length) const
  560. {
  561. StringBase< T > result;
  562. size_type offset = 0;
  563. // Loop until we reach the end of the string
  564. while (offset < Length())
  565. {
  566. // Look for the next search term
  567. size_type pos = _Find(find, find_length, offset);
  568. // Term not found, add remainder and return
  569. if (pos == npos)
  570. return result + (Substring(offset).CString());
  571. // Add the unchanged text and replacement after it
  572. result += Substring(offset, pos - offset);
  573. result._Append(replace, replace_length);
  574. // Advance the find position
  575. offset = pos + find_length;
  576. }
  577. return result;
  578. }
  579. template< typename T >
  580. StringBase< T >& StringBase< T >::_Append(const T* append, size_type append_length, size_type count)
  581. {
  582. size_type add_length = count < append_length ? count : append_length;
  583. if (add_length == 0)
  584. return *this;
  585. Modify(length + add_length);
  586. Copy(&value[length], append, add_length, true);
  587. length += add_length;
  588. return *this;
  589. }
  590. template< typename T >
  591. StringBase< T >& StringBase< T >::_Assign(const T* assign, size_type assign_length, size_type count)
  592. {
  593. size_type new_length = count < assign_length ? count : assign_length;
  594. if (new_length == 0)
  595. {
  596. Release();
  597. value = (T*)StringStorage::empty_string;
  598. }
  599. else
  600. {
  601. Modify(new_length, true);
  602. Copy(value, assign, new_length, true);
  603. }
  604. length = new_length;
  605. return *this;
  606. }
  607. template< typename T >
  608. void StringBase< T >::_Insert(size_type index, const T* insert, size_type insert_length, size_type count)
  609. {
  610. if (index >= length)
  611. {
  612. Append(insert, count);
  613. return;
  614. }
  615. size_type add_length = count < insert_length ? count : insert_length;
  616. Modify(length + add_length);
  617. for (size_type i = length + 1; i > index; i--)
  618. value[i + add_length - 1] = value[i - 1];
  619. Copy(&value[index], insert, add_length);
  620. length += add_length;
  621. }