DISTRHO Plugin Framework
DistrhoUtils.hpp
1 /*
2  * DISTRHO Plugin Framework (DPF)
3  * Copyright (C) 2012-2018 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_MAC) && ! defined(CARLA_OS_MAC) && ! defined(DISTRHO_PROPER_CPP11_SUPPORT)
37 namespace std {
38 inline float fmin(float __x, float __y)
39  { return __builtin_fminf(__x, __y); }
40 inline float fmax(float __x, float __y)
41  { return __builtin_fmaxf(__x, __y); }
42 inline float rint(float __x)
43  { return __builtin_rintf(__x); }
44 inline float round(float __x)
45  { return __builtin_roundf(__x); }
46 }
47 #endif
48 
49 #ifndef M_PI
50 # define M_PI 3.14159265358979323846
51 #endif
52 
53 #define DISTRHO_MACRO_AS_STRING(MACRO) #MACRO
54 
55 // -----------------------------------------------------------------------
56 // misc functions
57 
58 /*
59  * Return a 64-bit number from 4 8-bit numbers.
60  */
61 static inline
62 int64_t d_cconst(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) noexcept
63 {
64  return (a << 24) | (b << 16) | (c << 8) | (d << 0);
65 }
66 
67 /*
68  * Return an hexadecimal representation of a MAJ.MIN.MICRO version number.
69  */
70 static inline
71 uint32_t d_version(const uint8_t major, const uint8_t minor, const uint8_t micro) noexcept
72 {
73  return uint32_t(major << 16) | uint32_t(minor << 8) | (micro << 0);
74 }
75 
76 /*
77  * Dummy function.
78  */
79 static inline
80 void d_pass() noexcept {}
81 
82 // -----------------------------------------------------------------------
83 // string print functions
84 
85 /*
86  * Print a string to stdout with newline (gray color).
87  * Does nothing if DEBUG is not defined.
88  */
89 #ifndef DEBUG
90 # define d_debug(...)
91 #else
92 static inline
93 void d_debug(const char* const fmt, ...) noexcept
94 {
95  try {
96  ::va_list args;
97  ::va_start(args, fmt);
98  std::fprintf(stdout, "\x1b[30;1m");
99  std::vfprintf(stdout, fmt, args);
100  std::fprintf(stdout, "\x1b[0m\n");
101  ::va_end(args);
102  } catch (...) {}
103 }
104 #endif
105 
106 /*
107  * Print a string to stdout with newline.
108  */
109 static inline
110 void d_stdout(const char* const fmt, ...) noexcept
111 {
112  try {
113  ::va_list args;
114  ::va_start(args, fmt);
115  std::vfprintf(stdout, fmt, args);
116  std::fprintf(stdout, "\n");
117  ::va_end(args);
118  } catch (...) {}
119 }
120 
121 /*
122  * Print a string to stderr with newline.
123  */
124 static inline
125 void d_stderr(const char* const fmt, ...) noexcept
126 {
127  try {
128  ::va_list args;
129  ::va_start(args, fmt);
130  std::vfprintf(stderr, fmt, args);
131  std::fprintf(stderr, "\n");
132  ::va_end(args);
133  } catch (...) {}
134 }
135 
136 /*
137  * Print a string to stderr with newline (red color).
138  */
139 static inline
140 void d_stderr2(const char* const fmt, ...) noexcept
141 {
142  try {
143  ::va_list args;
144  ::va_start(args, fmt);
145  std::fprintf(stderr, "\x1b[31m");
146  std::vfprintf(stderr, fmt, args);
147  std::fprintf(stderr, "\x1b[0m\n");
148  ::va_end(args);
149  } catch (...) {}
150 }
151 
152 /*
153  * Print a safe assertion error message.
154  */
155 static inline
156 void d_safe_assert(const char* const assertion, const char* const file, const int line) noexcept
157 {
158  d_stderr2("assertion failure: \"%s\" in file %s, line %i", assertion, file, line);
159 }
160 
161 /*
162  * Print a safe assertion error message, with 1 extra signed integer value.
163  */
164 static inline
165 void d_safe_assert_int(const char* const assertion, const char* const file,
166  const int line, const int value) noexcept
167 {
168  d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %i", assertion, file, line, value);
169 }
170 
171 /*
172  * Print a safe assertion error message, with 1 extra unsigned integer value.
173  */
174 static inline
175 void d_safe_assert_uint(const char* const assertion, const char* const file,
176  const int line, const uint value) noexcept
177 {
178  d_stderr2("assertion failure: \"%s\" in file %s, line %i, value %u", assertion, file, line, value);
179 }
180 
181 /*
182  * Print a safe assertion error message, with 2 extra signed integer values.
183  */
184 static inline
185 void d_safe_assert_int2(const char* const assertion, const char* const file,
186  const int line, const int v1, const int v2) noexcept
187 {
188  d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %i, v2 %i", assertion, file, line, v1, v2);
189 }
190 
191 /*
192  * Print a safe assertion error message, with 2 extra unsigned integer values.
193  */
194 static inline
195 void d_safe_assert_uint2(const char* const assertion, const char* const file,
196  const int line, const uint v1, const uint v2) noexcept
197 {
198  d_stderr2("assertion failure: \"%s\" in file %s, line %i, v1 %u, v2 %u", assertion, file, line, v1, v2);
199 }
200 
201 /*
202  * Print a safe exception error message.
203  */
204 static inline
205 void d_safe_exception(const char* const exception, const char* const file, const int line) noexcept
206 {
207  d_stderr2("exception caught: \"%s\" in file %s, line %i", exception, file, line);
208 }
209 
210 // -----------------------------------------------------------------------
211 // math functions
212 
213 /*
214  * Safely compare two floating point numbers.
215  * Returns true if they match.
216  */
217 template<typename T>
218 static inline
219 bool d_isEqual(const T& v1, const T& v2)
220 {
221  return std::abs(v1-v2) < std::numeric_limits<T>::epsilon();
222 }
223 
224 /*
225  * Safely compare two floating point numbers.
226  * Returns true if they don't match.
227  */
228 template<typename T>
229 static inline
230 bool d_isNotEqual(const T& v1, const T& v2)
231 {
232  return std::abs(v1-v2) >= std::numeric_limits<T>::epsilon();
233 }
234 
235 /*
236  * Safely check if a floating point number is zero.
237  */
238 template<typename T>
239 static inline
240 bool d_isZero(const T& value)
241 {
242  return std::abs(value) < std::numeric_limits<T>::epsilon();
243 }
244 
245 /*
246  * Safely check if a floating point number is not zero.
247  */
248 template<typename T>
249 static inline
250 bool d_isNotZero(const T& value)
251 {
252  return std::abs(value) >= std::numeric_limits<T>::epsilon();
253 }
254 
255 /*
256  * Get next power of 2.
257  */
258 static inline
259 uint32_t d_nextPowerOf2(uint32_t size) noexcept
260 {
261  DISTRHO_SAFE_ASSERT_RETURN(size > 0, 0);
262 
263  // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
264  --size;
265  size |= size >> 1;
266  size |= size >> 2;
267  size |= size >> 4;
268  size |= size >> 8;
269  size |= size >> 16;
270  return ++size;
271 }
272 
273 // -----------------------------------------------------------------------
274 
275 #ifndef DONT_SET_USING_DISTRHO_NAMESPACE
276  // If your code uses a lot of DISTRHO classes, then this will obviously save you
277  // a lot of typing, but can be disabled by setting DONT_SET_USING_DISTRHO_NAMESPACE.
278  namespace DISTRHO_NAMESPACE {}
279  using namespace DISTRHO_NAMESPACE;
280 #endif
281 
282 // -----------------------------------------------------------------------
283 
284 #endif // DISTRHO_UTILS_HPP_INCLUDED