File indexing completed on 2024-05-19 04:25:03

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