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.

579 lines
12KB

  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. static inline
  130. void d_setenv(const char* key, const char* value)
  131. {
  132. #if DISTRHO_OS_WINDOWS
  133. SetEnvironmentVariableA(key, value);
  134. #else
  135. setenv(key, value, 1);
  136. #endif
  137. }
  138. // -------------------------------------------------
  139. class d_string
  140. {
  141. public:
  142. // ---------------------------------------------
  143. // constructors (no explicit conversions allowed)
  144. explicit d_string()
  145. {
  146. _init();
  147. _dup(nullptr);
  148. }
  149. explicit d_string(char* const strBuf)
  150. {
  151. _init();
  152. _dup(strBuf);
  153. }
  154. explicit d_string(const char* const strBuf)
  155. {
  156. _init();
  157. _dup(strBuf);
  158. }
  159. explicit d_string(const int value)
  160. {
  161. char strBuf[0xff] = { '\0' };
  162. std::snprintf(strBuf, 0xff, "%d", value);
  163. _init();
  164. _dup(strBuf);
  165. }
  166. explicit d_string(const unsigned int value, const bool hexadecimal = false)
  167. {
  168. char strBuf[0xff] = { '\0' };
  169. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%x" : "%u", value);
  170. _init();
  171. _dup(strBuf);
  172. }
  173. explicit d_string(const long int value)
  174. {
  175. char strBuf[0xff] = { '\0' };
  176. std::snprintf(strBuf, 0xff, "%ld", value);
  177. _init();
  178. _dup(strBuf);
  179. }
  180. explicit d_string(const unsigned long int value, const bool hexadecimal = false)
  181. {
  182. char strBuf[0xff] = { '\0' };
  183. std::snprintf(strBuf, 0xff, hexadecimal ? "0x%lx" : "%lu", value);
  184. _init();
  185. _dup(strBuf);
  186. }
  187. explicit d_string(const float value)
  188. {
  189. char strBuf[0xff] = { '\0' };
  190. std::snprintf(strBuf, 0xff, "%f", value);
  191. _init();
  192. _dup(strBuf);
  193. }
  194. explicit d_string(const double value)
  195. {
  196. char strBuf[0xff] = { '\0' };
  197. std::snprintf(strBuf, 0xff, "%g", value);
  198. _init();
  199. _dup(strBuf);
  200. }
  201. // ---------------------------------------------
  202. // non-explicit constructor
  203. d_string(const d_string& str)
  204. {
  205. _init();
  206. _dup(str.buffer);
  207. }
  208. // ---------------------------------------------
  209. // deconstructor
  210. ~d_string()
  211. {
  212. assert(buffer != nullptr);
  213. delete[] buffer;
  214. }
  215. // ---------------------------------------------
  216. // public methods
  217. size_t length() const
  218. {
  219. return bufferLen;
  220. }
  221. bool isEmpty() const
  222. {
  223. return (bufferLen == 0);
  224. }
  225. bool isNotEmpty() const
  226. {
  227. return (bufferLen != 0);
  228. }
  229. #ifdef __USE_GNU
  230. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  231. {
  232. if (strBuf == nullptr)
  233. return false;
  234. if (ignoreCase)
  235. return (strcasestr(buffer, strBuf) != nullptr);
  236. else
  237. return (std::strstr(buffer, strBuf) != nullptr);
  238. }
  239. bool contains(const d_string& str, const bool ignoreCase = false) const
  240. {
  241. return contains(str.buffer, ignoreCase);
  242. }
  243. #else
  244. bool contains(const char* const strBuf) const
  245. {
  246. if (strBuf == nullptr)
  247. return false;
  248. return (std::strstr(buffer, strBuf) != nullptr);
  249. }
  250. bool contains(const d_string& str) const
  251. {
  252. return contains(str.buffer);
  253. }
  254. #endif
  255. bool isDigit(const size_t pos) const
  256. {
  257. if (pos >= bufferLen)
  258. return false;
  259. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  260. }
  261. void clear()
  262. {
  263. truncate(0);
  264. }
  265. size_t find(const char c) const
  266. {
  267. for (size_t i=0; i < bufferLen; ++i)
  268. {
  269. if (buffer[i] == c)
  270. return i;
  271. }
  272. return 0;
  273. }
  274. size_t rfind(const char c) const
  275. {
  276. for (size_t i=bufferLen; i > 0; --i)
  277. {
  278. if (buffer[i-1] == c)
  279. return i-1;
  280. }
  281. return 0;
  282. }
  283. void replace(const char before, const char after)
  284. {
  285. if (after == '\0')
  286. return;
  287. for (size_t i=0; i < bufferLen; ++i)
  288. {
  289. if (buffer[i] == before)
  290. buffer[i] = after;
  291. else if (buffer[i] == '\0')
  292. break;
  293. }
  294. }
  295. void truncate(const size_t n)
  296. {
  297. if (n >= bufferLen)
  298. return;
  299. for (size_t i=n; i < bufferLen; ++i)
  300. buffer[i] = '\0';
  301. bufferLen = n;
  302. }
  303. void toBasic()
  304. {
  305. for (size_t i=0; i < bufferLen; ++i)
  306. {
  307. if (buffer[i] >= '0' && buffer[i] <= '9')
  308. continue;
  309. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  310. continue;
  311. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  312. continue;
  313. if (buffer[i] == '_')
  314. continue;
  315. buffer[i] = '_';
  316. }
  317. }
  318. void toLower()
  319. {
  320. static const char kCharDiff = 'a' - 'A';
  321. for (size_t i=0; i < bufferLen; ++i)
  322. {
  323. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  324. buffer[i] += kCharDiff;
  325. }
  326. }
  327. void toUpper()
  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. // ---------------------------------------------
  337. // public operators
  338. operator const char*() const
  339. {
  340. return buffer;
  341. }
  342. char& operator[](const size_t pos)
  343. {
  344. return buffer[pos];
  345. }
  346. bool operator==(const char* const strBuf) const
  347. {
  348. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  349. }
  350. bool operator==(const d_string& str) const
  351. {
  352. return operator==(str.buffer);
  353. }
  354. bool operator!=(const char* const strBuf) const
  355. {
  356. return !operator==(strBuf);
  357. }
  358. bool operator!=(const d_string& str) const
  359. {
  360. return !operator==(str.buffer);
  361. }
  362. d_string& operator=(const char* const strBuf)
  363. {
  364. _dup(strBuf);
  365. return *this;
  366. }
  367. d_string& operator=(const d_string& str)
  368. {
  369. return operator=(str.buffer);
  370. }
  371. d_string& operator+=(const char* const strBuf)
  372. {
  373. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  374. char newBuf[newBufSize];
  375. std::strcpy(newBuf, buffer);
  376. std::strcat(newBuf, strBuf);
  377. _dup(newBuf, newBufSize-1);
  378. return *this;
  379. }
  380. d_string& operator+=(const d_string& str)
  381. {
  382. return operator+=(str.buffer);
  383. }
  384. d_string operator+(const char* const strBuf)
  385. {
  386. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  387. char newBuf[newBufSize];
  388. std::strcpy(newBuf, buffer);
  389. std::strcat(newBuf, strBuf);
  390. return d_string(newBuf);
  391. }
  392. d_string operator+(const d_string& str)
  393. {
  394. return operator+(str.buffer);
  395. }
  396. // ---------------------------------------------
  397. private:
  398. char* buffer;
  399. size_t bufferLen;
  400. bool firstInit;
  401. void _init()
  402. {
  403. buffer = nullptr;
  404. bufferLen = 0;
  405. firstInit = true;
  406. }
  407. // allocate string strBuf if not null
  408. // size > 0 only if strBuf is valid
  409. void _dup(const char* const strBuf, const size_t size = 0)
  410. {
  411. if (strBuf != nullptr)
  412. {
  413. // don't recreate string if contents match
  414. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  415. {
  416. if (! firstInit)
  417. {
  418. assert(buffer != nullptr);
  419. delete[] buffer;
  420. }
  421. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  422. buffer = new char[bufferLen+1];
  423. std::strcpy(buffer, strBuf);
  424. buffer[bufferLen] = '\0';
  425. firstInit = false;
  426. }
  427. }
  428. else
  429. {
  430. assert(size == 0);
  431. // don't recreate null string
  432. if (firstInit || bufferLen != 0)
  433. {
  434. if (! firstInit)
  435. {
  436. assert(buffer != nullptr);
  437. delete[] buffer;
  438. }
  439. bufferLen = 0;
  440. buffer = new char[1];
  441. buffer[0] = '\0';
  442. firstInit = false;
  443. }
  444. }
  445. }
  446. };
  447. // -------------------------------------------------
  448. static inline
  449. d_string operator+(const d_string& strBefore, const char* const strBufAfter)
  450. {
  451. const char* const strBufBefore = (const char*)strBefore;
  452. const size_t newBufSize = strBefore.length() + ((strBufAfter != nullptr) ? std::strlen(strBufAfter) : 0) + 1;
  453. char newBuf[newBufSize];
  454. std::strcpy(newBuf, strBufBefore);
  455. std::strcat(newBuf, strBufAfter);
  456. return d_string(newBuf);
  457. }
  458. static inline
  459. d_string operator+(const char* const strBufBefore, const d_string& strAfter)
  460. {
  461. const char* const strBufAfter = (const char*)strAfter;
  462. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + strAfter.length() + 1;
  463. char newBuf[newBufSize];
  464. std::strcpy(newBuf, strBufBefore);
  465. std::strcat(newBuf, strBufAfter);
  466. return d_string(newBuf);
  467. }
  468. // -------------------------------------------------
  469. END_NAMESPACE_DISTRHO
  470. #endif // __DISTRHO_UTILS_HPP__