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.

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