DISTRHO Plugin Framework
DistrhoUtils.hpp
1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2024 Filipe Coelho <falktx@falktx.com>
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any purpose with
6  * or without fee is hereby granted, provided that the above copyright notice and this
7  * permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
10  * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
11  * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
13  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #ifndef DISTRHO_UTILS_HPP_INCLUDED
18 #define DISTRHO_UTILS_HPP_INCLUDED
19 
20 #include "src/DistrhoDefines.h"
21 
22 #include <cstdarg>
23 #include <cstdio>
24 #include <cstdlib>
25 #include <cstring>
26 
27 #include <cmath>
28 #include <limits>
29 
30 #ifdef DISTRHO_PROPER_CPP11_SUPPORT
31 # include <cstdint>
32 #else
33 # include <stdint.h>
34 #endif
35 
36 #if defined(DISTRHO_OS_WINDOWS) && defined(_MSC_VER)
37 #include <basetsd.h>
38 typedef SSIZE_T ssize_t;
39 #endif
40 
41 #if ! defined(CARLA_MATH_UTILS_HPP_INCLUDED) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT)
42 namespace std {
43 inline float fmin(float __x, float __y)
44  { return __builtin_fminf(__x, __y); }
45 inline float fmax(float __x, float __y)
46  { return __builtin_fmaxf(__x, __y); }
47 inline float rint(float __x)
48  { return __builtin_rintf(__x); }
49 inline float round(float __x)
50  { return __builtin_roundf(__x); }
51 }
52 #endif
53 
54 #ifndef M_PI
55 # define M_PI 3.14159265358979323846
56 #endif
57 
58 /* --------------------------------------------------------------------------------------------------------------------
59  * misc functions */
60 
61 /**
62  @defgroup MiscellaneousFunctions Miscellaneous functions
63 
64  @{
65  */
66 
67 /**
68  Return a 32-bit number from 4 8-bit numbers.@n
69  The return type is a int64_t for better compatibility with plugin formats that use such numbers.
70  */
71 static inline constexpr
72 int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
73 {
74  return (a << 24) | (b << 16) | (c << 8) | (d << 0);
75 }
76 
77 /**
78  Return a 32-bit number from 4 ASCII characters.
79  */
80 static inline constexpr
81 uint32_t d_cconst(const char str[4])
82 {
83  return (str[0] << 24) | (str[1] << 16) | (str[2] << 8) | str[3];
84 }
85 
86 /**
87  Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
88  */
89 static inline constexpr
90 uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
91 {
92  return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0);
93 }
94 
95 /**
96  Dummy, no-op function.
97  */
98 static inline
99 void d_pass() noexcept {}
100 
101 /** @} */
102 
103 /* --------------------------------------------------------------------------------------------------------------------
104  * string print functions */
105 
106 /**
107  @defgroup StringPrintFunctions String print functions
108 
109  @{
110  */
111 
112 /**
113  Print a string to stdout with newline (gray color).
114  Does nothing if DEBUG is not defined.
115  */
116 #ifndef DEBUG
117 # define d_debug(...)
118 #else
119 static inline
120 void d_debug(const char* const fmt, ...) noexcept
121 {
122  try {
123  va_list args;
124  va_start(args, fmt);
125  #ifdef DISTRHO_OS_MAC
126  std::fprintf(stdout, "\x1b[37;1m");
127  #else
128  std::fprintf(stdout, "\x1b[30;1m");
129  #endif
130  std::vfprintf(stdout, fmt, args);
131  std::fprintf(stdout, "\x1b[0m\n");
132  va_end(args);
133  } catch (...) {}
134 }
135 #endif
136 
137 /**
138  Print a string to stdout with newline.
139  */
140 static inline
141 void d_stdout(const char* const fmt, ...) noexcept
142 {
143  try {
144  va_list args;
145  va_start(args, fmt);
146  std::vfprintf(stdout, fmt, args);
147  std::fprintf(stdout, "\n");
148  va_end(args);
149  } catch (...) {}
150 }
151 
152 /**
153  Print a string to stderr with newline.
154  */
155 static inline
156 void d_stderr(const char* const fmt, ...) noexcept
157 {
158  try {
159  va_list args;
160  va_start(args, fmt);
161  std::vfprintf(stderr, fmt, args);
162  std::fprintf(stderr, "\n");
163  va_end(args);
164  } catch (...) {}
165 }
166 
167 /**
168  Print a string to stderr with newline (red color).
169  */
170 static inline
171 void d_stderr2(const char* const fmt, ...) noexcept
172 {
173  try {
174  va_list args;
175  va_start(args, fmt);
176  std::fprintf(stderr, "\x1b[31m");
177  std::vfprintf(stderr, fmt, args);
178  std::fprintf(stderr, "\x1b[0m\n");
179  va_end(args);
180  } catch (...) {}
181 }
182 
183 /**
184  Print a safe assertion error message.
185  */
186 static inline
187 void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
188 {
189  d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
190 }
191 
192 /**
193  Print a safe assertion error message, with 1 extra signed integer value.
194  */
195 static inline
196 void d_safe_assert_int(const char* const assertion, const char* const file,
197  const int line, const int value) noexcept
198 {
199  d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
200 }
201 
202 /**
203  Print a safe assertion error message, with 1 extra unsigned integer value.
204  */
205 static inline
206 void d_safe_assert_uint(const char* const assertion, const char* const file,
207  const int line, const uint value) noexcept
208 {
209  d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
210 }
211 
212 /**
213  Print a safe assertion error message, with 2 extra signed integer values.
214  */
215 static inline
216 void d_safe_assert_int2(const char* const assertion, const char* const file,
217  const int line, const int v1, const int v2) noexcept
218 {
219  d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
220 }
221 
222 /**
223  Print a safe assertion error message, with 2 extra unsigned integer values.
224  */
225 static inline
226 void d_safe_assert_uint2(const char* const assertion, const char* const file,
227  const int line, const uint v1, const uint v2) noexcept
228 {
229  d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
230 }
231 
232 /**
233  Print a safe assertion error message, with a custom error message.
234  */
235 static inline
236 void d_custom_safe_assert(const char* const message, const char* const assertion, const char* const file,
237  const int line) noexcept
238 {
239  d_stderr2("assertion failure: %s, condition \"%s\" in file %s, line %i", message, assertion, file, line);
240 }
241 
242 /**
243  Print a safe exception error message.
244  */
245 static inline
246 void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
247 {
248  d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
249 }
250 
251 /** @} */
252 
253 /* --------------------------------------------------------------------------------------------------------------------
254  * math functions */
255 
256 /**
257  @defgroup MathFunctions Math related functions
258 
259  @{
260  */
261 
262 /**
263  Safely compare two floating point numbers.
264  Returns true if they match.
265  */
266 template<typename T>
267 static inline constexpr
268 bool d_isEqual(const T& v1, const T& v2)
269 {
270  return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
271 }
272 
273 /**
274  Safely compare two floating point numbers.
275  Returns true if they don't match.
276  */
277 template<typename T>
278 static inline constexpr
279 bool d_isNotEqual(const T& v1, const T& v2)
280 {
281  return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
282 }
283 
284 /**
285  Safely check if a floating point number is zero.
286  */
287 template<typename T>
288 static inline constexpr
289 bool d_isZero(const T& value)
290 {
291  return std::abs(value) < std::numeric_limits<T>::epsilon();
292 }
293 
294 /**
295  Safely check if a floating point number is not zero.
296  */
297 template<typename T>
298 static inline constexpr
299 bool d_isNotZero(const T& value)
300 {
301  return std::abs(value) >= std::numeric_limits<T>::epsilon();
302 }
303 
304 /**
305  Get next power of 2.
306  */
307 static inline
308 uint32_t d_nextPowerOf2(uint32_t size) noexcept
309 {
310  DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0);
311 
312  // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
313  --size;
314  size |= size >> 1;
315  size |= size >> 2;
316  size |= size >> 4;
317  size |= size >> 8;
318  size |= size >> 16;
319  return ++size;
320 }
321 
322 /**
323  Round a floating point number to an integer.
324  Fast operation for values known to be 0 or positive.
325  */
326 template<typename T>
327 static inline constexpr
328 int32_t d_roundToIntPositive(const T& value)
329 {
330  return static_cast<int32_t>(value + static_cast<T>(0.5));
331 }
332 
333 /**
334  Round a floating point number to an unsigned integer.
335  Fast operation for values known to be 0 or positive.
336  */
337 template<typename T>
338 static inline constexpr
339 uint32_t d_roundToUnsignedInt(const T& value)
340 {
341  return static_cast<uint32_t>(value + static_cast<T>(0.5));
342 }
343 
344 /**
345  Round a floating point number to an integer.
346  Fast operation for values known to be 0 or negative.
347  */
348 template<typename T>
349 static inline constexpr
350 int32_t d_roundToIntNegative(const T& value)
351 {
352  return static_cast<int32_t>(value - static_cast<T>(0.5));
353 }
354 
355 /**
356  Round a floating point number to integer.
357  */
358 template<typename T>
359 static inline constexpr
360 int32_t d_roundToInt(const T& value)
361 {
362  return value >= 0 ? static_cast<int32_t>(value + static_cast<T>(0.5))
363  : static_cast<int32_t>(value - static_cast<T>(0.5));
364 }
365 
366 /** @} */
367 
368 /* --------------------------------------------------------------------------------------------------------------------
369  * math functions */
370 
371 #ifndef DONT_SET_USING_DISTRHO_NAMESPACE
372  // If your code uses a lot of DISTRHO classes, then this will obviously save you
373  // a lot of typing, but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE.
374  namespace DISTRHO_NAMESPACE {}
375  using namespace DISTRHO_NAMESPACE;
376 #endif
377 
378 #endif // DISTRHO_UTILS_HPP_INCLUDED
static constexpr uint32_t d_roundToUnsignedInt(const T &value)
Definition: DistrhoUtils.hpp:339
static constexpr bool d_isNotEqual(const T &v1, const T &v2)
Definition: DistrhoUtils.hpp:279
static constexpr int32_t d_roundToIntPositive(const T &value)
Definition: DistrhoUtils.hpp:328
static constexpr bool d_isEqual(const T &v1, const T &v2)
Definition: DistrhoUtils.hpp:268
static constexpr int32_t d_roundToInt(const T &value)
Definition: DistrhoUtils.hpp:360
static constexpr bool d_isNotZero(const T &value)
Definition: DistrhoUtils.hpp:299
static constexpr int32_t d_roundToIntNegative(const T &value)
Definition: DistrhoUtils.hpp:350
static uint32_t d_nextPowerOf2(uint32_t size) noexcept
Definition: DistrhoUtils.hpp:308
static constexpr bool d_isZero(const T &value)
Definition: DistrhoUtils.hpp:289
static void d_pass() noexcept
Definition: DistrhoUtils.hpp:99
static constexpr int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
Definition: DistrhoUtils.hpp:72
static constexpr uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
Definition: DistrhoUtils.hpp:90
#define DISTRHO_NAMESPACE
Definition: DistrhoInfo.hpp:936
static void d_stderr(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:156
static void d_custom_safe_assert(const char *const message, const char *const assertion, const char *const file, const int line) noexcept
Definition: DistrhoUtils.hpp:236
static void d_stdout(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:141
static void d_safe_assert(const char *const assertion, const char *const file, const int line) noexcept
Definition: DistrhoUtils.hpp:187
static void d_safe_exception(const char *const exception, const char *const file, const int line) noexcept
Definition: DistrhoUtils.hpp:246
static void d_stderr2(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:171
static void d_safe_assert_int2(const char *const assertion, const char *const file, const int line, const int v1, const int v2) noexcept
Definition: DistrhoUtils.hpp:216
static void d_debug(const char *const fmt,...) noexcept
Definition: DistrhoUtils.hpp:120
static void d_safe_assert_int(const char *const assertion, const char *const file, const int line, const int value) noexcept
Definition: DistrhoUtils.hpp:196
static void d_safe_assert_uint2(const char *const assertion, const char *const file, const int line, const uint v1, const uint v2) noexcept
Definition: DistrhoUtils.hpp:226
static void d_safe_assert_uint(const char *const assertion, const char *const file, const int line, const uint value) noexcept
Definition: DistrhoUtils.hpp:206