blob: ba40f00455ab1d55047472b12320260c25bf053d [file]
/*
*
* Copyright (c) 2026 Project CHIP Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* Define and implement basic support for handling assertions and aborting code execution.
* Macros and functions in this file do not perform any logging therefore can be used in
* contexts where I/O or memory allocation are not allowed.
*
* The abort function is customizable by defining `CHIP_CONFIG_ABORT`.
*/
#pragma once
#include <cstdlib>
#include <lib/core/CHIPConfig.h>
/**
* @brief
* Base-level abnormal termination.
*
* Terminate the program immediately, without invoking destructors, atexit callbacks, etc.
* Used to implement the default `chipAbort()` function.
*
* @note
* This should never be invoked directly by code outside this file.
*/
#if !defined(CHIP_CONFIG_ABORT)
#define CHIP_CONFIG_ABORT() abort()
#endif
/**
* @brief
* This is invoked when an assertion expression evaluates to false.
*
* Developers may override and customize this by defining #chipAbort
* before this file is included by the preprocessor.
*/
#ifndef chipAbort
extern "C" void chipAbort(void) __attribute((noreturn));
inline void chipAbort(void)
{
while (true)
{
CHIP_CONFIG_ABORT();
}
}
#endif // chipAbort
/**
* @def VerifyOrDieWithoutLogging(expr)
*
* @brief
* This checks for the specified @a cond, which is expected to
* commonly be true. Aborts if the condition is false. This macro
* does not log.
*
* @param[in] cond A Boolean expression to be evaluated.
*/
#define VerifyOrDieWithoutLogging(cond) \
do \
{ \
if (!(cond)) \
{ \
chipAbort(); \
} \
} while (false)
/**
* @def AbortWithAction(anAction...)
*
* @brief
* Do something and abort code execution by calling chipAbort()
*
* @param[in] ... Statements to execute.
*/
#define AbortWithAction(...) \
do \
{ \
__VA_ARGS__; \
chipAbort(); \
} while (false)
/**
* @def VerifyOrExit(aCondition, anAction)
*
* @brief
* This checks for the specified condition, which is expected to
* commonly be true, and both executes @a anAction and branches to
* the local label 'exit' if the condition is false.
*
* Example Usage:
*
* @code
* CHIP_ERROR MakeBuffer(const uint8_t *& buf)
* {
* CHIP_ERROR err = CHIP_NO_ERROR;
*
* buf = (uint8_t *)malloc(1024);
* VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
*
* memset(buf, 0, 1024);
*
* exit:
* return err;
* }
* @endcode
*
* @param[in] aCondition A Boolean expression to be evaluated.
* @param[in] anAction An expression or block to execute when the
* assertion fails.
*
*/
#define VerifyOrExit(aCondition, anAction) VerifyOrDo(aCondition, anAction; goto exit)
/**
* @def VerifyOrReturnError(expr, code, ...)
*
* @brief
* Returns a specified error code if expression evaluates to false
*
* Example usage:
*
* @code
* VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
* @endcode
*
* @param[in] expr A Boolean expression to be evaluated.
* @param[in] code A value to return if @a expr is false.
* @param[in] ... Statements to execute before returning. Optional.
*/
#define VerifyOrReturnError(expr, code, ...) VerifyOrReturnValue(expr, code, ##__VA_ARGS__)
/**
* @def VerifyOrReturnValue(expr, value, ...)
*
* @brief
* Returns a specified value if expression evaluates to false
*
* Example usage:
*
* @code
* VerifyOrReturnError(param != nullptr, Foo());
* @endcode
*
* @param[in] expr A Boolean expression to be evaluated.
* @param[in] value A value to return if @a expr is false.
* @param[in] ... Statements to execute before returning. Optional.
*/
#define VerifyOrReturnValue(expr, value, ...) \
do \
{ \
if (!(expr)) \
{ \
__VA_ARGS__; \
return (value); \
} \
} while (false)
/**
* @def VerifyOrReturn(expr, ...)
*
* @brief
* Returns from the void function if expression evaluates to false
*
* Example usage:
*
* @code
* VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
* @endcode
*
* @param[in] expr A Boolean expression to be evaluated.
* @param[in] ... Statements to execute before returning. Optional.
*/
#define VerifyOrReturn(expr, ...) \
do \
{ \
if (!(expr)) \
{ \
__VA_ARGS__; \
return; \
} \
} while (false)
/**
* @def VerifyOrDo(expr, ...)
*
* @brief
* do something if expression evaluates to false
*
* Example usage:
*
* @code
* VerifyOrDo(param != nullptr, LogError("param is nullptr"));
* @endcode
*
* @param[in] expr A Boolean expression to be evaluated.
* @param[in] ... Statements to execute.
*/
#define VerifyOrDo(expr, ...) \
do \
{ \
if (!(expr)) \
{ \
__VA_ARGS__; \
} \
} while (false)
/**
* @def ExitNow(...)
*
* @brief
* This unconditionally executes @a ... and branches to the local
* label 'exit'.
*
* @note The use of this interface implies neither success nor
* failure for the overall exit status of the enclosing function
* body.
*
* Example Usage:
*
* @code
* CHIP_ERROR ReadAll(Reader& reader)
* {
* CHIP_ERROR err;
*
* while (true)
* {
* err = reader.ReadNext();
* if (err == CHIP_ERROR_AT_END)
* ExitNow(err = CHIP_NO_ERROR);
* SuccessOrExit(err);
* DoSomething();
* }
*
* exit:
* return err;
* }
* @endcode
*
* @param[in] ... Statements to execute. Optional.
*/
#define ExitNow(...) \
do \
{ \
__VA_ARGS__; \
goto exit; \
} while (0)
/**
* @def IgnoreUnusedVariable(aVariable)
*
* @brief
* This casts the specified @a aVariable to void to quell any
* compiler-issued unused variable warnings or errors.
*
* @code
* void foo (int err)
* {
* IgnoreUnusedVariable(err)
* }
* @endcode
*
*/
#define IgnoreUnusedVariable(aVariable) ((void) (aVariable))