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.

686 lines
15KB

  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * Permission to use, copy, modify, and/or distribute this software for any purpose with
  6. * or without fee is hereby granted, provided that the above copyright notice and this
  7. * permission notice appear in all copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
  10. * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
  11. * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  12. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  13. * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef DISTRHO_UTILS_HPP_INCLUDED
  17. #define DISTRHO_UTILS_HPP_INCLUDED
  18. #include "src/DistrhoDefines.h"
  19. #include <cassert>
  20. #include <cstdarg>
  21. #include <cstdio>
  22. #include <cstdlib>
  23. #include <cstring>
  24. #ifdef PROPER_CPP11_SUPPORT
  25. # include <cstdint>
  26. #else
  27. # include <stdint.h>
  28. #endif
  29. #ifdef DISTRHO_OS_WINDOWS
  30. # include <winsock2.h>
  31. # include <windows.h>
  32. #else
  33. # include <unistd.h>
  34. #endif
  35. #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC)
  36. namespace std {
  37. inline float
  38. fmin(float __x, float __y)
  39. { return __builtin_fminf(__x, __y); }
  40. inline float
  41. fmax(float __x, float __y)
  42. { return __builtin_fmaxf(__x, __y); }
  43. inline float
  44. rint(float __x)
  45. { return __builtin_rintf(__x); }
  46. }
  47. #endif
  48. // -----------------------------------------------------------------------
  49. // misc functions
  50. static inline
  51. long d_cconst(int a, int b, int c, int d) noexcept
  52. {
  53. return (a << 24) | (b << 16) | (c << 8) | (d << 0);
  54. }
  55. // -----------------------------------------------------------------------
  56. // string print functions
  57. #ifndef DEBUG
  58. # define d_debug(...)
  59. #else
  60. static inline
  61. void d_debug(const char* const fmt, ...)
  62. {
  63. va_list args;
  64. va_start(args, fmt);
  65. std::fprintf(stdout, "\x1b[30;1m");
  66. std::vfprintf(stdout, fmt, args);
  67. std::fprintf(stdout, "\x1b[0m\n");
  68. va_end(args);
  69. }
  70. #endif
  71. static inline
  72. void d_stdout(const char* const fmt, ...)
  73. {
  74. va_list args;
  75. va_start(args, fmt);
  76. std::vfprintf(stdout, fmt, args);
  77. std::fprintf(stdout, "\n");
  78. va_end(args);
  79. }
  80. static inline
  81. void d_stderr(const char* const fmt, ...)
  82. {
  83. va_list args;
  84. va_start(args, fmt);
  85. std::vfprintf(stderr, fmt, args);
  86. std::fprintf(stderr, "\n");
  87. va_end(args);
  88. }
  89. static inline
  90. void d_stderr2(const char* const fmt, ...)
  91. {
  92. va_list args;
  93. va_start(args, fmt);
  94. std::fprintf(stderr, "\x1b[31m");
  95. std::vfprintf(stderr, fmt, args);
  96. std::fprintf(stderr, "\x1b[0m\n");
  97. va_end(args);
  98. }
  99. // -----------------------------------------------------------------------
  100. // d_*sleep
  101. static inline
  102. void d_sleep(unsigned int secs)
  103. {
  104. #ifdef DISTRHO_OS_WINDOWS
  105. Sleep(secs * 1000);
  106. #else
  107. sleep(secs);
  108. #endif
  109. }
  110. static inline
  111. void d_msleep(unsigned int msecs)
  112. {
  113. #ifdef DISTRHO_OS_WINDOWS
  114. Sleep(msecs);
  115. #else
  116. usleep(msecs * 1000);
  117. #endif
  118. }
  119. // -----------------------------------------------------------------------
  120. // d_string class
  121. class d_string
  122. {
  123. public:
  124. // -------------------------------------------------------------------
  125. // constructors (no explicit conversions allowed)
  126. /*
  127. * Empty string.
  128. */
  129. explicit d_string()
  130. {
  131. _init();
  132. _dup(nullptr);
  133. }
  134. /*
  135. * Simple character.
  136. */
  137. explicit d_string(const char c)
  138. {
  139. char ch[2];
  140. ch[0] = c;
  141. ch[1] = '\0';
  142. _init();
  143. _dup(ch);
  144. }
  145. /*
  146. * Simple char string.
  147. */
  148. explicit d_string(char* const strBuf)
  149. {
  150. _init();
  151. _dup(strBuf);
  152. }
  153. /*
  154. * Simple const char string.
  155. */
  156. explicit d_string(const char* const strBuf)
  157. {
  158. _init();
  159. _dup(strBuf);
  160. }
  161. /*
  162. * Integer.
  163. */
  164. explicit d_string(const int value)
  165. {
  166. char strBuf[0xff+1];
  167. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  168. std::snprintf(strBuf, 0xff, "%d", value);
  169. _init();
  170. _dup(strBuf);
  171. }
  172. /*
  173. * Unsigned integer, possibly in hexadecimal.
  174. */
  175. explicit d_string(const unsigned int value, const bool hexadecimal = false)
  176. {
  177. char strBuf[0xff+1];
  178. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  179. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  180. _init();
  181. _dup(strBuf);
  182. }
  183. /*
  184. * Long integer.
  185. */
  186. explicit d_string(const long int value)
  187. {
  188. char strBuf[0xff+1];
  189. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  190. std::snprintf(strBuf, 0xff, "%ld", value);
  191. _init();
  192. _dup(strBuf);
  193. }
  194. /*
  195. * Long unsigned integer, possibly hexadecimal.
  196. */
  197. explicit d_string(const unsigned long int value, const bool hexadecimal = false)
  198. {
  199. char strBuf[0xff+1];
  200. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  201. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  202. _init();
  203. _dup(strBuf);
  204. }
  205. /*
  206. * Single-precision floating point number.
  207. */
  208. explicit d_string(const float value)
  209. {
  210. char strBuf[0xff+1];
  211. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  212. std::snprintf(strBuf, 0xff, "%f", value);
  213. _init();
  214. _dup(strBuf);
  215. }
  216. /*
  217. * Double-precision floating point number.
  218. */
  219. explicit d_string(const double value)
  220. {
  221. char strBuf[0xff+1];
  222. std::memset(strBuf, 0, (0xff+1)*sizeof(char));
  223. std::snprintf(strBuf, 0xff, "%g", value);
  224. _init();
  225. _dup(strBuf);
  226. }
  227. // -------------------------------------------------------------------
  228. // non-explicit constructor
  229. /*
  230. * Create string from another string.
  231. */
  232. d_string(const d_string& str)
  233. {
  234. _init();
  235. _dup(str.fBuffer);
  236. }
  237. // -------------------------------------------------------------------
  238. // destructor
  239. /*
  240. * Destructor.
  241. */
  242. ~d_string()
  243. {
  244. assert(fBuffer != nullptr);
  245. delete[] fBuffer;
  246. fBuffer = nullptr;
  247. }
  248. // -------------------------------------------------------------------
  249. // public methods
  250. /*
  251. * Get length of the string.
  252. */
  253. size_t length() const noexcept
  254. {
  255. return fBufferLen;
  256. }
  257. /*
  258. * Check if the string is empty.
  259. */
  260. bool isEmpty() const noexcept
  261. {
  262. return (fBufferLen == 0);
  263. }
  264. /*
  265. * Check if the string is not empty.
  266. */
  267. bool isNotEmpty() const noexcept
  268. {
  269. return (fBufferLen != 0);
  270. }
  271. /*
  272. * Check if the string contains another string, optionally ignoring case.
  273. */
  274. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  275. {
  276. if (strBuf == nullptr)
  277. return false;
  278. if (ignoreCase)
  279. {
  280. #ifdef __USE_GNU
  281. return (strcasestr(fBuffer, strBuf) != nullptr);
  282. #else
  283. d_string tmp1(fBuffer), tmp2(strBuf);
  284. tmp1.toLower();
  285. tmp2.toLower();
  286. return (std::strstr((const char*)tmp1, (const char*)tmp2) != nullptr);
  287. #endif
  288. }
  289. return (std::strstr(fBuffer, strBuf) != nullptr);
  290. }
  291. /*
  292. * Overloaded function.
  293. */
  294. bool contains(const d_string& str, const bool ignoreCase = false) const
  295. {
  296. return contains(str.fBuffer, ignoreCase);
  297. }
  298. /*
  299. * Check if character at 'pos' is a digit.
  300. */
  301. bool isDigit(const size_t pos) const noexcept
  302. {
  303. if (pos >= fBufferLen)
  304. return false;
  305. return (fBuffer[pos] >= '0' && fBuffer[pos] <= '9');
  306. }
  307. /*
  308. * Check if the string starts with the character 'c'.
  309. */
  310. bool startsWith(const char c) const
  311. {
  312. if (c == '\0')
  313. return false;
  314. return (fBufferLen > 0 && fBuffer[0] == c);
  315. }
  316. /*
  317. * Check if the string starts with the string 'prefix'.
  318. */
  319. bool startsWith(const char* const prefix) const
  320. {
  321. if (prefix == nullptr)
  322. return false;
  323. const size_t prefixLen(std::strlen(prefix));
  324. if (fBufferLen < prefixLen)
  325. return false;
  326. return (std::strncmp(fBuffer + (fBufferLen-prefixLen), prefix, prefixLen) == 0);
  327. }
  328. /*
  329. * Check if the string ends with the character 'c'.
  330. */
  331. bool endsWith(const char c) const
  332. {
  333. if (c == '\0')
  334. return false;
  335. return (fBufferLen > 0 && fBuffer[fBufferLen] == c);
  336. }
  337. /*
  338. * Check if the string ends with the string 'suffix'.
  339. */
  340. bool endsWith(const char* const suffix) const
  341. {
  342. if (suffix == nullptr)
  343. return false;
  344. const size_t suffixLen(std::strlen(suffix));
  345. if (fBufferLen < suffixLen)
  346. return false;
  347. return (std::strncmp(fBuffer + (fBufferLen-suffixLen), suffix, suffixLen) == 0);
  348. }
  349. /*
  350. * Clear the string.
  351. */
  352. void clear() noexcept
  353. {
  354. truncate(0);
  355. }
  356. /*
  357. * Replace all occurrences of character 'before' with character 'after'.
  358. */
  359. void replace(const char before, const char after) noexcept
  360. {
  361. if (before == '\0' || after == '\0')
  362. return;
  363. for (size_t i=0; i < fBufferLen; ++i)
  364. {
  365. if (fBuffer[i] == before)
  366. fBuffer[i] = after;
  367. else if (fBuffer[i] == '\0')
  368. break;
  369. }
  370. }
  371. /*
  372. * Truncate the string to size 'n'.
  373. */
  374. void truncate(const size_t n) noexcept
  375. {
  376. if (n >= fBufferLen)
  377. return;
  378. for (size_t i=n; i < fBufferLen; ++i)
  379. fBuffer[i] = '\0';
  380. fBufferLen = n;
  381. }
  382. /*
  383. * Convert all non-basic characters to '_'.
  384. */
  385. void toBasic() noexcept
  386. {
  387. for (size_t i=0; i < fBufferLen; ++i)
  388. {
  389. if (fBuffer[i] >= '0' && fBuffer[i] <= '9')
  390. continue;
  391. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  392. continue;
  393. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  394. continue;
  395. if (fBuffer[i] == '_')
  396. continue;
  397. fBuffer[i] = '_';
  398. }
  399. }
  400. /*
  401. * Convert to all ascii characters to lowercase.
  402. */
  403. void toLower() noexcept
  404. {
  405. static const char kCharDiff('a' - 'A');
  406. for (size_t i=0; i < fBufferLen; ++i)
  407. {
  408. if (fBuffer[i] >= 'A' && fBuffer[i] <= 'Z')
  409. fBuffer[i] += kCharDiff;
  410. }
  411. }
  412. /*
  413. * Convert to all ascii characters to uppercase.
  414. */
  415. void toUpper() noexcept
  416. {
  417. static const char kCharDiff('a' - 'A');
  418. for (size_t i=0; i < fBufferLen; ++i)
  419. {
  420. if (fBuffer[i] >= 'a' && fBuffer[i] <= 'z')
  421. fBuffer[i] -= kCharDiff;
  422. }
  423. }
  424. // -------------------------------------------------------------------
  425. // public operators
  426. operator const char*() const noexcept
  427. {
  428. return fBuffer;
  429. }
  430. char& operator[](const size_t pos) const noexcept
  431. {
  432. return fBuffer[pos];
  433. }
  434. bool operator==(const char* const strBuf) const
  435. {
  436. return (strBuf != nullptr && std::strcmp(fBuffer, strBuf) == 0);
  437. }
  438. bool operator==(const d_string& str) const
  439. {
  440. return operator==(str.fBuffer);
  441. }
  442. bool operator!=(const char* const strBuf) const
  443. {
  444. return !operator==(strBuf);
  445. }
  446. bool operator!=(const d_string& str) const
  447. {
  448. return !operator==(str.fBuffer);
  449. }
  450. d_string& operator=(const char* const strBuf)
  451. {
  452. _dup(strBuf);
  453. return *this;
  454. }
  455. d_string& operator=(const d_string& str)
  456. {
  457. return operator=(str.fBuffer);
  458. }
  459. d_string& operator+=(const char* const strBuf)
  460. {
  461. if (strBuf == nullptr)
  462. return *this;
  463. const size_t newBufSize = fBufferLen + std::strlen(strBuf) + 1;
  464. char newBuf[newBufSize];
  465. std::strcpy(newBuf, fBuffer);
  466. std::strcat(newBuf, strBuf);
  467. _dup(newBuf, newBufSize-1);
  468. return *this;
  469. }
  470. d_string& operator+=(const d_string& str)
  471. {
  472. return operator+=(str.fBuffer);
  473. }
  474. d_string operator+(const char* const strBuf)
  475. {
  476. const size_t newBufSize = fBufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  477. char newBuf[newBufSize];
  478. std::strcpy(newBuf, fBuffer);
  479. if (strBuf != nullptr)
  480. std::strcat(newBuf, strBuf);
  481. return d_string(newBuf);
  482. }
  483. d_string operator+(const d_string& str)
  484. {
  485. return operator+(str.fBuffer);
  486. }
  487. // -------------------------------------------------------------------
  488. private:
  489. char* fBuffer; // the actual string buffer
  490. size_t fBufferLen; // string length
  491. bool fFirstInit; // true when first initiated
  492. /*
  493. * Shared init function.
  494. * Called on all constructors.
  495. */
  496. void _init() noexcept
  497. {
  498. fBuffer = nullptr;
  499. fBufferLen = 0;
  500. fFirstInit = true;
  501. }
  502. /*
  503. * Helper function.
  504. * Called whenever the string needs to be allocated.
  505. *
  506. * Notes:
  507. * - Allocates string only if first initiated, or if 'strBuf' is not null and new string contents are different
  508. * - If 'strBuf' is null 'size' must be 0
  509. */
  510. void _dup(const char* const strBuf, const size_t size = 0)
  511. {
  512. if (strBuf != nullptr)
  513. {
  514. // don't recreate string if contents match
  515. if (fFirstInit || std::strcmp(fBuffer, strBuf) != 0)
  516. {
  517. if (! fFirstInit)
  518. {
  519. assert(fBuffer != nullptr);
  520. delete[] fBuffer;
  521. }
  522. fBufferLen = (size > 0) ? size : std::strlen(strBuf);
  523. fBuffer = new char[fBufferLen+1];
  524. std::strcpy(fBuffer, strBuf);
  525. fBuffer[fBufferLen] = '\0';
  526. fFirstInit = false;
  527. }
  528. }
  529. else
  530. {
  531. assert(size == 0);
  532. // don't recreate null string
  533. if (fFirstInit || fBufferLen != 0)
  534. {
  535. if (! fFirstInit)
  536. {
  537. assert(fBuffer != nullptr);
  538. delete[] fBuffer;
  539. }
  540. fBufferLen = 0;
  541. fBuffer = new char[1];
  542. fBuffer[0] = '\0';
  543. fFirstInit = false;
  544. }
  545. }
  546. }
  547. };
  548. // -----------------------------------------------------------------------
  549. static inline
  550. d_string operator+(const d_string& strBefore, const char* const strBufAfter)
  551. {
  552. const char* const strBufBefore = (const char*)strBefore;
  553. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  554. char newBuf[newBufSize];
  555. std::strcpy(newBuf, strBufBefore);
  556. std::strcat(newBuf, strBufAfter);
  557. return d_string(newBuf);
  558. }
  559. static inline
  560. d_string operator+(const char* const strBufBefore, const d_string& strAfter)
  561. {
  562. const char* const strBufAfter = (const char*)strAfter;
  563. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  564. char newBuf[newBufSize];
  565. std::strcpy(newBuf, strBufBefore);
  566. std::strcat(newBuf, strBufAfter);
  567. return d_string(newBuf);
  568. }
  569. // -----------------------------------------------------------------------
  570. #endif // DISTRHO_UTILS_HPP_INCLUDED