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.

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