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.

776 lines
18KB

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