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.

685 lines
15KB

  1. /*
  2. * Carla common utils
  3. * Copyright (C) 2011-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 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 GPL.txt file
  16. */
  17. #ifndef __CARLA_UTILS_HPP__
  18. #define __CARLA_UTILS_HPP__
  19. #include "carla_juce_utils.hpp"
  20. #include <cstdio>
  21. #include <cstdlib>
  22. #include <cstring>
  23. #ifdef DONT_USE_PTHREAD
  24. # include <mutex>
  25. #else
  26. # include <pthread.h>
  27. #endif
  28. #if defined(Q_OS_HAIKU)
  29. # include <kernel/OS.h>
  30. #elif defined(Q_OS_LINUX)
  31. # include <sys/prctl.h>
  32. # include <linux/prctl.h>
  33. #endif
  34. // -------------------------------------------------
  35. // carla_assert*
  36. static inline
  37. void carla_assert(const char* const assertion, const char* const file, const int line)
  38. {
  39. qCritical("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
  40. }
  41. static inline
  42. void carla_assert_int(const char* const assertion, const char* const file, const int line, const int value)
  43. {
  44. qCritical("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
  45. }
  46. static inline
  47. void carla_assert_int2(const char* const assertion, const char* const file, const int line, const int v1, const int v2)
  48. {
  49. qCritical("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
  50. }
  51. // -------------------------------------------------
  52. // carla_*sleep
  53. static inline
  54. void carla_sleep(const unsigned int secs)
  55. {
  56. CARLA_ASSERT(secs > 0);
  57. #ifdef Q_OS_WIN
  58. Sleep(secs * 1000);
  59. #else
  60. sleep(secs);
  61. #endif
  62. }
  63. static inline
  64. void carla_msleep(const unsigned int msecs)
  65. {
  66. CARLA_ASSERT(msecs > 0);
  67. #ifdef Q_OS_WIN
  68. Sleep(msecs);
  69. #else
  70. usleep(msecs * 1000);
  71. #endif
  72. }
  73. static inline
  74. void carla_usleep(const unsigned int usecs)
  75. {
  76. CARLA_ASSERT(usecs > 0);
  77. #ifdef Q_OS_WIN
  78. Sleep(usecs / 1000);
  79. #else
  80. usleep(usecs);
  81. #endif
  82. }
  83. // -------------------------------------------------
  84. // carla_setenv
  85. static inline
  86. void carla_setenv(const char* const key, const char* const value)
  87. {
  88. CARLA_ASSERT(key != nullptr);
  89. CARLA_ASSERT(value != nullptr);
  90. #ifdef Q_OS_WIN
  91. SetEnvironmentVariableA(key, value);
  92. #else
  93. setenv(key, value, 1);
  94. #endif
  95. }
  96. // -------------------------------------------------
  97. // carla_setprocname (not available on all platforms)
  98. static inline
  99. void carla_setprocname(const char* const name)
  100. {
  101. CARLA_ASSERT(name != nullptr);
  102. #if defined(Q_OS_HAIKU)
  103. if ((thread_id this_thread = find_thread(nullptr)) != B_NAME_NOT_FOUND)
  104. rename_thread(this_thread, name);
  105. #elif defined(Q_OS_LINUX)
  106. prctl(PR_SET_NAME, name);
  107. #else
  108. qWarning("carla_setprocname(\"%s\") - unsupported on this platform", name);
  109. #endif
  110. }
  111. // -------------------------------------------------
  112. // math functions
  113. template<typename T>
  114. static inline
  115. const T& carla_min(const T& v1, const T& v2, const T& min)
  116. {
  117. return ((v1 < min || v2 < min) ? min : (v1 < v2 ? v1 : v2));
  118. }
  119. template<typename T>
  120. static inline
  121. const T& carla_fixValue(const T& min, const T& max, const T& value)
  122. {
  123. if (value < min)
  124. return min;
  125. if (value > max)
  126. return max;
  127. return value;
  128. }
  129. template<typename T>
  130. static inline
  131. void carla_fill(T* data, const unsigned int size, const T v)
  132. {
  133. CARLA_ASSERT(data != nullptr);
  134. CARLA_ASSERT(size > 0);
  135. if (data == nullptr)
  136. return;
  137. for (unsigned int i=0; i < size; i++)
  138. *data++ = v;
  139. }
  140. static inline
  141. void carla_zeroDouble(double* data, const unsigned size)
  142. {
  143. carla_fill<double>(data, size, 0.0);
  144. }
  145. static inline
  146. void carla_zeroFloat(float* data, const unsigned size)
  147. {
  148. carla_fill<float>(data, size, 0.0f);
  149. }
  150. // -------------------------------------------------
  151. // memory functions
  152. static inline
  153. void carla_zeroMem(void* const memory, const size_t numBytes)
  154. {
  155. CARLA_ASSERT(memory != nullptr);
  156. if (memory == nullptr)
  157. return;
  158. std::memset(memory, 0, numBytes);
  159. }
  160. template <typename T>
  161. static inline
  162. void carla_zeroStruct(T& structure)
  163. {
  164. std::memset(&structure, 0, sizeof(T));
  165. }
  166. // -------------------------------------------------
  167. // other misc functions
  168. static inline
  169. const char* bool2str(const bool yesNo)
  170. {
  171. return yesNo ? "true" : "false";
  172. }
  173. static inline
  174. void pass() {}
  175. // -------------------------------------------------
  176. // CarlaMutex class
  177. class CarlaMutex
  178. {
  179. public:
  180. CarlaMutex()
  181. {
  182. #ifndef DONT_USE_PTHREAD
  183. pthread_mutex_init(&pmutex, nullptr);
  184. #endif
  185. }
  186. ~CarlaMutex()
  187. {
  188. #ifndef DONT_USE_PTHREAD
  189. pthread_mutex_destroy(&pmutex);
  190. #endif
  191. }
  192. bool lock()
  193. {
  194. #ifdef DONT_USE_PTHREAD
  195. cmutex.lock();
  196. return true;
  197. #else
  198. return (pthread_mutex_lock(&pmutex) == 0);
  199. #endif
  200. }
  201. bool tryLock()
  202. {
  203. #ifdef DONT_USE_PTHREAD
  204. return cmutex.try_lock();
  205. #else
  206. return (pthread_mutex_trylock(&pmutex) == 0);
  207. #endif
  208. }
  209. bool unlock()
  210. {
  211. #ifdef DONT_USE_PTHREAD
  212. cmutex.unlock();
  213. return true;
  214. #else
  215. return (pthread_mutex_unlock(&pmutex) == 0);
  216. #endif
  217. }
  218. class ScopedLocker
  219. {
  220. public:
  221. ScopedLocker(CarlaMutex* const mutex)
  222. : fMutex(mutex)
  223. {
  224. fMutex->lock();
  225. }
  226. ~ScopedLocker()
  227. {
  228. fMutex->unlock();
  229. }
  230. private:
  231. CarlaMutex* const fMutex;
  232. CARLA_PREVENT_HEAP_ALLOCATION
  233. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker)
  234. };
  235. private:
  236. #ifdef DONT_USE_PTHREAD
  237. std::mutex cmutex;
  238. #else
  239. pthread_mutex_t pmutex;
  240. #endif
  241. CARLA_PREVENT_HEAP_ALLOCATION
  242. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex)
  243. };
  244. // -------------------------------------------------
  245. // CarlaString class
  246. class CarlaString
  247. {
  248. public:
  249. // ---------------------------------------------
  250. // constructors (no explicit conversions allowed)
  251. explicit CarlaString()
  252. {
  253. _init();
  254. _dup(nullptr);
  255. }
  256. explicit CarlaString(char* const strBuf)
  257. {
  258. _init();
  259. _dup(strBuf);
  260. }
  261. explicit CarlaString(const char* const strBuf)
  262. {
  263. _init();
  264. _dup(strBuf);
  265. }
  266. explicit CarlaString(const int value)
  267. {
  268. const size_t strBufSize = std::abs(value/10) + 3;
  269. char strBuf[strBufSize];
  270. std::snprintf(strBuf, strBufSize, "%d", value);
  271. _init();
  272. _dup(strBuf, strBufSize);
  273. }
  274. explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
  275. {
  276. const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
  277. char strBuf[strBufSize];
  278. std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%x" : "%u", value);
  279. _init();
  280. _dup(strBuf, strBufSize);
  281. }
  282. explicit CarlaString(const long int value)
  283. {
  284. const size_t strBufSize = std::abs(value/10) + 3;
  285. char strBuf[strBufSize];
  286. std::snprintf(strBuf, strBufSize, "%ld", value);
  287. _init();
  288. _dup(strBuf, strBufSize);
  289. }
  290. explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
  291. {
  292. const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
  293. char strBuf[strBufSize];
  294. std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%lx" : "%lu", value);
  295. _init();
  296. _dup(strBuf, strBufSize);
  297. }
  298. explicit CarlaString(const float value)
  299. {
  300. char strBuf[0xff];
  301. std::snprintf(strBuf, 0xff, "%f", value);
  302. _init();
  303. _dup(strBuf);
  304. }
  305. explicit CarlaString(const double value)
  306. {
  307. char strBuf[0xff];
  308. std::snprintf(strBuf, 0xff, "%g", value);
  309. _init();
  310. _dup(strBuf);
  311. }
  312. // ---------------------------------------------
  313. // non-explicit constructor
  314. CarlaString(const CarlaString& str)
  315. {
  316. _init();
  317. _dup(str.buffer);
  318. }
  319. // ---------------------------------------------
  320. // deconstructor
  321. ~CarlaString()
  322. {
  323. CARLA_ASSERT(buffer);
  324. delete[] buffer;
  325. }
  326. // ---------------------------------------------
  327. // public methods
  328. size_t length() const
  329. {
  330. return bufferLen;
  331. }
  332. bool isEmpty() const
  333. {
  334. return (bufferLen == 0);
  335. }
  336. bool isNotEmpty() const
  337. {
  338. return (bufferLen != 0);
  339. }
  340. #if __USE_GNU && 0
  341. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  342. {
  343. if (strBuf == nullptr)
  344. return false;
  345. if (ignoreCase)
  346. return (std::strcasestr(buffer, strBuf) != nullptr);
  347. else
  348. return (std::strstr(buffer, strBuf) != nullptr);
  349. }
  350. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  351. {
  352. return contains(str.buffer, ignoreCase);
  353. }
  354. #else
  355. bool contains(const char* const strBuf) const
  356. {
  357. if (strBuf == nullptr)
  358. return false;
  359. return (std::strstr(buffer, strBuf) != nullptr);
  360. }
  361. bool contains(const CarlaString& str) const
  362. {
  363. return contains(str.buffer);
  364. }
  365. #endif
  366. bool isDigit(const size_t pos) const
  367. {
  368. if (pos >= bufferLen)
  369. return false;
  370. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  371. }
  372. void clear()
  373. {
  374. truncate(0);
  375. }
  376. void replace(const char before, const char after)
  377. {
  378. if (after == '\0')
  379. return;
  380. for (size_t i=0; i < bufferLen; i++)
  381. {
  382. if (buffer[i] == before)
  383. buffer[i] = after;
  384. else if (buffer[i] == '\0')
  385. break;
  386. }
  387. }
  388. void truncate(const size_t n)
  389. {
  390. if (n >= bufferLen)
  391. return;
  392. for (size_t i=n; i < bufferLen; i++)
  393. buffer[i] = '\0';
  394. bufferLen = n;
  395. }
  396. void toBasic()
  397. {
  398. for (size_t i=0; i < bufferLen; i++)
  399. {
  400. if (buffer[i] >= '0' && buffer[i] <= '9')
  401. continue;
  402. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  403. continue;
  404. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  405. continue;
  406. if (buffer[i] == '_')
  407. continue;
  408. buffer[i] = '_';
  409. }
  410. }
  411. void toLower()
  412. {
  413. static const char charDiff = 'a' - 'A';
  414. for (size_t i=0; i < bufferLen; i++)
  415. {
  416. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  417. buffer[i] += charDiff;
  418. }
  419. }
  420. void toUpper()
  421. {
  422. static const char charDiff = 'a' - 'A';
  423. for (size_t i=0; i < bufferLen; i++)
  424. {
  425. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  426. buffer[i] -= charDiff;
  427. }
  428. }
  429. // ---------------------------------------------
  430. // public operators
  431. operator const char*() const
  432. {
  433. return buffer;
  434. }
  435. char& operator[](const size_t pos)
  436. {
  437. return buffer[pos];
  438. }
  439. bool operator==(const char* const strBuf) const
  440. {
  441. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  442. }
  443. bool operator==(const CarlaString& str) const
  444. {
  445. return operator==(str.buffer);
  446. }
  447. bool operator!=(const char* const strBuf) const
  448. {
  449. return !operator==(strBuf);
  450. }
  451. bool operator!=(const CarlaString& str) const
  452. {
  453. return !operator==(str.buffer);
  454. }
  455. CarlaString& operator=(const char* const strBuf)
  456. {
  457. _dup(strBuf);
  458. return *this;
  459. }
  460. CarlaString& operator=(const CarlaString& str)
  461. {
  462. return operator=(str.buffer);
  463. }
  464. CarlaString& operator+=(const char* const strBuf)
  465. {
  466. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  467. char newBuf[newBufSize];
  468. std::strcpy(newBuf, buffer);
  469. std::strcat(newBuf, strBuf);
  470. _dup(newBuf, newBufSize-1);
  471. return *this;
  472. }
  473. CarlaString& operator+=(const CarlaString& str)
  474. {
  475. return operator+=(str.buffer);
  476. }
  477. CarlaString operator+(const char* const strBuf)
  478. {
  479. const size_t newBufSize = bufferLen + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  480. char newBuf[newBufSize];
  481. std::strcpy(newBuf, buffer);
  482. std::strcat(newBuf, strBuf);
  483. return CarlaString(newBuf);
  484. }
  485. CarlaString operator+(const CarlaString& str)
  486. {
  487. return operator+(str.buffer);
  488. }
  489. // ---------------------------------------------
  490. private:
  491. char* buffer;
  492. size_t bufferLen;
  493. bool firstInit;
  494. void _init()
  495. {
  496. buffer = nullptr;
  497. bufferLen = 0;
  498. firstInit = true;
  499. }
  500. // allocate string strBuf if not null
  501. // size > 0 only if strBuf is valid
  502. void _dup(const char* const strBuf, const size_t size = 0)
  503. {
  504. if (strBuf != nullptr)
  505. {
  506. // don't recreate string if contents match
  507. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  508. {
  509. if (! firstInit)
  510. {
  511. CARLA_ASSERT(buffer);
  512. delete[] buffer;
  513. }
  514. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  515. buffer = new char[bufferLen+1];
  516. std::strcpy(buffer, strBuf);
  517. buffer[bufferLen] = '\0';
  518. firstInit = false;
  519. }
  520. }
  521. else
  522. {
  523. CARLA_ASSERT(size == 0);
  524. // don't recreate null string
  525. if (firstInit || bufferLen != 0)
  526. {
  527. if (! firstInit)
  528. {
  529. CARLA_ASSERT(buffer);
  530. delete[] buffer;
  531. }
  532. bufferLen = 0;
  533. buffer = new char[1];
  534. buffer[0] = '\0';
  535. firstInit = false;
  536. }
  537. }
  538. }
  539. CARLA_LEAK_DETECTOR(CarlaString)
  540. CARLA_PREVENT_HEAP_ALLOCATION
  541. };
  542. static inline
  543. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  544. {
  545. const char* const strBufAfter = (const char*)strAfter;
  546. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + std::strlen(strBufAfter) + 1;
  547. char newBuf[newBufSize];
  548. std::strcpy(newBuf, strBufBefore);
  549. std::strcat(newBuf, strBufAfter);
  550. return CarlaString(newBuf);
  551. }
  552. // -------------------------------------------------
  553. #endif // __CARLA_UTILS_HPP__