3232
3333#include < cstddef>
3434#include < cstdint>
35- #include < cstring >
35+ #include < utility >
3636
3737namespace godot {
3838
@@ -64,30 +64,216 @@ namespace godot {
6464#endif
6565#endif
6666
67- // Should always inline, except in debug builds because it makes debugging harder.
67+ // Should always inline, except in dev builds because it makes debugging harder,
68+ // or `size_enabled` builds where inlining is actively avoided.
6869#ifndef _FORCE_INLINE_
69- #ifdef DISABLE_FORCED_INLINE
70+ #if defined(DEV_ENABLED) || defined(SIZE_EXTRA)
7071#define _FORCE_INLINE_ inline
7172#else
7273#define _FORCE_INLINE_ _ALWAYS_INLINE_
7374#endif
7475#endif
7576
77+ // Should never inline.
78+ #ifndef _NO_INLINE_
79+ #if defined(__GNUC__)
80+ #define _NO_INLINE_ __attribute__ ((noinline))
81+ #elif defined(_MSC_VER)
82+ #define _NO_INLINE_ __declspec (noinline)
83+ #else
84+ #define _NO_INLINE_
85+ #endif
86+ #endif
87+
88+ // In some cases [[nodiscard]] will get false positives,
89+ // we can prevent the warning in specific cases by preceding the call with a cast.
90+ #ifndef _ALLOW_DISCARD_
91+ #define _ALLOW_DISCARD_ (void )
92+ #endif
93+
7694// Windows badly defines a lot of stuff we'll never use. Undefine it.
7795#ifdef _WIN32
7896#undef min // override standard definition
7997#undef max // override standard definition
8098#undef ERROR // override (really stupid) wingdi.h standard definition
8199#undef DELETE // override (another really stupid) winnt.h standard definition
82100#undef MessageBox // override winuser.h standard definition
83- #undef MIN // override standard definition
84- #undef MAX // override standard definition
85- #undef CLAMP // override standard definition
86101#undef Error
87102#undef OK
88103#undef CONNECT_DEFERRED // override from Windows SDK, clashes with Object enum
104+ #undef MemoryBarrier
105+ #undef MONO_FONT
106+ #endif
107+
108+ // Make room for our constexpr's below by overriding potential system-specific macros.
109+ #undef SIGN
110+ #undef MIN
111+ #undef MAX
112+ #undef CLAMP
113+
114+ template <typename T>
115+ constexpr const T SIGN (const T m_v) {
116+ return m_v > 0 ? +1 .0f : (m_v < 0 ? -1 .0f : 0 .0f );
117+ }
118+
119+ template <typename T, typename T2>
120+ constexpr auto MIN (const T m_a, const T2 m_b) {
121+ return m_a < m_b ? m_a : m_b;
122+ }
123+
124+ template <typename T, typename T2>
125+ constexpr auto MAX (const T m_a, const T2 m_b) {
126+ return m_a > m_b ? m_a : m_b;
127+ }
128+
129+ template <typename T, typename T2, typename T3>
130+ constexpr auto CLAMP (const T m_a, const T2 m_min, const T3 m_max) {
131+ return m_a < m_min ? m_min : (m_a > m_max ? m_max : m_a);
132+ }
133+
134+ // Generic swap template.
135+ #ifndef SWAP
136+ #define SWAP (m_x, m_y ) std::swap((m_x), (m_y))
137+ #endif // SWAP
138+
139+ /* Functions to handle powers of 2 and shifting. */
140+
141+ // Returns `true` if a positive integer is a power of 2, `false` otherwise.
142+ template <typename T>
143+ inline bool is_power_of_2 (const T x) {
144+ return x && ((x & (x - 1 )) == 0 );
145+ }
146+
147+ // Function to find the next power of 2 to an integer.
148+ static _FORCE_INLINE_ unsigned int next_power_of_2 (unsigned int x) {
149+ if (x == 0 ) {
150+ return 0 ;
151+ }
152+
153+ --x;
154+ x |= x >> 1 ;
155+ x |= x >> 2 ;
156+ x |= x >> 4 ;
157+ x |= x >> 8 ;
158+ x |= x >> 16 ;
159+
160+ return ++x;
161+ }
162+
163+ // Function to find the previous power of 2 to an integer.
164+ static _FORCE_INLINE_ unsigned int previous_power_of_2 (unsigned int x) {
165+ x |= x >> 1 ;
166+ x |= x >> 2 ;
167+ x |= x >> 4 ;
168+ x |= x >> 8 ;
169+ x |= x >> 16 ;
170+ return x - (x >> 1 );
171+ }
172+
173+ // Function to find the closest power of 2 to an integer.
174+ static _FORCE_INLINE_ unsigned int closest_power_of_2 (unsigned int x) {
175+ unsigned int nx = next_power_of_2 (x);
176+ unsigned int px = previous_power_of_2 (x);
177+ return (nx - x) > (x - px) ? px : nx;
178+ }
179+
180+ // Get a shift value from a power of 2.
181+ static inline int get_shift_from_power_of_2 (unsigned int p_bits) {
182+ for (unsigned int i = 0 ; i < 32 ; i++) {
183+ if (p_bits == (unsigned int )(1 << i)) {
184+ return i;
185+ }
186+ }
187+
188+ return -1 ;
189+ }
190+
191+ template <typename T>
192+ static _FORCE_INLINE_ T nearest_power_of_2_templated (T x) {
193+ --x;
194+
195+ // The number of operations on x is the base two logarithm
196+ // of the number of bits in the type. Add three to account
197+ // for sizeof(T) being in bytes.
198+ size_t num = get_shift_from_power_of_2 (sizeof (T)) + 3 ;
199+
200+ // If the compiler is smart, it unrolls this loop.
201+ // If it's dumb, this is a bit slow.
202+ for (size_t i = 0 ; i < num; i++) {
203+ x |= x >> (1 << i);
204+ }
205+
206+ return ++x;
207+ }
208+
209+ // Function to find the nearest (bigger) power of 2 to an integer.
210+ static inline unsigned int nearest_shift (unsigned int p_number) {
211+ for (int i = 30 ; i >= 0 ; i--) {
212+ if (p_number & (1 << i)) {
213+ return i + 1 ;
214+ }
215+ }
216+
217+ return 0 ;
218+ }
219+
220+ // constexpr function to find the floored log2 of a number
221+ template <typename T>
222+ constexpr T floor_log2 (T x) {
223+ return x < 2 ? x : 1 + floor_log2 (x >> 1 );
224+ }
225+
226+ // Get the number of bits needed to represent the number.
227+ // IE, if you pass in 8, you will get 4.
228+ // If you want to know how many bits are needed to store 8 values however, pass in (8 - 1).
229+ template <typename T>
230+ constexpr T get_num_bits (T x) {
231+ return floor_log2 (x);
232+ }
233+
234+ // Swap 16, 32 and 64 bits value for endianness.
235+ #if defined(__GNUC__)
236+ #define BSWAP16 (x ) __builtin_bswap16(x)
237+ #define BSWAP32 (x ) __builtin_bswap32(x)
238+ #define BSWAP64 (x ) __builtin_bswap64(x)
239+ #elif defined(_MSC_VER)
240+ #define BSWAP16 (x ) _byteswap_ushort(x)
241+ #define BSWAP32 (x ) _byteswap_ulong(x)
242+ #define BSWAP64 (x ) _byteswap_uint64(x)
243+ #else
244+ static inline uint16_t BSWAP16 (uint16_t x) {
245+ return (x >> 8 ) | (x << 8 );
246+ }
247+
248+ static inline uint32_t BSWAP32 (uint32_t x) {
249+ return ((x << 24 ) | ((x << 8 ) & 0x00FF0000 ) | ((x >> 8 ) & 0x0000FF00 ) | (x >> 24 ));
250+ }
251+
252+ static inline uint64_t BSWAP64 (uint64_t x) {
253+ x = (x & 0x00000000FFFFFFFF ) << 32 | (x & 0xFFFFFFFF00000000 ) >> 32 ;
254+ x = (x & 0x0000FFFF0000FFFF ) << 16 | (x & 0xFFFF0000FFFF0000 ) >> 16 ;
255+ x = (x & 0x00FF00FF00FF00FF ) << 8 | (x & 0xFF00FF00FF00FF00 ) >> 8 ;
256+ return x;
257+ }
89258#endif
90259
260+ // Generic comparator used in Map, List, etc.
261+ template <typename T>
262+ struct Comparator {
263+ _ALWAYS_INLINE_ bool operator ()(const T &p_a, const T &p_b) const { return (p_a < p_b); }
264+ };
265+
266+ // Global lock macro, relies on the static Mutex::_global_mutex.
267+ void _global_lock ();
268+ void _global_unlock ();
269+
270+ struct _GlobalLock {
271+ _GlobalLock () { _global_lock (); }
272+ ~_GlobalLock () { _global_unlock (); }
273+ };
274+
275+ #define GLOBAL_LOCK_FUNCTION _GlobalLock _global_lock_;
276+
91277#if defined(__GNUC__)
92278#define likely (x ) __builtin_expect(!!(x), 1 )
93279#define unlikely (x ) __builtin_expect(!!(x), 0 )
@@ -96,22 +282,17 @@ namespace godot {
96282#define unlikely (x ) x
97283#endif
98284
99- #ifdef REAL_T_IS_DOUBLE
100- typedef double real_t ;
285+ #if defined(__GNUC__)
286+ #define _PRINTF_FORMAT_ATTRIBUTE_2_0 __attribute__ ((format(printf, 2 , 0 )))
287+ #define _PRINTF_FORMAT_ATTRIBUTE_2_3 __attribute__ ((format(printf, 2 , 3 )))
101288#else
102- typedef float real_t ;
289+ #define _PRINTF_FORMAT_ATTRIBUTE_2_0
290+ #define _PRINTF_FORMAT_ATTRIBUTE_2_3
103291#endif
104292
105- // Generic swap template.
106- #ifndef SWAP
107- #define SWAP (m_x, m_y ) __swap_tmpl((m_x), (m_y))
108- template <typename T>
109- inline void __swap_tmpl (T &x, T &y) {
110- T aux = x;
111- x = y;
112- y = aux;
113- }
114- #endif // SWAP
293+ // This is needed due to a strange OpenGL API that expects a pointer
294+ // type for an argument that is actually an offset.
295+ #define CAST_INT_TO_UCHAR_PTR (ptr ) ((uint8_t *)(uintptr_t )(ptr))
115296
116297// Home-made index sequence trick, so it can be used everywhere without the costly include of std::tuple.
117298// https://stackoverflow.com/questions/15014096/c-index-of-type-during-variadic-template-expansion
@@ -124,8 +305,36 @@ struct BuildIndexSequence : BuildIndexSequence<N - 1, N - 1, Is...> {};
124305template <size_t ... Is>
125306struct BuildIndexSequence <0 , Is...> : IndexSequence<Is...> {};
126307
127- } // namespace godot
308+ // Limit the depth of recursive algorithms when dealing with Array/Dictionary
309+ #define MAX_RECURSION 100
310+
311+ #ifdef DEBUG_ENABLED
312+ #define DEBUG_METHODS_ENABLED
313+ #endif
314+
315+ // Macro GD_IS_DEFINED() allows to check if a macro is defined. It needs to be defined to anything (say 1) to work.
316+ #define __GDARG_PLACEHOLDER_1 false ,
317+ #define __gd_take_second_arg (__ignored, val, ...) val
318+ #define ____gd_is_defined (arg1_or_junk ) __gd_take_second_arg(arg1_or_junk true , false )
319+ #define ___gd_is_defined (val ) ____gd_is_defined(__GDARG_PLACEHOLDER_##val)
320+ #define GD_IS_DEFINED (x ) ___gd_is_defined(x)
128321
129- // To maintain compatibility an alias is defined outside the namespace.
130- // Consider it deprecated.
131- using real_t = godot::real_t ;
322+ // Whether the default value of a type is just all-0 bytes.
323+ // This can most commonly be exploited by using memset for these types instead of loop-construct.
324+ // Trivially constructible types are also zero-constructible.
325+ template <typename T>
326+ struct is_zero_constructible : std::is_trivially_constructible<T> {};
327+
328+ template <typename T>
329+ struct is_zero_constructible <const T> : is_zero_constructible<T> {};
330+
331+ template <typename T>
332+ struct is_zero_constructible <volatile T> : is_zero_constructible<T> {};
333+
334+ template <typename T>
335+ struct is_zero_constructible <const volatile T> : is_zero_constructible<T> {};
336+
337+ template <typename T>
338+ inline constexpr bool is_zero_constructible_v = is_zero_constructible<T>::value;
339+
340+ } // namespace godot
0 commit comments