Audio plugin host https://kx.studio/carla
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.

856 lines
21KB

  1. /*
  2. * Carla String
  3. * Copyright (C) 2013-2015 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #ifndef CARLA_STRING_HPP_INCLUDED
  18. #define CARLA_STRING_HPP_INCLUDED
  19. #include "CarlaJuceUtils.hpp"
  20. #include "CarlaMathUtils.hpp"
  21. // -----------------------------------------------------------------------
  22. // CarlaString class
  23. class CarlaString
  24. {
  25. public:
  26. // -------------------------------------------------------------------
  27. // constructors (no explicit conversions allowed)
  28. /*
  29. * Empty string.
  30. */
  31. explicit CarlaString() noexcept
  32. : fBuffer(_null()),
  33. fBufferLen(0) {}
  34. /*
  35. * Simple character.
  36. */
  37. explicit CarlaString(const char c) noexcept
  38. : fBuffer(_null()),
  39. fBufferLen(0)
  40. {
  41. char ch[2];
  42. ch[0] = c;
  43. ch[1] = '\0';
  44. _dup(ch);
  45. }
  46. /*
  47. * Simple char string.
  48. */
  49. explicit CarlaString(char* const strBuf) noexcept
  50. : fBuffer(_null()),
  51. fBufferLen(0)
  52. {
  53. _dup(strBuf);
  54. }
  55. /*
  56. * Simple const char string.
  57. */
  58. explicit CarlaString(const char* const strBuf) noexcept
  59. : fBuffer(_null()),
  60. fBufferLen(0)
  61. {
  62. _dup(strBuf);
  63. }
  64. /*
  65. * Integer.
  66. */
  67. explicit CarlaString(const int value) noexcept
  68. : fBuffer(_null()),
  69. fBufferLen(0)
  70. {
  71. char strBuf[0xff+1];
  72. std::snprintf(strBuf, 0xff, "%d", value);
  73. strBuf[0xff] = '\0';
  74. _dup(strBuf);
  75. }
  76. /*
  77. * Unsigned integer, possibly in hexadecimal.
  78. */
  79. explicit CarlaString(const unsigned int value, const bool hexadecimal = false) noexcept
  80. : fBuffer(_null()),
  81. fBufferLen(0)
  82. {
  83. char strBuf[0xff+1];
  84. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  85. strBuf[0xff] = '\0';
  86. _dup(strBuf);
  87. }
  88. /*
  89. * Long integer.
  90. */
  91. explicit CarlaString(const long value) noexcept
  92. : fBuffer(_null()),
  93. fBufferLen(0)
  94. {
  95. char strBuf[0xff+1];
  96. std::snprintf(strBuf, 0xff, "%ld", value);
  97. strBuf[0xff] = '\0';
  98. _dup(strBuf);
  99. }
  100. /*
  101. * Long unsigned integer, possibly hexadecimal.
  102. */
  103. explicit CarlaString(const unsigned long value, const bool hexadecimal = false) noexcept
  104. : fBuffer(_null()),
  105. fBufferLen(0)
  106. {
  107. char strBuf[0xff+1];
  108. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  109. strBuf[0xff] = '\0';
  110. _dup(strBuf);
  111. }
  112. /*
  113. * Long long integer.
  114. */
  115. explicit CarlaString(const long long value) noexcept
  116. : fBuffer(_null()),
  117. fBufferLen(0)
  118. {
  119. char strBuf[0xff+1];
  120. std::snprintf(strBuf, 0xff, "%lld", value);
  121. strBuf[0xff] = '\0';
  122. _dup(strBuf);
  123. }
  124. /*
  125. * Long long unsigned integer, possibly hexadecimal.
  126. */
  127. explicit CarlaString(const unsigned long long value, const bool hexadecimal = false) noexcept
  128. : fBuffer(_null()),
  129. fBufferLen(0)
  130. {
  131. char strBuf[0xff+1];
  132. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%llx" : "%llu", value);
  133. strBuf[0xff] = '\0';
  134. _dup(strBuf);
  135. }
  136. /*
  137. * Single-precision floating point number.
  138. */
  139. explicit CarlaString(const float value) noexcept
  140. : fBuffer(_null()),
  141. fBufferLen(0)
  142. {
  143. char strBuf[0xff+1];
  144. std::snprintf(strBuf, 0xff, "%f", value);
  145. strBuf[0xff] = '\0';
  146. _dup(strBuf);
  147. }
  148. /*
  149. * Double-precision floating point number.
  150. */
  151. explicit CarlaString(const double value) noexcept
  152. : fBuffer(_null()),
  153. fBufferLen(0)
  154. {
  155. char strBuf[0xff+1];
  156. std::snprintf(strBuf, 0xff, "%g", value);
  157. strBuf[0xff] = '\0';
  158. _dup(strBuf);
  159. }
  160. // -------------------------------------------------------------------
  161. // non-explicit constructor
  162. /*
  163. * Create string from another string.
  164. */
  165. CarlaString(const CarlaString& str) noexcept
  166. : fBuffer(_null()),
  167. fBufferLen(0)
  168. {
  169. _dup(str.fBuffer);
  170. }
  171. // -------------------------------------------------------------------
  172. // destructor
  173. /*
  174. * Destructor.
  175. */
  176. ~CarlaString() noexcept
  177. {
  178. CARLA_SAFE_ASSERT_RETURN(fBuffer != nullptr,);
  179. if (fBuffer == _null())
  180. return;
  181. std::free(fBuffer);
  182. fBuffer = nullptr;
  183. fBufferLen = 0;
  184. }
  185. // -------------------------------------------------------------------
  186. // public methods
  187. /*
  188. * Get length of the string.
  189. */
  190. std::size_t length() const noexcept
  191. {
  192. return fBufferLen;
  193. }
  194. /*
  195. * Check if the string is empty.
  196. */
  197. bool isEmpty() const noexcept
  198. {
  199. return (fBufferLen == 0);
  200. }
  201. /*
  202. * Check if the string is not empty.
  203. */
  204. bool isNotEmpty() const noexcept
  205. {
  206. return (fBufferLen != 0);
  207. }
  208. /*
  209. * Check if the string contains another string, optionally ignoring case.
  210. */
  211. bool contains(const char* const strBuf, const bool ignoreCase = false) const noexcept
  212. {
  213. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, false);
  214. if (ignoreCase)
  215. {
  216. #ifdef __USE_GNU
  217. return (strcasestr(fBuffer, strBuf) != nullptr);
  218. #else
  219. CarlaString tmp1(fBuffer), tmp2(strBuf);
  220. // memory allocation failed or empty string(s)
  221. if (tmp1.fBuffer == _null() || tmp2.fBuffer == _null())
  222. return false;
  223. tmp1.toLower();
  224. tmp2.toLower();
  225. return (std::strstr(tmp1, tmp2) != nullptr);
  226. #endif
  227. }
  228. return (std::strstr(fBuffer, strBuf) != nullptr);
  229. }
  230. /*
  231. * Check if character at 'pos' is a digit.
  232. */
  233. bool isDigit(const std::size_t pos) const noexcept
  234. {
  235. CARLA_SAFE_ASSERT_RETURN(pos < fBufferLen, false);
  236. return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
  237. }
  238. /*
  239. * Check if the string starts with the character 'c'.
  240. */
  241. bool startsWith(const char c) const noexcept
  242. {
  243. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  244. return (fBufferLen > 0 && fBuffer[0] == c);
  245. }
  246. /*
  247. * Check if the string starts with the string 'prefix'.
  248. */
  249. bool startsWith(const char* const prefix) const noexcept
  250. {
  251. CARLA_SAFE_ASSERT_RETURN(prefix != nullptr, false);
  252. const std::size_t prefixLen(std::strlen(prefix));
  253. if (fBufferLen < prefixLen)
  254. return false;
  255. return (std::strncmp(fBuffer, prefix, prefixLen) == 0);
  256. }
  257. /*
  258. * Check if the string ends with the character 'c'.
  259. */
  260. bool endsWith(const char c) const noexcept
  261. {
  262. CARLA_SAFE_ASSERT_RETURN(c != '\0', false);
  263. return (fBufferLen > 0 && fBuffer[fBufferLen-1] == c);
  264. }
  265. /*
  266. * Check if the string ends with the string 'suffix'.
  267. */
  268. bool endsWith(const char* const suffix) const noexcept
  269. {
  270. CARLA_SAFE_ASSERT_RETURN(suffix != nullptr, false);
  271. const std::size_t suffixLen(std::strlen(suffix));
  272. if (fBufferLen < suffixLen)
  273. return false;
  274. return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
  275. }
  276. /*
  277. * Find the first occurrence of character 'c' in the string.
  278. * Returns "length()" if the character is not found.
  279. */
  280. std::size_t find(const char c, bool* const found = nullptr) const noexcept
  281. {
  282. if (fBufferLen == 0 || c == '\0')
  283. {
  284. if (found != nullptr)
  285. *found = false;
  286. return fBufferLen;
  287. }
  288. for (std::size_t i=0; i < fBufferLen; ++i)
  289. {
  290. if (fBuffer[i] == c)
  291. {
  292. if (found != nullptr)
  293. *found = true;
  294. return i;
  295. }
  296. }
  297. if (found != nullptr)
  298. *found = false;
  299. return fBufferLen;
  300. }
  301. /*
  302. * Find the first occurrence of string 'strBuf' in the string.
  303. * Returns "length()" if the string is not found.
  304. */
  305. std::size_t find(const char* const strBuf, bool* const found = nullptr) const noexcept
  306. {
  307. if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
  308. {
  309. if (found != nullptr)
  310. *found = false;
  311. return fBufferLen;
  312. }
  313. if (char* const subStrBuf = std::strstr(fBuffer, strBuf))
  314. {
  315. const ssize_t ret(subStrBuf - fBuffer);
  316. if (ret < 0)
  317. {
  318. // should never happen!
  319. carla_safe_assert_int("ret >= 0", __FILE__, __LINE__, int(ret));
  320. if (found != nullptr)
  321. *found = false;
  322. return fBufferLen;
  323. }
  324. if (found != nullptr)
  325. *found = true;
  326. return static_cast<std::size_t>(ret);
  327. }
  328. if (found != nullptr)
  329. *found = false;
  330. return fBufferLen;
  331. }
  332. /*
  333. * Find the last occurrence of character 'c' in the string.
  334. * Returns "length()" if the character is not found.
  335. */
  336. std::size_t rfind(const char c, bool* const found = nullptr) const noexcept
  337. {
  338. if (fBufferLen == 0 || c == '\0')
  339. {
  340. if (found != nullptr)
  341. *found = false;
  342. return fBufferLen;
  343. }
  344. for (std::size_t i=fBufferLen; i > 0; --i)
  345. {
  346. if (fBuffer[i-1] == c)
  347. {
  348. if (found != nullptr)
  349. *found = true;
  350. return i-1;
  351. }
  352. }
  353. if (found != nullptr)
  354. *found = false;
  355. return fBufferLen;
  356. }
  357. /*
  358. * Find the last occurrence of string 'strBuf' in the string.
  359. * Returns "length()" if the string is not found.
  360. */
  361. std::size_t rfind(const char* const strBuf, bool* const found = nullptr) const noexcept
  362. {
  363. if (found != nullptr)
  364. *found = false;
  365. if (fBufferLen == 0 || strBuf == nullptr || strBuf[0] == '\0')
  366. return fBufferLen;
  367. const std::size_t strBufLen(std::strlen(strBuf));
  368. std::size_t ret = fBufferLen;
  369. const char* tmpBuf = fBuffer;
  370. for (std::size_t i=0; i < fBufferLen; ++i)
  371. {
  372. if (std::strstr(tmpBuf+1, strBuf) == nullptr && std::strncmp(tmpBuf, strBuf, strBufLen) == 0)
  373. {
  374. if (found != nullptr)
  375. *found = true;
  376. break;
  377. }
  378. --ret;
  379. ++tmpBuf;
  380. }
  381. return fBufferLen-ret;
  382. }
  383. /*
  384. * Clear the string.
  385. */
  386. void clear() noexcept
  387. {
  388. truncate(0);
  389. }
  390. /*
  391. * Replace all occurrences of character 'before' with character 'after'.
  392. */
  393. CarlaString& replace(const char before, const char after) noexcept
  394. {
  395. CARLA_SAFE_ASSERT_RETURN(before != '\0' && after != '\0', *this);
  396. for (std::size_t i=0; i < fBufferLen; ++i)
  397. {
  398. if (fBuffer[i] == before)
  399. fBuffer[i] = after;
  400. }
  401. return *this;
  402. }
  403. /*
  404. * Truncate the string to size 'n'.
  405. */
  406. CarlaString& truncate(const std::size_t n) noexcept
  407. {
  408. if (n >= fBufferLen)
  409. return *this;
  410. for (std::size_t i=n; i < fBufferLen; ++i)
  411. fBuffer[i] = '\0';
  412. fBufferLen = n;
  413. return *this;
  414. }
  415. /*
  416. * Convert all non-basic characters to '_'.
  417. */
  418. CarlaString& toBasic() noexcept
  419. {
  420. for (std::size_t i=0; i < fBufferLen; ++i)
  421. {
  422. if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
  423. continue;
  424. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  425. continue;
  426. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  427. continue;
  428. if (fBuffer[i] == '_')
  429. continue;
  430. fBuffer[i] = '_';
  431. }
  432. return *this;
  433. }
  434. /*
  435. * Convert to all ascii characters to lowercase.
  436. */
  437. CarlaString& toLower() noexcept
  438. {
  439. static const char kCharDiff('a' - 'A');
  440. for (std::size_t i=0; i < fBufferLen; ++i)
  441. {
  442. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  443. fBuffer[i] = static_cast<char>(fBuffer[i] + kCharDiff);
  444. }
  445. return *this;
  446. }
  447. /*
  448. * Convert to all ascii characters to uppercase.
  449. */
  450. CarlaString& toUpper() noexcept
  451. {
  452. static const char kCharDiff('a' - 'A');
  453. for (std::size_t i=0; i < fBufferLen; ++i)
  454. {
  455. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  456. fBuffer[i] = static_cast<char>(fBuffer[i] - kCharDiff);
  457. }
  458. return *this;
  459. }
  460. /*
  461. * Direct access to the string buffer (read-only).
  462. */
  463. const char* buffer() const noexcept
  464. {
  465. return fBuffer;
  466. }
  467. /*
  468. * Return a duplicate string buffer.
  469. * May throw.
  470. */
  471. const char* dup() const
  472. {
  473. return carla_strdup(fBuffer);
  474. }
  475. /*
  476. * Return a duplicate string buffer or null.
  477. */
  478. const char* dupSafe() const noexcept
  479. {
  480. return carla_strdup_safe(fBuffer);
  481. }
  482. // -------------------------------------------------------------------
  483. // base64 stuff, based on http://www.adp-gmbh.ch/cpp/common/base64.html
  484. // Copyright (C) 2004-2008 René Nyffenegger
  485. static CarlaString asBase64(const void* const data, const std::size_t dataSize)
  486. {
  487. static const char* const kBase64Chars =
  488. "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  489. "abcdefghijklmnopqrstuvwxyz"
  490. "0123456789+/";
  491. const std::size_t kTmpBufSize = carla_nextPowerOf2(static_cast<uint32_t>(dataSize/3));
  492. const uchar* bytesToEncode((const uchar*)data);
  493. uint i=0, j=0;
  494. uint charArray3[3], charArray4[4];
  495. char strBuf[kTmpBufSize+1];
  496. strBuf[kTmpBufSize] = '\0';
  497. std::size_t strBufIndex = 0;
  498. CarlaString ret;
  499. for (std::size_t s=0; s<dataSize; ++s)
  500. {
  501. charArray3[i++] = *(bytesToEncode++);
  502. if (i == 3)
  503. {
  504. charArray4[0] = (charArray3[0] & 0xfc) >> 2;
  505. charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
  506. charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
  507. charArray4[3] = charArray3[2] & 0x3f;
  508. for (i=0; i<4; ++i)
  509. strBuf[strBufIndex++] = kBase64Chars[charArray4[i]];
  510. if (strBufIndex >= kTmpBufSize-7)
  511. {
  512. strBuf[strBufIndex] = '\0';
  513. strBufIndex = 0;
  514. ret += strBuf;
  515. }
  516. i = 0;
  517. }
  518. }
  519. if (i != 0)
  520. {
  521. for (j=i; j<3; ++j)
  522. charArray3[j] = '\0';
  523. charArray4[0] = (charArray3[0] & 0xfc) >> 2;
  524. charArray4[1] = ((charArray3[0] & 0x03) << 4) + ((charArray3[1] & 0xf0) >> 4);
  525. charArray4[2] = ((charArray3[1] & 0x0f) << 2) + ((charArray3[2] & 0xc0) >> 6);
  526. charArray4[3] = charArray3[2] & 0x3f;
  527. for (j=0; j<4 && i<3 && j<i+1; ++j)
  528. strBuf[strBufIndex++] = kBase64Chars[charArray4[j]];
  529. for (; i++ < 3;)
  530. strBuf[strBufIndex++] = '=';
  531. }
  532. if (strBufIndex != 0)
  533. {
  534. strBuf[strBufIndex] = '\0';
  535. ret += strBuf;
  536. }
  537. return ret;
  538. }
  539. // -------------------------------------------------------------------
  540. // public operators
  541. operator const char*() const noexcept
  542. {
  543. return fBuffer;
  544. }
  545. char operator[](const std::size_t pos) const noexcept
  546. {
  547. if (pos < fBufferLen)
  548. return fBuffer[pos];
  549. carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
  550. static char fallback;
  551. fallback = '\0';
  552. return fallback;
  553. }
  554. char& operator[](const std::size_t pos) noexcept
  555. {
  556. if (pos < fBufferLen)
  557. return fBuffer[pos];
  558. carla_safe_assert("pos < fBufferLen", __FILE__, __LINE__);
  559. static char fallback;
  560. fallback = '\0';
  561. return fallback;
  562. }
  563. bool operator==(const char* const strBuf) const noexcept
  564. {
  565. return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
  566. }
  567. bool operator==(const CarlaString& str) const noexcept
  568. {
  569. return operator==(str.fBuffer);
  570. }
  571. bool operator!=(const char* const strBuf) const noexcept
  572. {
  573. return !operator==(strBuf);
  574. }
  575. bool operator!=(const CarlaString& str) const noexcept
  576. {
  577. return !operator==(str.fBuffer);
  578. }
  579. CarlaString& operator=(const char* const strBuf) noexcept
  580. {
  581. _dup(strBuf);
  582. return *this;
  583. }
  584. CarlaString& operator=(const CarlaString& str) noexcept
  585. {
  586. _dup(str.fBuffer);
  587. return *this;
  588. }
  589. CarlaString& operator+=(const char* const strBuf) noexcept
  590. {
  591. if (strBuf == nullptr)
  592. return *this;
  593. const std::size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
  594. char newBuf[newBufSize];
  595. std::strcpy(newBuf, fBuffer);
  596. std::strcat(newBuf, strBuf);
  597. _dup(newBuf, newBufSize-1);
  598. return *this;
  599. }
  600. CarlaString& operator+=(const CarlaString& str) noexcept
  601. {
  602. return operator+=(str.fBuffer);
  603. }
  604. CarlaString operator+(const char* const strBuf) noexcept
  605. {
  606. const std::size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  607. char newBuf[newBufSize];
  608. std::strcpy(newBuf, fBuffer);
  609. if (strBuf != nullptr)
  610. std::strcat(newBuf, strBuf);
  611. return CarlaString(newBuf);
  612. }
  613. CarlaString operator+(const CarlaString& str) noexcept
  614. {
  615. return operator+(str.fBuffer);
  616. }
  617. // -------------------------------------------------------------------
  618. private:
  619. char* fBuffer; // the actual string buffer
  620. std::size_t fBufferLen; // string length
  621. /*
  622. * Static null string.
  623. * Prevents allocation for new and/or empty strings.
  624. */
  625. static char* _null() noexcept
  626. {
  627. static char sNull = '\0';
  628. return &sNull;
  629. }
  630. /*
  631. * Helper function.
  632. * Called whenever the string needs to be allocated.
  633. *
  634. * Notes:
  635. * - Allocates string only if 'strBuf' is not null and new string contents are different
  636. * - If 'strBuf' is null, 'size' must be 0
  637. */
  638. void _dup(const char* const strBuf, const std::size_t size = 0) noexcept
  639. {
  640. if (strBuf != nullptr)
  641. {
  642. // don't recreate string if contents match
  643. if (std::strcmp(fBuffer, strBuf) == 0)
  644. return;
  645. if (fBuffer != _null())
  646. std::free(fBuffer);
  647. fBufferLen = (size > 0) ? size : std::strlen(strBuf);
  648. fBuffer = (char*)std::malloc(fBufferLen+1);
  649. if (fBuffer == nullptr)
  650. {
  651. fBuffer = _null();
  652. fBufferLen = 0;
  653. return;
  654. }
  655. std::strcpy(fBuffer, strBuf);
  656. fBuffer[fBufferLen] = '\0';
  657. }
  658. else
  659. {
  660. CARLA_SAFE_ASSERT(size == 0);
  661. // don't recreate null string
  662. if (fBuffer == _null())
  663. return;
  664. CARLA_SAFE_ASSERT(fBuffer != nullptr);
  665. std::free(fBuffer);
  666. fBuffer = _null();
  667. fBufferLen = 0;
  668. }
  669. }
  670. CARLA_PREVENT_HEAP_ALLOCATION
  671. };
  672. // -----------------------------------------------------------------------
  673. static inline
  674. CarlaString operator+(const CarlaString& strBefore, const char* const strBufAfter) noexcept
  675. {
  676. const char* const strBufBefore = strBefore.buffer();
  677. const std::size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  678. char newBuf[newBufSize];
  679. std::strcpy(newBuf, strBufBefore);
  680. std::strcat(newBuf, strBufAfter);
  681. return CarlaString(newBuf);
  682. }
  683. static inline
  684. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter) noexcept
  685. {
  686. const char* const strBufAfter = strAfter.buffer();
  687. const std::size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  688. char newBuf[newBufSize];
  689. std::strcpy(newBuf, strBufBefore);
  690. std::strcat(newBuf, strBufAfter);
  691. return CarlaString(newBuf);
  692. }
  693. // -----------------------------------------------------------------------
  694. #endif // CARLA_STRING_HPP_INCLUDED