PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/support/msString.cpp

http://github.com/gavofyork/Martta
C++ | 830 lines | 713 code | 71 blank | 46 comment | 219 complexity | 97b597267abe63266d195b0206ecc8f2 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MarttaSupport License version 1.0
  3. *
  4. * The contents of this file are subject to the MarttaSupport License
  5. * version 1.0 (the "License"); you may not use this file except in
  6. * compliance with the License. You should have received a copy of the
  7. * MarttaSupport License "COPYING.MarttaSupport" along with Martta; if not
  8. * you may obtain a copy of the License at http://quidprocode.co.uk/Martta/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS"
  11. * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  12. * License for the specific language governing rights and limitations under
  13. * the License.
  14. *
  15. * The Initial Developer of the code in this file is Gavin Wood.
  16. * Portions created by the Initial Developer are Copyright (C) 2008
  17. * quid pro code, Ltd. All Rights Reserved.
  18. *
  19. * ***** END LICENSE BLOCK ***** */
  20. #if __linux__
  21. #include <cstddef>
  22. #endif
  23. #include <wchar.h>
  24. #include <wctype.h>
  25. #include <cstring>
  26. #include <cerrno>
  27. #include "msList.h"
  28. #include "msString.h"
  29. #include "msStringList.h"
  30. #include "msDebug.h"
  31. namespace MarttaSupport
  32. {
  33. String const String::null;
  34. /*m_inline void memcpy(void* _d, void const* _s, int _c)
  35. {
  36. char* d = (char*)_d + _c;
  37. char const* s = (char const*)_s + _c;
  38. while (d != _d)
  39. *(d--) = *(s--);
  40. }
  41. m_inline int strlen(char const* _s)
  42. {
  43. int ret = 0;
  44. if (_s)
  45. while (*(_s++))
  46. ++ret;
  47. return ret;
  48. }*/
  49. bool Char::operator==(char _ch)
  50. {
  51. return (int)m_value == (int)btowc(_ch);
  52. }
  53. Char::Char(char _ch):
  54. m_value(btowc(_ch))
  55. {
  56. }
  57. Char& Char::operator=(char _ch)
  58. {
  59. m_value = btowc(_ch);
  60. return *this;
  61. }
  62. Char::operator char() const
  63. {
  64. return wctob(m_value);
  65. }
  66. bool Char::isNumber() const
  67. {
  68. return m_value != L'\x7f' && iswdigit(m_value);
  69. }
  70. bool Char::isLetter() const
  71. {
  72. return m_value != L'\x7f' && iswalpha(m_value);
  73. }
  74. bool Char::isAlphaNumeric() const
  75. {
  76. return m_value != L'\x7f' && iswalnum(m_value);
  77. }
  78. bool Char::isSpace() const
  79. {
  80. return iswspace(m_value);
  81. }
  82. bool Char::isGraph() const
  83. {
  84. return m_value != L'\x7f' && iswgraph(m_value);
  85. }
  86. bool Char::isLower() const
  87. {
  88. return m_value != L'\x7f' && iswlower(m_value);
  89. }
  90. bool Char::isUpper() const
  91. {
  92. return m_value != L'\x7f' && iswupper(m_value);
  93. }
  94. Char Char::toUpper() const
  95. {
  96. return (wchar_t)towupper(m_value);
  97. }
  98. Char Char::toLower() const
  99. {
  100. return (wchar_t)towlower(m_value);
  101. }
  102. String& String::operator=(char const* _latin1)
  103. {
  104. uint l = _latin1 ? std::strlen(_latin1) : 0;
  105. reserve(l);
  106. m_length = l;
  107. if (m_data)
  108. {
  109. wchar_t* d = m_data;
  110. if (_latin1)
  111. while (*_latin1)
  112. *(d++) = btowc(*(_latin1++));
  113. *d = 0;
  114. }
  115. changed();
  116. return *this;
  117. }
  118. String& String::operator=(wchar_t const* _unicode)
  119. {
  120. sizeto(_unicode ? wcslen(_unicode) : 0);
  121. if (m_data)
  122. memcpy(m_data, _unicode, m_length * sizeof(wchar_t));
  123. changed();
  124. return *this;
  125. }
  126. String& String::operator=(String const& _other)
  127. {
  128. sizeto(_other.m_length);
  129. if (m_data)
  130. std::memcpy(m_data, _other.m_data, _other.m_length * sizeof(wchar_t));
  131. changed();
  132. return *this;
  133. }
  134. bool String::boolCompare(String const& _other) const
  135. {
  136. return m_length == _other.m_length && !memcmp(m_data, _other.m_data, m_length * sizeof(wchar_t));
  137. }
  138. bool String::boolCompare(wchar_t const* _other) const
  139. {
  140. return m_length == wcslen(_other) && !memcmp(m_data, _other, m_length * sizeof(wchar_t));
  141. }
  142. int String::compare(wchar_t const* _other) const
  143. {
  144. if (!_other && !m_data)
  145. return 0;
  146. else if (!m_data)
  147. return wcscmp(L"", _other);
  148. else if (!_other)
  149. return wcscmp(m_data, L"");
  150. else
  151. return wcscmp(m_data, _other);
  152. }
  153. int String::toInt(bool* _ok, int _base) const
  154. {
  155. errno = 0;
  156. int ret = m_data ? wcstol(m_data, 0, _base) : 0;
  157. if (_ok)
  158. *_ok = !errno && m_data && (ret || simplified() == L"0");
  159. return ret;
  160. }
  161. uint String::toUint(bool* _ok, int _base) const
  162. {
  163. errno = 0;
  164. uint ret = m_data ? wcstoul(m_data, 0, _base) : 0u;
  165. if (_ok)
  166. *_ok = !errno && m_data && (ret || simplified() == L"0");
  167. return ret;
  168. }
  169. double String::toDouble(bool* _ok) const
  170. {
  171. errno = 0;
  172. double ret = m_data ? wcstod(m_data, 0) : 0.;
  173. if (_ok)
  174. *_ok = !errno && m_data && (ret || simplified() == L"0");
  175. return ret;
  176. }
  177. bool String::endsWith(String const& _str) const
  178. {
  179. if (m_length < _str.m_length)
  180. return false;
  181. return !memcmp(_str.m_data, m_data + m_length - _str.m_length, _str.m_length * sizeof(wchar_t));
  182. }
  183. bool String::startsWith(String const& _str) const
  184. {
  185. if (m_length < _str.m_length)
  186. return false;
  187. return !memcmp(_str.m_data, m_data, _str.m_length * sizeof(wchar_t));
  188. }
  189. String& String::fill(Char _ch, int _len)
  190. {
  191. if (_len >= 0)
  192. sizeto(_len);
  193. if (m_length)
  194. wmemset(m_data, _ch, m_length);
  195. changed();
  196. return *this;
  197. }
  198. int String::count(String const& _str) const
  199. {
  200. if (m_length < _str.m_length || !_str.m_length)
  201. return 0;
  202. int ret = 0;
  203. wchar_t* i = m_data + m_length - _str.m_length + 1;
  204. while (i != m_data)
  205. if (!memcmp(--i, _str.m_data, _str.m_length * sizeof(wchar_t)))
  206. ret++;
  207. return ret;
  208. }
  209. int String::count(Char _ch) const
  210. {
  211. int ret = 0;
  212. wchar_t* i = m_data + m_length;
  213. while (i != m_data)
  214. if (*--i == _ch)
  215. ret++;
  216. return ret;
  217. }
  218. bool String::contains(String const& _str) const
  219. {
  220. if (m_length < _str.m_length || !_str.m_length)
  221. return false;
  222. wchar_t* i = m_data + m_length - _str.m_length + 1;
  223. while (i != m_data)
  224. if (!memcmp(--i, _str.m_data, _str.m_length * sizeof(wchar_t)))
  225. return true;
  226. return false;
  227. }
  228. bool String::contains(Char _ch) const
  229. {
  230. wchar_t* i = m_data + m_length;
  231. while (i != m_data)
  232. if (*--i == _ch)
  233. return true;
  234. return false;
  235. }
  236. int String::lastIndexOf(String const& _str, int _from) const
  237. {
  238. if (m_length < _str.m_length || !_str.m_length)
  239. return -1;
  240. wchar_t* i;
  241. if (_from < 0)
  242. if (_from < -(int)(m_length - _str.m_length + 1))
  243. return -1;
  244. else
  245. i = m_data + m_length - _str.m_length + 2 + _from;
  246. else
  247. i = m_data + min<int>(m_length - _str.m_length, _from) + 1;
  248. while (i != m_data)
  249. if (!memcmp(--i, _str.m_data, _str.m_length * sizeof(wchar_t)))
  250. return i - m_data;
  251. return -1;
  252. }
  253. int String::lastIndexOf(Char _ch, int _from) const
  254. {
  255. wchar_t* i;
  256. if (_from < 0)
  257. if (_from < -(int)(m_length))
  258. return -1;
  259. else
  260. i = m_data + m_length + 1 + _from;
  261. else
  262. i = m_data + min<int>(m_length, _from + 1);
  263. while (i != m_data)
  264. if (*--i == _ch)
  265. return i - m_data;
  266. return -1;
  267. }
  268. int String::indexOf(String const& _str, int _from) const
  269. {
  270. if (m_length < _str.m_length || !_str.m_length)
  271. return -1;
  272. wchar_t* i;
  273. if (_from < 0)
  274. if (_from < -(int)(m_length - _str.m_length + 1))
  275. i = m_data;
  276. else
  277. i = m_data + m_length - _str.m_length + 1 + _from;
  278. else
  279. if (_from > (int)m_length - (int)_str.m_length)
  280. return -1;
  281. else
  282. i = m_data + _from;
  283. wchar_t* en = m_data + m_length - _str.m_length + 1;
  284. while (i != en)
  285. if (!memcmp(i++, _str.m_data, _str.m_length * sizeof(wchar_t)))
  286. return i - m_data - 1;
  287. return -1;
  288. }
  289. int String::indexOf(wchar_t const* _str, int _from) const
  290. {
  291. uint sl = wcslen(_str);
  292. if (m_length < sl || !sl)
  293. return -1;
  294. wchar_t* i;
  295. if (_from < 0)
  296. if (_from < -(int)(m_length - sl + 1))
  297. i = m_data;
  298. else
  299. i = m_data + m_length - sl + 1 + _from;
  300. else
  301. if (_from > (int)m_length - (int)sl)
  302. return -1;
  303. else
  304. i = m_data + _from;
  305. wchar_t* en = m_data + m_length - sl + 1;
  306. while (i != en)
  307. if (!memcmp(i++, _str, sl * sizeof(wchar_t)))
  308. return i - m_data - 1;
  309. return -1;
  310. }
  311. int String::indexOf(Char _ch, int _from) const
  312. {
  313. wchar_t* i;
  314. if (_from < 0)
  315. if (_from < -(int)(m_length))
  316. return -1;
  317. else
  318. i = m_data + m_length + _from;
  319. else
  320. i = m_data + min<int>(m_length, _from);
  321. wchar_t* en = m_data + m_length;
  322. while (i != en)
  323. if (*(i++) == _ch)
  324. return i - m_data - 1;
  325. return -1;
  326. }
  327. StringList String::split(String const& _sep) const
  328. {
  329. StringList ret;
  330. if (!m_length)
  331. return ret;
  332. int last = 0;
  333. uint endIndex = m_length - _sep.m_length + 1;
  334. for (uint i = 0; i < endIndex;)
  335. if (!memcmp(m_data + i, _sep.m_data, _sep.m_length * sizeof(wchar_t)))
  336. {
  337. ret << mid(last, i - last);
  338. i += _sep.m_length;
  339. last = i;
  340. }
  341. else i++;
  342. ret << mid(last, m_length - last);
  343. return ret;
  344. }
  345. StringList String::split(Char _sep) const
  346. {
  347. StringList ret;
  348. if (!m_length)
  349. return ret;
  350. int last = 0;
  351. for (uint i = 0; i < m_length; i++)
  352. if (m_data[i] == _sep)
  353. {
  354. ret << mid(last, i - last);
  355. last = i + 1;
  356. }
  357. ret << mid(last, m_length - last);
  358. return ret;
  359. }
  360. int String::indexOfNth(String const& _str, uint _th) const
  361. {
  362. if (_th == 0)
  363. return -1;
  364. uint c = 0;
  365. for (uint i = 0; i < m_length && c < _th;)
  366. if (!memcmp(m_data + i, _str.m_data, _str.m_length * sizeof(wchar_t)))
  367. if (++c == _th)
  368. return i;
  369. else
  370. i += _str.m_length;
  371. else
  372. i++;
  373. if (c == _th - 1)
  374. return m_length;
  375. return -1;
  376. }
  377. int String::indexOfNth(Char _ch, uint _th) const
  378. {
  379. // for *this == _ch:
  380. // _th == 0 -> -1
  381. // _th == 1 -> 0
  382. // _th == 2 -> 1
  383. // _th >= 3 -> -1
  384. if (_th == 0)
  385. return -1;
  386. uint c = 0;
  387. for (uint from = 0; from < m_length && c < _th; from++)
  388. if (m_data[from] == _ch)
  389. if (++c == _th)
  390. return from;
  391. if (c == _th - 1)
  392. return m_length;
  393. return -1;
  394. }
  395. int String::lastIndexOfNth(String const& _str, uint _th) const
  396. {
  397. if (_th == 0)
  398. return m_length;
  399. uint c = 0;
  400. for (int i = m_length - _str.m_length; i >= 0 && c < _th;)
  401. if (!memcmp(m_data + i, _str.m_data, _str.m_length * sizeof(wchar_t)))
  402. if (++c == _th)
  403. return i;
  404. else
  405. i -= _str.m_length;
  406. else
  407. i--;
  408. return -1;
  409. }
  410. int String::lastIndexOfNth(Char _ch, uint _th) const
  411. {
  412. // for *this == _ch:
  413. // _th == 0 -> 1
  414. // _th == 1 -> 0
  415. // _th >= 2 -> -1
  416. if (_th == 0)
  417. return m_length;
  418. uint c = 0;
  419. for (int from = m_length - 1; from >= 0 && c < _th; from--)
  420. if (m_data[from] == _ch)
  421. if (++c == _th)
  422. return from;
  423. return -1;
  424. }
  425. String String::toLower() const
  426. {
  427. String ret;
  428. ret.sizeto(m_length);
  429. wchar_t* s = m_data + m_length;
  430. wchar_t* d = ret.m_data + m_length;
  431. while (s != m_data)
  432. *--d = towlower(*--s);
  433. ret.changed();
  434. return ret;
  435. }
  436. String String::toUpper() const
  437. {
  438. String ret;
  439. ret.sizeto(m_length);
  440. wchar_t* s = m_data + m_length;
  441. wchar_t* d = ret.m_data + m_length;
  442. while (s != m_data)
  443. *--d = towupper(*--s);
  444. ret.changed();
  445. return ret;
  446. }
  447. String& String::replace(uint _position, uint _n, String const& _after)
  448. {
  449. AssertNR(_position < m_length);
  450. AssertNR(_position + _n <= m_length);
  451. if (_n == _after.m_length)
  452. memcpy(m_data + _position, _after.m_data, _n * sizeof(wchar_t));
  453. else if (m_length - _n + _after.m_length)
  454. {
  455. wchar_t* nd = new wchar_t[m_length - _n + _after.m_length + 1];
  456. memcpy(nd, m_data, _position * sizeof(wchar_t));
  457. memcpy(nd + _position, _after.m_data, _after.m_length * sizeof(wchar_t));
  458. memcpy(nd + _position + _after.m_length, m_data + _position + _n, (m_length - _position - _n) * sizeof(wchar_t));
  459. delete [] m_data;
  460. m_data = nd;
  461. m_length += _after.m_length - _n;
  462. m_data[m_length] = 0;
  463. m_allocated = m_length + 1;
  464. }
  465. else
  466. sizeto(0);
  467. changed();
  468. return *this;
  469. }
  470. String& String::replace(uint _position, uint _n, Char _after)
  471. {
  472. AssertNR(_position <= m_length);
  473. AssertNR(_position + _n <= m_length);
  474. if (_n == 1)
  475. m_data[_position] = _after;
  476. else if (m_length - _n + 1)
  477. {
  478. wchar_t* nd = new wchar_t[m_length - _n + 2];
  479. memcpy(nd, m_data, _position * sizeof(wchar_t));
  480. nd[_position] = _after;
  481. memcpy(nd + _position + 1, m_data + _position + _n, (m_length - _position - _n) * sizeof(wchar_t));
  482. delete [] m_data;
  483. m_data = nd;
  484. m_length += 1 - _n;
  485. m_data[m_length] = 0;
  486. m_allocated = m_length + 1;
  487. }
  488. else
  489. sizeto(0);
  490. changed();
  491. return *this;
  492. }
  493. String& String::replace(String const& _before, String const& _after)
  494. {
  495. int i = 0;
  496. while (i < (int)m_length && (i = indexOf(_before, i)) != -1)
  497. {
  498. replace(i, _before.m_length, _after);
  499. i += _after.m_length;
  500. }
  501. changed();
  502. return *this;
  503. }
  504. String& String::replace(Char _ch, String const& _after)
  505. {
  506. int i = 0;
  507. while (i < (int)m_length && (i = indexOf(_ch, i)) != -1)
  508. {
  509. replace(i, 1, _after);
  510. i += _after.m_length;
  511. }
  512. changed();
  513. return *this;
  514. }
  515. String& String::replace(Char _before, Char _after)
  516. {
  517. wchar_t* i = m_data + m_length;
  518. while (i != m_data)
  519. if (*--i == _before)
  520. {
  521. changed();
  522. *i = _after;
  523. }
  524. return *this;
  525. }
  526. String String::section(String const& _sep, int _start, int _end) const
  527. {
  528. if (!m_length)
  529. return String::null;
  530. int f = ((_start < 0) ? lastIndexOfNth(_sep, -_start) : indexOfNth(_sep, _start));
  531. f += f == -1 ? 1 : _sep.length();
  532. int t = (_end < 0) ? lastIndexOfNth(_sep, -_end - 1) : indexOfNth(_sep, _end + 1);
  533. if (t == -1)
  534. t = m_length;
  535. return f < t ? mid(f, t - f) : String::null;
  536. }
  537. String String::section(Char _sep, int _start, int _end) const
  538. {
  539. if (!m_length)
  540. return String::null;
  541. int f = ((_start < 0) ? lastIndexOfNth(_sep, -_start) : indexOfNth(_sep, _start)) + 1;
  542. int t = (_end < 0) ? lastIndexOfNth(_sep, -_end - 1) : indexOfNth(_sep, _end + 1);
  543. if (t == -1)
  544. t = m_length;
  545. return f < t ? mid(f, t - f) : String::null;
  546. }
  547. String& String::append(String const& _str)
  548. {
  549. if (!_str.m_length)
  550. return *this;
  551. reserve(m_length + _str.m_length);
  552. memcpy(m_data + m_length, _str.m_data, _str.m_length * sizeof(wchar_t));
  553. m_length += _str.m_length;
  554. m_data[m_length] = 0;
  555. changed();
  556. return *this;
  557. }
  558. String& String::append(char const* _latin1)
  559. {
  560. uint l = std::strlen(_latin1);
  561. if (!l)
  562. return *this;
  563. reserve(m_length + l);
  564. wchar_t* d = m_data + m_length;
  565. if (_latin1)
  566. while (*_latin1)
  567. *(d++) = btowc(*(_latin1++));
  568. *d = 0;
  569. m_length += l;
  570. changed();
  571. return *this;
  572. }
  573. String& String::append(Char _ch)
  574. {
  575. sizeto(m_length + 1);
  576. m_data[m_length - 1] = _ch;
  577. changed();
  578. return *this;
  579. }
  580. String String::trimmed() const
  581. {
  582. if (!m_length)
  583. return String::null;
  584. uint i;
  585. for (i = 0; i < m_length && iswspace(m_data[i]); i++) ;
  586. uint j;
  587. for (j = m_length - 1; j > i && iswspace(m_data[j]); j--) ;
  588. return mid(i, j - i + 1);
  589. }
  590. String String::simplified() const
  591. {
  592. String src = trimmed();
  593. String ret;
  594. if (!src.m_length)
  595. return String::null;
  596. ret.reserve(src.length());
  597. wchar_t* d = ret.m_data;
  598. wchar_t* s = src.m_data;
  599. while (*s)
  600. {
  601. if (iswspace(*s))
  602. {
  603. *(d++) = L' ';
  604. do s++;
  605. while (*s && iswspace(*s));
  606. }
  607. else
  608. *(d++) = *(s++);
  609. }
  610. *d = 0;
  611. ret.m_length = d - ret.m_data;
  612. return ret;
  613. }
  614. String String::mid(uint _i, uint _length) const
  615. {
  616. if (_i >= m_length)
  617. return null;
  618. if (_i + _length > m_length)
  619. _length = m_length - _i;
  620. String ret;
  621. ret.sizeto(_length);
  622. memcpy(ret.m_data, m_data + _i, _length * sizeof(wchar_t));
  623. ret.changed();
  624. return ret;
  625. }
  626. String String::number(long _n)
  627. {
  628. static wchar_t s_format[] = L"%d";
  629. static wchar_t s_result[128];
  630. int c = swprintf(s_result, 128, s_format, _n);
  631. String ret;
  632. ret.sizeto(c);
  633. memcpy(ret.m_data, s_result, c * sizeof(wchar_t));
  634. ret.changed();
  635. return ret;
  636. }
  637. String String::number(unsigned long _n, int _base)
  638. {
  639. static wchar_t s_format[] = L"%d";
  640. static wchar_t s_result[128];
  641. AssertNR(_base == 10 || _base == 8 || _base == 16);
  642. s_format[1] = (_base == 10) ? L'u' : (_base == 16) ? L'x' : L'o';
  643. int c = swprintf(s_result, 128, s_format, _n);
  644. String ret;
  645. ret.sizeto(c);
  646. memcpy(ret.m_data, s_result, c * sizeof(wchar_t));
  647. ret.changed();
  648. return ret;
  649. }
  650. String String::number(double _n, char _format, int _precision)
  651. {
  652. static wchar_t s_format[] = L"%.*g";
  653. static wchar_t s_result[128];
  654. s_format[3] = _format;
  655. int c = swprintf(s_result, 128, s_format, _precision, _n);
  656. String ret;
  657. ret.sizeto(c);
  658. memcpy(ret.m_data, s_result, c * sizeof(wchar_t));
  659. ret.changed();
  660. return ret;
  661. }
  662. String String::arg(String const& _a, int _fieldWidth, Char _fillChar) const
  663. {
  664. String ret(*this);
  665. wchar_t const* token;
  666. String const* a = &_a;
  667. String jic;
  668. if ((int)_a.m_length < abs(_fieldWidth))
  669. {
  670. if (_fieldWidth < 0)
  671. a = &((*new String(_a)) += String(-_fieldWidth - _a.m_length, _fillChar));
  672. else
  673. a = &((*new String(_fieldWidth - _a.m_length, _fillChar)) += _a);
  674. }
  675. for (int p = findNextPlaceholder(&token); p != -1; p = ret.indexOf(token, p + a->m_length))
  676. ret.replace(p, token[2] ? 3 : 2, *a);
  677. if (a != &_a)
  678. delete a;
  679. return ret;
  680. }
  681. String String::arg(Char _a, int _fieldWidth, Char _fillChar) const
  682. {
  683. if (_fieldWidth > 1 || _fieldWidth < -1)
  684. return arg(String(1, _a), _fieldWidth, _fillChar);
  685. String ret(*this);
  686. wchar_t const* token;
  687. for (int p = findNextPlaceholder(&token); p != -1; p = ret.indexOf(token, p + 1))
  688. ret.replace(p, token[2] ? 3 : 2, _a);
  689. return ret;
  690. }
  691. int String::findNextPlaceholder(wchar_t const** _token) const
  692. {
  693. // Only goes below 10 at the moment.
  694. // If making it go below 100, don't forget that %10 should never match for %1 (it did originally).
  695. static wchar_t s[3] = L"%0";
  696. for (uint i = 1; i < 10; i++)
  697. {
  698. s[1] = L'0' + i, s[2] = 0;
  699. int n;
  700. if ((n = indexOf(s)) != -1)
  701. {
  702. if (_token)
  703. *_token = s;
  704. return n;
  705. }
  706. }
  707. return -1;
  708. }
  709. void String::reserve(uint _len)
  710. {
  711. if (m_allocated <= _len)
  712. {
  713. wchar_t* nd = new wchar_t[_len + 1];
  714. std::memcpy(nd, m_data, m_length * sizeof(wchar_t));
  715. delete [] m_data;
  716. m_data = nd;
  717. m_data[m_length] = 0;
  718. m_allocated = _len + 1;
  719. }
  720. }
  721. void String::checkCache() const
  722. {
  723. if (!m_cache)
  724. {
  725. m_cache = new char[m_length + 1];
  726. wchar_t const* s = m_data;
  727. char* d = m_cache;
  728. if (s)
  729. while (*s)
  730. *(d++) = wctob(*(s++));
  731. *d = 0;
  732. }
  733. }
  734. String times(int _s, int _omte, String const& _btwn)
  735. {
  736. String r;
  737. if (_omte <= _s)
  738. return r;
  739. r = String::number(_s);
  740. for (int i = _s + 1; i < _omte; i++)
  741. r += _btwn + String::number(i);
  742. return r;
  743. }
  744. String camelCase(String const& _t, bool _upperFirst)
  745. {
  746. if (!_t.size())
  747. return _t;
  748. String t = _t.simplified();
  749. String ret;
  750. ret.reserve(t.size());
  751. for(int i = 0; i < t.size(); i++)
  752. if (t[i] == ' ')
  753. ret += String("%1").arg(t[++i]).toUpper()[0];
  754. else
  755. ret += _upperFirst && !i ? t[i].toUpper() : t[i].toLower();
  756. return ret;
  757. }
  758. }