diff options
| author | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
|---|---|---|
| committer | 3gg <3gg@shellblade.net> | 2025-12-27 12:03:39 -0800 |
| commit | 5a079a2d114f96d4847d1ee305d5b7c16eeec50e (patch) | |
| tree | 8926ab44f168acf787d8e19608857b3af0f82758 /contrib/SDL-3.2.8/include/SDL3/SDL_assert.h | |
Initial commit
Diffstat (limited to 'contrib/SDL-3.2.8/include/SDL3/SDL_assert.h')
| -rw-r--r-- | contrib/SDL-3.2.8/include/SDL3/SDL_assert.h | 662 |
1 files changed, 662 insertions, 0 deletions
diff --git a/contrib/SDL-3.2.8/include/SDL3/SDL_assert.h b/contrib/SDL-3.2.8/include/SDL3/SDL_assert.h new file mode 100644 index 0000000..6c90acc --- /dev/null +++ b/contrib/SDL-3.2.8/include/SDL3/SDL_assert.h | |||
| @@ -0,0 +1,662 @@ | |||
| 1 | /* | ||
| 2 | Simple DirectMedia Layer | ||
| 3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> | ||
| 4 | |||
| 5 | This software is provided 'as-is', without any express or implied | ||
| 6 | warranty. In no event will the authors be held liable for any damages | ||
| 7 | arising from the use of this software. | ||
| 8 | |||
| 9 | Permission is granted to anyone to use this software for any purpose, | ||
| 10 | including commercial applications, and to alter it and redistribute it | ||
| 11 | freely, subject to the following restrictions: | ||
| 12 | |||
| 13 | 1. The origin of this software must not be misrepresented; you must not | ||
| 14 | claim that you wrote the original software. If you use this software | ||
| 15 | in a product, an acknowledgment in the product documentation would be | ||
| 16 | appreciated but is not required. | ||
| 17 | 2. Altered source versions must be plainly marked as such, and must not be | ||
| 18 | misrepresented as being the original software. | ||
| 19 | 3. This notice may not be removed or altered from any source distribution. | ||
| 20 | */ | ||
| 21 | |||
| 22 | /** | ||
| 23 | * # CategoryAssert | ||
| 24 | * | ||
| 25 | * A helpful assertion macro! | ||
| 26 | * | ||
| 27 | * SDL assertions operate like your usual `assert` macro, but with some added | ||
| 28 | * features: | ||
| 29 | * | ||
| 30 | * - It uses a trick with the `sizeof` operator, so disabled assertions | ||
| 31 | * vaporize out of the compiled code, but variables only referenced in the | ||
| 32 | * assertion won't trigger compiler warnings about being unused. | ||
| 33 | * - It is safe to use with a dangling-else: `if (x) SDL_assert(y); else | ||
| 34 | * do_something();` | ||
| 35 | * - It works the same everywhere, instead of counting on various platforms' | ||
| 36 | * compiler and C runtime to behave. | ||
| 37 | * - It provides multiple levels of assertion (SDL_assert, SDL_assert_release, | ||
| 38 | * SDL_assert_paranoid) instead of a single all-or-nothing option. | ||
| 39 | * - It offers a variety of responses when an assertion fails (retry, trigger | ||
| 40 | * the debugger, abort the program, ignore the failure once, ignore it for | ||
| 41 | * the rest of the program's run). | ||
| 42 | * - It tries to show the user a dialog by default, if possible, but the app | ||
| 43 | * can provide a callback to handle assertion failures however they like. | ||
| 44 | * - It lets failed assertions be retried. Perhaps you had a network failure | ||
| 45 | * and just want to retry the test after plugging your network cable back | ||
| 46 | * in? You can. | ||
| 47 | * - It lets the user ignore an assertion failure, if there's a harmless | ||
| 48 | * problem that one can continue past. | ||
| 49 | * - It lets the user mark an assertion as ignored for the rest of the | ||
| 50 | * program's run; if there's a harmless problem that keeps popping up. | ||
| 51 | * - It provides statistics and data on all failed assertions to the app. | ||
| 52 | * - It allows the default assertion handler to be controlled with environment | ||
| 53 | * variables, in case an automated script needs to control it. | ||
| 54 | * - It can be used as an aid to Clang's static analysis; it will treat SDL | ||
| 55 | * assertions as universally true (under the assumption that you are serious | ||
| 56 | * about the asserted claims and that your debug builds will detect when | ||
| 57 | * these claims were wrong). This can help the analyzer avoid false | ||
| 58 | * positives. | ||
| 59 | * | ||
| 60 | * To use it: compile a debug build and just sprinkle around tests to check | ||
| 61 | * your code! | ||
| 62 | */ | ||
| 63 | |||
| 64 | #ifndef SDL_assert_h_ | ||
| 65 | #define SDL_assert_h_ | ||
| 66 | |||
| 67 | #include <SDL3/SDL_stdinc.h> | ||
| 68 | |||
| 69 | #include <SDL3/SDL_begin_code.h> | ||
| 70 | /* Set up for C function definitions, even when using C++ */ | ||
| 71 | #ifdef __cplusplus | ||
| 72 | extern "C" { | ||
| 73 | #endif | ||
| 74 | |||
| 75 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 76 | |||
| 77 | /** | ||
| 78 | * The level of assertion aggressiveness. | ||
| 79 | * | ||
| 80 | * This value changes depending on compiler options and other preprocessor | ||
| 81 | * defines. | ||
| 82 | * | ||
| 83 | * It is currently one of the following values, but future SDL releases might | ||
| 84 | * add more: | ||
| 85 | * | ||
| 86 | * - 0: All SDL assertion macros are disabled. | ||
| 87 | * - 1: Release settings: SDL_assert disabled, SDL_assert_release enabled. | ||
| 88 | * - 2: Debug settings: SDL_assert and SDL_assert_release enabled. | ||
| 89 | * - 3: Paranoid settings: All SDL assertion macros enabled, including | ||
| 90 | * SDL_assert_paranoid. | ||
| 91 | * | ||
| 92 | * \since This macro is available since SDL 3.2.0. | ||
| 93 | */ | ||
| 94 | #define SDL_ASSERT_LEVEL SomeNumberBasedOnVariousFactors | ||
| 95 | |||
| 96 | #elif !defined(SDL_ASSERT_LEVEL) | ||
| 97 | #ifdef SDL_DEFAULT_ASSERT_LEVEL | ||
| 98 | #define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL | ||
| 99 | #elif defined(_DEBUG) || defined(DEBUG) || \ | ||
| 100 | (defined(__GNUC__) && !defined(__OPTIMIZE__)) | ||
| 101 | #define SDL_ASSERT_LEVEL 2 | ||
| 102 | #else | ||
| 103 | #define SDL_ASSERT_LEVEL 1 | ||
| 104 | #endif | ||
| 105 | #endif | ||
| 106 | |||
| 107 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 108 | |||
| 109 | /** | ||
| 110 | * Attempt to tell an attached debugger to pause. | ||
| 111 | * | ||
| 112 | * This allows an app to programmatically halt ("break") the debugger as if it | ||
| 113 | * had hit a breakpoint, allowing the developer to examine program state, etc. | ||
| 114 | * | ||
| 115 | * This is a macro--not a function--so that the debugger breaks on the source | ||
| 116 | * code line that used SDL_TriggerBreakpoint and not in some random guts of | ||
| 117 | * SDL. SDL_assert uses this macro for the same reason. | ||
| 118 | * | ||
| 119 | * If the program is not running under a debugger, SDL_TriggerBreakpoint will | ||
| 120 | * likely terminate the app, possibly without warning. If the current platform | ||
| 121 | * isn't supported, this macro is left undefined. | ||
| 122 | * | ||
| 123 | * \threadsafety It is safe to call this macro from any thread. | ||
| 124 | * | ||
| 125 | * \since This macro is available since SDL 3.2.0. | ||
| 126 | */ | ||
| 127 | #define SDL_TriggerBreakpoint() TriggerABreakpointInAPlatformSpecificManner | ||
| 128 | |||
| 129 | #elif defined(_MSC_VER) && _MSC_VER >= 1310 | ||
| 130 | /* Don't include intrin.h here because it contains C++ code */ | ||
| 131 | extern void __cdecl __debugbreak(void); | ||
| 132 | #define SDL_TriggerBreakpoint() __debugbreak() | ||
| 133 | #elif defined(_MSC_VER) && defined(_M_IX86) | ||
| 134 | #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } | ||
| 135 | #elif defined(ANDROID) | ||
| 136 | #include <assert.h> | ||
| 137 | #define SDL_TriggerBreakpoint() assert(0) | ||
| 138 | #elif SDL_HAS_BUILTIN(__builtin_debugtrap) | ||
| 139 | #define SDL_TriggerBreakpoint() __builtin_debugtrap() | ||
| 140 | #elif SDL_HAS_BUILTIN(__builtin_trap) | ||
| 141 | #define SDL_TriggerBreakpoint() __builtin_trap() | ||
| 142 | #elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) | ||
| 143 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" ) | ||
| 144 | #elif (defined(__GNUC__) || defined(__clang__)) && defined(__riscv) | ||
| 145 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "ebreak\n\t" ) | ||
| 146 | #elif ( defined(SDL_PLATFORM_APPLE) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */ | ||
| 147 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" ) | ||
| 148 | #elif defined(SDL_PLATFORM_APPLE) && defined(__arm__) | ||
| 149 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" ) | ||
| 150 | #elif defined(_WIN32) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__arm64__) || defined(__aarch64__)) ) | ||
| 151 | #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #0xF000\n\t" ) | ||
| 152 | #elif defined(__GNUC__) || defined(__clang__) | ||
| 153 | #define SDL_TriggerBreakpoint() __builtin_trap() /* older gcc may not support SDL_HAS_BUILTIN(__builtin_trap) above */ | ||
| 154 | #elif defined(__386__) && defined(__WATCOMC__) | ||
| 155 | #define SDL_TriggerBreakpoint() { _asm { int 0x03 } } | ||
| 156 | #elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__) | ||
| 157 | #include <signal.h> | ||
| 158 | #define SDL_TriggerBreakpoint() raise(SIGTRAP) | ||
| 159 | #else | ||
| 160 | /* SDL_TriggerBreakpoint is intentionally left undefined on unknown platforms. */ | ||
| 161 | #endif | ||
| 162 | |||
| 163 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 164 | |||
| 165 | /** | ||
| 166 | * A macro that reports the current function being compiled. | ||
| 167 | * | ||
| 168 | * If SDL can't figure how the compiler reports this, it will use "???". | ||
| 169 | * | ||
| 170 | * \since This macro is available since SDL 3.2.0. | ||
| 171 | */ | ||
| 172 | #define SDL_FUNCTION __FUNCTION__ | ||
| 173 | |||
| 174 | #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */ | ||
| 175 | # define SDL_FUNCTION __func__ | ||
| 176 | #elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__)) | ||
| 177 | # define SDL_FUNCTION __FUNCTION__ | ||
| 178 | #else | ||
| 179 | # define SDL_FUNCTION "???" | ||
| 180 | #endif | ||
| 181 | |||
| 182 | /** | ||
| 183 | * A macro that reports the current file being compiled. | ||
| 184 | * | ||
| 185 | * \since This macro is available since SDL 3.2.0. | ||
| 186 | */ | ||
| 187 | #define SDL_FILE __FILE__ | ||
| 188 | |||
| 189 | /** | ||
| 190 | * A macro that reports the current line number of the file being compiled. | ||
| 191 | * | ||
| 192 | * \since This macro is available since SDL 3.2.0. | ||
| 193 | */ | ||
| 194 | #define SDL_LINE __LINE__ | ||
| 195 | |||
| 196 | /* | ||
| 197 | sizeof (x) makes the compiler still parse the expression even without | ||
| 198 | assertions enabled, so the code is always checked at compile time, but | ||
| 199 | doesn't actually generate code for it, so there are no side effects or | ||
| 200 | expensive checks at run time, just the constant size of what x WOULD be, | ||
| 201 | which presumably gets optimized out as unused. | ||
| 202 | This also solves the problem of... | ||
| 203 | |||
| 204 | int somevalue = blah(); | ||
| 205 | SDL_assert(somevalue == 1); | ||
| 206 | |||
| 207 | ...which would cause compiles to complain that somevalue is unused if we | ||
| 208 | disable assertions. | ||
| 209 | */ | ||
| 210 | |||
| 211 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 212 | |||
| 213 | /** | ||
| 214 | * A macro for wrapping code in `do {} while (0);` without compiler warnings. | ||
| 215 | * | ||
| 216 | * Visual Studio with really aggressive warnings enabled needs this to avoid | ||
| 217 | * compiler complaints. | ||
| 218 | * | ||
| 219 | * the `do {} while (0);` trick is useful for wrapping code in a macro that | ||
| 220 | * may or may not be a single statement, to avoid various C language | ||
| 221 | * accidents. | ||
| 222 | * | ||
| 223 | * To use: | ||
| 224 | * | ||
| 225 | * ```c | ||
| 226 | * do { SomethingOnce(); } while (SDL_NULL_WHILE_LOOP_CONDITION (0)); | ||
| 227 | * ``` | ||
| 228 | * | ||
| 229 | * \since This macro is available since SDL 3.2.0. | ||
| 230 | */ | ||
| 231 | #define SDL_NULL_WHILE_LOOP_CONDITION (0) | ||
| 232 | |||
| 233 | #elif defined(_MSC_VER) /* Avoid /W4 warnings. */ | ||
| 234 | /* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking | ||
| 235 | this condition isn't constant. And looks like an owl's face! */ | ||
| 236 | #define SDL_NULL_WHILE_LOOP_CONDITION (0,0) | ||
| 237 | #else | ||
| 238 | #define SDL_NULL_WHILE_LOOP_CONDITION (0) | ||
| 239 | #endif | ||
| 240 | |||
| 241 | /** | ||
| 242 | * The macro used when an assertion is disabled. | ||
| 243 | * | ||
| 244 | * This isn't for direct use by apps, but this is the code that is inserted | ||
| 245 | * when an SDL_assert is disabled (perhaps in a release build). | ||
| 246 | * | ||
| 247 | * The code does nothing, but wraps `condition` in a sizeof operator, which | ||
| 248 | * generates no code and has no side effects, but avoid compiler warnings | ||
| 249 | * about unused variables. | ||
| 250 | * | ||
| 251 | * \param condition the condition to assert (but not actually run here). | ||
| 252 | * | ||
| 253 | * \since This macro is available since SDL 3.2.0. | ||
| 254 | */ | ||
| 255 | #define SDL_disabled_assert(condition) \ | ||
| 256 | do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION) | ||
| 257 | |||
| 258 | /** | ||
| 259 | * Possible outcomes from a triggered assertion. | ||
| 260 | * | ||
| 261 | * When an enabled assertion triggers, it may call the assertion handler | ||
| 262 | * (possibly one provided by the app via SDL_SetAssertionHandler), which will | ||
| 263 | * return one of these values, possibly after asking the user. | ||
| 264 | * | ||
| 265 | * Then SDL will respond based on this outcome (loop around to retry the | ||
| 266 | * condition, try to break in a debugger, kill the program, or ignore the | ||
| 267 | * problem). | ||
| 268 | * | ||
| 269 | * \since This enum is available since SDL 3.2.0. | ||
| 270 | */ | ||
| 271 | typedef enum SDL_AssertState | ||
| 272 | { | ||
| 273 | SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */ | ||
| 274 | SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */ | ||
| 275 | SDL_ASSERTION_ABORT, /**< Terminate the program. */ | ||
| 276 | SDL_ASSERTION_IGNORE, /**< Ignore the assert. */ | ||
| 277 | SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */ | ||
| 278 | } SDL_AssertState; | ||
| 279 | |||
| 280 | /** | ||
| 281 | * Information about an assertion failure. | ||
| 282 | * | ||
| 283 | * This structure is filled in with information about a triggered assertion, | ||
| 284 | * used by the assertion handler, then added to the assertion report. This is | ||
| 285 | * returned as a linked list from SDL_GetAssertionReport(). | ||
| 286 | * | ||
| 287 | * \since This struct is available since SDL 3.2.0. | ||
| 288 | */ | ||
| 289 | typedef struct SDL_AssertData | ||
| 290 | { | ||
| 291 | bool always_ignore; /**< true if app should always continue when assertion is triggered. */ | ||
| 292 | unsigned int trigger_count; /**< Number of times this assertion has been triggered. */ | ||
| 293 | const char *condition; /**< A string of this assert's test code. */ | ||
| 294 | const char *filename; /**< The source file where this assert lives. */ | ||
| 295 | int linenum; /**< The line in `filename` where this assert lives. */ | ||
| 296 | const char *function; /**< The name of the function where this assert lives. */ | ||
| 297 | const struct SDL_AssertData *next; /**< next item in the linked list. */ | ||
| 298 | } SDL_AssertData; | ||
| 299 | |||
| 300 | /** | ||
| 301 | * Never call this directly. | ||
| 302 | * | ||
| 303 | * Use the SDL_assert macros instead. | ||
| 304 | * | ||
| 305 | * \param data assert data structure. | ||
| 306 | * \param func function name. | ||
| 307 | * \param file file name. | ||
| 308 | * \param line line number. | ||
| 309 | * \returns assert state. | ||
| 310 | * | ||
| 311 | * \threadsafety It is safe to call this function from any thread. | ||
| 312 | * | ||
| 313 | * \since This function is available since SDL 3.2.0. | ||
| 314 | */ | ||
| 315 | extern SDL_DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *data, | ||
| 316 | const char *func, | ||
| 317 | const char *file, int line) SDL_ANALYZER_NORETURN; | ||
| 318 | |||
| 319 | |||
| 320 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 321 | |||
| 322 | /** | ||
| 323 | * The macro used when an assertion triggers a breakpoint. | ||
| 324 | * | ||
| 325 | * This isn't for direct use by apps; use SDL_assert or SDL_TriggerBreakpoint | ||
| 326 | * instead. | ||
| 327 | * | ||
| 328 | * \since This macro is available since SDL 3.2.0. | ||
| 329 | */ | ||
| 330 | #define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() | ||
| 331 | |||
| 332 | #elif !defined(SDL_AssertBreakpoint) | ||
| 333 | # if defined(ANDROID) && defined(assert) | ||
| 334 | /* Define this as empty in case assert() is defined as SDL_assert */ | ||
| 335 | # define SDL_AssertBreakpoint() | ||
| 336 | # else | ||
| 337 | # define SDL_AssertBreakpoint() SDL_TriggerBreakpoint() | ||
| 338 | # endif | ||
| 339 | #endif /* !SDL_AssertBreakpoint */ | ||
| 340 | |||
| 341 | /** | ||
| 342 | * The macro used when an assertion is enabled. | ||
| 343 | * | ||
| 344 | * This isn't for direct use by apps, but this is the code that is inserted | ||
| 345 | * when an SDL_assert is enabled. | ||
| 346 | * | ||
| 347 | * The `do {} while(0)` avoids dangling else problems: | ||
| 348 | * | ||
| 349 | * ```c | ||
| 350 | * if (x) SDL_assert(y); else blah(); | ||
| 351 | * ``` | ||
| 352 | * | ||
| 353 | * ... without the do/while, the "else" could attach to this macro's "if". We | ||
| 354 | * try to handle just the minimum we need here in a macro...the loop, the | ||
| 355 | * static vars, and break points. The heavy lifting is handled in | ||
| 356 | * SDL_ReportAssertion(). | ||
| 357 | * | ||
| 358 | * \param condition the condition to assert. | ||
| 359 | * | ||
| 360 | * \since This macro is available since SDL 3.2.0. | ||
| 361 | */ | ||
| 362 | #define SDL_enabled_assert(condition) \ | ||
| 363 | do { \ | ||
| 364 | while ( !(condition) ) { \ | ||
| 365 | static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \ | ||
| 366 | const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \ | ||
| 367 | if (sdl_assert_state == SDL_ASSERTION_RETRY) { \ | ||
| 368 | continue; /* go again. */ \ | ||
| 369 | } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \ | ||
| 370 | SDL_AssertBreakpoint(); \ | ||
| 371 | } \ | ||
| 372 | break; /* not retrying. */ \ | ||
| 373 | } \ | ||
| 374 | } while (SDL_NULL_WHILE_LOOP_CONDITION) | ||
| 375 | |||
| 376 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION | ||
| 377 | |||
| 378 | /** | ||
| 379 | * An assertion test that is normally performed only in debug builds. | ||
| 380 | * | ||
| 381 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 2, otherwise it is | ||
| 382 | * disabled. This is meant to only do these tests in debug builds, so they can | ||
| 383 | * tend to be more expensive, and they are meant to bring everything to a halt | ||
| 384 | * when they fail, with the programmer there to assess the problem. | ||
| 385 | * | ||
| 386 | * In short: you can sprinkle these around liberally and assume they will | ||
| 387 | * evaporate out of the build when building for end-users. | ||
| 388 | * | ||
| 389 | * When assertions are disabled, this wraps `condition` in a `sizeof` | ||
| 390 | * operator, which means any function calls and side effects will not run, but | ||
| 391 | * the compiler will not complain about any otherwise-unused variables that | ||
| 392 | * are only referenced in the assertion. | ||
| 393 | * | ||
| 394 | * One can set the environment variable "SDL_ASSERT" to one of several strings | ||
| 395 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | ||
| 396 | * behavior, which may be desirable for automation purposes. If your platform | ||
| 397 | * requires GUI interfaces to happen on the main thread but you're debugging | ||
| 398 | * an assertion in a background thread, it might be desirable to set this to | ||
| 399 | * "break" so that your debugger takes control as soon as assert is triggered, | ||
| 400 | * instead of risking a bad UI interaction (deadlock, etc) in the application. | ||
| 401 | * | ||
| 402 | * \param condition boolean value to test. | ||
| 403 | * | ||
| 404 | * \threadsafety It is safe to call this macro from any thread. | ||
| 405 | * | ||
| 406 | * \since This macro is available since SDL 3.2.0. | ||
| 407 | */ | ||
| 408 | #define SDL_assert(condition) if (assertion_enabled && (condition)) { trigger_assertion; } | ||
| 409 | |||
| 410 | /** | ||
| 411 | * An assertion test that is performed even in release builds. | ||
| 412 | * | ||
| 413 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 1, otherwise it is | ||
| 414 | * disabled. This is meant to be for tests that are cheap to make and | ||
| 415 | * extremely unlikely to fail; generally it is frowned upon to have an | ||
| 416 | * assertion failure in a release build, so these assertions generally need to | ||
| 417 | * be of more than life-and-death importance if there's a chance they might | ||
| 418 | * trigger. You should almost always consider handling these cases more | ||
| 419 | * gracefully than an assert allows. | ||
| 420 | * | ||
| 421 | * When assertions are disabled, this wraps `condition` in a `sizeof` | ||
| 422 | * operator, which means any function calls and side effects will not run, but | ||
| 423 | * the compiler will not complain about any otherwise-unused variables that | ||
| 424 | * are only referenced in the assertion. | ||
| 425 | * | ||
| 426 | * One can set the environment variable "SDL_ASSERT" to one of several strings | ||
| 427 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | ||
| 428 | * behavior, which may be desirable for automation purposes. If your platform | ||
| 429 | * requires GUI interfaces to happen on the main thread but you're debugging | ||
| 430 | * an assertion in a background thread, it might be desirable to set this to | ||
| 431 | * "break" so that your debugger takes control as soon as assert is triggered, | ||
| 432 | * instead of risking a bad UI interaction (deadlock, etc) in the application. | ||
| 433 | * * | ||
| 434 | * | ||
| 435 | * \param condition boolean value to test. | ||
| 436 | * | ||
| 437 | * \threadsafety It is safe to call this macro from any thread. | ||
| 438 | * | ||
| 439 | * \since This macro is available since SDL 3.2.0. | ||
| 440 | */ | ||
| 441 | #define SDL_assert_release(condition) SDL_disabled_assert(condition) | ||
| 442 | |||
| 443 | /** | ||
| 444 | * An assertion test that is performed only when built with paranoid settings. | ||
| 445 | * | ||
| 446 | * This macro is enabled when the SDL_ASSERT_LEVEL is >= 3, otherwise it is | ||
| 447 | * disabled. This is a higher level than both release and debug, so these | ||
| 448 | * tests are meant to be expensive and only run when specifically looking for | ||
| 449 | * extremely unexpected failure cases in a special build. | ||
| 450 | * | ||
| 451 | * When assertions are disabled, this wraps `condition` in a `sizeof` | ||
| 452 | * operator, which means any function calls and side effects will not run, but | ||
| 453 | * the compiler will not complain about any otherwise-unused variables that | ||
| 454 | * are only referenced in the assertion. | ||
| 455 | * | ||
| 456 | * One can set the environment variable "SDL_ASSERT" to one of several strings | ||
| 457 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | ||
| 458 | * behavior, which may be desirable for automation purposes. If your platform | ||
| 459 | * requires GUI interfaces to happen on the main thread but you're debugging | ||
| 460 | * an assertion in a background thread, it might be desirable to set this to | ||
| 461 | * "break" so that your debugger takes control as soon as assert is triggered, | ||
| 462 | * instead of risking a bad UI interaction (deadlock, etc) in the application. | ||
| 463 | * | ||
| 464 | * \param condition boolean value to test. | ||
| 465 | * | ||
| 466 | * \threadsafety It is safe to call this macro from any thread. | ||
| 467 | * | ||
| 468 | * \since This macro is available since SDL 3.2.0. | ||
| 469 | */ | ||
| 470 | #define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | ||
| 471 | |||
| 472 | /* Enable various levels of assertions. */ | ||
| 473 | #elif SDL_ASSERT_LEVEL == 0 /* assertions disabled */ | ||
| 474 | # define SDL_assert(condition) SDL_disabled_assert(condition) | ||
| 475 | # define SDL_assert_release(condition) SDL_disabled_assert(condition) | ||
| 476 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | ||
| 477 | #elif SDL_ASSERT_LEVEL == 1 /* release settings. */ | ||
| 478 | # define SDL_assert(condition) SDL_disabled_assert(condition) | ||
| 479 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) | ||
| 480 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | ||
| 481 | #elif SDL_ASSERT_LEVEL == 2 /* debug settings. */ | ||
| 482 | # define SDL_assert(condition) SDL_enabled_assert(condition) | ||
| 483 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) | ||
| 484 | # define SDL_assert_paranoid(condition) SDL_disabled_assert(condition) | ||
| 485 | #elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */ | ||
| 486 | # define SDL_assert(condition) SDL_enabled_assert(condition) | ||
| 487 | # define SDL_assert_release(condition) SDL_enabled_assert(condition) | ||
| 488 | # define SDL_assert_paranoid(condition) SDL_enabled_assert(condition) | ||
| 489 | #else | ||
| 490 | # error Unknown assertion level. | ||
| 491 | #endif | ||
| 492 | |||
| 493 | /** | ||
| 494 | * An assertion test that is always performed. | ||
| 495 | * | ||
| 496 | * This macro is always enabled no matter what SDL_ASSERT_LEVEL is set to. You | ||
| 497 | * almost never want to use this, as it could trigger on an end-user's system, | ||
| 498 | * crashing your program. | ||
| 499 | * | ||
| 500 | * One can set the environment variable "SDL_ASSERT" to one of several strings | ||
| 501 | * ("abort", "break", "retry", "ignore", "always_ignore") to force a default | ||
| 502 | * behavior, which may be desirable for automation purposes. If your platform | ||
| 503 | * requires GUI interfaces to happen on the main thread but you're debugging | ||
| 504 | * an assertion in a background thread, it might be desirable to set this to | ||
| 505 | * "break" so that your debugger takes control as soon as assert is triggered, | ||
| 506 | * instead of risking a bad UI interaction (deadlock, etc) in the application. | ||
| 507 | * | ||
| 508 | * \param condition boolean value to test. | ||
| 509 | * | ||
| 510 | * \threadsafety It is safe to call this macro from any thread. | ||
| 511 | * | ||
| 512 | * \since This macro is available since SDL 3.2.0. | ||
| 513 | */ | ||
| 514 | #define SDL_assert_always(condition) SDL_enabled_assert(condition) | ||
| 515 | |||
| 516 | |||
| 517 | /** | ||
| 518 | * A callback that fires when an SDL assertion fails. | ||
| 519 | * | ||
| 520 | * \param data a pointer to the SDL_AssertData structure corresponding to the | ||
| 521 | * current assertion. | ||
| 522 | * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler(). | ||
| 523 | * \returns an SDL_AssertState value indicating how to handle the failure. | ||
| 524 | * | ||
| 525 | * \threadsafety This callback may be called from any thread that triggers an | ||
| 526 | * assert at any time. | ||
| 527 | * | ||
| 528 | * \since This datatype is available since SDL 3.2.0. | ||
| 529 | */ | ||
| 530 | typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)( | ||
| 531 | const SDL_AssertData *data, void *userdata); | ||
| 532 | |||
| 533 | /** | ||
| 534 | * Set an application-defined assertion handler. | ||
| 535 | * | ||
| 536 | * This function allows an application to show its own assertion UI and/or | ||
| 537 | * force the response to an assertion failure. If the application doesn't | ||
| 538 | * provide this, SDL will try to do the right thing, popping up a | ||
| 539 | * system-specific GUI dialog, and probably minimizing any fullscreen windows. | ||
| 540 | * | ||
| 541 | * This callback may fire from any thread, but it runs wrapped in a mutex, so | ||
| 542 | * it will only fire from one thread at a time. | ||
| 543 | * | ||
| 544 | * This callback is NOT reset to SDL's internal handler upon SDL_Quit()! | ||
| 545 | * | ||
| 546 | * \param handler the SDL_AssertionHandler function to call when an assertion | ||
| 547 | * fails or NULL for the default handler. | ||
| 548 | * \param userdata a pointer that is passed to `handler`. | ||
| 549 | * | ||
| 550 | * \threadsafety It is safe to call this function from any thread. | ||
| 551 | * | ||
| 552 | * \since This function is available since SDL 3.2.0. | ||
| 553 | * | ||
| 554 | * \sa SDL_GetAssertionHandler | ||
| 555 | */ | ||
| 556 | extern SDL_DECLSPEC void SDLCALL SDL_SetAssertionHandler( | ||
| 557 | SDL_AssertionHandler handler, | ||
| 558 | void *userdata); | ||
| 559 | |||
| 560 | /** | ||
| 561 | * Get the default assertion handler. | ||
| 562 | * | ||
| 563 | * This returns the function pointer that is called by default when an | ||
| 564 | * assertion is triggered. This is an internal function provided by SDL, that | ||
| 565 | * is used for assertions when SDL_SetAssertionHandler() hasn't been used to | ||
| 566 | * provide a different function. | ||
| 567 | * | ||
| 568 | * \returns the default SDL_AssertionHandler that is called when an assert | ||
| 569 | * triggers. | ||
| 570 | * | ||
| 571 | * \threadsafety It is safe to call this function from any thread. | ||
| 572 | * | ||
| 573 | * \since This function is available since SDL 3.2.0. | ||
| 574 | * | ||
| 575 | * \sa SDL_GetAssertionHandler | ||
| 576 | */ | ||
| 577 | extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void); | ||
| 578 | |||
| 579 | /** | ||
| 580 | * Get the current assertion handler. | ||
| 581 | * | ||
| 582 | * This returns the function pointer that is called when an assertion is | ||
| 583 | * triggered. This is either the value last passed to | ||
| 584 | * SDL_SetAssertionHandler(), or if no application-specified function is set, | ||
| 585 | * is equivalent to calling SDL_GetDefaultAssertionHandler(). | ||
| 586 | * | ||
| 587 | * The parameter `puserdata` is a pointer to a void*, which will store the | ||
| 588 | * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value | ||
| 589 | * will always be NULL for the default handler. If you don't care about this | ||
| 590 | * data, it is safe to pass a NULL pointer to this function to ignore it. | ||
| 591 | * | ||
| 592 | * \param puserdata pointer which is filled with the "userdata" pointer that | ||
| 593 | * was passed to SDL_SetAssertionHandler(). | ||
| 594 | * \returns the SDL_AssertionHandler that is called when an assert triggers. | ||
| 595 | * | ||
| 596 | * \threadsafety It is safe to call this function from any thread. | ||
| 597 | * | ||
| 598 | * \since This function is available since SDL 3.2.0. | ||
| 599 | * | ||
| 600 | * \sa SDL_SetAssertionHandler | ||
| 601 | */ | ||
| 602 | extern SDL_DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata); | ||
| 603 | |||
| 604 | /** | ||
| 605 | * Get a list of all assertion failures. | ||
| 606 | * | ||
| 607 | * This function gets all assertions triggered since the last call to | ||
| 608 | * SDL_ResetAssertionReport(), or the start of the program. | ||
| 609 | * | ||
| 610 | * The proper way to examine this data looks something like this: | ||
| 611 | * | ||
| 612 | * ```c | ||
| 613 | * const SDL_AssertData *item = SDL_GetAssertionReport(); | ||
| 614 | * while (item) { | ||
| 615 | * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n", | ||
| 616 | * item->condition, item->function, item->filename, | ||
| 617 | * item->linenum, item->trigger_count, | ||
| 618 | * item->always_ignore ? "yes" : "no"); | ||
| 619 | * item = item->next; | ||
| 620 | * } | ||
| 621 | * ``` | ||
| 622 | * | ||
| 623 | * \returns a list of all failed assertions or NULL if the list is empty. This | ||
| 624 | * memory should not be modified or freed by the application. This | ||
| 625 | * pointer remains valid until the next call to SDL_Quit() or | ||
| 626 | * SDL_ResetAssertionReport(). | ||
| 627 | * | ||
| 628 | * \threadsafety This function is not thread safe. Other threads calling | ||
| 629 | * SDL_ResetAssertionReport() simultaneously, may render the | ||
| 630 | * returned pointer invalid. | ||
| 631 | * | ||
| 632 | * \since This function is available since SDL 3.2.0. | ||
| 633 | * | ||
| 634 | * \sa SDL_ResetAssertionReport | ||
| 635 | */ | ||
| 636 | extern SDL_DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void); | ||
| 637 | |||
| 638 | /** | ||
| 639 | * Clear the list of all assertion failures. | ||
| 640 | * | ||
| 641 | * This function will clear the list of all assertions triggered up to that | ||
| 642 | * point. Immediately following this call, SDL_GetAssertionReport will return | ||
| 643 | * no items. In addition, any previously-triggered assertions will be reset to | ||
| 644 | * a trigger_count of zero, and their always_ignore state will be false. | ||
| 645 | * | ||
| 646 | * \threadsafety This function is not thread safe. Other threads triggering an | ||
| 647 | * assertion, or simultaneously calling this function may cause | ||
| 648 | * memory leaks or crashes. | ||
| 649 | * | ||
| 650 | * \since This function is available since SDL 3.2.0. | ||
| 651 | * | ||
| 652 | * \sa SDL_GetAssertionReport | ||
| 653 | */ | ||
| 654 | extern SDL_DECLSPEC void SDLCALL SDL_ResetAssertionReport(void); | ||
| 655 | |||
| 656 | /* Ends C function definitions when using C++ */ | ||
| 657 | #ifdef __cplusplus | ||
| 658 | } | ||
| 659 | #endif | ||
| 660 | #include <SDL3/SDL_close_code.h> | ||
| 661 | |||
| 662 | #endif /* SDL_assert_h_ */ | ||
