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.

606 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. static inline
  330. int carla_strcasecmp(const char* const str1, const char* const str2) noexcept
  331. {
  332. return ::StrCmpIA(str1, str2);
  333. }
  334. static inline
  335. const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
  336. {
  337. return ::StrStrIA(haystack, needle);
  338. }
  339. #else
  340. static inline
  341. ssize_t carla_strcasecmp(const char* const str1, const char* const str2) noexcept
  342. {
  343. return ::strcasecmp(str1, str2);
  344. }
  345. static inline
  346. const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
  347. {
  348. return ::strcasestr(haystack, needle);
  349. }
  350. #endif
  351. // --------------------------------------------------------------------------------------------------------------------
  352. // memory functions
  353. /*
  354. * Add array values to another array.
  355. */
  356. template<typename T>
  357. static inline
  358. void carla_add(T dest[], const T src[], const std::size_t count) noexcept
  359. {
  360. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  361. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  362. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  363. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  364. for (std::size_t i=0; i<count; ++i)
  365. dest[i] += src[i];
  366. }
  367. /*
  368. * Add array values to another array, with a multiplication factor.
  369. */
  370. template<typename T>
  371. static inline
  372. void carla_addWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
  373. {
  374. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  375. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  376. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  377. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  378. for (std::size_t i=0; i<count; ++i)
  379. dest[i] += src[i] * multiplier;
  380. }
  381. /*
  382. * Copy array values to another array.
  383. */
  384. template<typename T>
  385. static inline
  386. void carla_copy(T dest[], const T src[], const std::size_t count) noexcept
  387. {
  388. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  389. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  390. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  391. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  392. std::memcpy(dest, src, count*sizeof(T));
  393. }
  394. /*
  395. * Copy array values to another array, with a multiplication factor.
  396. */
  397. template<typename T>
  398. static inline
  399. void carla_copyWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
  400. {
  401. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  402. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  403. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  404. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  405. for (std::size_t i=0; i<count; ++i)
  406. dest[i] = src[i] * multiplier;
  407. }
  408. /*
  409. * Fill an array with a fixed value.
  410. */
  411. template<typename T>
  412. static inline
  413. void carla_fill(T data[], const T& value, const std::size_t count) noexcept
  414. {
  415. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  416. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  417. if (value == 0)
  418. {
  419. std::memset(data, 0, count*sizeof(T));
  420. }
  421. else
  422. {
  423. for (std::size_t i=0; i<count; ++i)
  424. data[i] = value;
  425. }
  426. }
  427. /*
  428. * Multiply an array with a fixed value.
  429. */
  430. template<typename T>
  431. static inline
  432. void carla_multiply(T data[], const T& multiplier, const std::size_t count) noexcept
  433. {
  434. CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
  435. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  436. if (multiplier == 0)
  437. {
  438. std::memset(data, 0, count*sizeof(T));
  439. }
  440. else
  441. {
  442. for (std::size_t i=0; i<count; ++i)
  443. data[i] *= multiplier;
  444. }
  445. }
  446. /*
  447. * Clear a byte array.
  448. */
  449. static inline
  450. void carla_zeroBytes(uint8_t bytes[], const std::size_t count) noexcept
  451. {
  452. CARLA_SAFE_ASSERT_RETURN(bytes != nullptr,);
  453. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  454. std::memset(bytes, 0, count*sizeof(uint8_t));
  455. }
  456. /*
  457. * Clear a char array.
  458. */
  459. static inline
  460. void carla_zeroChars(char chars[], const std::size_t count) noexcept
  461. {
  462. CARLA_SAFE_ASSERT_RETURN(chars != nullptr,);
  463. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  464. std::memset(chars, 0, count*sizeof(char));
  465. }
  466. /*
  467. * Clear a pointer array.
  468. */
  469. template<typename T>
  470. static inline
  471. void carla_zeroPointers(T* ptrs[], const std::size_t count) noexcept
  472. {
  473. CARLA_SAFE_ASSERT_RETURN(ptrs != nullptr,);
  474. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  475. std::memset(ptrs, 0, count*sizeof(T*));
  476. }
  477. /*
  478. * Clear a single struct.
  479. */
  480. template <typename T>
  481. static inline
  482. void carla_zeroStruct(T& s) noexcept
  483. {
  484. std::memset(&s, 0, sizeof(T));
  485. }
  486. /*
  487. * Clear a struct array.
  488. */
  489. template <typename T>
  490. static inline
  491. void carla_zeroStructs(T structs[], const std::size_t count) noexcept
  492. {
  493. CARLA_SAFE_ASSERT_RETURN(structs != nullptr,);
  494. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  495. std::memset(structs, 0, count*sizeof(T));
  496. }
  497. /*
  498. * Copy a single struct.
  499. */
  500. template <typename T>
  501. static inline
  502. void carla_copyStruct(T& dest, const T& src) noexcept
  503. {
  504. std::memcpy(&dest, &src, sizeof(T));
  505. }
  506. /*
  507. * Copy a struct array.
  508. */
  509. template <typename T>
  510. static inline
  511. void carla_copyStructs(T dest[], const T src[], const std::size_t count) noexcept
  512. {
  513. CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
  514. CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
  515. CARLA_SAFE_ASSERT_RETURN(dest != src,);
  516. CARLA_SAFE_ASSERT_RETURN(count > 0,);
  517. std::memcpy(dest, src, count*sizeof(T));
  518. }
  519. // --------------------------------------------------------------------------------------------------------------------
  520. #endif // CARLA_UTILS_HPP_INCLUDED