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.

2158 lines
56KB

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