Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
PlatformDefines.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2018 DIVIDE-Studio
3 Copyright (c) 2009 Ionut Cava
4
5 This file is part of DIVIDE Framework.
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software
9 and associated documentation files (the "Software"), to deal in the Software
10 without restriction,
11 including without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense,
13 and/or sell copies of the Software, and to permit persons to whom the
14 Software is furnished to do so,
15 subject to the following conditions:
16
17 The above copyright notice and this permission notice shall be included in
18 all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED,
22 INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
23 PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
27 IN CONNECTION WITH THE SOFTWARE
28 OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 */
31
32#pragma once
33#ifndef DVD_PLATFORM_DEFINES_H_
34#define DVD_PLATFORM_DEFINES_H_
35
36#include "config.h"
40
41#define EXP( x ) x
42
43#define GET_3RD_ARG(arg1, arg2, arg3, ...) arg3
44#define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
45#define GET_5TH_ARG(arg1, arg2, arg3, arg4, arg5, ...) arg5
46#define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6
47
48#if defined(_DEBUG)
49#define STUBBED(x) \
50do { \
51 static bool seen_this = false; \
52 if (!seen_this) { \
53 seen_this = true; \
54 Console::errorfn("[ STUBBED ] {} ({} : {})\n",\
55 x, __FILE__, __LINE__); \
56 } \
57} while (0)
58
59#else
60#define STUBBED(x) static_assert(true, "")
61#endif
62
63#ifndef TO_STRING
64#define TO_STRING_NAME(X) #X
65#define TO_STRING(X) TO_STRING_NAME(X)
66#endif //TO_STRING
67
73#define TYPEDEF_SMART_POINTERS_FOR_TYPE(T) \
74 using T ## _wptr = std::weak_ptr<T>; \
75 using T ## _ptr = std::shared_ptr<T>; \
76 using T ## _cwptr = std::weak_ptr<const T>; \
77 using T ## _cptr = std::shared_ptr<const T>;\
78 using T ## _uptr = std::unique_ptr<T>;
79
80
81#define FWD_DECLARE_MANAGED_CLASS(T) \
82 class T; \
83 TYPEDEF_SMART_POINTERS_FOR_TYPE(T)
84
85#define FWD_DECLARE_MANAGED_STRUCT(T) \
86 struct T; \
87 TYPEDEF_SMART_POINTERS_FOR_TYPE(T)
88
89
90#define CONCATENATE_IMPL(s1, s2) s1##s2
91#define CONCATENATE(s1, s2) CONCATENATE_IMPL(s1, s2)
92#ifdef __COUNTER__
93#define ANONYMOUS_VARIABLE(str) CONCATENATE(str, __COUNTER__)
94#else
95#define ANONYMOUSE_VARIABLE(str) CONCATENATE(str, __LINE__)
96#endif
97
98 // Multumesc Andrei A.!
99#if defined(_MSC_VER)
100#define _FUNCTION_NAME_AND_SIG_ __FUNCSIG__
101#elif defined(__GNUC__)
102#define _FUNCTION_NAME_AND_SIG_ __PRETTY_FUNCTION__
103#else
104#define _FUNCTION_NAME_AND_SIG_ __FUNCTION__
105#endif
106
107#ifndef NO_DESTROY
108#if defined(USING_CLANG)
109#define NO_DESTROY [[clang::no_destroy]]
110#else //CLANG_COMPILER
111#define NO_DESTROY
112#endif
113#endif //NO_DESTROY
114
115#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF) \
116template<typename... Args> \
117constexpr auto highLevelF(Args&&... args) -> decltype(lowLevelF(FWD(args)...)) \
118{ \
119 return lowLevelF(FWD(args)...); \
120}
121
123
124//ref: https://vittorioromeo.info/index/blog/passing_functions_to_functions.html
125template <typename TSignature>
127
128template <typename TReturn, typename... TArgs>
129class function_view<TReturn(TArgs...)> final
130{
131 typedef TReturn signature_type(void*, TArgs...);
132
133 void* _ptr;
134 TReturn(*_erased_fn)(void*, TArgs...);
135
136public:
137 template <typename T> requires std::is_invocable_v<T&(TArgs...)> && (!std::is_same_v<std::decay_t<T>, function_view>)
138 function_view(T&& x) noexcept : _ptr{ (void*)std::addressof(x) } {
139 _erased_fn = [](void* ptr, TArgs... xs) -> TReturn {
140 return (*reinterpret_cast<std::add_pointer_t<T>>(ptr))(
141 FWD(xs)...);
142 };
143 }
144
145 decltype(auto) operator()(TArgs... xs) const
146 noexcept(noexcept(_erased_fn(_ptr, FWD(xs)...))) {
147 return _erased_fn(_ptr, FWD(xs)...);
148 }
149};
150
151namespace Divide {
152
154
155// FNV1a c++11 constexpr compile time hash functions, 32 and 64 bit
156// str should be a null terminated string literal, value should be left out
157// e.g hash_32_fnv1a_const("example")
158// code license: public domain or equivalent
159// post: https://notes.underscorediscovery.com/constexpr-fnv1a/
160
161constexpr U32 val_32_const = 0x811c9dc5;
162constexpr U32 prime_32_const = 0x1000193;
163constexpr U64 val_64_const = 0xcbf29ce484222325;
164constexpr U64 prime_64_const = 0x100000001b3;
165
166[[nodiscard]] constexpr U64 _ID_VIEW(const char* const str, const size_t len, const U64 value = val_64_const) noexcept
167{
168 return len == 0 ? value : _ID_VIEW(&str[1], len - 1, (value ^ to_U64(str[0])) * prime_64_const);
169}
170
171[[nodiscard]] constexpr U64 _ID(const char* const str, const U64 value = val_64_const) noexcept
172{
173 return str[0] == '\0' ? value : _ID(&str[1], (value ^ to_U64(str[0])) * prime_64_const);
174}
175
176[[nodiscard]] constexpr U64 _ID( const std::string_view str, const U64 value = val_64_const ) noexcept
177{
178 return _ID_VIEW(str.data(), str.size(), value);
179}
180
181[[nodiscard]] constexpr U64 operator ""_id(const char* str, const size_t len)
182{
183 return _ID_VIEW(str, len);
184}
185
187{
190};
191
192[[nodiscard]] SysInfo& sysInfo() noexcept;
193[[nodiscard]] const SysInfo& const_sysInfo() noexcept;
194
195void InitSysInfo(SysInfo& info, I32 argc, char** argv);
196
197extern F32 PlatformDefaultDPI() noexcept;
198
199struct WindowHandle;
200extern void GetWindowHandle(void* window, WindowHandle& handleOut) noexcept;
201
202enum class ThreadPriority : U8 {
203 IDLE = 0,
205 NORMAL,
207 HIGHEST,
209 COUNT
210};
211
212extern void SetThreadPriority(ThreadPriority priority);
213
214extern void SetThreadName(std::string_view threadName) noexcept;
215
216extern bool CallSystemCmd(std::string_view cmd, std::string_view args);
217
218bool DebugBreak(bool condition = true) noexcept;
219
220[[nodiscard]] ErrorCode PlatformInit(int argc, char** argv);
221[[nodiscard]] bool PlatformClose();
222[[nodiscard]] bool GetAvailableMemory(SysInfo& info);
223
224void EnforceDPIScaling() noexcept;
225
226[[nodiscard]] const char* GetClipboardText() noexcept;
227void SetClipboardText(const char* text) noexcept;
228
229void ToggleCursor(bool state) noexcept;
230
231[[nodiscard]] bool CursorState() noexcept;
232
233[[nodiscard]] std::string CurrentDateTimeString();
234
236template<typename T>
237[[nodiscard]] constexpr T toBit(const T X) {
238 return 1 << X;
239}
240
241[[nodiscard]] constexpr U32 powerOfTwo(U32 X) noexcept
242{
243 U32 r = 0u;
244 while (X >>= 1)
245 {
246 r++;
247 }
248 return r;
249}
250
251[[nodiscard]] constexpr U32 previousPowerOfTwo(const U32 X) noexcept
252{
253 U32 r = 1u;
254 while (r * 2 < X)
255 {
256 r *= 2;
257 }
258
259 return r;
260}
261
262[[nodiscard]] constexpr U32 mipLevels(U32 width, U32 height) noexcept
263{
264 U32 result = 1u;
265
266 while (width > 1u || height > 1u)
267 {
268 ++result;
269 width /= 2u;
270 height /= 2u;
271 }
272
273 return result;
274}
275
276template<typename T> requires std::is_unsigned_v<T>
277[[nodiscard]] constexpr bool isPowerOfTwo(const T x) noexcept {
278 return !(x == 0) && !(x & (x - 1));
279}
280
281[[nodiscard]] constexpr size_t realign_offset(const size_t offset, const size_t align) noexcept {
282 return (offset + align - 1) & ~(align - 1);
283}
284
285//ref: http://stackoverflow.com/questions/14226952/partitioning-batch-chunk-a-container-into-equal-sized-pieces-using-std-algorithm
286template<typename Iterator, typename Pred>
287void for_each_interval(Iterator from, Iterator to, std::ptrdiff_t partition_size, Pred&& operation)
288{
289 if (partition_size > 0) {
290 Iterator partition_end = from;
291 while (partition_end != to)
292 {
293 while (partition_end != to && std::distance(from, partition_end) < partition_size)
294 {
295 ++partition_end;
296 }
297 operation(from, partition_end);
298 from = partition_end;
299 }
300 }
301}
302
303//ref: http://stackoverflow.com/questions/9530928/checking-a-member-exists-possibly-in-a-base-class-c11-version
304template<typename C>
305concept has_reserve = requires(C c) {
306 c.reserve( std::declval<typename C::size_type>() );
307};
308
309template<typename C>
310concept has_emplace_back = requires(C c) {
311 c.emplace_back( std::declval<typename C::value_type>() );
312};
313
314//ref: https://github.com/ParBLiSS/kmerind/blob/master/src/utils/container_traits.hpp
315template<typename C>
316concept has_assign = requires(C c) {
317 c.assign( std::declval<decltype(std::declval<C>().begin())>(),
318 std::declval<decltype(std::declval<C>().end())>());
319};
320
321template< typename C > requires (!has_reserve<C>)
322void optional_reserve(C&, std::size_t) {}
323
324template< typename C > requires has_reserve<C>
325void optional_reserve(C& c, std::size_t n) {
326 c.reserve(c.size() + n);
327}
328
329
330using std::make_index_sequence;
331using std::index_sequence;
332
333namespace detail
334{
335 template <typename T, std::size_t ... Is>
336 constexpr std::array<T, sizeof...(Is)>
337 create_array(T value, index_sequence<Is...>)
338 {
339 // cast Is to void to remove the warning: unused value
340 return { {(static_cast<void>(Is), value)...} };
341 }
342
343 template <typename T, std::size_t ... Is>
344 constexpr eastl::array<T, sizeof...(Is)>
345 create_eastl_array(T value, index_sequence<Is...>) {
346 // cast Is to void to remove the warning: unused value
347 return { {(static_cast<void>(Is), value)...} };
348 }
349}
350
351
352template <std::size_t N, typename T>
353constexpr std::array<T, N> create_array(const T& value)
354{
355 return detail::create_array(value, make_index_sequence<N>());
356}
357
358template <std::size_t N, typename T>
359constexpr eastl::array<T, N> create_eastl_array(const T& value) {
360 return detail::create_eastl_array(value, make_index_sequence<N>());
361}
362
363/* See
364http://randomascii.wordpress.com/2012/01/11/tricks-with-the-floating-point-format/
365for the potential portability problems with the union and bit-fields below.
366*/
367union Float_t {
368 explicit Float_t(const F32 num = 0.0f) noexcept : f(num) {}
369
370 // Portable extraction of components.
371 [[nodiscard]] bool Negative() const noexcept { return (i >> 31) != 0; }
372 [[nodiscard]] I32 RawMantissa() const noexcept { return i & ((1 << 23) - 1); }
373 [[nodiscard]] I32 RawExponent() const noexcept { return (i >> 23) & 0xFF; }
374
377};
378
379union Double_t {
380 explicit Double_t(const D64 num = 0.0) noexcept : d(num) {}
381
382 // Portable extraction of components.
383 [[nodiscard]] bool Negative() const noexcept { return (i >> 63) != 0; }
384 [[nodiscard]] I64 RawMantissa() const noexcept { return i & ((1LL << 52) - 1); }
385 [[nodiscard]] I64 RawExponent() const noexcept { return (i >> 52) & 0x7FF; }
386
389};
390
391[[nodiscard]]
392inline bool AlmostEqualUlpsAndAbs(const F32 A, const F32 B, const F32 maxDiff, const I32 maxUlpsDiff) noexcept {
393 // Check if the numbers are really close -- needed when comparing numbers near zero.
394 const F32 absDiff = std::abs(A - B);
395 if (absDiff <= maxDiff) {
396 return true;
397 }
398
399 const Float_t uA(A);
400 const Float_t uB(B);
401
402 // Different signs means they do not match.
403 if (uA.Negative() != uB.Negative()) {
404 return false;
405 }
406
407 // Find the difference in ULPs.
408 return std::abs(uA.i - uB.i) <= maxUlpsDiff;
409}
410
411[[nodiscard]]
412inline bool AlmostEqualUlpsAndAbs(const D64 A, const D64 B, const D64 maxDiff, const I32 maxUlpsDiff) noexcept {
413 // Check if the numbers are really close -- needed when comparing numbers near zero.
414 const D64 absDiff = std::abs(A - B);
415 if (absDiff <= maxDiff) {
416 return true;
417 }
418
419 const Double_t uA(A);
420 const Double_t uB(B);
421
422 // Different signs means they do not match.
423 if (uA.Negative() != uB.Negative()) {
424 return false;
425 }
426
427 // Find the difference in ULPs.
428 return std::abs(uA.i - uB.i) <= maxUlpsDiff;
429}
430
431[[nodiscard]]
432inline bool AlmostEqualRelativeAndAbs(const F32 A, const F32 B, const F32 maxDiff, const F32 maxRelDiff) noexcept {
433 // Check if the numbers are really close -- needed when comparing numbers near zero.
434 const F32 diff = std::abs(A - B);
435 if (diff <= maxDiff) {
436 return true;
437 }
438
439 const F32 largest = std::max(std::abs(A), std::abs(B));
440 return diff <= largest * maxRelDiff;
441}
442
443[[nodiscard]]
444inline bool AlmostEqualRelativeAndAbs(D64 A, D64 B, const D64 maxDiff, const D64 maxRelDiff) noexcept {
445 // Check if the numbers are really close -- needed when comparing numbers near zero.
446 const D64 diff = std::abs(A - B);
447 if (diff <= maxDiff) {
448 return true;
449 }
450
451 A = std::abs(A);
452 B = std::abs(B);
453 const D64 largest = B > A ? B : A;
454
455 return diff <= largest * maxRelDiff;
456}
457
458#define NOP() static_assert(true, "")
459
460//Andrei Alexandrescu's ScopeGuard macros from "Declarative Control Flow" (CppCon 2015)
461//ref: https://gist.github.com/mmha/6bee3983caf2eab04d80af8e0eaddfbe
462namespace detail {
463 enum class ScopeGuardOnExit{};
464 enum class ScopeGuardOnFail{};
466
467 template <typename Fun>
469 {
470 public:
471 ScopeGuard(Fun &&fn) noexcept : fn(MOV(fn)) {}
473 private:
474 Fun fn;
475 };
476
478 {
480 public:
481 UncaughtExceptionCounter() noexcept : exceptionCount_(std::uncaught_exceptions()) {}
482 bool newUncaughtException() noexcept { return std::uncaught_exceptions() > exceptionCount_; }
483 };
484
485 template <typename FunctionType, bool executeOnException>
487 {
488 FunctionType function_;
490 public:
491 explicit ScopeGuardForNewException(const FunctionType &fn) : function_(fn) {}
492 explicit ScopeGuardForNewException(FunctionType &&fn) : function_(MOV(fn)) {}
493 ~ScopeGuardForNewException() noexcept(executeOnException) {
494 if (executeOnException == ec_.newUncaughtException()) {
495 function_();
496 }
497 }
498 };
499
500 template <typename Fun>
501 auto operator+(ScopeGuardOnExit, Fun &&fn) noexcept {
502 return ScopeGuard<Fun>(FWD(fn));
503 }
504
505 template <typename Fun>
506 auto operator+(ScopeGuardOnFail, Fun &&fn) {
508 }
509
510 template <typename Fun>
513 }
514} //namespace detail
515
516
517template <typename T>
518struct Handle
519{
520 union
521 {
522 struct
523 {
526 };
527
529 };
530
531 FORCE_INLINE bool operator==( const Handle& rhs ) const
532 {
533 return _data == rhs._data;
534 }
535};
536
537
538template<typename T>
539inline constexpr Handle<T> INVALID_HANDLE{ {._data = U32_MAX} };
540
541#define SCOPE_FAIL auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = detail::ScopeGuardOnFail() + [&]() noexcept
542#define SCOPE_SUCCESS auto ANONYMOUS_VARIABLE(SCOPE_FAIL_STATE) = detail::ScopeGuardOnSuccess() + [&]()
543#define SCOPE_EXIT auto ANONYMOUS_VARIABLE(SCOPE_EXIT_STATE) = detail::ScopeGuardOnExit() + [&]() noexcept
544
545constexpr F32 EPSILON_F32 = std::numeric_limits<F32>::epsilon();
546constexpr D64 EPSILON_D64 = std::numeric_limits<D64>::epsilon();
547
548template <typename T, typename U = T>
549[[nodiscard]] bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept {
550 return x >= min && x <= max;
551}
552template <typename T, typename U = T>
553[[nodiscard]] bool IS_IN_RANGE_EXCLUSIVE(const T x, const U min, const U max) noexcept {
554 return x > min && x < max;
555}
556
557template <typename T>
558[[nodiscard]] bool IS_ZERO(const T X) noexcept {
559 return X == 0;
560}
561
562template <>
563[[nodiscard]] inline bool IS_ZERO(const F32 X) noexcept {
564 return abs(X) < EPSILON_F32;
565}
566template <>
567[[nodiscard]] inline bool IS_ZERO(const D64 X) noexcept {
568 return abs(X) < EPSILON_D64;
569}
570
571template <typename T>
572[[nodiscard]] bool IS_TOLERANCE(const T X, const T TOLERANCE) noexcept {
573 return abs(X) <= TOLERANCE;
574}
575
576template<typename T, typename U = T>
577[[nodiscard]] bool COMPARE_TOLERANCE(const T X, const U Y, const T TOLERANCE) noexcept {
578 return abs(X - static_cast<T>(Y)) <= TOLERANCE;
579}
580
581template<typename T, typename U = T>
582[[nodiscard]] bool COMPARE_TOLERANCE_ACCURATE(const T X, const T Y, const T TOLERANCE) noexcept {
583 return COMPARE_TOLERANCE(X, Y, TOLERANCE);
584}
585
586template<>
587[[nodiscard]] inline bool COMPARE_TOLERANCE_ACCURATE(const F32 X, const F32 Y, const F32 TOLERANCE) noexcept {
588 return AlmostEqualUlpsAndAbs(X, Y, TOLERANCE, 4);
589}
590
591template<>
592[[nodiscard]] inline bool COMPARE_TOLERANCE_ACCURATE(const D64 X, const D64 Y, const D64 TOLERANCE) noexcept {
593 return AlmostEqualUlpsAndAbs(X, Y, TOLERANCE, 4);
594}
595
596template<typename T, typename U = T>
597[[nodiscard]] bool COMPARE(T X, U Y) noexcept {
598 return X == static_cast<T>(Y);
599}
600
601template<>
602[[nodiscard]] inline bool COMPARE(const F32 X, const F32 Y) noexcept {
603 return COMPARE_TOLERANCE(X, Y, EPSILON_F32);
604}
605
606template<>
607[[nodiscard]] inline bool COMPARE(const D64 X, const D64 Y) noexcept {
608 return COMPARE_TOLERANCE(X, Y, EPSILON_D64);
609}
610
612template <typename T>
613[[nodiscard]] bool IS_GEQUAL(T X, T Y) noexcept {
614 return X > Y || COMPARE(X, Y);
615}
616template <typename T>
617[[nodiscard]] bool IS_LEQUAL(T X, T Y) noexcept {
618 return X < Y || COMPARE(X, Y);
619}
620
622// base template
623template <bool IsFromSigned, bool IsToSigned>
625
626// template specialization for casting from an unsigned type into an unsigned type
627template <>
628struct safe_static_cast_helper<false, false>
629{
630 template <typename TO, typename FROM>
631 static TO cast(FROM from)
632 {
633 assert(IS_IN_RANGE_INCLUSIVE(std::is_enum<FROM>::value
634 ? static_cast<U32>(to_underlying_type(from))
635 : from,
636 std::numeric_limits<TO>::lowest(),
637 std::numeric_limits<TO>::max()) &&
638 "Number to cast exceeds numeric limits.");
639
640 return static_cast<TO>(from);
641 }
642};
643
644// template specialization for casting from an unsigned type into a signed type
645template <>
646struct safe_static_cast_helper<false, true>
647{
648 template <typename TO, typename FROM>
649 static TO cast(FROM from)
650 {
651 assert(IS_IN_RANGE_INCLUSIVE(from,
652 std::numeric_limits<TO>::lowest(),
653 std::numeric_limits<TO>::max()) &&
654 "Number to cast exceeds numeric limits.");
655
656 return static_cast<TO>(from);
657 }
658};
659
660// template specialization for casting from a signed type into an unsigned type
661template <>
662struct safe_static_cast_helper<true, false>
663{
664 template <typename TO, typename FROM>
665 static TO cast(FROM from)
666 {
667 // make sure the input is not negative
668 assert(from >= 0 && "Number to cast exceeds numeric limits.");
669
670 // assuring a positive input, we can safely cast it into its unsigned type and check the numeric limits
671 using UnsignedFrom = typename std::make_unsigned<FROM>::type;
672 assert(IS_IN_RANGE_INCLUSIVE(static_cast<UnsignedFrom>(from),
673 std::numeric_limits<TO>::lowest(),
674 std::numeric_limits<TO>::max()) &&
675 "Number to cast exceeds numeric limits.");
676 return static_cast<TO>(from);
677 }
678};
679
680// template specialization for casting from a signed type into a signed type
681template <>
682struct safe_static_cast_helper<true, true>
683{
684 template <typename TO, typename FROM>
685 static TO cast(FROM from)
686 {
687 assert(IS_IN_RANGE_INCLUSIVE(std::is_enum<FROM>::value ? to_underlying_type(from) : from,
688 std::numeric_limits<TO>::lowest(),
689 std::numeric_limits<TO>::max()) &&
690 "Number to cast exceeds numeric limits.");
691
692 return static_cast<TO>(from);
693 }
694};
695
696
697template <typename TO, typename FROM>
698[[nodiscard]] TO safe_static_cast(FROM from)
699{
700#if defined(_DEBUG)
701 // delegate the call to the proper helper class, depending on the signedness of both types
703 std::numeric_limits<TO>::is_signed>
704 ::template cast<TO>(from);
705#else
706 return static_cast<TO>(from);
707#endif
708}
709
710template <typename TO>
711[[nodiscard]] TO safe_static_cast(F32 from)
712{
713 return static_cast<TO>(from);
714}
715
716template <typename TO>
717[[nodiscard]] TO safe_static_cast(D64 from)
718{
719 return static_cast<TO>(from);
720}
721
722extern void DIVIDE_ASSERT_MSG_BOX(const char* failMessage) noexcept;
723
724namespace Assert
725{
727 bool DIVIDE_ASSERT_FUNC(bool expression, const char* expressionStr, const char* file, int line, const char* failMessage) noexcept;
728}
729
730#define DIVIDE_ASSERT_2_ARGS(expression, msg) Assert::DIVIDE_ASSERT_FUNC(expression, #expression, __FILE__, __LINE__, msg)
731#define DIVIDE_ASSERT_1_ARGS(expression) DIVIDE_ASSERT_2_ARGS(expression, "UNEXPECTED CALL")
732
733#define ___DETAIL_DIVIDE_ASSERT(...) EXP(GET_3RD_ARG(__VA_ARGS__, DIVIDE_ASSERT_2_ARGS, DIVIDE_ASSERT_1_ARGS, ))
734#define DIVIDE_ASSERT(...) EXP(___DETAIL_DIVIDE_ASSERT(__VA_ARGS__)(__VA_ARGS__))
735
736#define DIVIDE_UNEXPECTED_CALL_MSG(X) DIVIDE_ASSERT(false, X)
737#define DIVIDE_UNEXPECTED_CALL() DIVIDE_UNEXPECTED_CALL_MSG("UNEXPECTED CALL")
738
739template <typename Ret, typename... Args >
740using DELEGATE_EASTL = eastl::function< Ret(Args...) >;
741
742template <typename Ret, typename... Args >
743using DELEGATE_STD = std::function< Ret(Args...) >;
744
745template <typename Ret, typename... Args >
746using DELEGATE = DELEGATE_STD<Ret, Args...>;
747
748}; // namespace Divide
749
750#endif //DVD_PLATFORM_DEFINES_H_
#define FWD(...)
#define MOV(...)
#define ALIAS_TEMPLATE_FUNCTION(highLevelF, lowLevelF)
constexpr auto ArrayCount(Args &&... args) -> decltype(std::size(FWD(args)...))
#define FORCE_INLINE
char * argv[]
Definition: main.cpp:8
ScopeGuardForNewException(const FunctionType &fn)
~ScopeGuardForNewException() noexcept(executeOnException)
ScopeGuard(Fun &&fn) noexcept
TReturn signature_type(void *, TArgs...)
bool DIVIDE_ASSERT_FUNC(const bool expression, const char *expressionStr, const char *file, int line, const char *failMessage) noexcept
It is safe to call evaluate expressions and call functions inside the assert check as it will compile...
constexpr eastl::array< T, sizeof...(Is)> create_eastl_array(T value, index_sequence< Is... >)
auto operator+(ScopeGuardOnExit, Fun &&fn) noexcept
constexpr std::array< T, sizeof...(Is)> create_array(T value, index_sequence< Is... >)
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
void GetWindowHandle(void *window, WindowHandle &handleOut) noexcept
void SetClipboardText(const char *text) noexcept
DELEGATE_STD< Ret, Args... > DELEGATE
F32 PlatformDefaultDPI() noexcept
bool COMPARE_TOLERANCE_ACCURATE(const T X, const T Y, const T TOLERANCE) noexcept
void for_each_interval(Iterator from, Iterator to, std::ptrdiff_t partition_size, Pred &&operation)
bool IS_ZERO(const T X) noexcept
bool IS_IN_RANGE_EXCLUSIVE(const T x, const U min, const U max) noexcept
bool CursorState() noexcept
void SetThreadName(std::string_view threadName) noexcept
std::function< Ret(Args...) > DELEGATE_STD
constexpr eastl::array< T, N > create_eastl_array(const T &value)
constexpr U32 val_32_const
constexpr D64 EPSILON_D64
constexpr U64 to_U64(const T value)
SysInfo & sysInfo() noexcept
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
bool IS_LEQUAL(T X, T Y) noexcept
int32_t I32
TO safe_static_cast(FROM from)
uint8_t U8
bool CallSystemCmd(std::string_view cmd, std::string_view args)
bool DebugBreak(const bool condition) noexcept
std::string CurrentDateTimeString()
void DIVIDE_ASSERT_MSG_BOX(const char *failMessage) noexcept
Definition: GUI.cpp:110
const char * GetClipboardText() noexcept
constexpr U64 val_64_const
void SetThreadPriority(ThreadPriority priority)
void EnforceDPIScaling() noexcept
constexpr U64 _ID_VIEW(const char *const str, const size_t len, const U64 value=val_64_const) noexcept
bool IS_TOLERANCE(const T X, const T TOLERANCE) noexcept
constexpr F32 EPSILON_F32
ErrorCode PlatformInit(int argc, char **argv)
bool AlmostEqualRelativeAndAbs(const F32 A, const F32 B, const F32 maxDiff, const F32 maxRelDiff) noexcept
constexpr U32 powerOfTwo(U32 X) noexcept
const SysInfo & const_sysInfo() noexcept
constexpr U32 prime_32_const
constexpr size_t realign_offset(const size_t offset, const size_t align) noexcept
bool PlatformClose()
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
constexpr bool isPowerOfTwo(const T x) noexcept
bool COMPARE_TOLERANCE(const T X, const U Y, const T TOLERANCE) noexcept
constexpr U64 prime_64_const
constexpr U32 mipLevels(U32 width, U32 height) noexcept
constexpr U32 U32_MAX
constexpr U32 previousPowerOfTwo(const U32 X) noexcept
double D64
constexpr Handle< T > INVALID_HANDLE
void optional_reserve(C &, std::size_t)
constexpr std::array< T, N > create_array(const T &value)
bool GetAvailableMemory(SysInfo &info)
bool AlmostEqualUlpsAndAbs(const F32 A, const F32 B, const F32 maxDiff, const I32 maxUlpsDiff) noexcept
bool COMPARE(T X, U Y) noexcept
void ToggleCursor(bool state) noexcept
eastl::function< Ret(Args...) > DELEGATE_EASTL
int64_t I64
uint32_t U32
bool IS_GEQUAL(T X, T Y) noexcept
should be fast enough as the first condition is almost always true
uint64_t U64
constexpr T toBit(const T X)
Converts an arbitrary positive integer value to a bitwise value used for masks.
void InitSysInfo(SysInfo &info, I32 argc, char **argv)
FORCE_INLINE bool operator==(const Handle &rhs) const
ResourcePath _workingDirectory
size_t _availableRamInBytes
ref: http://blog.molecular-matters.com/2011/08/12/a-safer-static_cast/#more-120
I64 RawExponent() const noexcept
I64 RawMantissa() const noexcept
bool Negative() const noexcept
Double_t(const D64 num=0.0) noexcept
bool Negative() const noexcept
I32 RawMantissa() const noexcept
Float_t(const F32 num=0.0f) noexcept
I32 RawExponent() const noexcept