The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

2239 lines
58KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-7 by Raw Material Software ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the
  7. GNU General Public License, as published by the Free Software Foundation;
  8. either version 2 of the License, or (at your option) any later version.
  9. JUCE is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with JUCE; if not, visit www.gnu.org/licenses or write to the
  15. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  16. Boston, MA 02111-1307 USA
  17. ------------------------------------------------------------------------------
  18. If you'd like to release a closed-source product which uses JUCE, commercial
  19. licenses are also available: visit www.rawmaterialsoftware.com/juce for
  20. more information.
  21. ==============================================================================
  22. */
  23. #ifdef _MSC_VER
  24. #pragma warning (disable: 4514)
  25. #pragma warning (push)
  26. #endif
  27. #include <locale>
  28. #include "../basics/juce_StandardHeader.h"
  29. #if JUCE_MSVC
  30. #include <float.h>
  31. #endif
  32. BEGIN_JUCE_NAMESPACE
  33. #include "juce_String.h"
  34. #include "../basics/juce_Atomic.h"
  35. #ifdef _MSC_VER
  36. #pragma warning (pop)
  37. #endif
  38. //==============================================================================
  39. static const char* const emptyCharString = "\0\0\0\0JUCE";
  40. static const int safeEmptyStringRefCount = 0x3fffffff;
  41. String::InternalRefCountedStringHolder String::emptyString = { safeEmptyStringRefCount, 0, { 0 } };
  42. static tchar decimalPoint = T('.');
  43. void juce_initialiseStrings()
  44. {
  45. decimalPoint = String::fromUTF8 ((const uint8*) localeconv()->decimal_point) [0];
  46. }
  47. //==============================================================================
  48. void String::deleteInternal() throw()
  49. {
  50. if (atomicDecrementAndReturn (text->refCount) == 0)
  51. juce_free (text);
  52. }
  53. void String::createInternal (const int numChars) throw()
  54. {
  55. jassert (numChars > 0);
  56. text = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder)
  57. + numChars * sizeof (tchar));
  58. text->refCount = 1;
  59. text->allocatedNumChars = numChars;
  60. text->text[0] = 0;
  61. }
  62. void String::createInternal (const tchar* const t, const tchar* const textEnd) throw()
  63. {
  64. jassert (*(textEnd - 1) == 0); // must have a null terminator
  65. const int numChars = (int) (textEnd - t);
  66. createInternal (numChars - 1);
  67. memcpy (text->text, t, numChars * sizeof (tchar));
  68. }
  69. void String::appendInternal (const tchar* const newText,
  70. const int numExtraChars) throw()
  71. {
  72. if (numExtraChars > 0)
  73. {
  74. const int oldLen = CharacterFunctions::length (text->text);
  75. const int newTotalLen = oldLen + numExtraChars;
  76. if (text->refCount > 1)
  77. {
  78. // it's in use by other strings as well, so we need to make a private copy before messing with it..
  79. InternalRefCountedStringHolder* const newTextHolder
  80. = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder)
  81. + newTotalLen * sizeof (tchar));
  82. newTextHolder->refCount = 1;
  83. newTextHolder->allocatedNumChars = newTotalLen;
  84. memcpy (newTextHolder->text, text->text, oldLen * sizeof (tchar));
  85. memcpy (newTextHolder->text + oldLen, newText, numExtraChars * sizeof (tchar));
  86. InternalRefCountedStringHolder* const old = text;
  87. text = newTextHolder;
  88. if (atomicDecrementAndReturn (old->refCount) == 0)
  89. juce_free (old);
  90. }
  91. else
  92. {
  93. // no other strings using it, so just expand it if needed..
  94. if (newTotalLen > text->allocatedNumChars)
  95. {
  96. text = (InternalRefCountedStringHolder*)
  97. juce_realloc (text, sizeof (InternalRefCountedStringHolder)
  98. + newTotalLen * sizeof (tchar));
  99. text->allocatedNumChars = newTotalLen;
  100. }
  101. memcpy (text->text + oldLen, newText, numExtraChars * sizeof (tchar));
  102. }
  103. text->text [newTotalLen] = 0;
  104. }
  105. }
  106. void String::dupeInternalIfMultiplyReferenced() throw()
  107. {
  108. if (text->refCount > 1)
  109. {
  110. InternalRefCountedStringHolder* const old = text;
  111. const int len = old->allocatedNumChars;
  112. InternalRefCountedStringHolder* const newTextHolder
  113. = (InternalRefCountedStringHolder*) juce_malloc (sizeof (InternalRefCountedStringHolder)
  114. + len * sizeof (tchar));
  115. newTextHolder->refCount = 1;
  116. newTextHolder->allocatedNumChars = len;
  117. memcpy (newTextHolder->text, old->text, (len + 1) * sizeof (tchar));
  118. text = newTextHolder;
  119. if (atomicDecrementAndReturn (old->refCount) == 0)
  120. juce_free (old);
  121. }
  122. }
  123. //==============================================================================
  124. const String String::empty;
  125. //==============================================================================
  126. String::String() throw()
  127. : text (&emptyString)
  128. {
  129. }
  130. String::String (const String& other) throw()
  131. : text (other.text)
  132. {
  133. atomicIncrement (text->refCount);
  134. }
  135. String::String (const int numChars,
  136. const int /*dummyVariable*/) throw()
  137. {
  138. createInternal (numChars);
  139. }
  140. String::String (const char* const t) throw()
  141. {
  142. if (t != 0 && *t != 0)
  143. {
  144. const int len = CharacterFunctions::length (t);
  145. createInternal (len);
  146. #if JUCE_STRINGS_ARE_UNICODE
  147. CharacterFunctions::copy (text->text, t, len + 1);
  148. #else
  149. memcpy (text->text, t, len + 1);
  150. #endif
  151. }
  152. else
  153. {
  154. text = &emptyString;
  155. emptyString.refCount = safeEmptyStringRefCount;
  156. }
  157. }
  158. String::String (const juce_wchar* const t) throw()
  159. {
  160. if (t != 0 && *t != 0)
  161. {
  162. #if JUCE_STRINGS_ARE_UNICODE
  163. const int len = CharacterFunctions::length (t);
  164. createInternal (len);
  165. memcpy (text->text, t, (len + 1) * sizeof (tchar));
  166. #else
  167. const int len = CharacterFunctions::bytesRequiredForCopy (t);
  168. createInternal (len);
  169. CharacterFunctions::copy (text->text, t, len + 1);
  170. #endif
  171. }
  172. else
  173. {
  174. text = &emptyString;
  175. emptyString.refCount = safeEmptyStringRefCount;
  176. }
  177. }
  178. String::String (const char* const t,
  179. const int maxChars) throw()
  180. {
  181. int i;
  182. for (i = 0; i < maxChars; ++i)
  183. if (t[i] == 0)
  184. break;
  185. if (i > 0)
  186. {
  187. createInternal (i);
  188. #if JUCE_STRINGS_ARE_UNICODE
  189. CharacterFunctions::copy (text->text, t, i);
  190. #else
  191. memcpy (text->text, t, i);
  192. #endif
  193. text->text [i] = 0;
  194. }
  195. else
  196. {
  197. text = &emptyString;
  198. emptyString.refCount = safeEmptyStringRefCount;
  199. }
  200. }
  201. String::String (const juce_wchar* const t,
  202. const int maxChars) throw()
  203. {
  204. int i;
  205. for (i = 0; i < maxChars; ++i)
  206. if (t[i] == 0)
  207. break;
  208. if (i > 0)
  209. {
  210. createInternal (i);
  211. #if JUCE_STRINGS_ARE_UNICODE
  212. memcpy (text->text, t, i * sizeof (tchar));
  213. #else
  214. CharacterFunctions::copy (text->text, t, i);
  215. #endif
  216. text->text [i] = 0;
  217. }
  218. else
  219. {
  220. text = &emptyString;
  221. emptyString.refCount = safeEmptyStringRefCount;
  222. }
  223. }
  224. const String String::charToString (const tchar character) throw()
  225. {
  226. tchar temp[2];
  227. temp[0] = character;
  228. temp[1] = 0;
  229. return String (temp);
  230. }
  231. // pass in a pointer to the END of a buffer..
  232. static tchar* int64ToCharString (tchar* t, const int64 n) throw()
  233. {
  234. *--t = 0;
  235. int64 v = (n >= 0) ? n : -n;
  236. do
  237. {
  238. *--t = (tchar) (T('0') + (int) (v % 10));
  239. v /= 10;
  240. } while (v > 0);
  241. if (n < 0)
  242. *--t = T('-');
  243. return t;
  244. }
  245. static tchar* intToCharString (tchar* t, const int n) throw()
  246. {
  247. if (n == (int) 0x80000000) // (would cause an overflow)
  248. return int64ToCharString (t, n);
  249. *--t = 0;
  250. int v = abs (n);
  251. do
  252. {
  253. *--t = (tchar) (T('0') + (v % 10));
  254. v /= 10;
  255. } while (v > 0);
  256. if (n < 0)
  257. *--t = T('-');
  258. return t;
  259. }
  260. static tchar* uintToCharString (tchar* t, unsigned int v) throw()
  261. {
  262. *--t = 0;
  263. do
  264. {
  265. *--t = (tchar) (T('0') + (v % 10));
  266. v /= 10;
  267. } while (v > 0);
  268. return t;
  269. }
  270. String::String (const int number) throw()
  271. {
  272. tchar buffer [16];
  273. tchar* const end = buffer + 16;
  274. createInternal (intToCharString (end, number), end);
  275. }
  276. String::String (const unsigned int number) throw()
  277. {
  278. tchar buffer [16];
  279. tchar* const end = buffer + 16;
  280. createInternal (uintToCharString (end, number), end);
  281. }
  282. String::String (const short number) throw()
  283. {
  284. tchar buffer [16];
  285. tchar* const end = buffer + 16;
  286. createInternal (intToCharString (end, (int) number), end);
  287. }
  288. String::String (const unsigned short number) throw()
  289. {
  290. tchar buffer [16];
  291. tchar* const end = buffer + 16;
  292. createInternal (uintToCharString (end, (unsigned int) number), end);
  293. }
  294. String::String (const int64 number) throw()
  295. {
  296. tchar buffer [32];
  297. tchar* const end = buffer + 32;
  298. createInternal (int64ToCharString (end, number), end);
  299. }
  300. String::String (const uint64 number) throw()
  301. {
  302. tchar buffer [32];
  303. tchar* const end = buffer + 32;
  304. tchar* t = end;
  305. *--t = 0;
  306. int64 v = number;
  307. do
  308. {
  309. *--t = (tchar) (T('0') + (int) (v % 10));
  310. v /= 10;
  311. } while (v > 0);
  312. createInternal (t, end);
  313. }
  314. // a double-to-string routine that actually uses the number of dec. places you asked for
  315. // without resorting to exponent notation if the number's too big or small (which is what printf does).
  316. void String::doubleToStringWithDecPlaces (double n, int numDecPlaces) throw()
  317. {
  318. const int bufSize = 80;
  319. tchar buffer [bufSize];
  320. int len;
  321. tchar* t;
  322. if (numDecPlaces > 0 && n > -1.0e20 && n < 1.0e20)
  323. {
  324. int64 v = (int64) (pow (10.0, numDecPlaces) * fabs (n) + 0.5);
  325. t = buffer + bufSize;
  326. *--t = (tchar) 0;
  327. while (numDecPlaces >= 0 || v > 0)
  328. {
  329. if (numDecPlaces == 0)
  330. *--t = decimalPoint;
  331. *--t = (tchar) (T('0') + (v % 10));
  332. v /= 10;
  333. --numDecPlaces;
  334. }
  335. if (n < 0)
  336. *--t = T('-');
  337. len = (int) ((buffer + bufSize) - t);
  338. }
  339. else
  340. {
  341. len = CharacterFunctions::printf (buffer, bufSize, T("%.9g"), n) + 1;
  342. t = buffer;
  343. }
  344. if (len > 1)
  345. {
  346. jassert (len < numElementsInArray (buffer));
  347. createInternal (len - 1);
  348. memcpy (text->text, t, len * sizeof (tchar));
  349. }
  350. else
  351. {
  352. jassert (*t == 0);
  353. text = &emptyString;
  354. emptyString.refCount = safeEmptyStringRefCount;
  355. }
  356. }
  357. String::String (const float number,
  358. const int numberOfDecimalPlaces) throw()
  359. {
  360. doubleToStringWithDecPlaces ((double) number,
  361. numberOfDecimalPlaces);
  362. }
  363. String::String (const double number,
  364. const int numberOfDecimalPlaces) throw()
  365. {
  366. doubleToStringWithDecPlaces (number,
  367. numberOfDecimalPlaces);
  368. }
  369. String::~String() throw()
  370. {
  371. emptyString.refCount = safeEmptyStringRefCount;
  372. if (atomicDecrementAndReturn (text->refCount) == 0)
  373. juce_free (text);
  374. }
  375. //==============================================================================
  376. void String::preallocateStorage (const int numChars) throw()
  377. {
  378. if (numChars > text->allocatedNumChars)
  379. {
  380. dupeInternalIfMultiplyReferenced();
  381. text = (InternalRefCountedStringHolder*) juce_realloc (text, sizeof (InternalRefCountedStringHolder)
  382. + numChars * sizeof (tchar));
  383. text->allocatedNumChars = numChars;
  384. }
  385. }
  386. //==============================================================================
  387. #if JUCE_STRINGS_ARE_UNICODE
  388. String::operator const char*() const throw()
  389. {
  390. if (isEmpty())
  391. {
  392. return (const char*) emptyCharString;
  393. }
  394. else
  395. {
  396. String* const mutableThis = const_cast <String*> (this);
  397. mutableThis->dupeInternalIfMultiplyReferenced();
  398. int len = CharacterFunctions::bytesRequiredForCopy (text->text) + 1;
  399. mutableThis->text = (InternalRefCountedStringHolder*)
  400. juce_realloc (text, sizeof (InternalRefCountedStringHolder)
  401. + (len * sizeof (juce_wchar) + len));
  402. char* otherCopy = (char*) (text->text + len);
  403. --len;
  404. CharacterFunctions::copy (otherCopy, text->text, len);
  405. otherCopy [len] = 0;
  406. return otherCopy;
  407. }
  408. }
  409. #else
  410. String::operator const juce_wchar*() const throw()
  411. {
  412. if (isEmpty())
  413. {
  414. return (const juce_wchar*) emptyCharString;
  415. }
  416. else
  417. {
  418. String* const mutableThis = const_cast <String*> (this);
  419. mutableThis->dupeInternalIfMultiplyReferenced();
  420. int len = CharacterFunctions::length (text->text) + 1;
  421. mutableThis->text = (InternalRefCountedStringHolder*)
  422. juce_realloc (text, sizeof (InternalRefCountedStringHolder)
  423. + (len * sizeof (juce_wchar) + len));
  424. juce_wchar* otherCopy = (juce_wchar*) (text->text + len);
  425. --len;
  426. CharacterFunctions::copy (otherCopy, text->text, len);
  427. otherCopy [len] = 0;
  428. return otherCopy;
  429. }
  430. }
  431. #endif
  432. void String::copyToBuffer (char* const destBuffer,
  433. const int bufferSizeBytes) const throw()
  434. {
  435. #if JUCE_STRINGS_ARE_UNICODE
  436. const int len = jmin (bufferSizeBytes, CharacterFunctions::bytesRequiredForCopy (text->text));
  437. CharacterFunctions::copy (destBuffer, text->text, len);
  438. #else
  439. const int len = jmin (bufferSizeBytes, length());
  440. memcpy (destBuffer, text->text, len * sizeof (tchar));
  441. #endif
  442. destBuffer [len] = 0;
  443. }
  444. void String::copyToBuffer (juce_wchar* const destBuffer,
  445. const int maxCharsToCopy) const throw()
  446. {
  447. const int len = jmin (maxCharsToCopy, length());
  448. #if JUCE_STRINGS_ARE_UNICODE
  449. memcpy (destBuffer, text->text, len * sizeof (juce_wchar));
  450. #else
  451. CharacterFunctions::copy (destBuffer, text->text, len);
  452. #endif
  453. destBuffer [len] = 0;
  454. }
  455. //==============================================================================
  456. int String::length() const throw()
  457. {
  458. return CharacterFunctions::length (text->text);
  459. }
  460. int String::hashCode() const throw()
  461. {
  462. const tchar* t = text->text;
  463. int result = 0;
  464. while (*t != (tchar) 0)
  465. result = 31 * result + *t++;
  466. return result;
  467. }
  468. int64 String::hashCode64() const throw()
  469. {
  470. const tchar* t = text->text;
  471. int64 result = 0;
  472. while (*t != (tchar) 0)
  473. result = 101 * result + *t++;
  474. return result;
  475. }
  476. //==============================================================================
  477. const String& String::operator= (const tchar* const otherText) throw()
  478. {
  479. if (otherText != 0 && *otherText != 0)
  480. {
  481. const int otherLen = CharacterFunctions::length (otherText);
  482. if (otherLen > 0)
  483. {
  484. // avoid resizing the memory block if the string is
  485. // shrinking..
  486. if (text->refCount > 1
  487. || otherLen > text->allocatedNumChars
  488. || otherLen <= (text->allocatedNumChars >> 1))
  489. {
  490. deleteInternal();
  491. createInternal (otherLen);
  492. }
  493. memcpy (text->text, otherText, (otherLen + 1) * sizeof (tchar));
  494. return *this;
  495. }
  496. }
  497. deleteInternal();
  498. text = &emptyString;
  499. emptyString.refCount = safeEmptyStringRefCount;
  500. return *this;
  501. }
  502. const String& String::operator= (const String& other) throw()
  503. {
  504. if (this != &other)
  505. {
  506. atomicIncrement (other.text->refCount);
  507. if (atomicDecrementAndReturn (text->refCount) == 0)
  508. juce_free (text);
  509. text = other.text;
  510. }
  511. return *this;
  512. }
  513. //==============================================================================
  514. bool String::operator== (const String& other) const throw()
  515. {
  516. return text == other.text
  517. || CharacterFunctions::compare (text->text, other.text->text) == 0;
  518. }
  519. bool String::operator== (const tchar* const t) const throw()
  520. {
  521. return t != 0 ? CharacterFunctions::compare (text->text, t) == 0
  522. : isEmpty();
  523. }
  524. bool String::equalsIgnoreCase (const tchar* t) const throw()
  525. {
  526. return t != 0 ? CharacterFunctions::compareIgnoreCase (text->text, t) == 0
  527. : isEmpty();
  528. }
  529. bool String::equalsIgnoreCase (const String& other) const throw()
  530. {
  531. return text == other.text
  532. || CharacterFunctions::compareIgnoreCase (text->text, other.text->text) == 0;
  533. }
  534. bool String::operator!= (const String& other) const throw()
  535. {
  536. return text != other.text
  537. && CharacterFunctions::compare (text->text, other.text->text) != 0;
  538. }
  539. bool String::operator!= (const tchar* const t) const throw()
  540. {
  541. return t != 0 ? (CharacterFunctions::compare (text->text, t) != 0)
  542. : isNotEmpty();
  543. }
  544. bool String::operator> (const String& other) const throw()
  545. {
  546. return compare (other) > 0;
  547. }
  548. bool String::operator< (const tchar* const other) const throw()
  549. {
  550. return compare (other) < 0;
  551. }
  552. bool String::operator>= (const String& other) const throw()
  553. {
  554. return compare (other) >= 0;
  555. }
  556. bool String::operator<= (const tchar* const other) const throw()
  557. {
  558. return compare (other) <= 0;
  559. }
  560. int String::compare (const tchar* const other) const throw()
  561. {
  562. return other != 0 ? CharacterFunctions::compare (text->text, other)
  563. : isEmpty();
  564. }
  565. int String::compareIgnoreCase (const tchar* const other) const throw()
  566. {
  567. return other != 0 ? CharacterFunctions::compareIgnoreCase (text->text, other)
  568. : isEmpty();
  569. }
  570. int String::compareLexicographically (const tchar* other) const throw()
  571. {
  572. if (other == 0)
  573. return isEmpty();
  574. const tchar* s1 = text->text;
  575. while (*s1 != 0 && ! CharacterFunctions::isLetterOrDigit (*s1))
  576. ++s1;
  577. while (*other != 0 && ! CharacterFunctions::isLetterOrDigit (*other))
  578. ++other;
  579. return CharacterFunctions::compareIgnoreCase (s1, other);
  580. }
  581. //==============================================================================
  582. const String String::operator+ (const String& other) const throw()
  583. {
  584. if (*(other.text->text) == 0)
  585. return *this;
  586. if (isEmpty())
  587. return other;
  588. const int len = CharacterFunctions::length (text->text);
  589. const int otherLen = CharacterFunctions::length (other.text->text);
  590. String result (len + otherLen, (int) 0);
  591. memcpy (result.text->text, text->text, len * sizeof (tchar));
  592. memcpy (result.text->text + len, other.text->text, otherLen * sizeof (tchar));
  593. result.text->text [len + otherLen] = 0;
  594. return result;
  595. }
  596. const String String::operator+ (const tchar* const textToAppend) const throw()
  597. {
  598. if (textToAppend == 0 || *textToAppend == 0)
  599. return *this;
  600. const int len = CharacterFunctions::length (text->text);
  601. const int otherLen = CharacterFunctions::length (textToAppend);
  602. String result (len + otherLen, (int) 0);
  603. memcpy (result.text->text, text->text, len * sizeof (tchar));
  604. memcpy (result.text->text + len, textToAppend, otherLen * sizeof (tchar));
  605. result.text->text [len + otherLen] = 0;
  606. return result;
  607. }
  608. const String String::operator+ (const tchar characterToAppend) const throw()
  609. {
  610. if (characterToAppend == 0)
  611. return *this;
  612. const int len = CharacterFunctions::length (text->text);
  613. String result ((int) (len + 1), (int) 0);
  614. memcpy (result.text->text, text->text, len * sizeof (tchar));
  615. result.text->text[len] = characterToAppend;
  616. result.text->text[len + 1] = 0;
  617. return result;
  618. }
  619. //==============================================================================
  620. const String JUCE_PUBLIC_FUNCTION operator+ (const char* const string1,
  621. const String& string2) throw()
  622. {
  623. String s (string1);
  624. s += string2;
  625. return s;
  626. }
  627. const String JUCE_PUBLIC_FUNCTION operator+ (const juce_wchar* const string1,
  628. const String& string2) throw()
  629. {
  630. String s (string1);
  631. s += string2;
  632. return s;
  633. }
  634. //==============================================================================
  635. const String& String::operator+= (const tchar* const t) throw()
  636. {
  637. if (t != 0)
  638. appendInternal (t, CharacterFunctions::length (t));
  639. return *this;
  640. }
  641. const String& String::operator+= (const String& other) throw()
  642. {
  643. if (isEmpty())
  644. operator= (other);
  645. else
  646. appendInternal (other.text->text,
  647. CharacterFunctions::length (other.text->text));
  648. return *this;
  649. }
  650. const String& String::operator+= (const char ch) throw()
  651. {
  652. char asString[2];
  653. asString[0] = ch;
  654. asString[1] = 0;
  655. #if JUCE_STRINGS_ARE_UNICODE
  656. operator+= (String (asString));
  657. #else
  658. appendInternal (asString, 1);
  659. #endif
  660. return *this;
  661. }
  662. const String& String::operator+= (const juce_wchar ch) throw()
  663. {
  664. juce_wchar asString[2];
  665. asString[0] = ch;
  666. asString[1] = 0;
  667. #if JUCE_STRINGS_ARE_UNICODE
  668. appendInternal (asString, 1);
  669. #else
  670. operator+= (String (asString));
  671. #endif
  672. return *this;
  673. }
  674. void String::append (const tchar* const other,
  675. const int howMany) throw()
  676. {
  677. if (howMany > 0)
  678. {
  679. int i;
  680. for (i = 0; i < howMany; ++i)
  681. if (other[i] == 0)
  682. break;
  683. appendInternal (other, i);
  684. }
  685. }
  686. String& String::operator<< (const int number) throw()
  687. {
  688. tchar buffer [64];
  689. tchar* const end = buffer + 64;
  690. const tchar* const t = intToCharString (end, number);
  691. appendInternal (t, (int) (end - t) - 1);
  692. return *this;
  693. }
  694. String& String::operator<< (const unsigned int number) throw()
  695. {
  696. tchar buffer [64];
  697. tchar* const end = buffer + 64;
  698. const tchar* const t = uintToCharString (end, number);
  699. appendInternal (t, (int) (end - t) - 1);
  700. return *this;
  701. }
  702. String& String::operator<< (const short number) throw()
  703. {
  704. tchar buffer [64];
  705. tchar* const end = buffer + 64;
  706. const tchar* const t = intToCharString (end, (int) number);
  707. appendInternal (t, (int) (end - t) - 1);
  708. return *this;
  709. }
  710. String& String::operator<< (const double number) throw()
  711. {
  712. operator+= (String (number));
  713. return *this;
  714. }
  715. String& String::operator<< (const float number) throw()
  716. {
  717. operator+= (String (number));
  718. return *this;
  719. }
  720. String& String::operator<< (const char character) throw()
  721. {
  722. operator+= (character);
  723. return *this;
  724. }
  725. String& String::operator<< (const juce_wchar character) throw()
  726. {
  727. operator+= (character);
  728. return *this;
  729. }
  730. String& String::operator<< (const char* const t) throw()
  731. {
  732. #if JUCE_STRINGS_ARE_UNICODE
  733. operator+= (String (t));
  734. #else
  735. operator+= (t);
  736. #endif
  737. return *this;
  738. }
  739. String& String::operator<< (const juce_wchar* const t) throw()
  740. {
  741. #if JUCE_STRINGS_ARE_UNICODE
  742. operator+= (t);
  743. #else
  744. operator+= (String (t));
  745. #endif
  746. return *this;
  747. }
  748. String& String::operator<< (const String& t) throw()
  749. {
  750. operator+= (t);
  751. return *this;
  752. }
  753. //==============================================================================
  754. int String::indexOfChar (const tchar character) const throw()
  755. {
  756. const tchar* t = text->text;
  757. for (;;)
  758. {
  759. if (*t == character)
  760. return (int) (t - text->text);
  761. if (*t++ == 0)
  762. return -1;
  763. }
  764. }
  765. int String::lastIndexOfChar (const tchar character) const throw()
  766. {
  767. for (int i = CharacterFunctions::length (text->text); --i >= 0;)
  768. if (text->text[i] == character)
  769. return i;
  770. return -1;
  771. }
  772. int String::indexOf (const tchar* const t) const throw()
  773. {
  774. const tchar* const r = CharacterFunctions::find (text->text, t);
  775. return (r == 0) ? -1
  776. : (int) (r - text->text);
  777. }
  778. int String::indexOfChar (const int startIndex,
  779. const tchar character) const throw()
  780. {
  781. if (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text))
  782. return -1;
  783. const tchar* t = text->text + jmax (0, startIndex);
  784. for (;;)
  785. {
  786. if (*t == character)
  787. return (int) (t - text->text);
  788. if (*t++ == 0)
  789. return -1;
  790. }
  791. }
  792. int String::indexOfAnyOf (const tchar* const charactersToLookFor,
  793. const int startIndex,
  794. const bool ignoreCase) const throw()
  795. {
  796. if (charactersToLookFor == 0
  797. || (startIndex >= 0 && startIndex >= CharacterFunctions::length (text->text)))
  798. return -1;
  799. const tchar* t = text->text + jmax (0, startIndex);
  800. while (*t != 0)
  801. {
  802. if (CharacterFunctions::indexOfChar (charactersToLookFor, *t, ignoreCase) >= 0)
  803. return (int) (t - text->text);
  804. ++t;
  805. }
  806. return -1;
  807. }
  808. int String::indexOf (const int startIndex,
  809. const tchar* const other) const throw()
  810. {
  811. if (other == 0 || startIndex >= CharacterFunctions::length (text->text))
  812. return -1;
  813. const tchar* const found = CharacterFunctions::find (text->text + jmax (0, startIndex),
  814. other);
  815. return (found == 0) ? -1
  816. : (int) (found - text->text);
  817. }
  818. int String::indexOfIgnoreCase (const tchar* const other) const throw()
  819. {
  820. if (other != 0 && *other != 0)
  821. {
  822. const int len = CharacterFunctions::length (other);
  823. const int end = CharacterFunctions::length (text->text) - len;
  824. for (int i = 0; i <= end; ++i)
  825. if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0)
  826. return i;
  827. }
  828. return -1;
  829. }
  830. int String::indexOfIgnoreCase (const int startIndex,
  831. const tchar* const other) const throw()
  832. {
  833. if (other != 0 && *other != 0)
  834. {
  835. const int len = CharacterFunctions::length (other);
  836. const int end = length() - len;
  837. for (int i = jmax (0, startIndex); i <= end; ++i)
  838. if (CharacterFunctions::compareIgnoreCase (text->text + i, other, len) == 0)
  839. return i;
  840. }
  841. return -1;
  842. }
  843. int String::lastIndexOf (const tchar* const other) const throw()
  844. {
  845. if (other != 0 && *other != 0)
  846. {
  847. const int len = CharacterFunctions::length (other);
  848. int i = length() - len;
  849. if (i >= 0)
  850. {
  851. const tchar* n = text->text + i;
  852. while (i >= 0)
  853. {
  854. if (CharacterFunctions::compare (n--, other, len) == 0)
  855. return i;
  856. --i;
  857. }
  858. }
  859. }
  860. return -1;
  861. }
  862. int String::lastIndexOfIgnoreCase (const tchar* const other) const throw()
  863. {
  864. if (other != 0 && *other != 0)
  865. {
  866. const int len = CharacterFunctions::length (other);
  867. int i = length() - len;
  868. if (i >= 0)
  869. {
  870. const tchar* n = text->text + i;
  871. while (i >= 0)
  872. {
  873. if (CharacterFunctions::compareIgnoreCase (n--, other, len) == 0)
  874. return i;
  875. --i;
  876. }
  877. }
  878. }
  879. return -1;
  880. }
  881. int String::lastIndexOfAnyOf (const tchar* const charactersToLookFor,
  882. const bool ignoreCase) const throw()
  883. {
  884. for (int i = CharacterFunctions::length (text->text); --i >= 0;)
  885. if (CharacterFunctions::indexOfChar (charactersToLookFor, text->text [i], ignoreCase) >= 0)
  886. return i;
  887. return -1;
  888. }
  889. bool String::contains (const tchar* const other) const throw()
  890. {
  891. return indexOf (other) >= 0;
  892. }
  893. bool String::containsChar (const tchar character) const throw()
  894. {
  895. return indexOfChar (character) >= 0;
  896. }
  897. bool String::containsIgnoreCase (const tchar* const t) const throw()
  898. {
  899. return indexOfIgnoreCase (t) >= 0;
  900. }
  901. int String::indexOfWholeWord (const tchar* const word) const throw()
  902. {
  903. if (word != 0 && *word != 0)
  904. {
  905. const int wordLen = CharacterFunctions::length (word);
  906. const int end = length() - wordLen;
  907. const tchar* t = text->text;
  908. for (int i = 0; i <= end; ++i)
  909. {
  910. if (CharacterFunctions::compare (t, word, wordLen) == 0
  911. && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1)))
  912. && ! CharacterFunctions::isLetterOrDigit (t [wordLen]))
  913. {
  914. return i;
  915. }
  916. ++t;
  917. }
  918. }
  919. return -1;
  920. }
  921. int String::indexOfWholeWordIgnoreCase (const tchar* const word) const throw()
  922. {
  923. if (word != 0 && *word != 0)
  924. {
  925. const int wordLen = CharacterFunctions::length (word);
  926. const int end = length() - wordLen;
  927. const tchar* t = text->text;
  928. for (int i = 0; i <= end; ++i)
  929. {
  930. if (CharacterFunctions::compareIgnoreCase (t, word, wordLen) == 0
  931. && (i == 0 || ! CharacterFunctions::isLetterOrDigit (* (t - 1)))
  932. && ! CharacterFunctions::isLetterOrDigit (t [wordLen]))
  933. {
  934. return i;
  935. }
  936. ++t;
  937. }
  938. }
  939. return -1;
  940. }
  941. bool String::containsWholeWord (const tchar* const wordToLookFor) const throw()
  942. {
  943. return indexOfWholeWord (wordToLookFor) >= 0;
  944. }
  945. bool String::containsWholeWordIgnoreCase (const tchar* const wordToLookFor) const throw()
  946. {
  947. return indexOfWholeWordIgnoreCase (wordToLookFor) >= 0;
  948. }
  949. //==============================================================================
  950. static int indexOfMatch (const tchar* const wildcard,
  951. const tchar* const test,
  952. const bool ignoreCase) throw()
  953. {
  954. int start = 0;
  955. while (test [start] != 0)
  956. {
  957. int i = 0;
  958. for (;;)
  959. {
  960. const tchar wc = wildcard [i];
  961. const tchar c = test [i + start];
  962. if (wc == c
  963. || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c))
  964. || (wc == T('?') && c != 0))
  965. {
  966. if (wc == 0)
  967. return start;
  968. ++i;
  969. }
  970. else
  971. {
  972. if (wc == T('*') && (wildcard [i + 1] == 0
  973. || indexOfMatch (wildcard + i + 1,
  974. test + start + i,
  975. ignoreCase) >= 0))
  976. {
  977. return start;
  978. }
  979. break;
  980. }
  981. }
  982. ++start;
  983. }
  984. return -1;
  985. }
  986. bool String::matchesWildcard (const tchar* wildcard, const bool ignoreCase) const throw()
  987. {
  988. int i = 0;
  989. for (;;)
  990. {
  991. const tchar wc = wildcard [i];
  992. const tchar c = text->text [i];
  993. if (wc == c
  994. || (ignoreCase && CharacterFunctions::toLowerCase (wc) == CharacterFunctions::toLowerCase (c))
  995. || (wc == T('?') && c != 0))
  996. {
  997. if (wc == 0)
  998. return true;
  999. ++i;
  1000. }
  1001. else
  1002. {
  1003. return wc == T('*') && (wildcard [i + 1] == 0
  1004. || indexOfMatch (wildcard + i + 1,
  1005. text->text + i,
  1006. ignoreCase) >= 0);
  1007. }
  1008. }
  1009. }
  1010. //==============================================================================
  1011. void String::printf (const tchar* const pf, ...) throw()
  1012. {
  1013. va_list list;
  1014. va_start (list, pf);
  1015. vprintf (pf, list);
  1016. }
  1017. const String String::formatted (const tchar* const pf, ...) throw()
  1018. {
  1019. va_list list;
  1020. va_start (list, pf);
  1021. String result;
  1022. result.vprintf (pf, list);
  1023. return result;
  1024. }
  1025. //==============================================================================
  1026. void String::vprintf (const tchar* const pf, va_list& args) throw()
  1027. {
  1028. tchar stackBuf [256];
  1029. unsigned int bufSize = 256;
  1030. tchar* buf = stackBuf;
  1031. deleteInternal();
  1032. do
  1033. {
  1034. #if JUCE_LINUX && JUCE_64BIT
  1035. va_list tempArgs;
  1036. va_copy (tempArgs, args);
  1037. const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, tempArgs);
  1038. va_end (tempArgs);
  1039. #else
  1040. const int num = CharacterFunctions::vprintf (buf, bufSize - 1, pf, args);
  1041. #endif
  1042. if (num > 0)
  1043. {
  1044. createInternal (num);
  1045. memcpy (text->text, buf, (num + 1) * sizeof (tchar));
  1046. break;
  1047. }
  1048. else if (num == 0)
  1049. {
  1050. text = &emptyString;
  1051. emptyString.refCount = safeEmptyStringRefCount;
  1052. break;
  1053. }
  1054. if (buf != stackBuf)
  1055. juce_free (buf);
  1056. bufSize += 256;
  1057. buf = (tchar*) juce_malloc (bufSize * sizeof (tchar));
  1058. }
  1059. while (bufSize < 65536); // this is a sanity check to avoid situations where vprintf repeatedly
  1060. // returns -1 because of an error rather than because it needs more space.
  1061. if (buf != stackBuf)
  1062. juce_free (buf);
  1063. }
  1064. //==============================================================================
  1065. const String String::repeatedString (const tchar* const stringToRepeat,
  1066. int numberOfTimesToRepeat) throw()
  1067. {
  1068. const int len = CharacterFunctions::length (stringToRepeat);
  1069. String result ((int) (len * numberOfTimesToRepeat + 1), (int) 0);
  1070. tchar* n = result.text->text;
  1071. n[0] = 0;
  1072. while (--numberOfTimesToRepeat >= 0)
  1073. {
  1074. CharacterFunctions::append (n, stringToRepeat);
  1075. n += len;
  1076. }
  1077. return result;
  1078. }
  1079. //==============================================================================
  1080. const String String::replaceSection (int index,
  1081. int numCharsToReplace,
  1082. const tchar* const stringToInsert) const throw()
  1083. {
  1084. if (index < 0)
  1085. {
  1086. // a negative index to replace from?
  1087. jassertfalse
  1088. index = 0;
  1089. }
  1090. if (numCharsToReplace < 0)
  1091. {
  1092. // replacing a negative number of characters?
  1093. numCharsToReplace = 0;
  1094. jassertfalse;
  1095. }
  1096. const int len = length();
  1097. if (index + numCharsToReplace > len)
  1098. {
  1099. if (index > len)
  1100. {
  1101. // replacing beyond the end of the string?
  1102. index = len;
  1103. jassertfalse
  1104. }
  1105. numCharsToReplace = len - index;
  1106. }
  1107. const int newStringLen = (stringToInsert != 0) ? CharacterFunctions::length (stringToInsert) : 0;
  1108. const int newTotalLen = len + newStringLen - numCharsToReplace;
  1109. if (newTotalLen <= 0)
  1110. return String::empty;
  1111. String result (newTotalLen, (int) 0);
  1112. memcpy (result.text->text,
  1113. text->text,
  1114. index * sizeof (tchar));
  1115. if (newStringLen > 0)
  1116. memcpy (result.text->text + index,
  1117. stringToInsert,
  1118. newStringLen * sizeof (tchar));
  1119. const int endStringLen = newTotalLen - (index + newStringLen);
  1120. if (endStringLen > 0)
  1121. memcpy (result.text->text + (index + newStringLen),
  1122. text->text + (index + numCharsToReplace),
  1123. endStringLen * sizeof (tchar));
  1124. result.text->text [newTotalLen] = 0;
  1125. return result;
  1126. }
  1127. const String String::replace (const tchar* const stringToReplace,
  1128. const tchar* const stringToInsert,
  1129. const bool ignoreCase) const throw()
  1130. {
  1131. const int stringToReplaceLen = CharacterFunctions::length (stringToReplace);
  1132. const int stringToInsertLen = CharacterFunctions::length (stringToInsert);
  1133. int i = 0;
  1134. String result (*this);
  1135. while ((i = (ignoreCase ? result.indexOfIgnoreCase (i, stringToReplace)
  1136. : result.indexOf (i, stringToReplace))) >= 0)
  1137. {
  1138. result = result.replaceSection (i, stringToReplaceLen, stringToInsert);
  1139. i += stringToInsertLen;
  1140. }
  1141. return result;
  1142. }
  1143. const String String::replaceCharacter (const tchar charToReplace,
  1144. const tchar charToInsert) const throw()
  1145. {
  1146. const int index = indexOfChar (charToReplace);
  1147. if (index < 0)
  1148. return *this;
  1149. String result (*this);
  1150. result.dupeInternalIfMultiplyReferenced();
  1151. tchar* t = result.text->text + index;
  1152. while (*t != 0)
  1153. {
  1154. if (*t == charToReplace)
  1155. *t = charToInsert;
  1156. ++t;
  1157. }
  1158. return result;
  1159. }
  1160. const String String::replaceCharacters (const String& charactersToReplace,
  1161. const tchar* const charactersToInsertInstead) const throw()
  1162. {
  1163. String result (*this);
  1164. result.dupeInternalIfMultiplyReferenced();
  1165. tchar* t = result.text->text;
  1166. const int len2 = CharacterFunctions::length (charactersToInsertInstead);
  1167. // the two strings passed in are supposed to be the same length!
  1168. jassert (len2 == charactersToReplace.length());
  1169. while (*t != 0)
  1170. {
  1171. const int index = charactersToReplace.indexOfChar (*t);
  1172. if (((unsigned int) index) < (unsigned int) len2)
  1173. *t = charactersToInsertInstead [index];
  1174. ++t;
  1175. }
  1176. return result;
  1177. }
  1178. //==============================================================================
  1179. bool String::startsWith (const tchar* const other) const throw()
  1180. {
  1181. return other != 0
  1182. && CharacterFunctions::compare (text->text, other, CharacterFunctions::length (other)) == 0;
  1183. }
  1184. bool String::startsWithIgnoreCase (const tchar* const other) const throw()
  1185. {
  1186. return other != 0
  1187. && CharacterFunctions::compareIgnoreCase (text->text, other, CharacterFunctions::length (other)) == 0;
  1188. }
  1189. bool String::startsWithChar (const tchar character) const throw()
  1190. {
  1191. jassert (character != 0); // strings can't contain a null character!
  1192. return text->text[0] == character;
  1193. }
  1194. bool String::endsWithChar (const tchar character) const throw()
  1195. {
  1196. jassert (character != 0); // strings can't contain a null character!
  1197. return text->text[0] != 0
  1198. && text->text [length() - 1] == character;
  1199. }
  1200. bool String::endsWith (const tchar* const other) const throw()
  1201. {
  1202. if (other == 0)
  1203. return false;
  1204. const int thisLen = length();
  1205. const int otherLen = CharacterFunctions::length (other);
  1206. return thisLen >= otherLen
  1207. && CharacterFunctions::compare (text->text + thisLen - otherLen, other) == 0;
  1208. }
  1209. bool String::endsWithIgnoreCase (const tchar* const other) const throw()
  1210. {
  1211. if (other == 0)
  1212. return false;
  1213. const int thisLen = length();
  1214. const int otherLen = CharacterFunctions::length (other);
  1215. return thisLen >= otherLen
  1216. && CharacterFunctions::compareIgnoreCase (text->text + thisLen - otherLen, other) == 0;
  1217. }
  1218. //==============================================================================
  1219. const String String::toUpperCase() const throw()
  1220. {
  1221. String result (*this);
  1222. result.dupeInternalIfMultiplyReferenced();
  1223. CharacterFunctions::toUpperCase (result.text->text);
  1224. return result;
  1225. }
  1226. const String String::toLowerCase() const throw()
  1227. {
  1228. String result (*this);
  1229. result.dupeInternalIfMultiplyReferenced();
  1230. CharacterFunctions::toLowerCase (result.text->text);
  1231. return result;
  1232. }
  1233. //==============================================================================
  1234. tchar& String::operator[] (const int index) throw()
  1235. {
  1236. jassert (((unsigned int) index) <= (unsigned int) length());
  1237. dupeInternalIfMultiplyReferenced();
  1238. return text->text [index];
  1239. }
  1240. tchar String::getLastCharacter() const throw()
  1241. {
  1242. return (isEmpty()) ? ((tchar) 0)
  1243. : text->text [CharacterFunctions::length (text->text) - 1];
  1244. }
  1245. const String String::substring (int start, int end) const throw()
  1246. {
  1247. if (start < 0)
  1248. start = 0;
  1249. else if (end <= start)
  1250. return empty;
  1251. int len = 0;
  1252. const tchar* const t = text->text;
  1253. while (len <= end && t [len] != 0)
  1254. ++len;
  1255. if (end >= len)
  1256. {
  1257. if (start == 0)
  1258. return *this;
  1259. end = len;
  1260. }
  1261. return String (text->text + start,
  1262. end - start);
  1263. }
  1264. const String String::substring (const int start) const throw()
  1265. {
  1266. if (start <= 0)
  1267. return *this;
  1268. const int len = CharacterFunctions::length (text->text);
  1269. if (start >= len)
  1270. return empty;
  1271. else
  1272. return String (text->text + start,
  1273. len - start);
  1274. }
  1275. const String String::dropLastCharacters (const int numberToDrop) const throw()
  1276. {
  1277. return String (text->text,
  1278. jmax (0, CharacterFunctions::length (text->text) - numberToDrop));
  1279. }
  1280. const String String::fromFirstOccurrenceOf (const tchar* const sub,
  1281. const bool includeSubString,
  1282. const bool ignoreCase) const throw()
  1283. {
  1284. const int i = ignoreCase ? indexOfIgnoreCase (sub)
  1285. : indexOf (sub);
  1286. if (i < 0)
  1287. return empty;
  1288. else
  1289. return substring (includeSubString ? i : i + CharacterFunctions::length (sub));
  1290. }
  1291. const String String::fromLastOccurrenceOf (const tchar* const sub,
  1292. const bool includeSubString,
  1293. const bool ignoreCase) const throw()
  1294. {
  1295. const int i = ignoreCase ? lastIndexOfIgnoreCase (sub)
  1296. : lastIndexOf (sub);
  1297. if (i < 0)
  1298. return *this;
  1299. else
  1300. return substring (includeSubString ? i : i + CharacterFunctions::length (sub));
  1301. }
  1302. const String String::upToFirstOccurrenceOf (const tchar* const sub,
  1303. const bool includeSubString,
  1304. const bool ignoreCase) const throw()
  1305. {
  1306. const int i = ignoreCase ? indexOfIgnoreCase (sub)
  1307. : indexOf (sub);
  1308. if (i < 0)
  1309. return *this;
  1310. else
  1311. return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i);
  1312. }
  1313. const String String::upToLastOccurrenceOf (const tchar* const sub,
  1314. const bool includeSubString,
  1315. const bool ignoreCase) const throw()
  1316. {
  1317. const int i = ignoreCase ? lastIndexOfIgnoreCase (sub)
  1318. : lastIndexOf (sub);
  1319. if (i < 0)
  1320. return *this;
  1321. return substring (0, includeSubString ? i + CharacterFunctions::length (sub) : i);
  1322. }
  1323. bool String::isQuotedString() const throw()
  1324. {
  1325. const String trimmed (trimStart());
  1326. return trimmed[0] == T('"')
  1327. || trimmed[0] == T('\'');
  1328. }
  1329. const String String::unquoted() const throw()
  1330. {
  1331. String s (*this);
  1332. if (s[0] == T('"') || s[0] == T('\''))
  1333. s = s.substring (1);
  1334. const int lastCharIndex = s.length() - 1;
  1335. if (lastCharIndex >= 0
  1336. && (s [lastCharIndex] == T('"') || s[lastCharIndex] == T('\'')))
  1337. s [lastCharIndex] = 0;
  1338. return s;
  1339. }
  1340. const String String::quoted (const tchar quoteCharacter) const throw()
  1341. {
  1342. if (isEmpty())
  1343. return charToString (quoteCharacter) + quoteCharacter;
  1344. String t (*this);
  1345. if (! t.startsWithChar (quoteCharacter))
  1346. t = charToString (quoteCharacter) + t;
  1347. if (! t.endsWithChar (quoteCharacter))
  1348. t += quoteCharacter;
  1349. return t;
  1350. }
  1351. //==============================================================================
  1352. const String String::trim() const throw()
  1353. {
  1354. if (isEmpty())
  1355. return empty;
  1356. int start = 0;
  1357. while (CharacterFunctions::isWhitespace (text->text [start]))
  1358. ++start;
  1359. const int len = CharacterFunctions::length (text->text);
  1360. int end = len - 1;
  1361. while ((end >= start) && CharacterFunctions::isWhitespace (text->text [end]))
  1362. --end;
  1363. ++end;
  1364. if (end <= start)
  1365. return empty;
  1366. else if (start > 0 || end < len)
  1367. return String (text->text + start, end - start);
  1368. else
  1369. return *this;
  1370. }
  1371. const String String::trimStart() const throw()
  1372. {
  1373. if (isEmpty())
  1374. return empty;
  1375. const tchar* t = text->text;
  1376. while (CharacterFunctions::isWhitespace (*t))
  1377. ++t;
  1378. if (t == text->text)
  1379. return *this;
  1380. else
  1381. return String (t);
  1382. }
  1383. const String String::trimEnd() const throw()
  1384. {
  1385. if (isEmpty())
  1386. return empty;
  1387. const tchar* endT = text->text + (CharacterFunctions::length (text->text) - 1);
  1388. while ((endT >= text->text) && CharacterFunctions::isWhitespace (*endT))
  1389. --endT;
  1390. return String (text->text, (int) (++endT - text->text));
  1391. }
  1392. //==============================================================================
  1393. const String String::retainCharacters (const tchar* const charactersToRetain) const throw()
  1394. {
  1395. jassert (charactersToRetain != 0);
  1396. if (isEmpty())
  1397. return empty;
  1398. String result (text->allocatedNumChars, (int) 0);
  1399. tchar* dst = result.text->text;
  1400. const tchar* src = text->text;
  1401. while (*src != 0)
  1402. {
  1403. if (CharacterFunctions::indexOfCharFast (charactersToRetain, *src) >= 0)
  1404. *dst++ = *src;
  1405. ++src;
  1406. }
  1407. *dst = 0;
  1408. return result;
  1409. }
  1410. const String String::removeCharacters (const tchar* const charactersToRemove) const throw()
  1411. {
  1412. jassert (charactersToRemove != 0);
  1413. if (isEmpty())
  1414. return empty;
  1415. String result (text->allocatedNumChars, (int) 0);
  1416. tchar* dst = result.text->text;
  1417. const tchar* src = text->text;
  1418. while (*src != 0)
  1419. {
  1420. if (CharacterFunctions::indexOfCharFast (charactersToRemove, *src) < 0)
  1421. *dst++ = *src;
  1422. ++src;
  1423. }
  1424. *dst = 0;
  1425. return result;
  1426. }
  1427. const String String::initialSectionContainingOnly (const tchar* const permittedCharacters) const throw()
  1428. {
  1429. return substring (0, CharacterFunctions::getIntialSectionContainingOnly (text->text, permittedCharacters));
  1430. }
  1431. const String String::initialSectionNotContaining (const tchar* const charactersToStopAt) const throw()
  1432. {
  1433. jassert (charactersToStopAt != 0);
  1434. const tchar* const t = text->text;
  1435. int i = 0;
  1436. while (t[i] != 0)
  1437. {
  1438. if (CharacterFunctions::indexOfCharFast (charactersToStopAt, t[i]) >= 0)
  1439. return String (text->text, i);
  1440. ++i;
  1441. }
  1442. return empty;
  1443. }
  1444. bool String::containsOnly (const tchar* const chars) const throw()
  1445. {
  1446. jassert (chars != 0);
  1447. const tchar* t = text->text;
  1448. while (*t != 0)
  1449. if (CharacterFunctions::indexOfCharFast (chars, *t++) < 0)
  1450. return false;
  1451. return true;
  1452. }
  1453. bool String::containsAnyOf (const tchar* const chars) const throw()
  1454. {
  1455. jassert (chars != 0);
  1456. const tchar* t = text->text;
  1457. while (*t != 0)
  1458. if (CharacterFunctions::indexOfCharFast (chars, *t++) >= 0)
  1459. return true;
  1460. return false;
  1461. }
  1462. bool String::containsNonWhitespaceChars() const throw()
  1463. {
  1464. const tchar* t = text->text;
  1465. while (*t != 0)
  1466. if (! CharacterFunctions::isWhitespace (*t++))
  1467. return true;
  1468. return false;
  1469. }
  1470. //==============================================================================
  1471. int String::getIntValue() const throw()
  1472. {
  1473. return CharacterFunctions::getIntValue (text->text);
  1474. }
  1475. int String::getTrailingIntValue() const throw()
  1476. {
  1477. int n = 0;
  1478. int mult = 1;
  1479. const tchar* t = text->text + length();
  1480. while (--t >= text->text)
  1481. {
  1482. const tchar c = *t;
  1483. if (! CharacterFunctions::isDigit (c))
  1484. {
  1485. if (c == T('-'))
  1486. n = -n;
  1487. break;
  1488. }
  1489. n += mult * (c - T('0'));
  1490. mult *= 10;
  1491. }
  1492. return n;
  1493. }
  1494. int64 String::getLargeIntValue() const throw()
  1495. {
  1496. return CharacterFunctions::getInt64Value (text->text);
  1497. }
  1498. float String::getFloatValue() const throw()
  1499. {
  1500. return (float) CharacterFunctions::getDoubleValue (text->text);
  1501. }
  1502. double String::getDoubleValue() const throw()
  1503. {
  1504. return CharacterFunctions::getDoubleValue (text->text);
  1505. }
  1506. static const tchar* const hexDigits = T("0123456789abcdef");
  1507. const String String::toHexString (const int number) throw()
  1508. {
  1509. tchar buffer[32];
  1510. tchar* const end = buffer + 32;
  1511. tchar* t = end;
  1512. *--t = 0;
  1513. unsigned int v = (unsigned int) number;
  1514. do
  1515. {
  1516. *--t = hexDigits [v & 15];
  1517. v >>= 4;
  1518. } while (v != 0);
  1519. return String (t, (int) (((char*) end) - (char*) t) - 1);
  1520. }
  1521. const String String::toHexString (const int64 number) throw()
  1522. {
  1523. tchar buffer[32];
  1524. tchar* const end = buffer + 32;
  1525. tchar* t = end;
  1526. *--t = 0;
  1527. uint64 v = (uint64) number;
  1528. do
  1529. {
  1530. *--t = hexDigits [(int) (v & 15)];
  1531. v >>= 4;
  1532. } while (v != 0);
  1533. return String (t, (int) (((char*) end) - (char*) t));
  1534. }
  1535. const String String::toHexString (const short number) throw()
  1536. {
  1537. return toHexString ((int) (unsigned short) number);
  1538. }
  1539. const String String::toHexString (const unsigned char* data,
  1540. const int size,
  1541. const int groupSize) throw()
  1542. {
  1543. if (size <= 0)
  1544. return empty;
  1545. int numChars = (size * 2) + 2;
  1546. if (groupSize > 0)
  1547. numChars += size / groupSize;
  1548. String s (numChars, (int) 0);
  1549. tchar* d = s.text->text;
  1550. for (int i = 0; i < size; ++i)
  1551. {
  1552. *d++ = hexDigits [(*data) >> 4];
  1553. *d++ = hexDigits [(*data) & 0xf];
  1554. ++data;
  1555. if (groupSize > 0 && (i % groupSize) == (groupSize - 1) && i < (size - 1))
  1556. *d++ = T(' ');
  1557. }
  1558. *d = 0;
  1559. return s;
  1560. }
  1561. int String::getHexValue32() const throw()
  1562. {
  1563. int result = 0;
  1564. const tchar* c = text->text;
  1565. for (;;)
  1566. {
  1567. const int hexValue = CharacterFunctions::getHexDigitValue (*c);
  1568. if (hexValue >= 0)
  1569. result = (result << 4) | hexValue;
  1570. else if (*c == 0)
  1571. break;
  1572. ++c;
  1573. }
  1574. return result;
  1575. }
  1576. int64 String::getHexValue64() const throw()
  1577. {
  1578. int64 result = 0;
  1579. const tchar* c = text->text;
  1580. for (;;)
  1581. {
  1582. const int hexValue = CharacterFunctions::getHexDigitValue (*c);
  1583. if (hexValue >= 0)
  1584. result = (result << 4) | hexValue;
  1585. else if (*c == 0)
  1586. break;
  1587. ++c;
  1588. }
  1589. return result;
  1590. }
  1591. //==============================================================================
  1592. const String String::createStringFromData (const void* const data_,
  1593. const int size) throw()
  1594. {
  1595. const char* const data = (const char*) data_;
  1596. if (size <= 0 || data == 0)
  1597. {
  1598. return empty;
  1599. }
  1600. else if (size < 2)
  1601. {
  1602. return charToString (data[0]);
  1603. }
  1604. else if ((data[0] == (char)-2 && data[1] == (char)-1)
  1605. || (data[0] == (char)-1 && data[1] == (char)-2))
  1606. {
  1607. // assume it's 16-bit unicode
  1608. const bool bigEndian = (data[0] == (char)-2);
  1609. const int numChars = size / 2 - 1;
  1610. String result;
  1611. result.preallocateStorage (numChars + 2);
  1612. const uint16* const src = (const uint16*) (data + 2);
  1613. tchar* const dst = const_cast <tchar*> ((const tchar*) result);
  1614. if (bigEndian)
  1615. {
  1616. for (int i = 0; i < numChars; ++i)
  1617. dst[i] = (tchar) swapIfLittleEndian (src[i]);
  1618. }
  1619. else
  1620. {
  1621. for (int i = 0; i < numChars; ++i)
  1622. dst[i] = (tchar) swapIfBigEndian (src[i]);
  1623. }
  1624. dst [numChars] = 0;
  1625. return result;
  1626. }
  1627. else
  1628. {
  1629. return String::fromUTF8 ((const uint8*) data, size);
  1630. }
  1631. }
  1632. //==============================================================================
  1633. const char* String::toUTF8() const throw()
  1634. {
  1635. if (isEmpty())
  1636. {
  1637. return (const char*) emptyCharString;
  1638. }
  1639. else
  1640. {
  1641. String* const mutableThis = const_cast <String*> (this);
  1642. mutableThis->dupeInternalIfMultiplyReferenced();
  1643. const int currentLen = CharacterFunctions::length (text->text) + 1;
  1644. const int utf8BytesNeeded = copyToUTF8 (0);
  1645. mutableThis->text = (InternalRefCountedStringHolder*)
  1646. juce_realloc (text, sizeof (InternalRefCountedStringHolder)
  1647. + (currentLen * sizeof (juce_wchar) + utf8BytesNeeded));
  1648. char* const otherCopy = (char*) (text->text + currentLen);
  1649. copyToUTF8 ((uint8*) otherCopy);
  1650. return otherCopy;
  1651. }
  1652. }
  1653. int String::copyToUTF8 (uint8* const buffer, const int maxBufferSizeBytes) const throw()
  1654. {
  1655. jassert (maxBufferSizeBytes >= 0); // keep this value positive, or no characters will be copied!
  1656. #if JUCE_STRINGS_ARE_UNICODE
  1657. int num = 0, index = 0;
  1658. for (;;)
  1659. {
  1660. const uint32 c = (uint32) text->text [index++];
  1661. if (c >= 0x80)
  1662. {
  1663. int numExtraBytes = 1;
  1664. if (c >= 0x800)
  1665. {
  1666. ++numExtraBytes;
  1667. if (c >= 0x10000)
  1668. {
  1669. ++numExtraBytes;
  1670. if (c >= 0x200000)
  1671. {
  1672. ++numExtraBytes;
  1673. if (c >= 0x4000000)
  1674. ++numExtraBytes;
  1675. }
  1676. }
  1677. }
  1678. if (buffer != 0)
  1679. {
  1680. if (num + numExtraBytes >= maxBufferSizeBytes)
  1681. {
  1682. buffer [num++] = 0;
  1683. break;
  1684. }
  1685. else
  1686. {
  1687. buffer [num++] = (uint8) ((0xff << (7 - numExtraBytes)) | (c >> (numExtraBytes * 6)));
  1688. while (--numExtraBytes >= 0)
  1689. buffer [num++] = (uint8) (0x80 | (0x3f & (c >> (numExtraBytes * 6))));
  1690. }
  1691. }
  1692. else
  1693. {
  1694. num += numExtraBytes + 1;
  1695. }
  1696. }
  1697. else
  1698. {
  1699. if (buffer != 0)
  1700. {
  1701. if (num + 1 >= maxBufferSizeBytes)
  1702. {
  1703. buffer [num++] = 0;
  1704. break;
  1705. }
  1706. buffer [num] = (uint8) c;
  1707. }
  1708. ++num;
  1709. }
  1710. if (c == 0)
  1711. break;
  1712. }
  1713. return num;
  1714. #else
  1715. const int numBytes = jmin (maxBufferSizeBytes, length() + 1);
  1716. if (buffer != 0)
  1717. copyToBuffer ((char*) buffer, maxBufferSizeBytes);
  1718. return numBytes;
  1719. #endif
  1720. }
  1721. const String String::fromUTF8 (const uint8* const buffer, int bufferSizeBytes) throw()
  1722. {
  1723. if (buffer == 0)
  1724. return empty;
  1725. if (bufferSizeBytes < 0)
  1726. bufferSizeBytes = INT_MAX;
  1727. int numBytes;
  1728. for (numBytes = 0; numBytes < bufferSizeBytes; ++numBytes)
  1729. if (buffer [numBytes] == 0)
  1730. break;
  1731. String result (numBytes + 1, 0);
  1732. tchar* dest = result.text->text;
  1733. int i = 0;
  1734. while (i < numBytes)
  1735. {
  1736. const uint8 c = buffer [i++];
  1737. if ((c & 0x80) != 0)
  1738. {
  1739. int mask = 0x7f;
  1740. int bit = 0x40;
  1741. int numExtraValues = 0;
  1742. while (bit != 0 && (c & bit) != 0)
  1743. {
  1744. bit >>= 1;
  1745. mask >>= 1;
  1746. ++numExtraValues;
  1747. }
  1748. int n = (c & mask);
  1749. while (--numExtraValues >= 0 && i < bufferSizeBytes)
  1750. {
  1751. const uint8 c = buffer[i];
  1752. if ((c & 0xc0) != 0x80)
  1753. break;
  1754. n <<= 6;
  1755. n |= (c & 0x3f);
  1756. ++i;
  1757. }
  1758. *dest++ = (tchar) n;
  1759. }
  1760. else
  1761. {
  1762. *dest++ = (tchar) c;
  1763. }
  1764. }
  1765. *dest = 0;
  1766. return result;
  1767. }
  1768. END_JUCE_NAMESPACE