Cleanup
[carla.git] / source / utils / CarlaUtils.hpp
blob5962e5539c8fc2b42b39559558267005422dd6ad
1 // SPDX-FileCopyrightText: 2011-2024 Filipe Coelho <falktx@falktx.com>
2 // SPDX-License-Identifier: GPL-2.0-or-later
4 #ifndef CARLA_UTILS_HPP_INCLUDED
5 #define CARLA_UTILS_HPP_INCLUDED
7 #include "CarlaDefines.h"
9 #include <cassert>
10 #include <cstdarg>
11 #include <cstdio>
12 #include <cstdlib>
13 #include <cstring>
15 #ifdef CARLA_PROPER_CPP11_SUPPORT
16 # ifdef __GNUC__
17 # include <cxxabi.h>
18 # endif
19 # include <cstdint>
20 #else
21 # include <stdint.h>
22 #endif
24 #ifdef CARLA_OS_WIN
25 # ifndef NOMINMAX
26 # define NOMINMAX
27 # endif
28 # define WIN32_LEAN_AND_MEAN 1
29 # include <shlwapi.h>
30 # include <winsock2.h>
31 # include <windows.h>
32 #else
33 # include <strings.h>
34 # include <unistd.h>
35 #endif
37 // --------------------------------------------------------------------------------------------------------------------
38 // misc functions
41 * Return "true" or "false" according to yesNo.
43 static inline
44 const char* bool2str(const bool yesNo) noexcept
46 return yesNo ? "true" : "false";
50 * Set a string as empty/null.
52 static inline
53 void nullStrBuf(char* const strBuf) noexcept
55 strBuf[0] = '\0';
59 * Dummy function.
61 static inline
62 void pass() noexcept {}
64 // --------------------------------------------------------------------------------------------------------------------
65 // string print functions
68 * Internal noexcept-safe fopen function.
70 static inline
71 FILE* __carla_fopen(const char* const filename, FILE* const fallback) noexcept
73 #ifdef CARLA_OS_LINUX
74 if (std::getenv("CARLA_CAPTURE_CONSOLE_OUTPUT") == nullptr)
75 return fallback;
77 FILE* ret = nullptr;
79 try {
80 ret = std::fopen(filename, "a+");
81 } CARLA_CATCH_UNWIND catch (...) {}
83 if (ret == nullptr)
84 ret = fallback;
86 return ret;
87 #else
88 return fallback;
89 // unused
90 (void)filename;
91 #endif
95 * Print a string to stdout with newline (gray color).
96 * Does nothing if DEBUG is not defined.
98 #ifndef DEBUG
99 # define carla_debug(...)
100 #else
101 static inline
102 void carla_debug(const char* const fmt, ...) noexcept
104 static FILE* const output = __carla_fopen("/tmp/carla.debug.log", stdout);
106 try {
107 va_list args;
108 va_start(args, fmt);
110 if (output == stdout)
112 #ifdef CARLA_OS_MAC
113 std::fprintf(output, "\x1b[37;1m[carla] ");
114 #else
115 std::fprintf(output, "\x1b[30;1m[carla] ");
116 #endif
117 std::vfprintf(output, fmt, args);
118 std::fprintf(output, "\x1b[0m\n");
120 else
122 std::fprintf(output, "[carla] ");
123 std::vfprintf(output, fmt, args);
124 std::fprintf(output, "\n");
127 std::fflush(output);
128 va_end(args);
129 } CARLA_CATCH_UNWIND catch (...) {}
131 #endif
134 * Print a string to stdout with newline.
136 static inline
137 void carla_stdout(const char* const fmt, ...) noexcept
139 static FILE* const output = __carla_fopen("/tmp/carla.stdout.log", stdout);
141 try {
142 va_list args;
143 va_start(args, fmt);
144 std::fprintf(output, "[carla] ");
145 std::vfprintf(output, fmt, args);
146 std::fprintf(output, "\n");
147 #ifndef DEBUG
148 if (output != stdout)
149 #endif
150 std::fflush(output);
151 va_end(args);
152 } CARLA_CATCH_UNWIND catch (...) {}
156 * Print a string to stderr with newline.
158 static inline
159 void carla_stderr(const char* const fmt, ...) noexcept
161 static FILE* const output = __carla_fopen("/tmp/carla.stderr.log", stderr);
163 try {
164 va_list args;
165 va_start(args, fmt);
166 std::fprintf(output, "[carla] ");
167 std::vfprintf(output, fmt, args);
168 std::fprintf(output, "\n");
169 #ifndef DEBUG
170 if (output != stderr)
171 #endif
172 std::fflush(output);
173 va_end(args);
174 } CARLA_CATCH_UNWIND catch (...) {}
178 * Print a string to stderr with newline (red color).
180 static inline
181 void carla_stderr2(const char* const fmt, ...) noexcept
183 static FILE* const output = __carla_fopen("/tmp/carla.stderr2.log", stderr);
185 try {
186 va_list args;
187 va_start(args, fmt);
189 if (output == stderr)
191 std::fprintf(output, "\x1b[31m[carla] ");
192 std::vfprintf(output, fmt, args);
193 std::fprintf(output, "\x1b[0m\n");
195 else
197 std::fprintf(output, "[carla] ");
198 std::vfprintf(output, fmt, args);
199 std::fprintf(output, "\n");
202 std::fflush(output);
203 va_end(args);
204 } CARLA_CATCH_UNWIND catch (...) {}
207 // --------------------------------------------------------------------------------------------------------------------
208 // carla_safe_assert*
211 * Print a safe assertion error message.
213 static inline
214 void carla_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
216 carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
220 * Print a safe assertion error message, with 1 extra signed integer value.
222 static inline
223 void carla_safe_assert_int(const char* const assertion, const char* const file,
224 const int line, const int value) noexcept
226 carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
230 * Print a safe assertion error message, with 1 extra unsigned integer value.
232 static inline
233 void carla_safe_assert_uint(const char* const assertion, const char* const file,
234 const int line, const uint value) noexcept
236 carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
240 * Print a safe assertion error message, with 2 extra signed integer values.
242 static inline
243 void carla_safe_assert_int2(const char* const assertion, const char* const file,
244 const int line, const int v1, const int v2) noexcept
246 carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
250 * Print a safe assertion error message, with 2 extra unsigned integer values.
252 static inline
253 void carla_safe_assert_uint2(const char* const assertion, const char* const file,
254 const int line, const uint v1, const uint v2) noexcept
256 carla_stderr2("Carla assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
260 * Print a safe assertion error message, with a custom error message.
262 static inline
263 void carla_custom_safe_assert(const char* const message,
264 const char* const assertion, const char* const file, const int line) noexcept
266 carla_stderr2("Carla assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
269 // --------------------------------------------------------------------------------------------------------------------
270 // carla_safe_exception*
273 * Print a safe exception error message.
275 static inline
276 void carla_safe_exception(const char* const exception, const char* const file, const int line) noexcept
278 carla_stderr2("Carla exception caught: \"%s\" in file %s, line %i", exception, file, line);
281 // --------------------------------------------------------------------------------------------------------------------
282 // carla_setenv
285 * Set environment variable 'key' to 'value'.
287 static inline
288 void carla_setenv(const char* const key, const char* const value) noexcept
290 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
291 CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
293 #ifdef CARLA_OS_WIN
294 try {
295 ::SetEnvironmentVariableA(key, value);
296 } CARLA_SAFE_EXCEPTION("carla_setenv");
297 #else
298 ::setenv(key, value, 1);
299 #endif
303 * Unset environment variable 'key'.
305 static inline
306 void carla_unsetenv(const char* const key) noexcept
308 CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
310 #ifdef CARLA_OS_WIN
311 try {
312 ::SetEnvironmentVariableA(key, nullptr);
313 } CARLA_SAFE_EXCEPTION("carla_unsetenv");
314 #else
315 ::unsetenv(key);
316 #endif
319 // --------------------------------------------------------------------------------------------------------------------
320 // carla_strdup
323 * Custom 'strdup' function.
324 * Returned value is always valid, and must be freed with "delete[] var".
325 * May throw.
327 static inline
328 const char* carla_strdup(const char* const strBuf)
330 CARLA_SAFE_ASSERT(strBuf != nullptr);
332 const std::size_t bufferLen = (strBuf != nullptr) ? std::strlen(strBuf) : 0;
333 char* const buffer = new char[bufferLen+1];
335 if (bufferLen > 0)
336 std::memcpy(buffer, strBuf, bufferLen);
338 buffer[bufferLen] = '\0';
340 return buffer;
344 * Custom 'strdup' function.
345 * Calls "std::free(strBuf)".
346 * Returned value is always valid, and must be freed with "delete[] var".
347 * May throw.
349 static inline
350 const char* carla_strdup_free(char* const strBuf)
352 const char* const buffer = carla_strdup(strBuf);
353 std::free(strBuf);
354 return buffer;
358 * Custom 'strdup' function, safe version.
359 * Returned value may be null. It must be freed with "delete[] var".
361 static inline
362 const char* carla_strdup_safe(const char* const strBuf) noexcept
364 CARLA_SAFE_ASSERT_RETURN(strBuf != nullptr, nullptr);
366 const std::size_t bufferLen = std::strlen(strBuf);
367 char* buffer;
369 try {
370 buffer = new char[bufferLen+1];
371 } CARLA_SAFE_EXCEPTION_RETURN("carla_strdup_safe", nullptr);
373 if (bufferLen > 0)
374 std::memcpy(buffer, strBuf, bufferLen);
376 buffer[bufferLen] = '\0';
378 return buffer;
381 // --------------------------------------------------------------------------------------------------------------------
382 // carla_strcase*
384 #ifdef CARLA_OS_WIN
385 # ifdef _MSC_VER
386 # pragma comment(lib, "shlwapi.lib")
387 # endif
389 static inline
390 int carla_strcasecmp(const char* const str1, const char* const str2) noexcept
392 return ::StrCmpIA(str1, str2);
395 static inline
396 const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
398 return ::StrStrIA(haystack, needle);
400 #else
401 static inline
402 ssize_t carla_strcasecmp(const char* const str1, const char* const str2) noexcept
404 return ::strcasecmp(str1, str2);
407 static inline
408 const char* carla_strcasestr(const char* const haystack, const char* const needle) noexcept
410 return ::strcasestr(haystack, needle);
412 #endif
414 // --------------------------------------------------------------------------------------------------------------------
415 // memory functions
418 * Add array values to another array.
420 template<typename T>
421 static inline
422 void carla_add(T dest[], const T src[], const std::size_t count) noexcept
424 CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
425 CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
426 CARLA_SAFE_ASSERT_RETURN(dest != src,);
427 CARLA_SAFE_ASSERT_RETURN(count > 0,);
429 for (std::size_t i=0; i<count; ++i)
430 dest[i] += src[i];
434 * Add array values to another array, with a multiplication factor.
436 template<typename T>
437 static inline
438 void carla_addWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
440 CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
441 CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
442 CARLA_SAFE_ASSERT_RETURN(dest != src,);
443 CARLA_SAFE_ASSERT_RETURN(count > 0,);
445 for (std::size_t i=0; i<count; ++i)
446 dest[i] += src[i] * multiplier;
450 * Copy array values to another array.
452 template<typename T>
453 static inline
454 void carla_copy(T dest[], const T src[], const std::size_t count) noexcept
456 CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
457 CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
458 CARLA_SAFE_ASSERT_RETURN(dest != src,);
459 CARLA_SAFE_ASSERT_RETURN(count > 0,);
461 std::memcpy(dest, src, count*sizeof(T));
465 * Copy array values to another array, with a multiplication factor.
467 template<typename T>
468 static inline
469 void carla_copyWithMultiply(T dest[], const T src[], const T& multiplier, const std::size_t count) noexcept
471 CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
472 CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
473 CARLA_SAFE_ASSERT_RETURN(dest != src,);
474 CARLA_SAFE_ASSERT_RETURN(count > 0,);
476 for (std::size_t i=0; i<count; ++i)
477 dest[i] = src[i] * multiplier;
481 * Fill an array with a fixed value.
483 template<typename T>
484 static inline
485 void carla_fill(T data[], const T& value, const std::size_t count) noexcept
487 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
488 CARLA_SAFE_ASSERT_RETURN(count > 0,);
490 if (value == 0)
492 std::memset(data, 0, count*sizeof(T));
494 else
496 for (std::size_t i=0; i<count; ++i)
497 data[i] = value;
502 * Multiply an array with a fixed value.
504 template<typename T>
505 static inline
506 void carla_multiply(T data[], const T& multiplier, const std::size_t count) noexcept
508 CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
509 CARLA_SAFE_ASSERT_RETURN(count > 0,);
511 if (multiplier == 0)
513 std::memset(data, 0, count*sizeof(T));
515 else
517 for (std::size_t i=0; i<count; ++i)
518 data[i] *= multiplier;
523 * Clear a byte array.
525 static inline
526 void carla_zeroBytes(uint8_t bytes[], const std::size_t count) noexcept
528 CARLA_SAFE_ASSERT_RETURN(bytes != nullptr,);
529 CARLA_SAFE_ASSERT_RETURN(count > 0,);
531 std::memset(bytes, 0, count*sizeof(uint8_t));
535 * Clear a char array.
537 static inline
538 void carla_zeroChars(char chars[], const std::size_t count) noexcept
540 CARLA_SAFE_ASSERT_RETURN(chars != nullptr,);
541 CARLA_SAFE_ASSERT_RETURN(count > 0,);
543 std::memset(chars, 0, count*sizeof(char));
547 * Clear a pointer array.
549 template<typename T>
550 static inline
551 void carla_zeroPointers(T* ptrs[], const std::size_t count) noexcept
553 CARLA_SAFE_ASSERT_RETURN(ptrs != nullptr,);
554 CARLA_SAFE_ASSERT_RETURN(count > 0,);
556 std::memset(ptrs, 0, count*sizeof(T*));
560 * Clear a single struct.
562 template <typename T>
563 static inline
564 void carla_zeroStruct(T& s) noexcept
566 std::memset(&s, 0, sizeof(T));
570 * Clear a struct array.
572 template <typename T>
573 static inline
574 void carla_zeroStructs(T structs[], const std::size_t count) noexcept
576 CARLA_SAFE_ASSERT_RETURN(structs != nullptr,);
577 CARLA_SAFE_ASSERT_RETURN(count > 0,);
579 std::memset(structs, 0, count*sizeof(T));
583 * Copy a single struct.
585 template <typename T>
586 static inline
587 void carla_copyStruct(T& dest, const T& src) noexcept
589 std::memcpy(&dest, &src, sizeof(T));
593 * Copy a struct array.
595 template <typename T>
596 static inline
597 void carla_copyStructs(T dest[], const T src[], const std::size_t count) noexcept
599 CARLA_SAFE_ASSERT_RETURN(dest != nullptr,);
600 CARLA_SAFE_ASSERT_RETURN(src != nullptr,);
601 CARLA_SAFE_ASSERT_RETURN(dest != src,);
602 CARLA_SAFE_ASSERT_RETURN(count > 0,);
604 std::memcpy(dest, src, count*sizeof(T));
607 // --------------------------------------------------------------------------------------------------------------------
609 #endif // CARLA_UTILS_HPP_INCLUDED