File indexing completed on 2024-05-12 15:56:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #ifndef __KIS_ASSERT_H
0008 #define __KIS_ASSERT_H
0009 
0010 #include <QtGlobal>
0011 #include <kritaglobal_export.h>
0012 
0013 KRITAGLOBAL_EXPORT void kis_assert_exception(const char *assertion, const char *file, int line);
0014 KRITAGLOBAL_EXPORT void kis_assert_recoverable(const char *assertion, const char *file, int line);
0015 KRITAGLOBAL_EXPORT void kis_assert_x_exception(const char *assertion, const char *where, const char *what, const char *file, int line);
0016 
0017 KRITAGLOBAL_EXPORT void kis_safe_assert_recoverable(const char *assertion, const char *file, int line);
0018 
0019 
0020 /**
0021  * KIS_ASSERT family of macros allows the user to choose whether to
0022  * try to continue working in Krita or to abort an application and see
0023  * a backtrace.
0024  *
0025  * Note, the macro are present in Release mode by default!
0026  */
0027 
0028 /**
0029  * Checks the condition and depending on the user action either aborts
0030  * the program or throws an exception, which restarts event loop.
0031  */
0032 #define KIS_ASSERT(cond) ((!(cond)) ? kis_assert_exception(#cond,__FILE__,__LINE__) : qt_noop())
0033 
0034 /**
0035  * Same as KIS_ASSERT, but allows to show more text to the user.
0036  *
0037  * \see KIS_ASSERT
0038  */
0039 #define KIS_ASSERT_X(cond, where, what) ((!(cond)) ? kis_assert_x_exception(#cond,where, what,__FILE__,__LINE__) : qt_noop())
0040 
0041 
0042 /**
0043  * This is a recoverable variant of KIS_ASSERT. It doesn't throw any
0044  * exceptions.  It checks the condition, and either aborts the
0045  * application, or executes user-supplied code. The typical usecase is
0046  * the following:
0047  *
0048  * int fooBar = ...;
0049  * KIS_ASSERT_RECOVER (fooBar > 0) {
0050  *     // the code which is executed in a case of emergency
0051  * }
0052  *
0053  */
0054 #define KIS_ASSERT_RECOVER(cond) if (!(cond) && (kis_assert_recoverable(#cond,__FILE__,__LINE__), true))
0055 
0056 /**
0057  * Equivalent of the following:
0058  *
0059  * KIS_ASSERT_RECOVER(cond) {
0060  *     break;
0061  * }
0062  *
0063  */
0064 #define KIS_ASSERT_RECOVER_BREAK(cond) do { KIS_ASSERT_RECOVER(cond) { break; } } while (0)
0065 
0066 /**
0067  * Equivalent of the following:
0068  *
0069  * KIS_ASSERT_RECOVER(cond) {
0070  *     return;
0071  * }
0072  *
0073  */
0074 #define KIS_ASSERT_RECOVER_RETURN(cond) do { KIS_ASSERT_RECOVER(cond) { return; } } while (0)
0075 
0076 /**
0077  * Equivalent of the following:
0078  *
0079  * KIS_ASSERT_RECOVER(cond) {
0080  *     return val;
0081  * }
0082  *
0083  */
0084 #define KIS_ASSERT_RECOVER_RETURN_VALUE(cond, val) do { KIS_ASSERT_RECOVER(cond) { return (val); } } while (0)
0085 
0086 /**
0087  * Does nothing in case of a failure. Just continues execution.
0088  *
0089  * Equivalent of the following:
0090  *
0091  * KIS_ASSERT_RECOVER(cond) {
0092  *     qt_noop();
0093  * }
0094  *
0095  */
0096 #define KIS_ASSERT_RECOVER_NOOP(cond) do { KIS_ASSERT_RECOVER(cond) { qt_noop(); } } while (0)
0097 
0098 
0099 /**
0100  * This set of macros work in exactly the same way as their non-safe
0101  * counterparts, but they are automatically converted into console
0102  * warnings in release builds. That is the user will not see any
0103  * message box, just a warning message will be printed in a terminal
0104  * and a recovery branch will be taken automatically.
0105  *
0106  * Rules when to use "safe" asserts. Use them if the following
0107  * conditions are met:
0108  *
0109  * 1) The condition in the assert shows that a real *bug* has
0110  *    happened. It is not just a warning. It is a bug that should be
0111  *    fixed.
0112  *
0113  * 2) The recovery branch will *workaround* the bug and the user will
0114  *    be able to continue his work *as if nothing has
0115  *    happened*. Again, please mark the assert "safe" if and only if
0116  *    you are 100% sure Krita will not crash in a minute after you
0117  *    faced that bug. The user is not notified about this bug, so he
0118  *    is not going to take any emergency steps like saving his work
0119  *    and restarting Krita!
0120  *
0121  * 3) If you think that Krita should be better restarted after this
0122  *    bug, please use a usual KIS_ASSERT_RECOVER.
0123  */
0124 
0125 #define KIS_SAFE_ASSERT_RECOVER(cond) if (!(cond) && (kis_safe_assert_recoverable(#cond,__FILE__,__LINE__), true))
0126 #define KIS_SAFE_ASSERT_RECOVER_BREAK(cond) do { KIS_SAFE_ASSERT_RECOVER(cond) { break; } } while (0)
0127 #define KIS_SAFE_ASSERT_RECOVER_RETURN(cond) do { KIS_SAFE_ASSERT_RECOVER(cond) { return; } } while (0)
0128 #define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val) do { KIS_SAFE_ASSERT_RECOVER(cond) { return (val); } } while (0)
0129 #define KIS_SAFE_ASSERT_RECOVER_NOOP(cond) do { KIS_SAFE_ASSERT_RECOVER(cond) { qt_noop(); } } while (0)
0130 
0131 #endif /* __KIS_ASSERT_H */