2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* error_macros.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
2018-01-05 00:50:27 +01:00
2014-02-10 02:10:30 +01:00
# ifndef ERROR_MACROS_H
# define ERROR_MACROS_H
2018-09-11 18:13:45 +02:00
# include "core/typedefs.h"
2014-02-10 02:10:30 +01:00
2023-01-09 10:15:35 +01:00
# include <atomic> // We'd normally use safe_refcount.h, but that would cause circular includes.
2021-02-10 19:22:13 +01:00
2019-11-06 08:38:23 +01:00
class String ;
2014-02-10 02:10:30 +01:00
enum ErrorHandlerType {
ERR_HANDLER_ERROR ,
ERR_HANDLER_WARNING ,
2016-10-10 23:31:01 +02:00
ERR_HANDLER_SCRIPT ,
ERR_HANDLER_SHADER ,
2014-02-10 02:10:30 +01:00
} ;
2019-11-06 08:38:23 +01:00
// Pointer to the error handler printing function. Reassign to any function to have errors printed.
// Parameters: userdata, function, file, line, error, explanation, type.
2021-09-22 17:36:40 +02:00
typedef void ( * ErrorHandlerFunc ) ( void * , const char * , const char * , int p_line , const char * , const char * , bool p_editor_notify , ErrorHandlerType p_type ) ;
2014-02-10 02:10:30 +01:00
struct ErrorHandlerList {
2020-05-12 17:01:17 +02:00
ErrorHandlerFunc errfunc = nullptr ;
void * userdata = nullptr ;
2014-02-10 02:10:30 +01:00
2020-05-12 17:01:17 +02:00
ErrorHandlerList * next = nullptr ;
2014-02-10 02:10:30 +01:00
2020-05-12 17:01:17 +02:00
ErrorHandlerList ( ) { }
2014-02-10 02:10:30 +01:00
} ;
void add_error_handler ( ErrorHandlerList * p_handler ) ;
2022-04-05 12:40:26 +02:00
void remove_error_handler ( const ErrorHandlerList * p_handler ) ;
2014-02-10 02:10:30 +01:00
2019-11-06 08:38:23 +01:00
// Functions used by the error macros.
2021-09-22 17:36:40 +02:00
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const char * p_error , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const String & p_error , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const char * p_error , const char * p_message , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const String & p_error , const char * p_message , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const char * p_error , const String & p_message , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_error ( const char * p_function , const char * p_file , int p_line , const String & p_error , const String & p_message , bool p_editor_notify = false , ErrorHandlerType p_type = ERR_HANDLER_ERROR ) ;
void _err_print_index_error ( const char * p_function , const char * p_file , int p_line , int64_t p_index , int64_t p_size , const char * p_index_str , const char * p_size_str , const char * p_message = " " , bool p_editor_notify = false , bool fatal = false ) ;
void _err_print_index_error ( const char * p_function , const char * p_file , int p_line , int64_t p_index , int64_t p_size , const char * p_index_str , const char * p_size_str , const String & p_message , bool p_editor_notify = false , bool fatal = false ) ;
2022-02-05 13:31:54 +01:00
void _err_flush_stdout ( ) ;
2014-02-10 02:10:30 +01:00
# ifdef __GNUC__
//#define FUNCTION_STR __PRETTY_FUNCTION__ - too annoying
# define FUNCTION_STR __FUNCTION__
# else
# define FUNCTION_STR __FUNCTION__
# endif
2017-05-26 21:11:16 +02:00
# ifdef _MSC_VER
2020-02-05 14:39:12 +01:00
/**
* Don ' t use GENERATE_TRAP ( ) directly , should only be used be the macros below .
*/
2019-11-06 08:38:23 +01:00
# define GENERATE_TRAP() __debugbreak()
2017-05-26 21:11:16 +02:00
# else
2020-02-05 14:39:12 +01:00
/**
* Don ' t use GENERATE_TRAP ( ) directly , should only be used be the macros below .
*/
2019-11-06 08:38:23 +01:00
# define GENERATE_TRAP() __builtin_trap()
2017-05-26 21:11:16 +02:00
# endif
2020-01-24 16:53:52 +01:00
/**
2019-11-06 08:38:23 +01:00
* Error macros .
* WARNING : These macros work in the opposite way to assert ( ) .
*
* Unlike exceptions and asserts , these macros try to maintain consistency and stability .
* In most cases , bugs and / or invalid data are not fatal . They should never allow a perfectly
* running application to fail or crash .
* Always try to return processable data , so the engine can keep running well .
* Use the _MSG versions to print a meaningful message to help with debugging .
2020-05-15 17:48:09 +02:00
*
* The ` ( ( void ) 0 ) ` no - op statement is used as a trick to force us to put a semicolon after
* those macros , making them look like proper statements .
* The if wrappers are used to ensure that the macro replacement does not trigger unexpected
* issues when expanded e . g . after an ` if ( cond ) ERR_FAIL ( ) ; ` without braces .
2020-01-24 16:53:52 +01:00
*/
2019-11-06 08:38:23 +01:00
// Index out of bounds error macros.
// These macros should be used instead of `ERR_FAIL_COND` for bounds checking.
// Integer index out of bounds error macros.
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_INDEX_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , the current function returns .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_INDEX(m_index, m_size) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) ) ; \
return ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , prints ` m_msg ` and the current function returns .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_INDEX_MSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg ) ; \
return ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_INDEX_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_INDEX_EDMSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , true ) ; \
return ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_INDEX_V_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , the current function returns ` m_retval ` .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_INDEX_V(m_index, m_size, m_retval) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2017-05-26 21:11:16 +02:00
2020-02-05 14:39:12 +01:00
/**
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , prints ` m_msg ` and the current function returns ` m_retval ` .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_INDEX_V_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , true ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_INDEX_MSG ` or ` ERR_FAIL_INDEX_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable , and
* there is no sensible error message .
*
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , the application crashes .
*/
2023-01-22 12:23:56 +01:00
# define CRASH_BAD_INDEX(m_index, m_size) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , " " , false , true ) ; \
_err_flush_stdout ( ) ; \
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_INDEX_MSG ` or ` ERR_FAIL_INDEX_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable .
*
* Ensures an integer index ` m_index ` is less than ` m_size ` and greater than or equal to 0.
* If not , prints ` m_msg ` and the application crashes .
*/
2023-01-22 12:23:56 +01:00
# define CRASH_BAD_INDEX_MSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) < 0 | | ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , false , true ) ; \
_err_flush_stdout ( ) ; \
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
// Unsigned integer index out of bounds error macros.
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_UNSIGNED_INDEX_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , the current function returns .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_UNSIGNED_INDEX(m_index, m_size) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) ) ; \
return ; \
} else \
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , prints ` m_msg ` and the current function returns .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg ) ; \
return ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2022-10-04 16:33:49 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_UNSIGNED_INDEX_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_UNSIGNED_INDEX_EDMSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , true ) ; \
return ; \
} else \
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_UNSIGNED_INDEX_V_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , the current function returns ` m_retval ` .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_UNSIGNED_INDEX_V(m_index, m_size, m_retval) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2019-02-20 21:59:03 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , prints ` m_msg ` and the current function returns ` m_retval ` .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_UNSIGNED_INDEX_V_MSG(m_index, m_size, m_retval, m_msg) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_UNSIGNED_INDEX_V_EDMSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_UNSIGNED_INDEX_V_EDMSG(m_index, m_size, m_retval, m_msg) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , true ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_UNSIGNED_INDEX_MSG ` or ` ERR_FAIL_UNSIGNED_INDEX_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable , and
* there is no sensible error message .
*
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , the application crashes .
*/
2023-01-22 12:23:56 +01:00
# define CRASH_BAD_UNSIGNED_INDEX(m_index, m_size) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , " " , false , true ) ; \
_err_flush_stdout ( ) ; \
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_UNSIGNED_INDEX_MSG ` or ` ERR_FAIL_UNSIGNED_INDEX_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable .
*
* Ensures an unsigned integer index ` m_index ` is less than ` m_size ` .
* If not , prints ` m_msg ` and the application crashes .
*/
2023-01-22 12:23:56 +01:00
# define CRASH_BAD_UNSIGNED_INDEX_MSG(m_index, m_size, m_msg) \
if ( unlikely ( ( m_index ) > = ( m_size ) ) ) { \
_err_print_index_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_index , m_size , _STR ( m_index ) , _STR ( m_size ) , m_msg , false , true ) ; \
_err_flush_stdout ( ) ; \
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
// Null reference error macros.
2019-07-28 17:00:50 +02:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_NULL_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures a pointer ` m_param ` is not null .
* If it is null , the current function returns .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_NULL(m_param) \
2020-06-12 20:37:47 +02:00
if ( unlikely ( m_param = = nullptr ) ) { \
2020-02-08 08:35:52 +01:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " ) ; \
return ; \
} else \
( ( void ) 0 )
2017-03-05 16:44:50 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures a pointer ` m_param ` is not null .
* If it is null , prints ` m_msg ` and the current function returns .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_NULL_MSG(m_param, m_msg) \
if ( unlikely ( m_param = = nullptr ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " , m_msg ) ; \
return ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_NULL_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_NULL_EDMSG(m_param, m_msg) \
if ( unlikely ( m_param = = nullptr ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " , m_msg , true ) ; \
return ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_NULL_V_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures a pointer ` m_param ` is not null .
* If it is null , the current function returns ` m_retval ` .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_NULL_V(m_param, m_retval) \
2020-06-12 20:37:47 +02:00
if ( unlikely ( m_param = = nullptr ) ) { \
2020-02-08 08:35:52 +01:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures a pointer ` m_param ` is not null .
* If it is null , prints ` m_msg ` and the current function returns ` m_retval ` .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_NULL_V_MSG(m_param, m_retval, m_msg) \
if ( unlikely ( m_param = = nullptr ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " , m_msg ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_NULL_V_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_NULL_V_EDMSG(m_param, m_retval, m_msg) \
if ( unlikely ( m_param = = nullptr ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Parameter \" " _STR ( m_param ) " \" is null. " , m_msg , true ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_MSG ` .
* Only use this macro if there is no sensible error message .
* If checking for null use ERR_FAIL_NULL_MSG instead .
* If checking index bounds use ERR_FAIL_INDEX_MSG instead .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , the current function returns .
*/
2020-02-08 08:35:52 +01:00
# define ERR_FAIL_COND(m_cond) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. " ) ; \
return ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , prints ` m_msg ` and the current function returns .
*
* If checking for null use ERR_FAIL_NULL_MSG instead .
* If checking index bounds use ERR_FAIL_INDEX_MSG instead .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_COND_MSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. " , m_msg ) ; \
return ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_COND_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_COND_EDMSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. " , m_msg , true ) ; \
return ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_V_MSG ` .
* Only use this macro if there is no sensible error message .
* If checking for null use ERR_FAIL_NULL_V_MSG instead .
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , the current function returns ` m_retval ` .
*/
2020-05-15 17:48:09 +02:00
# define ERR_FAIL_COND_V(m_cond, m_retval) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Returning: " _STR ( m_retval ) ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , prints ` m_msg ` and the current function returns ` m_retval ` .
*
* If checking for null use ERR_FAIL_NULL_V_MSG instead .
* If checking index bounds use ERR_FAIL_INDEX_V_MSG instead .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_COND_V_MSG(m_cond, m_retval, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Returning: " _STR ( m_retval ) , m_msg ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_COND_V_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_COND_V_EDMSG(m_cond, m_retval, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Returning: " _STR ( m_retval ) , m_msg , true ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_CONTINUE_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , the current loop continues .
*/
2020-02-08 08:35:52 +01:00
# define ERR_CONTINUE(m_cond) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Continuing. " ) ; \
continue ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , prints ` m_msg ` and the current loop continues .
*/
2021-10-04 19:45:56 +02:00
# define ERR_CONTINUE_MSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Continuing. " , m_msg ) ; \
continue ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_CONTINUE_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_CONTINUE_EDMSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Continuing. " , m_msg , true ) ; \
continue ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_BREAK_MSG ` .
* Only use this macro if there is no sensible error message .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , the current loop breaks .
*/
2020-02-08 08:35:52 +01:00
# define ERR_BREAK(m_cond) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Breaking. " ) ; \
break ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , prints ` m_msg ` and the current loop breaks .
*/
2021-10-04 19:45:56 +02:00
# define ERR_BREAK_MSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Breaking. " , m_msg ) ; \
break ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_BREAK_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_BREAK_EDMSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Condition \" " _STR ( m_cond ) " \" is true. Breaking. " , m_msg , true ) ; \
break ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_MSG ` or ` ERR_FAIL_COND_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable , and
* there is no sensible error message .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , the application crashes .
*/
2020-02-08 08:35:52 +01:00
# define CRASH_COND(m_cond) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " FATAL: Condition \" " _STR ( m_cond ) " \" is true. " ) ; \
2022-03-07 12:15:45 +01:00
_err_flush_stdout ( ) ; \
2020-02-08 08:35:52 +01:00
GENERATE_TRAP ( ) ; \
} else \
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_MSG ` or ` ERR_FAIL_COND_V_MSG ` .
* Only use this macro if there is no sensible fallback i . e . the error is unrecoverable .
*
* Ensures ` m_cond ` is false .
* If ` m_cond ` is true , prints ` m_msg ` and the application crashes .
*/
2021-10-04 19:45:56 +02:00
# define CRASH_COND_MSG(m_cond, m_msg) \
if ( unlikely ( m_cond ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " FATAL: Condition \" " _STR ( m_cond ) " \" is true. " , m_msg ) ; \
2022-03-07 12:15:45 +01:00
_err_flush_stdout ( ) ; \
2021-10-04 19:45:56 +02:00
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2019-11-06 08:38:23 +01:00
// Generic error macros.
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_MSG ` or ` ERR_FAIL_MSG ` .
* Only use this macro if more complex error detection or recovery is required , and
* there is no sensible error message .
*
* The current function returns .
*/
2019-11-06 08:38:23 +01:00
# define ERR_FAIL() \
2020-07-05 19:22:23 +02:00
if ( true ) { \
2020-05-15 17:48:09 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. " ) ; \
2019-11-06 08:38:23 +01:00
return ; \
2020-02-08 08:35:52 +01:00
} else \
( ( void ) 0 )
2017-05-26 21:11:16 +02:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_MSG ` .
* Only use this macro if more complex error detection or recovery is required .
*
* Prints ` m_msg ` , and the current function returns .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_MSG(m_msg) \
if ( true ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. " , m_msg ) ; \
return ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2017-05-26 21:11:16 +02:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_EDMSG(m_msg) \
if ( true ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. " , m_msg , true ) ; \
return ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_V_MSG ` or ` ERR_FAIL_V_MSG ` .
* Only use this macro if more complex error detection or recovery is required , and
* there is no sensible error message .
*
* The current function returns ` m_retval ` .
*/
2020-03-11 21:01:02 +01:00
# define ERR_FAIL_V(m_retval) \
2020-07-05 19:22:23 +02:00
if ( true ) { \
2020-05-15 17:48:09 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. Returning: " _STR ( m_retval ) ) ; \
2020-03-11 21:01:02 +01:00
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2020-02-05 14:39:12 +01:00
/**
* Try using ` ERR_FAIL_COND_V_MSG ` .
* Only use this macro if more complex error detection or recovery is required .
*
* Prints ` m_msg ` , and the current function returns ` m_retval ` .
*/
2021-10-04 19:45:56 +02:00
# define ERR_FAIL_V_MSG(m_retval, m_msg) \
if ( true ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. Returning: " _STR ( m_retval ) , m_msg ) ; \
return m_retval ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2014-02-10 02:10:30 +01:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_FAIL_V_MSG ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_FAIL_V_EDMSG(m_retval, m_msg) \
if ( true ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " Method/function failed. Returning: " _STR ( m_retval ) , m_msg , true ) ; \
return m_retval ; \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
2022-10-04 16:33:49 +02:00
* Try using ` ERR_FAIL_COND_MSG ` , ` ERR_FAIL_COND_V_MSG ` , ` ERR_CONTINUE_MSG ` or ` ERR_BREAK_MSG ` .
2020-02-05 14:39:12 +01:00
* Only use this macro at the start of a function that has not been implemented yet , or
* if more complex error detection or recovery is required .
*
* Prints ` m_msg ` .
*/
2020-02-08 08:35:52 +01:00
# define ERR_PRINT(m_msg) \
2020-05-01 14:34:23 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg )
2014-02-10 02:10:30 +01:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_PRINT ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_PRINT_ED(m_msg) \
2022-10-04 16:33:49 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , true )
2021-09-22 17:36:40 +02:00
2020-02-05 14:39:12 +01:00
/**
* Prints ` m_msg ` once during the application lifetime .
*/
2020-05-01 14:34:23 +02:00
# define ERR_PRINT_ONCE(m_msg) \
2020-07-05 19:22:23 +02:00
if ( true ) { \
2020-05-01 14:34:23 +02:00
static bool first_print = true ; \
if ( first_print ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg ) ; \
first_print = false ; \
} \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-03-01 20:01:21 +01:00
2021-09-22 17:36:40 +02:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` ERR_PRINT_ONCE ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define ERR_PRINT_ONCE_ED(m_msg) \
if ( true ) { \
static bool first_print = true ; \
if ( first_print ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , true ) ; \
first_print = false ; \
} \
} else \
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
// Print warning message macros.
2020-02-05 14:39:12 +01:00
/**
* Prints ` m_msg ` .
*
* If warning about deprecated usage , use ` WARN_DEPRECATED ` or ` WARN_DEPRECATED_MSG ` instead .
*/
2020-02-08 08:35:52 +01:00
# define WARN_PRINT(m_msg) \
2021-09-22 17:36:40 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , false , ERR_HANDLER_WARNING )
/**
2022-10-04 16:33:49 +02:00
* Same as ` WARN_PRINT ` but also notifies the editor .
2021-09-22 17:36:40 +02:00
*/
# define WARN_PRINT_ED(m_msg) \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , true , ERR_HANDLER_WARNING )
2014-02-10 02:10:30 +01:00
2020-02-05 14:39:12 +01:00
/**
* Prints ` m_msg ` once during the application lifetime .
*
* If warning about deprecated usage , use ` WARN_DEPRECATED ` or ` WARN_DEPRECATED_MSG ` instead .
*/
2021-09-22 17:36:40 +02:00
# define WARN_PRINT_ONCE(m_msg) \
if ( true ) { \
static bool first_print = true ; \
if ( first_print ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , false , ERR_HANDLER_WARNING ) ; \
first_print = false ; \
} \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-03-01 20:01:21 +01:00
2020-02-05 14:39:12 +01:00
/**
2022-10-04 16:33:49 +02:00
* Same as ` WARN_PRINT_ONCE ` but also notifies the editor .
2020-02-05 14:39:12 +01:00
*/
2021-09-22 17:36:40 +02:00
# define WARN_PRINT_ONCE_ED(m_msg) \
if ( true ) { \
static bool first_print = true ; \
if ( first_print ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , m_msg , true , ERR_HANDLER_WARNING ) ; \
first_print = false ; \
} \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-07 10:37:44 +01:00
2021-09-22 17:36:40 +02:00
// Print deprecated warning message macros.
2020-02-05 14:39:12 +01:00
/**
2021-09-22 17:36:40 +02:00
* Warns that the current function is deprecated .
2020-02-05 14:39:12 +01:00
*/
2021-09-22 17:36:40 +02:00
# define WARN_DEPRECATED \
2021-10-04 19:45:56 +02:00
if ( true ) { \
2023-01-09 10:15:35 +01:00
static std : : atomic < bool > warning_shown ; \
if ( ! warning_shown . load ( ) ) { \
2021-09-22 17:36:40 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " This method has been deprecated and will be removed in the future. " , false , ERR_HANDLER_WARNING ) ; \
2023-01-09 10:15:35 +01:00
warning_shown . store ( true ) ; \
2021-10-04 19:45:56 +02:00
} \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2021-09-22 17:36:40 +02:00
/**
* Warns that the current function is deprecated and prints ` m_msg ` .
*/
# define WARN_DEPRECATED_MSG(m_msg) \
if ( true ) { \
2023-01-09 10:15:35 +01:00
static std : : atomic < bool > warning_shown ; \
if ( ! warning_shown . load ( ) ) { \
2021-09-22 17:36:40 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " This method has been deprecated and will be removed in the future. " , m_msg , false , ERR_HANDLER_WARNING ) ; \
2023-01-09 10:15:35 +01:00
warning_shown . store ( true ) ; \
2021-09-22 17:36:40 +02:00
} \
} else \
( ( void ) 0 )
2020-02-05 14:39:12 +01:00
/**
* Do not use .
* If the application should never reach this point use CRASH_NOW_MSG ( m_msg ) to explain why .
*
* The application crashes .
*/
2019-11-06 08:38:23 +01:00
# define CRASH_NOW() \
2020-07-05 19:22:23 +02:00
if ( true ) { \
2020-05-15 17:48:09 +02:00
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " FATAL: Method/function failed. " ) ; \
2022-02-05 13:31:54 +01:00
_err_flush_stdout ( ) ; \
2019-11-06 08:38:23 +01:00
GENERATE_TRAP ( ) ; \
2020-02-08 08:35:52 +01:00
} else \
( ( void ) 0 )
2019-11-06 08:38:23 +01:00
2020-02-05 14:39:12 +01:00
/**
* Only use if the application should never reach this point .
*
* Prints ` m_msg ` , and then the application crashes .
*/
2021-10-04 19:45:56 +02:00
# define CRASH_NOW_MSG(m_msg) \
if ( true ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " FATAL: Method/function failed. " , m_msg ) ; \
2022-02-05 13:31:54 +01:00
_err_flush_stdout ( ) ; \
2021-10-04 19:45:56 +02:00
GENERATE_TRAP ( ) ; \
} else \
2020-02-08 08:35:52 +01:00
( ( void ) 0 )
2019-07-28 17:00:50 +02:00
2022-03-07 12:15:45 +01:00
/**
* This should be a ' free ' assert for program flow and should not be needed in any releases ,
* only used in dev builds .
*/
# ifdef DEV_ENABLED
# define DEV_ASSERT(m_cond) \
if ( unlikely ( ! ( m_cond ) ) ) { \
_err_print_error ( FUNCTION_STR , __FILE__ , __LINE__ , " FATAL: DEV_ASSERT failed \" " _STR ( m_cond ) " \" is false. " ) ; \
_err_flush_stdout ( ) ; \
GENERATE_TRAP ( ) ; \
} else \
( ( void ) 0 )
# else
# define DEV_ASSERT(m_cond)
# endif
2020-03-25 11:10:34 +01:00
# endif // ERROR_MACROS_H