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. * 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 = (unsigned int)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 = (unsigned long)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. _dup(strBuf);
  303. }
  304. explicit CarlaString(const double value)
  305. {
  306. char strBuf[0xff];
  307. std::snprintf(strBuf, 0xff, "%g", value);
  308. _init();
  309. _dup(strBuf);
  310. }
  311. // ---------------------------------------------
  312. // non-explicit constructor
  313. CarlaString(const CarlaString& str)
  314. {
  315. _init();
  316. _dup(str.buffer);
  317. }
  318. // ---------------------------------------------
  319. // deconstructor
  320. ~CarlaString()
  321. {
  322. CARLA_ASSERT(buffer);
  323. delete[] buffer;
  324. }
  325. // ---------------------------------------------
  326. // public methods
  327. size_t length() const
  328. {
  329. return bufferLen;
  330. }
  331. bool isEmpty() const
  332. {
  333. return (bufferLen == 0);
  334. }
  335. bool isNotEmpty() const
  336. {
  337. return (bufferLen != 0);
  338. }
  339. #if __USE_GNU && 0
  340. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  341. {
  342. if (strBuf == nullptr)
  343. return false;
  344. if (bufferLen == 0)
  345. return false;
  346. if (ignoreCase)
  347. return (std::strcasestr(buffer, strBuf) != nullptr);
  348. else
  349. return (std::strstr(buffer, strBuf) != nullptr);
  350. }
  351. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  352. {
  353. return contains(str.buffer, ignoreCase);
  354. }
  355. #else
  356. bool contains(const char* const strBuf) const
  357. {
  358. if (strBuf == nullptr)
  359. return false;
  360. if (bufferLen == 0)
  361. return false;
  362. return (std::strstr(buffer, strBuf) != nullptr);
  363. }
  364. bool contains(const CarlaString& str) const
  365. {
  366. return contains(str.buffer);
  367. }
  368. #endif
  369. bool isDigit(const size_t pos) const
  370. {
  371. if (pos >= bufferLen)
  372. return false;
  373. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  374. }
  375. void clear()
  376. {
  377. truncate(0);
  378. }
  379. void replace(const char before, const char after)
  380. {
  381. if (after == '\0')
  382. return;
  383. for (size_t i=0; i < bufferLen; i++)
  384. {
  385. if (buffer[i] == before)
  386. buffer[i] = after;
  387. else if (buffer[i] == '\0')
  388. break;
  389. }
  390. }
  391. void truncate(const size_t n)
  392. {
  393. for (size_t i=n; i < bufferLen; i++)
  394. buffer[i] = '\0';
  395. // FIXME
  396. bufferLen = std::strlen(buffer);
  397. }
  398. void toBasic()
  399. {
  400. for (size_t i=0; i < bufferLen; i++)
  401. {
  402. if (buffer[i] >= '0' && buffer[i] <= '9')
  403. continue;
  404. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  405. continue;
  406. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  407. continue;
  408. if (buffer[i] == '_')
  409. continue;
  410. buffer[i] = '_';
  411. }
  412. }
  413. void toLower()
  414. {
  415. static const char charDiff = 'a' - 'A';
  416. for (size_t i=0; i < bufferLen; i++)
  417. {
  418. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  419. buffer[i] = char(buffer[i] + charDiff);
  420. }
  421. }
  422. void toUpper()
  423. {
  424. static const char charDiff = 'a' - 'A';
  425. for (size_t i=0; i < bufferLen; i++)
  426. {
  427. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  428. buffer[i] = char(buffer[i] + charDiff);
  429. }
  430. }
  431. // ---------------------------------------------
  432. // public operators
  433. operator const char*() const
  434. {
  435. return buffer;
  436. }
  437. char& operator[](const size_t pos)
  438. {
  439. return buffer[pos];
  440. }
  441. bool operator==(const char* const strBuf) const
  442. {
  443. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  444. }
  445. bool operator==(const CarlaString& str) const
  446. {
  447. return operator==(str.buffer);
  448. }
  449. bool operator!=(const char* const strBuf) const
  450. {
  451. return !operator==(strBuf);
  452. }
  453. bool operator!=(const CarlaString& str) const
  454. {
  455. return !operator==(str.buffer);
  456. }
  457. CarlaString& operator=(const char* const strBuf)
  458. {
  459. _dup(strBuf);
  460. return *this;
  461. }
  462. CarlaString& operator=(const CarlaString& str)
  463. {
  464. return operator=(str.buffer);
  465. }
  466. CarlaString& operator+=(const char* const strBuf)
  467. {
  468. const size_t newBufSize = std::strlen(buffer) + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  469. char newBuf[newBufSize];
  470. std::strcpy(newBuf, buffer);
  471. std::strcat(newBuf, strBuf);
  472. _dup(newBuf, newBufSize);
  473. return *this;
  474. }
  475. CarlaString& operator+=(const CarlaString& str)
  476. {
  477. return operator+=(str.buffer);
  478. }
  479. CarlaString operator+(const char* const strBuf)
  480. {
  481. const size_t newBufSize = std::strlen(buffer) + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  482. char newBuf[newBufSize];
  483. std::strcpy(newBuf, buffer);
  484. std::strcat(newBuf, strBuf);
  485. return CarlaString(newBuf);
  486. }
  487. CarlaString operator+(const CarlaString& str)
  488. {
  489. return operator+(str.buffer);
  490. }
  491. // ---------------------------------------------
  492. private:
  493. char* buffer;
  494. size_t bufferLen;
  495. bool firstInit;
  496. void _init()
  497. {
  498. buffer = nullptr;
  499. bufferLen = 0;
  500. firstInit = true;
  501. }
  502. // allocate string strBuf if not null
  503. // size > 0 only if strBuf is valid
  504. void _dup(const char* const strBuf, const size_t size = 0)
  505. {
  506. if (strBuf != nullptr)
  507. {
  508. // don't recreate string if contents match
  509. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  510. {
  511. if (! firstInit)
  512. {
  513. CARLA_ASSERT(buffer);
  514. delete[] buffer;
  515. }
  516. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  517. buffer = new char[bufferLen+1];
  518. std::strcpy(buffer, strBuf);
  519. buffer[bufferLen] = '\0';
  520. firstInit = false;
  521. }
  522. }
  523. else
  524. {
  525. CARLA_ASSERT(size == 0);
  526. // don't recreate null string
  527. if (firstInit || bufferLen != 0)
  528. {
  529. if (! firstInit)
  530. {
  531. CARLA_ASSERT(buffer);
  532. delete[] buffer;
  533. }
  534. bufferLen = 0;
  535. buffer = new char[1];
  536. buffer[0] = '\0';
  537. firstInit = false;
  538. }
  539. }
  540. }
  541. CARLA_LEAK_DETECTOR(CarlaString)
  542. CARLA_PREVENT_HEAP_ALLOCATION
  543. };
  544. static inline
  545. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  546. {
  547. const char* const strBufAfter = (const char*)strAfter;
  548. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + std::strlen(strBufAfter) + 1;
  549. char newBuf[newBufSize];
  550. std::strcpy(newBuf, strBufBefore);
  551. std::strcat(newBuf, strBufAfter);
  552. return CarlaString(newBuf);
  553. }
  554. // -------------------------------------------------
  555. #endif // __CARLA_UTILS_HPP__