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.

610 lines
15KB

  1. // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #ifndef CARLA_UTILS_HPP_INCLUDED
  4. #define CARLA_UTILS_HPP_INCLUDED
  5. #include "CarlaDefines.h"
  6. #include <cassert>
  7. #include <cstdarg>
  8. #include <cstdio>
  9. #include <cstdlib>
  10. #include <cstring>
  11. #ifdef CARLA_PROPER_CPP11_SUPPORT
  12. # ifdef __GNUC__
  13. # include <cxxabi.h>
  14. # endif
  15. # include <cstdint>
  16. #else
  17. # include <stdint.h>
  18. #endif
  19. #ifdef CARLA_OS_WIN
  20. # ifndef NOMINMAX
  21. # define NOMINMAX
  22. # endif
  23. # define WIN32_LEAN_AND_MEAN 1
  24. # include <shlwapi.h>
  25. # include <winsock2.h>
  26. # include <windows.h>
  27. #else
  28. # include <strings.h>
  29. # include <unistd.h>
  30. #endif
  31. // --------------------------------------------------------------------------------------------------------------------
  32. // misc functions
  33. /*
  34. * Return "true" or "false" according to yesNo.
  35. */
  36. static inline
  37. const char* bool2str(const bool yesNo) noexcept
  38. {
  39. return yesNo ? "true" : "false";
  40. }
  41. /*
  42. * Set a string as empty/null.
  43. */
  44. static inline
  45. void nullStrBuf(char* const strBuf) noexcept
  46. {
  47. strBuf[0] = '\0';
  48. }
  49. /*
  50. * Dummy function.
  51. */
  52. static inline
  53. void pass() noexcept {}
  54. // --------------------------------------------------------------------------------------------------------------------
  55. // string print functions
  56. /*
  57. * Internal noexcept-safe fopen function.
  58. */
  59. static inline
  60. FILE* __carla_fopen(const char* const filename, FILE* const fallback) noexcept
  61. {
  62. #ifdef CARLA_OS_LINUX
  63. if (std::getenv("CARLA_CAPTURE_CONSOLE_OUTPUT") == nullptr)
  64. return fallback;
  65. FILE* ret = nullptr;
  66. try {
  67. ret = std::fopen(filename, "a+");
  68. } CARLA_CATCH_UNWIND catch (...) {}
  69. if (ret == nullptr)
  70. ret = fallback;
  71. return ret;
  72. #else
  73. return fallback;
  74. // unused
  75. (void)filename;
  76. #endif
  77. }
  78. /*
  79. * Print a string to stdout with newline (gray color).
  80. * Does nothing if DEBUG is not defined.
  81. */
  82. #ifndef DEBUG
  83. # define carla_debug(...)
  84. #else
  85. static inline
  86. void carla_debug(const char* const fmt, ...) noexcept
  87. {
  88. static FILE* const output = __carla_fopen("/tmp/carla.debug.log", stdout);
  89. try {
  90. va_list args;
  91. va_start(args, fmt);
  92. if (output == stdout)
  93. {
  94. #ifdef CARLA_OS_MAC
  95. std::fprintf(output, "\x1b[37;1m[carla] ");
  96. #else
  97. std::fprintf(output, "\x1b[30;1m[carla] ");
  98. #endif
  99. std::vfprintf(output, fmt, args);
  100. std::fprintf(output, "\x1b[0m\n");
  101. }
  102. else
  103. {
  104. std::fprintf(output, "[carla] ");
  105. std::vfprintf(output, fmt, args);
  106. std::fprintf(output, "\n");
  107. }
  108. std::fflush(output);
  109. va_end(args);
  110. } CARLA_CATCH_UNWIND catch (...) {}
  111. }
  112. #endif
  113. /*
  114. * Print a string to stdout with newline.
  115. */
  116. static inline
  117. void carla_stdout(const char* const fmt, ...) noexcept
  118. {
  119. static FILE* const output = __carla_fopen("/tmp/carla.stdout.log", stdout);
  120. try {
  121. va_list args;
  122. va_start(args, fmt);
  123. std::fprintf(output, "[carla] ");
  124. std::vfprintf(output, fmt, args);
  125. std::fprintf(output, "\n");
  126. #ifndef DEBUG
  127. if (output != stdout)
  128. #endif
  129. std::fflush(output);
  130. va_end(args);
  131. } CARLA_CATCH_UNWIND catch (...) {}
  132. }
  133. /*
  134. * Print a string to stderr with newline.
  135. */
  136. static inline
  137. void carla_stderr(const char* const fmt, ...) noexcept
  138. {
  139. static FILE* const output = __carla_fopen("/tmp/carla.stderr.log", stderr);
  140. try {
  141. va_list args;
  142. va_start(args, fmt);
  143. std::fprintf(output, "[carla] ");
  144. std::vfprintf(output, fmt, args);
  145. std::fprintf(output, "\n");
  146. #ifndef DEBUG
  147. if (output != stderr)
  148. #endif
  149. std::fflush(output);
  150. va_end(args);
  151. } CARLA_CATCH_UNWIND catch (...) {}
  152. }
  153. /*
  154. * Print a string to stderr with newline (red color).
  155. */
  156. static inline
  157. void carla_stderr2(const char* const fmt, ...) noexcept
  158. {
  159. static FILE* const output = __carla_fopen("/tmp/carla.stderr2.log", stderr);
  160. try {
  161. va_list args;
  162. va_start(args, fmt);
  163. if (output == stderr)
  164. {
  165. std::fprintf(output, "\x1b[31m[carla] ");
  166. std::vfprintf(output, fmt, args);
  167. std::fprintf(output, "\x1b[0m\n");
  168. }
  169. else
  170. {
  171. std::fprintf(output, "[carla] ");
  172. std::vfprintf(output, fmt, args);
  173. std::fprintf(output, "\n");
  174. }
  175. std::fflush(output);
  176. va_end(args);
  177. } CARLA_CATCH_UNWIND catch (...) {}
  178. }
  179. // --------------------------------------------------------------------------------------------------------------------
  180. // carla_safe_assert*
  181. /*
  182. * Print a safe assertion error message.
  183. */
  184. static inline
  185. void carla_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
  186. {
  187. carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
  188. }
  189. /*
  190. * Print a safe assertion error message, with 1 extra signed integer value.
  191. */
  192. static inline
  193. void carla_safe_assert_int(const char* const assertion, const char* const file,
  194. const int line, const int value) noexcept
  195. {
  196. carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
  197. }
  198. /*
  199. * Print a safe assertion error message, with 1 extra unsigned integer value.
  200. */
  201. static inline
  202. void carla_safe_assert_uint(const char* const assertion, const char* const file,
  203. const int line, const uint value) noexcept
  204. {
  205. carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
  206. }
  207. /*
  208. * Print a safe assertion error message, with 2 extra signed integer values.
  209. */
  210. static inline
  211. void carla_safe_assert_int2(const char* const assertion, const char* const file,
  212. const int line, const int v1, const int v2) noexcept
  213. {
  214. carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
  215. }
  216. /*
  217. * Print a safe assertion error message, with 2 extra unsigned integer values.
  218. */
  219. static inline
  220. void carla_safe_assert_uint2(const char* const assertion, const char* const file,
  221. const int line, const uint v1, const uint v2) noexcept
  222. {
  223. carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
  224. }
  225. /*
  226. * Print a safe assertion error message, with a custom error message.
  227. */
  228. static inline
  229. void carla_custom_safe_assert(const char* const message,
  230. const char* const assertion, const char* const file, const int line) noexcept
  231. {
  232. carla_stderr2("Carla assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
  233. }
  234. // --------------------------------------------------------------------------------------------------------------------
  235. // carla_safe_exception*
  236. /*
  237. * Print a safe exception error message.
  238. */
  239. static inline
  240. void carla_safe_exception(const char* const exception, const char* const file, const int line) noexcept
  241. {
  242. carla_stderr2("Carla exception caught: \"%s\" in file %s, line %i", exception, file, line);
  243. }
  244. // --------------------------------------------------------------------------------------------------------------------
  245. // carla_setenv
  246. /*
  247. * Set environment variable 'key' to 'value'.
  248. */
  249. static inline
  250. void carla_setenv(const char* const key, const char* const value) noexcept
  251. {
  252. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  253. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  254. #ifdef CARLA_OS_WIN
  255. try {
  256. ::SetEnvironmentVariableA(key, value);
  257. } CARLA_SAFE_EXCEPTION("carla_setenv");
  258. #else
  259. ::setenv(key, value, 1);
  260. #endif
  261. }
  262. /*
  263. * Unset environment variable 'key'.
  264. */
  265. static inline
  266. void carla_unsetenv(const char* const key) noexcept
  267. {
  268. CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
  269. #ifdef CARLA_OS_WIN
  270. try {
  271. ::SetEnvironmentVariableA(key, nullptr);
  272. } CARLA_SAFE_EXCEPTION("carla_unsetenv");
  273. #else
  274. ::unsetenv(key);
  275. #endif
  276. }
  277. // --------------------------------------------------------------------------------------------------------------------
  278. // carla_strdup
  279. /*
  280. * Custom 'strdup' function.
  281. * Returned value is always valid, and must be freed with "delete[] var".
  282. * May throw.
  283. */
  284. static inline
  285. const char* carla_strdup(const char* const strBuf)
  286. {
  287. CARLA_SAFE_ASSERT(strBuf != nullptr);
  288. const std::size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0;
  289. char* const buffer = new char[bufferLen+1];
  290. if (bufferLen > 0)
  291. std::memcpy(buffer, strBuf, bufferLen);
  292. buffer[bufferLen] = '\0';
  293. return buffer;
  294. }
  295. /*
  296. * Custom 'strdup' function.
  297. * Calls "std::free(strBuf)".
  298. * Returned value is always valid, and must be freed with "delete[] var".
  299. * May throw.
  300. */
  301. static inline
  302. const char* carla_strdup_free(char* const strBuf)
  303. {
  304. const char* const buffer = carla_strdup(strBuf);
  305. std::free(strBuf);
  306. return buffer;
  307. }
  308. /*
  309. * Custom 'strdup' function, safe version.
  310. * Returned value may be null. It must be freed with "delete[] var".
  311. */
  312. static inline
  313. const char* carla_strdup_safe(const char* const strBuf) noexcept
  314. {
  315. CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, nullptr);
  316. const std::size_t bufferLen = std::strlen(strBuf);
  317. char* buffer;
  318. try {
  319. buffer = new char[bufferLen+1];
  320. } CARLA_SAFE_EXCEPTION_RETURN("carla_strdup_safe", nullptr);
  321. if (bufferLen > 0)
  322. std::memcpy(buffer, strBuf, bufferLen);
  323. buffer[bufferLen] = '\0';
  324. return buffer;
  325. }
  326. // --------------------------------------------------------------------------------------------------------------------
  327. // carla_strcase*
  328. #ifdef CARLA_OS_WIN
  329. # ifdef _MSC_VER
  330. # pragma comment(lib, "shlwapi.lib")
  331. # endif
  332. static inline
  333. int carla_strcasecmp(const char* const str1, const char* const str2) noexcept
  334. {
  335. return ::StrCmpIA(str1, str2);
  336. }
  337. static inline
  338. const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
  339. {
  340. return ::StrStrIA(haystack, needle);
  341. }
  342. #else
  343. static inline
  344. ssize_t carla_strcasecmp(const char* const str1, const char* const str2) noexcept
  345. {
  346. return ::strcasecmp(str1, str2);
  347. }
  348. static inline
  349. const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
  350. {
  351. return ::strcasestr(haystack, needle);
  352. }
  353. #endif
  354. // --------------------------------------------------------------------------------------------------------------------
  355. // memory functions
  356. /*
  357. * Add array values to another array.
  358. */
  359. template<typename T>
  360. static inline
  361. void carla_add(T dest[], const T src[], const std::size_t count) noexcept
  362. {
  363. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  364. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  365. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  366. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  367. for (std::size_t i=0; i<count; ++i)
  368. dest[i] += src[i];
  369. }
  370. /*
  371. * Add array values to another array, with a multiplication factor.
  372. */
  373. template<typename T>
  374. static inline
  375. void carla_addWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
  376. {
  377. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  378. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  379. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  380. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  381. for (std::size_t i=0; i<count; ++i)
  382. dest[i] += src[i] * multiplier;
  383. }
  384. /*
  385. * Copy array values to another array.
  386. */
  387. template<typename T>
  388. static inline
  389. void carla_copy(T dest[], const T src[], const std::size_t count) noexcept
  390. {
  391. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  392. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  393. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  394. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  395. std::memcpy(dest, src, count*sizeof(T));
  396. }
  397. /*
  398. * Copy array values to another array, with a multiplication factor.
  399. */
  400. template<typename T>
  401. static inline
  402. void carla_copyWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
  403. {
  404. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  405. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  406. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  407. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  408. for (std::size_t i=0; i<count; ++i)
  409. dest[i] = src[i] * multiplier;
  410. }
  411. /*
  412. * Fill an array with a fixed value.
  413. */
  414. template<typename T>
  415. static inline
  416. void carla_fill(T data[], const T& value, const std::size_t count) noexcept
  417. {
  418. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  419. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  420. if (value == 0)
  421. {
  422. std::memset(data, 0, count*sizeof(T));
  423. }
  424. else
  425. {
  426. for (std::size_t i=0; i<count; ++i)
  427. data[i] = value;
  428. }
  429. }
  430. /*
  431. * Multiply an array with a fixed value.
  432. */
  433. template<typename T>
  434. static inline
  435. void carla_multiply(T data[], const T& multiplier, const std::size_t count) noexcept
  436. {
  437. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  438. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  439. if (multiplier == 0)
  440. {
  441. std::memset(data, 0, count*sizeof(T));
  442. }
  443. else
  444. {
  445. for (std::size_t i=0; i<count; ++i)
  446. data[i] *= multiplier;
  447. }
  448. }
  449. /*
  450. * Clear a byte array.
  451. */
  452. static inline
  453. void carla_zeroBytes(uint8_t bytes[], const std::size_t count) noexcept
  454. {
  455. CARLA_SAFE_ASSERT_RETURN(bytes != nullptr,);
  456. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  457. std::memset(bytes, 0, count*sizeof(uint8_t));
  458. }
  459. /*
  460. * Clear a char array.
  461. */
  462. static inline
  463. void carla_zeroChars(char chars[], const std::size_t count) noexcept
  464. {
  465. CARLA_SAFE_ASSERT_RETURN(chars != nullptr,);
  466. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  467. std::memset(chars, 0, count*sizeof(char));
  468. }
  469. /*
  470. * Clear a pointer array.
  471. */
  472. template<typename T>
  473. static inline
  474. void carla_zeroPointers(T* ptrs[], const std::size_t count) noexcept
  475. {
  476. CARLA_SAFE_ASSERT_RETURN(ptrs != nullptr,);
  477. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  478. std::memset(ptrs, 0, count*sizeof(T*));
  479. }
  480. /*
  481. * Clear a single struct.
  482. */
  483. template <typename T>
  484. static inline
  485. void carla_zeroStruct(T& s) noexcept
  486. {
  487. std::memset(&s, 0, sizeof(T));
  488. }
  489. /*
  490. * Clear a struct array.
  491. */
  492. template <typename T>
  493. static inline
  494. void carla_zeroStructs(T structs[], const std::size_t count) noexcept
  495. {
  496. CARLA_SAFE_ASSERT_RETURN(structs != nullptr,);
  497. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  498. std::memset(structs, 0, count*sizeof(T));
  499. }
  500. /*
  501. * Copy a single struct.
  502. */
  503. template <typename T>
  504. static inline
  505. void carla_copyStruct(T& dest, const T& src) noexcept
  506. {
  507. std::memcpy(&dest, &src, sizeof(T));
  508. }
  509. /*
  510. * Copy a struct array.
  511. */
  512. template <typename T>
  513. static inline
  514. void carla_copyStructs(T dest[], const T src[], const std::size_t count) noexcept
  515. {
  516. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  517. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  518. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  519. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  520. std::memcpy(dest, src, count*sizeof(T));
  521. }
  522. // --------------------------------------------------------------------------------------------------------------------
  523. #endif // CARLA_UTILS_HPP_INCLUDED