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.

594 lines
13KB

  1. /*
  2. * DISTRHO Plugin Toolkit (DPT)
  3. * Copyright (C) 2012-2013 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 Lesser General Public
  7. * License as published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU Lesser General Public License for more details.
  13. *
  14. * For a full copy of the license see the LGPL.txt file
  15. */
  16. #ifndef __DISTRHO_UTILS_HPP__
  17. #define __DISTRHO_UTILS_HPP__
  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 <windows.h>
  31. #else
  32. # include <unistd.h>
  33. #endif
  34. #if defined(DISTRHO_OS_MAC) && ! defined(CARLA_OS_MAC)
  35. namespace std {
  36. inline float
  37. fmin(float __x, float __y)
  38. { return __builtin_fminf(__x, __y); }
  39. inline float
  40. fmax(float __x, float __y)
  41. { return __builtin_fmaxf(__x, __y); }
  42. inline float
  43. rint(float __x)
  44. { return __builtin_rintf(__x); }
  45. }
  46. #endif
  47. START_NAMESPACE_DISTRHO
  48. // -------------------------------------------------
  49. static inline
  50. long d_cconst(int a, int b, int c, int d)
  51. {
  52. return (a << 24) | (b << 16) | (c << 8) | (d << 0);
  53. }
  54. // -------------------------------------------------
  55. #ifndef DEBUG
  56. # define d_debug(...)
  57. #else
  58. static inline
  59. void d_debug(const char* const fmt, ...)
  60. {
  61. va_list args;
  62. va_start(args, fmt);
  63. # ifndef DISTRHO_OS_WINDOWS
  64. std::fprintf(stdout, "\x1b[30;1m");
  65. # endif
  66. std::vfprintf(stdout, fmt, args);
  67. # ifndef DISTRHO_OS_WINDOWS
  68. std::fprintf(stdout, "\x1b[0m\n");
  69. # else
  70. std::fprintf(stdout, "\n");
  71. # endif
  72. va_end(args);
  73. }
  74. #endif
  75. static inline
  76. void d_stdout(const char* const fmt, ...)
  77. {
  78. va_list args;
  79. va_start(args, fmt);
  80. std::vfprintf(stdout, fmt, args);
  81. std::fprintf(stdout, "\n");
  82. va_end(args);
  83. }
  84. static inline
  85. void d_stderr(const char* const fmt, ...)
  86. {
  87. va_list args;
  88. va_start(args, fmt);
  89. std::vfprintf(stderr, fmt, args);
  90. std::fprintf(stderr, "\n");
  91. va_end(args);
  92. }
  93. static inline
  94. void d_stderr2(const char* const fmt, ...)
  95. {
  96. va_list args;
  97. va_start(args, fmt);
  98. #ifndef DISTRHO_OS_WINDOWS
  99. std::fprintf(stderr, "\x1b[31m");
  100. #endif
  101. std::vfprintf(stderr, fmt, args);
  102. #ifndef DISTRHO_OS_WINDOWS
  103. std::fprintf(stderr, "\x1b[0m\n");
  104. #else
  105. std::fprintf(stderr, "\n");
  106. #endif
  107. va_end(args);
  108. }
  109. // -------------------------------------------------
  110. static inline
  111. void d_sleep(unsigned int secs)
  112. {
  113. #ifdef DISTRHO_OS_WINDOWS
  114. Sleep(secs * 1000);
  115. #else
  116. sleep(secs);
  117. #endif
  118. }
  119. static inline
  120. void d_msleep(unsigned int msecs)
  121. {
  122. #ifdef DISTRHO_OS_WINDOWS
  123. Sleep(msecs);
  124. #else
  125. usleep(msecs * 1000);
  126. #endif
  127. }
  128. // -------------------------------------------------
  129. class d_string
  130. {
  131. public:
  132. // ---------------------------------------------
  133. // constructors (no explicit conversions allowed)
  134. explicit d_string()
  135. {
  136. _init();
  137. _dup(nullptr);
  138. }
  139. explicit d_string(char* const strBuf)
  140. {
  141. _init();
  142. _dup(strBuf);
  143. }
  144. explicit d_string(const char* const strBuf)
  145. {
  146. _init();
  147. _dup(strBuf);
  148. }
  149. explicit d_string(const int value)
  150. {
  151. char strBuf[0xff] = { '\0' };
  152. std::snprintf(strBuf, 0xff, "%d", value);
  153. _init();
  154. _dup(strBuf);
  155. }
  156. explicit d_string(const unsigned int value, const bool hexadecimal = false)
  157. {
  158. char strBuf[0xff] = { '\0' };
  159. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  160. _init();
  161. _dup(strBuf);
  162. }
  163. explicit d_string(const long int value)
  164. {
  165. char strBuf[0xff] = { '\0' };
  166. std::snprintf(strBuf, 0xff, "%ld", value);
  167. _init();
  168. _dup(strBuf);
  169. }
  170. explicit d_string(const unsigned long int value, const bool hexadecimal = false)
  171. {
  172. char strBuf[0xff] = { '\0' };
  173. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  174. _init();
  175. _dup(strBuf);
  176. }
  177. explicit d_string(const float value)
  178. {
  179. char strBuf[0xff] = { '\0' };
  180. std::snprintf(strBuf, 0xff, "%f", value);
  181. _init();
  182. _dup(strBuf);
  183. }
  184. explicit d_string(const double value)
  185. {
  186. char strBuf[0xff] = { '\0' };
  187. std::snprintf(strBuf, 0xff, "%g", value);
  188. _init();
  189. _dup(strBuf);
  190. }
  191. // ---------------------------------------------
  192. // non-explicit constructor
  193. d_string(const d_string& str)
  194. {
  195. _init();
  196. _dup(str.buffer);
  197. }
  198. // ---------------------------------------------
  199. // deconstructor
  200. ~d_string()
  201. {
  202. assert(buffer != nullptr);
  203. delete[] buffer;
  204. buffer = nullptr;
  205. }
  206. // ---------------------------------------------
  207. // public methods
  208. size_t length() const
  209. {
  210. return bufferLen;
  211. }
  212. bool isEmpty() const
  213. {
  214. return (bufferLen == 0);
  215. }
  216. bool isNotEmpty() const
  217. {
  218. return (bufferLen != 0);
  219. }
  220. #ifdef __USE_GNU
  221. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  222. {
  223. if (strBuf == nullptr)
  224. return false;
  225. if (ignoreCase)
  226. return (strcasestr(buffer, strBuf) != nullptr);
  227. else
  228. return (std::strstr(buffer, strBuf) != nullptr);
  229. }
  230. bool contains(const d_string& str, const bool ignoreCase = false) const
  231. {
  232. return contains(str.buffer, ignoreCase);
  233. }
  234. #else
  235. bool contains(const char* const strBuf) const
  236. {
  237. if (strBuf == nullptr)
  238. return false;
  239. return (std::strstr(buffer, strBuf) != nullptr);
  240. }
  241. bool contains(const d_string& str) const
  242. {
  243. return contains(str.buffer);
  244. }
  245. #endif
  246. bool isDigit(const size_t pos) const
  247. {
  248. if (pos >= bufferLen)
  249. return false;
  250. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  251. }
  252. bool startsWith(const char* const prefix) const
  253. {
  254. if (prefix == nullptr)
  255. return false;
  256. const size_t prefixLen(std::strlen(prefix));
  257. if (bufferLen < prefixLen)
  258. return false;
  259. return (std::strncmp(buffer + (bufferLen-prefixLen), prefix, prefixLen) == 0);
  260. }
  261. bool endsWith(const char* const suffix) const
  262. {
  263. if (suffix == nullptr)
  264. return false;
  265. const size_t suffixLen(std::strlen(suffix));
  266. if (bufferLen < suffixLen)
  267. return false;
  268. return (std::strncmp(buffer + (bufferLen-suffixLen), suffix, suffixLen) == 0);
  269. }
  270. void clear()
  271. {
  272. truncate(0);
  273. }
  274. size_t find(const char c) const
  275. {
  276. for (size_t i=0; i < bufferLen; ++i)
  277. {
  278. if (buffer[i] == c)
  279. return i;
  280. }
  281. return 0;
  282. }
  283. size_t rfind(const char c) const
  284. {
  285. for (size_t i=bufferLen; i > 0; --i)
  286. {
  287. if (buffer[i-1] == c)
  288. return i-1;
  289. }
  290. return 0;
  291. }
  292. void replace(const char before, const char after)
  293. {
  294. if (after == '\0')
  295. return;
  296. for (size_t i=0; i < bufferLen; ++i)
  297. {
  298. if (buffer[i] == before)
  299. buffer[i] = after;
  300. else if (buffer[i] == '\0')
  301. break;
  302. }
  303. }
  304. void truncate(const size_t n)
  305. {
  306. if (n >= bufferLen)
  307. return;
  308. for (size_t i=n; i < bufferLen; ++i)
  309. buffer[i] = '\0';
  310. bufferLen = n;
  311. }
  312. void toBasic()
  313. {
  314. for (size_t i=0; i < bufferLen; ++i)
  315. {
  316. if (buffer[i] >= '0' && buffer[i] <= '9')
  317. continue;
  318. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  319. continue;
  320. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  321. continue;
  322. if (buffer[i] == '_')
  323. continue;
  324. buffer[i] = '_';
  325. }
  326. }
  327. void toLower()
  328. {
  329. static const char kCharDiff = 'a' - 'A';
  330. for (size_t i=0; i < bufferLen; ++i)
  331. {
  332. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  333. buffer[i] += kCharDiff;
  334. }
  335. }
  336. void toUpper()
  337. {
  338. static const char kCharDiff = 'a' - 'A';
  339. for (size_t i=0; i < bufferLen; ++i)
  340. {
  341. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  342. buffer[i] -= kCharDiff;
  343. }
  344. }
  345. // ---------------------------------------------
  346. // public operators
  347. operator const char*() const
  348. {
  349. return buffer;
  350. }
  351. char& operator[](const size_t pos)
  352. {
  353. return buffer[pos];
  354. }
  355. bool operator==(const char* const strBuf) const
  356. {
  357. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  358. }
  359. bool operator==(const d_string& str) const
  360. {
  361. return operator==(str.buffer);
  362. }
  363. bool operator!=(const char* const strBuf) const
  364. {
  365. return !operator==(strBuf);
  366. }
  367. bool operator!=(const d_string& str) const
  368. {
  369. return !operator==(str.buffer);
  370. }
  371. d_string& operator=(const char* const strBuf)
  372. {
  373. _dup(strBuf);
  374. return *this;
  375. }
  376. d_string& operator=(const d_string& str)
  377. {
  378. return operator=(str.buffer);
  379. }
  380. d_string& operator+=(const char* const strBuf)
  381. {
  382. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  383. char newBuf[newBufSize];
  384. std::strcpy(newBuf, buffer);
  385. std::strcat(newBuf, strBuf);
  386. _dup(newBuf, newBufSize-1);
  387. return *this;
  388. }
  389. d_string& operator+=(const d_string& str)
  390. {
  391. return operator+=(str.buffer);
  392. }
  393. d_string operator+(const char* const strBuf)
  394. {
  395. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  396. char newBuf[newBufSize];
  397. std::strcpy(newBuf, buffer);
  398. std::strcat(newBuf, strBuf);
  399. return d_string(newBuf);
  400. }
  401. d_string operator+(const d_string& str)
  402. {
  403. return operator+(str.buffer);
  404. }
  405. // ---------------------------------------------
  406. private:
  407. char* buffer;
  408. size_t bufferLen;
  409. bool firstInit;
  410. void _init()
  411. {
  412. buffer = nullptr;
  413. bufferLen = 0;
  414. firstInit = true;
  415. }
  416. // allocate string strBuf if not null
  417. // size > 0 only if strBuf is valid
  418. void _dup(const char* const strBuf, const size_t size = 0)
  419. {
  420. if (strBuf != nullptr)
  421. {
  422. // don't recreate string if contents match
  423. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  424. {
  425. if (! firstInit)
  426. {
  427. assert(buffer != nullptr);
  428. delete[] buffer;
  429. }
  430. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  431. buffer = new char[bufferLen+1];
  432. std::strcpy(buffer, strBuf);
  433. buffer[bufferLen] = '\0';
  434. firstInit = false;
  435. }
  436. }
  437. else
  438. {
  439. assert(size == 0);
  440. // don't recreate null string
  441. if (firstInit || bufferLen != 0)
  442. {
  443. if (! firstInit)
  444. {
  445. assert(buffer != nullptr);
  446. delete[] buffer;
  447. }
  448. bufferLen = 0;
  449. buffer = new char[1];
  450. buffer[0] = '\0';
  451. firstInit = false;
  452. }
  453. }
  454. }
  455. };
  456. // -------------------------------------------------
  457. static inline
  458. d_string operator+(const d_string& strBefore, const char* const strBufAfter)
  459. {
  460. const char* const strBufBefore = (const char*)strBefore;
  461. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  462. char newBuf[newBufSize];
  463. std::strcpy(newBuf, strBufBefore);
  464. std::strcat(newBuf, strBufAfter);
  465. return d_string(newBuf);
  466. }
  467. static inline
  468. d_string operator+(const char* const strBufBefore, const d_string& strAfter)
  469. {
  470. const char* const strBufAfter = (const char*)strAfter;
  471. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  472. char newBuf[newBufSize];
  473. std::strcpy(newBuf, strBufBefore);
  474. std::strcat(newBuf, strBufAfter);
  475. return d_string(newBuf);
  476. }
  477. // -------------------------------------------------
  478. END_NAMESPACE_DISTRHO
  479. #endif // __DISTRHO_UTILS_HPP__