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.

2281 lines
59KB

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