3 * Copyright (c) 2020 Project CHIP Authors
4 * Copyright (c) 2013-2017 Nest Labs, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 * This file defines and implements a number of miscellaneous
22 * templates for finding object minima and maxima and interface
23 * macros for assertion checking.
31 #include <core/CHIPError.h>
32 #include <support/ErrorStr.h>
33 #include <support/logging/CHIPLogging.h>
36 * @name chip-specific nlassert.h Overrides
43 * @def CHIP_ASSERT_ABORT()
46 * This implements a chip-specific override for #CHIP_ASSERT_ABORT *
50 #if !defined(CHIP_ASSERT_ABORT)
51 #define CHIP_ASSERT_ABORT() chipDie()
55 * @def CHIP_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)
58 * This implements a chip-specific override for \c CHIP_ASSERT_LOG
61 * @param[in] aPrefix A pointer to a NULL-terminated C string printed
62 * at the beginning of the logged assertion
63 * message. Typically this is and should be
64 * \c CHIP_ASSERT_PREFIX_STRING.
65 * @param[in] aName A pointer to a NULL-terminated C string printed
66 * following @a aPrefix that indicates what
67 * module, program, application or subsystem
68 * the assertion occurred in Typically this
70 * \c CHIP_ASSERT_COMPONENT_STRING.
71 * @param[in] aCondition A pointer to a NULL-terminated C string indicating
72 * the expression that evaluated to false in
73 * the assertion. Typically this is a
74 * stringified version of the actual
75 * assertion expression.
76 * @param[in] aLabel An optional pointer to a NULL-terminated C string
77 * indicating, for exception-style
78 * assertions, the label that will be
79 * branched to when the assertion expression
81 * @param[in] aFile A pointer to a NULL-terminated C string indicating
82 * the file in which the exception
83 * occurred. Typically this is and should be
84 * \_\_FILE\_\_ from the C preprocessor.
85 * @param[in] aLine The line number in @a aFile on which the assertion
86 * expression evaluated to false. Typically
87 * this is and should be \_\_LINE\_\_ from the C
89 * @param[in] aMessage An optional pointer to a NULL-terminated C string
90 * containing a caller-specified message
91 * further describing the assertion failure.
95 #if !defined(CHIP_ASSERT_LOG)
96 #define CHIP_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage) \
99 ChipLogError(NotSpecified, \
100 CHIP_ASSERT_LOG_FORMAT_DEFAULT, \
102 (((aName) == 0) || (*(aName) == '\0')) ? "" : aName, \
103 (((aName) == 0) || (*(aName) == '\0')) ? "" : ": ", \
105 (((aMessage) == 0) ? "" : aMessage), \
106 (((aMessage) == 0) ? "" : ", "), \
114 * @} chip-specific nlassert.h Overrides
118 #include <nlassert.h>
122 // Generic min() and max() functions
124 template <typename _T>
125 constexpr inline const _T & min(const _T & a, const _T & b)
133 template <typename _T>
134 constexpr inline const _T & max(const _T & a, const _T & b)
145 * @def IgnoreUnusedVariable(aVariable)
148 * This casts the specified @a aVariable to void to quell any
149 * compiler-issued unused variable warnings or errors.
154 * IgnoreUnusedVariable(err)
159 #define IgnoreUnusedVariable(aVariable) ((void) (aVariable))
162 * @def ReturnErrorOnFailure(expr)
165 * Returns the error code if the expression returns something different
166 * than CHIP_NO_ERROR.
171 * ReturnErrorOnFailure(channel->SendMsg(msg));
174 * @param[in] expr A scalar expression to be evaluated against CHIP_NO_ERROR.
176 #define ReturnErrorOnFailure(expr) \
179 CHIP_ERROR __err = (expr); \
180 if (__err != CHIP_NO_ERROR) \
187 * @def ReturnOnFailure(expr)
190 * Returns if the expression returns something different than CHIP_NO_ERROR
195 * ReturnOnFailure(channel->SendMsg(msg));
198 * @param[in] expr A scalar expression to be evaluated against CHIP_NO_ERROR.
200 #define ReturnOnFailure(expr) \
203 CHIP_ERROR __err = (expr); \
204 if (__err != CHIP_NO_ERROR) \
211 * @def VerifyOrReturn(expr, ...)
214 * Returns from the void function if expression evaluates to false
219 * VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
222 * @param[in] expr A Boolean expression to be evaluated.
224 #define VerifyOrReturn(expr, ...) \
235 * @def VerifyOrReturnError(expr, code)
238 * Returns a specified error code if expression evaluates to false
243 * VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
246 * @param[in] expr A Boolean expression to be evaluated.
247 * @param[in] code A value to return if @a expr is false.
249 #define VerifyOrReturnError(expr, code) \
259 * @def ReturnErrorCodeIf(expr, code)
262 * Returns a specified error code if expression evaluates to true
267 * ReturnErrorCodeIf(state == kInitialized, CHIP_NO_ERROR);
268 * ReturnErrorCodeIf(state == kInitialized, CHIP_ERROR_INVALID_STATE);
271 * @param[in] expr A Boolean expression to be evaluated.
272 * @param[in] code A value to return if @a expr is false.
274 #define ReturnErrorCodeIf(expr, code) \
284 * @def SuccessOrExit(aStatus)
287 * This checks for the specified status, which is expected to
288 * commonly be successful (CHIP_NO_ERROR), and branches to
289 * the local label 'exit' if the status is unsuccessful.
294 * CHIP_ERROR TryHard()
298 * err = TrySomething();
299 * SuccessOrExit(err);
301 * err = TrySomethingElse();
302 * SuccessOrExit(err);
309 * @param[in] aStatus A scalar status to be evaluated against zero (0).
312 #define SuccessOrExit(aStatus) nlEXPECT((aStatus) == CHIP_NO_ERROR, exit)
315 * @def VerifyOrExit(aCondition, anAction)
318 * This checks for the specified condition, which is expected to
319 * commonly be true, and both executes @a anAction and branches to
320 * the local label 'exit' if the condition is false.
325 * CHIP_ERROR MakeBuffer(const uint8_t *& buf)
327 * CHIP_ERROR err = CHIP_NO_ERROR;
329 * buf = (uint8_t *)malloc(1024);
330 * VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
332 * memset(buf, 0, 1024);
339 * @param[in] aCondition A Boolean expression to be evaluated.
340 * @param[in] anAction An expression or block to execute when the
344 #define VerifyOrExit(aCondition, anAction) nlEXPECT_ACTION(aCondition, exit, anAction)
350 * This unconditionally executes @a ... and branches to the local
353 * @note The use of this interface implies neither success nor
354 * failure for the overall exit status of the enclosing function
360 * CHIP_ERROR ReadAll(Reader& reader)
366 * err = reader.ReadNext();
367 * if (err == CHIP_ERROR_AT_END)
368 * ExitNow(err = CHIP_NO_ERROR);
369 * SuccessOrExit(err);
378 * @param[in] ... An optional expression or block to execute
379 * when the assertion fails.
383 #define ExitNow(...) \
392 * This is invoked when a #VerifyOrDie or #VerifyOrDieWithMsg
393 * assertion expression evaluates to false.
395 * Developers may override and customize this by defining #chipDie
396 * before CodeUtils.h is included by the preprocessor.
406 extern "C" void chipDie(void) __attribute((noreturn));
408 inline void chipDie(void)
410 ChipLogError(NotSpecified, "chipDie chipDie chipDie");
414 // CHIP_ASSERT_ABORT is redefined to be chipDie, so not useful here.
421 * @def VerifyOrDie(aCondition)
424 * This checks for the specified condition, which is expected to
425 * commonly be true and forces an immediate abort if the condition
431 * void FreeBuffer(const uint8_t *buf)
433 * VerifyOrDie(buf != NULL);
438 * @param[in] aCondition A Boolean expression to be evaluated.
440 * @sa #VerifyOrDieWithMsg
444 #define VerifyOrDie(aCondition) nlABORT(aCondition)
447 * @def VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)
450 * This checks for the specified condition, which is expected to
451 * commonly be true and both prints @a aMessage and forces an
452 * immediate abort if the condition is false.
457 * void FreeBuffer(const uint8_t *buf)
459 * VerifyOrDieWithMsg(buf != NULL, MemoryManagement, "Invalid pointer passed to FreeBuffer");
464 * @param[in] aCondition A Boolean expression to be evaluated.
465 * @param[in] aModule A chip LogModule short-hand mnemonic identifing
466 * the logical section of code that is a
467 * source the logged message.
468 * @param[in] aMessage A pointer to a NULL-terminated C string with
469 * C Standard Library-style format specifiers
470 * containing the log message to be formatted
472 * @param[in] ... A variadic argument list whose elements should
473 * correspond to the format specifiers in @a
480 #define VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...) \
481 nlABORT_ACTION(aCondition, ChipLogDetail(aModule, aMessage, ##__VA_ARGS__))
483 #if (__cplusplus >= 201103L)
486 #define __FINAL final
490 #define __OVERRIDE override
494 #define __CONSTEXPR constexpr
508 #define __CONSTEXPR constexpr
511 #endif // (__cplusplus >= 201103L)
513 #if ((__cplusplus >= 201703L) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__)) && (__clang_major__ >= 4))
514 #define CHECK_RETURN_VALUE [[nodiscard]]
515 #elif defined(__GNUC__) && (__GNUC__ >= 4)
516 #define CHECK_RETURN_VALUE __attribute__((warn_unused_result))
517 #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
518 #define CHECK_RETURN_VALUE _Check_return_
520 #define CHECK_RETURN_VALUE
523 #if defined(__clang__)
524 #define FALLTHROUGH [[clang::fallthrough]]
526 #define FALLTHROUGH (void) 0
529 #endif // __cplusplus
532 * @def ArraySize(aArray)
535 * Returns the size of an array in number of elements.
541 * SortNumbers(numbers, ArraySize(numbers));
544 * @return The size of an array in number of elements.
546 * @note Clever template-based solutions seem to fail when ArraySize is used
547 * with a variable-length array argument, so we just do the C-compatible
548 * thing in C++ as well.
550 #define ArraySize(a) (sizeof(a) / sizeof((a)[0]))