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.

670 lines
14KB

  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. void carla_fill(T* data, const unsigned int size, const T v)
  122. {
  123. CARLA_ASSERT(data != nullptr);
  124. CARLA_ASSERT(size > 0);
  125. if (data == nullptr)
  126. return;
  127. for (unsigned int i=0; i < size; i++)
  128. *data++ = v;
  129. }
  130. static inline
  131. void carla_zeroDouble(double* data, const unsigned size)
  132. {
  133. carla_fill<double>(data, size, 0.0);
  134. }
  135. static inline
  136. void carla_zeroFloat(float* data, const unsigned size)
  137. {
  138. carla_fill<float>(data, size, 0.0f);
  139. }
  140. // -------------------------------------------------
  141. // memory functions
  142. static inline
  143. void carla_zeroMem(void* const memory, const size_t numBytes)
  144. {
  145. CARLA_ASSERT(memory != nullptr);
  146. if (memory == nullptr)
  147. return;
  148. std::memset(memory, 0, numBytes);
  149. }
  150. template <typename T>
  151. static inline
  152. void carla_zeroStruct(T& structure)
  153. {
  154. std::memset(&structure, 0, sizeof(T));
  155. }
  156. // -------------------------------------------------
  157. // other misc functions
  158. static inline
  159. const char* bool2str(const bool yesNo)
  160. {
  161. return yesNo ? "true" : "false";
  162. }
  163. static inline
  164. void pass() {}
  165. // -------------------------------------------------
  166. // CarlaMutex class
  167. class CarlaMutex
  168. {
  169. public:
  170. CarlaMutex()
  171. {
  172. #ifndef DONT_USE_PTHREAD
  173. pthread_mutex_init(&pmutex, nullptr);
  174. #endif
  175. }
  176. ~CarlaMutex()
  177. {
  178. #ifndef DONT_USE_PTHREAD
  179. pthread_mutex_destroy(&pmutex);
  180. #endif
  181. }
  182. bool lock()
  183. {
  184. #ifdef DONT_USE_PTHREAD
  185. cmutex.lock();
  186. return true;
  187. #else
  188. return (pthread_mutex_lock(&pmutex) == 0);
  189. #endif
  190. }
  191. bool tryLock()
  192. {
  193. #ifdef DONT_USE_PTHREAD
  194. return cmutex.try_lock();
  195. #else
  196. return (pthread_mutex_trylock(&pmutex) == 0);
  197. #endif
  198. }
  199. bool unlock()
  200. {
  201. #ifdef DONT_USE_PTHREAD
  202. cmutex.unlock();
  203. return true;
  204. #else
  205. return (pthread_mutex_unlock(&pmutex) == 0);
  206. #endif
  207. }
  208. class ScopedLocker
  209. {
  210. public:
  211. ScopedLocker(CarlaMutex* const mutex_)
  212. : mutex(mutex_)
  213. {
  214. mutex->lock();
  215. }
  216. ~ScopedLocker()
  217. {
  218. mutex->unlock();
  219. }
  220. private:
  221. CarlaMutex* const mutex;
  222. CARLA_PREVENT_HEAP_ALLOCATION
  223. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ScopedLocker)
  224. };
  225. private:
  226. #ifdef DONT_USE_PTHREAD
  227. std::mutex cmutex;
  228. #else
  229. pthread_mutex_t pmutex;
  230. #endif
  231. CARLA_PREVENT_HEAP_ALLOCATION
  232. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaMutex)
  233. };
  234. // -------------------------------------------------
  235. // CarlaString class
  236. class CarlaString
  237. {
  238. public:
  239. // ---------------------------------------------
  240. // constructors (no explicit conversions allowed)
  241. explicit CarlaString()
  242. {
  243. _init();
  244. _dup(nullptr);
  245. }
  246. explicit CarlaString(char* const strBuf)
  247. {
  248. _init();
  249. _dup(strBuf);
  250. }
  251. explicit CarlaString(const char* const strBuf)
  252. {
  253. _init();
  254. _dup(strBuf);
  255. }
  256. explicit CarlaString(const int value)
  257. {
  258. const size_t strBufSize = (unsigned int)std::abs(value/10) + 3;
  259. char strBuf[strBufSize];
  260. std::snprintf(strBuf, strBufSize, "%d", value);
  261. _init();
  262. _dup(strBuf, strBufSize);
  263. }
  264. explicit CarlaString(const unsigned int value, const bool hexadecimal = false)
  265. {
  266. const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
  267. char strBuf[strBufSize];
  268. std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%x" : "%u", value);
  269. _init();
  270. _dup(strBuf, strBufSize);
  271. }
  272. explicit CarlaString(const long int value)
  273. {
  274. const size_t strBufSize = (unsigned long)std::abs(value/10) + 3;
  275. char strBuf[strBufSize];
  276. std::snprintf(strBuf, strBufSize, "%ld", value);
  277. _init();
  278. _dup(strBuf, strBufSize);
  279. }
  280. explicit CarlaString(const unsigned long int value, const bool hexadecimal = false)
  281. {
  282. const size_t strBufSize = value/10 + 2 + (hexadecimal ? 2 : 0);
  283. char strBuf[strBufSize];
  284. std::snprintf(strBuf, strBufSize, hexadecimal ? "0x%lx" : "%lu", value);
  285. _init();
  286. _dup(strBuf, strBufSize);
  287. }
  288. explicit CarlaString(const float value)
  289. {
  290. char strBuf[0xff];
  291. std::snprintf(strBuf, 0xff, "%f", value);
  292. _dup(strBuf);
  293. }
  294. explicit CarlaString(const double value)
  295. {
  296. char strBuf[0xff];
  297. std::snprintf(strBuf, 0xff, "%g", value);
  298. _init();
  299. _dup(strBuf);
  300. }
  301. // ---------------------------------------------
  302. // non-explicit constructor
  303. CarlaString(const CarlaString& str)
  304. {
  305. _init();
  306. _dup(str.buffer);
  307. }
  308. // ---------------------------------------------
  309. // deconstructor
  310. ~CarlaString()
  311. {
  312. CARLA_ASSERT(buffer);
  313. delete[] buffer;
  314. }
  315. // ---------------------------------------------
  316. // public methods
  317. size_t length() const
  318. {
  319. return bufferLen;
  320. }
  321. bool isEmpty() const
  322. {
  323. return (bufferLen == 0);
  324. }
  325. bool isNotEmpty() const
  326. {
  327. return (bufferLen != 0);
  328. }
  329. #if __USE_GNU && 0
  330. bool contains(const char* const strBuf, const bool ignoreCase = false) const
  331. {
  332. if (strBuf == nullptr)
  333. return false;
  334. if (bufferLen == 0)
  335. return false;
  336. if (ignoreCase)
  337. return (std::strcasestr(buffer, strBuf) != nullptr);
  338. else
  339. return (std::strstr(buffer, strBuf) != nullptr);
  340. }
  341. bool contains(const CarlaString& str, const bool ignoreCase = false) const
  342. {
  343. return contains(str.buffer, ignoreCase);
  344. }
  345. #else
  346. bool contains(const char* const strBuf) const
  347. {
  348. if (strBuf == nullptr)
  349. return false;
  350. if (bufferLen == 0)
  351. return false;
  352. return (std::strstr(buffer, strBuf) != nullptr);
  353. }
  354. bool contains(const CarlaString& str) const
  355. {
  356. return contains(str.buffer);
  357. }
  358. #endif
  359. bool isDigit(const size_t pos) const
  360. {
  361. if (pos >= bufferLen)
  362. return false;
  363. return (buffer[pos] >= '0' && buffer[pos] <= '9');
  364. }
  365. void clear()
  366. {
  367. truncate(0);
  368. }
  369. void replace(const char before, const char after)
  370. {
  371. if (after == '\0')
  372. return;
  373. for (size_t i=0; i < bufferLen; i++)
  374. {
  375. if (buffer[i] == before)
  376. buffer[i] = after;
  377. else if (buffer[i] == '\0')
  378. break;
  379. }
  380. }
  381. void truncate(const size_t n)
  382. {
  383. for (size_t i=n; i < bufferLen; i++)
  384. buffer[i] = '\0';
  385. }
  386. void toBasic()
  387. {
  388. for (size_t i=0; i < bufferLen; i++)
  389. {
  390. if (buffer[i] >= '0' && buffer[i] <= '9')
  391. continue;
  392. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  393. continue;
  394. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  395. continue;
  396. if (buffer[i] == '_')
  397. continue;
  398. buffer[i] = '_';
  399. }
  400. }
  401. void toLower()
  402. {
  403. static const char charDiff = 'a' - 'A';
  404. for (size_t i=0; i < bufferLen; i++)
  405. {
  406. if (buffer[i] >= 'A' && buffer[i] <= 'Z')
  407. buffer[i] += charDiff;
  408. }
  409. }
  410. void toUpper()
  411. {
  412. static const char charDiff = 'a' - 'A';
  413. for (size_t i=0; i < bufferLen; i++)
  414. {
  415. if (buffer[i] >= 'a' && buffer[i] <= 'z')
  416. buffer[i] -= charDiff;
  417. }
  418. }
  419. // ---------------------------------------------
  420. // public operators
  421. operator const char*() const
  422. {
  423. return buffer;
  424. }
  425. char& operator[](const size_t pos)
  426. {
  427. return buffer[pos];
  428. }
  429. bool operator==(const char* const strBuf) const
  430. {
  431. return (strBuf != nullptr && std::strcmp(buffer, strBuf) == 0);
  432. }
  433. bool operator==(const CarlaString& str) const
  434. {
  435. return operator==(str.buffer);
  436. }
  437. bool operator!=(const char* const strBuf) const
  438. {
  439. return !operator==(strBuf);
  440. }
  441. bool operator!=(const CarlaString& str) const
  442. {
  443. return !operator==(str.buffer);
  444. }
  445. CarlaString& operator=(const char* const strBuf)
  446. {
  447. _dup(strBuf);
  448. return *this;
  449. }
  450. CarlaString& operator=(const CarlaString& str)
  451. {
  452. return operator=(str.buffer);
  453. }
  454. CarlaString& operator+=(const char* const strBuf)
  455. {
  456. const size_t newBufSize = std::strlen(buffer) + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  457. char newBuf[newBufSize];
  458. std::strcpy(newBuf, buffer);
  459. std::strcat(newBuf, strBuf);
  460. _dup(newBuf, newBufSize);
  461. return *this;
  462. }
  463. CarlaString& operator+=(const CarlaString& str)
  464. {
  465. return operator+=(str.buffer);
  466. }
  467. CarlaString operator+(const char* const strBuf)
  468. {
  469. const size_t newBufSize = std::strlen(buffer) + ((strBuf != nullptr) ? std::strlen(strBuf) : 0) + 1;
  470. char newBuf[newBufSize];
  471. std::strcpy(newBuf, buffer);
  472. std::strcat(newBuf, strBuf);
  473. return CarlaString(newBuf);
  474. }
  475. CarlaString operator+(const CarlaString& str)
  476. {
  477. return operator+(str.buffer);
  478. }
  479. // ---------------------------------------------
  480. private:
  481. char* buffer;
  482. size_t bufferLen;
  483. bool firstInit;
  484. void _init()
  485. {
  486. buffer = nullptr;
  487. bufferLen = 0;
  488. firstInit = true;
  489. }
  490. // allocate string strBuf if not null
  491. // size > 0 only if strBuf is valid
  492. void _dup(const char* const strBuf, const size_t size = 0)
  493. {
  494. if (strBuf != nullptr)
  495. {
  496. // don't recreate string if contents match
  497. if (firstInit || std::strcmp(buffer, strBuf) != 0)
  498. {
  499. if (! firstInit)
  500. {
  501. CARLA_ASSERT(buffer);
  502. delete[] buffer;
  503. }
  504. bufferLen = (size > 0) ? size : std::strlen(strBuf);
  505. buffer = new char[bufferLen];
  506. std::strcpy(buffer, strBuf);
  507. firstInit = false;
  508. }
  509. }
  510. else
  511. {
  512. CARLA_ASSERT(size == 0);
  513. // don't recreate null string
  514. if (firstInit || bufferLen != 0)
  515. {
  516. if (! firstInit)
  517. {
  518. CARLA_ASSERT(buffer);
  519. delete[] buffer;
  520. }
  521. bufferLen = 0;
  522. buffer = new char[1];
  523. buffer[0] = 0;
  524. firstInit = false;
  525. }
  526. }
  527. }
  528. CARLA_LEAK_DETECTOR(CarlaString)
  529. CARLA_PREVENT_HEAP_ALLOCATION
  530. };
  531. static inline
  532. CarlaString operator+(const char* const strBufBefore, const CarlaString& strAfter)
  533. {
  534. const char* const strBufAfter = (const char*)strAfter;
  535. const size_t newBufSize = ((strBufBefore != nullptr) ? std::strlen(strBufBefore) : 0) + std::strlen(strBufAfter) + 1;
  536. char newBuf[newBufSize];
  537. std::strcpy(newBuf, strBufBefore);
  538. std::strcat(newBuf, strBufAfter);
  539. return CarlaString(newBuf);
  540. }
  541. // -------------------------------------------------
  542. #endif // __CARLA_UTILS_HPP__