Matter SDK Coverage Report
Current view: top level - lib/support - CodeUtils.h (source / functions) Coverage Total Hit
Test: SHA:8f943388af4d12dc5c484eae21b22723e03c3616 Lines: 54.5 % 11 6
Test Date: 2026-01-12 08:12:02 Functions: 33.3 % 9 3

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2020 Project CHIP Authors
       4              :  *    Copyright (c) 2013-2017 Nest Labs, Inc.
       5              :  *
       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
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      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.
      17              :  */
      18              : 
      19              : /**
      20              :  *    @file
      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.
      24              :  *
      25              :  */
      26              : 
      27              : #pragma once
      28              : 
      29              : #include <lib/core/CHIPConfig.h>
      30              : #include <lib/core/CHIPError.h>
      31              : #include <lib/core/ErrorStr.h>
      32              : #include <lib/support/ObjectDump.h>
      33              : #include <lib/support/VerificationMacrosNoLogging.h>
      34              : #include <lib/support/logging/TextOnlyLogging.h>
      35              : #include <memory>
      36              : 
      37              : /**
      38              :  * Base-level abnormal termination.
      39              :  *
      40              :  * Terminate the program immediately, without invoking destructors, atexit callbacks, etc.
      41              :  * Used to implement the default `chipDie()`.
      42              :  *
      43              :  * @note
      44              :  *  This should never be invoked directly by code outside this file.
      45              :  */
      46              : #if !defined(CHIP_CONFIG_ABORT)
      47              : #define CHIP_CONFIG_ABORT() abort()
      48              : #endif
      49              : 
      50              : /**
      51              :  *  @name chip-specific nlassert.h Overrides
      52              :  *
      53              :  *  @{
      54              :  *
      55              :  */
      56              : 
      57              : /**
      58              :  *  @def NL_ASSERT_ABORT()
      59              :  *
      60              :  *  @brief
      61              :  *    This implements a chip-specific override for #NL_ASSERT_ABORT *
      62              :  *    from nlassert.h.
      63              :  *
      64              :  */
      65              : #if !defined(NL_ASSERT_ABORT)
      66              : #define NL_ASSERT_ABORT() chipAbort()
      67              : #endif
      68              : 
      69              : /**
      70              :  *  @def NL_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)
      71              :  *
      72              :  *  @brief
      73              :  *    This implements a chip-specific override for \c NL_ASSERT_LOG
      74              :  *    from nlassert.h.
      75              :  *
      76              :  *  @param[in]  aPrefix     A pointer to a NULL-terminated C string printed
      77              :  *                          at the beginning of the logged assertion
      78              :  *                          message. Typically this is and should be
      79              :  *                          \c NL_ASSERT_PREFIX_STRING.
      80              :  *  @param[in]  aName       A pointer to a NULL-terminated C string printed
      81              :  *                          following @a aPrefix that indicates what
      82              :  *                          module, program, application or subsystem
      83              :  *                          the assertion occurred in Typically this
      84              :  *                          is and should be
      85              :  *                          \c NL_ASSERT_COMPONENT_STRING.
      86              :  *  @param[in]  aCondition  A pointer to a NULL-terminated C string indicating
      87              :  *                          the expression that evaluated to false in
      88              :  *                          the assertion. Typically this is a
      89              :  *                          stringified version of the actual
      90              :  *                          assertion expression.
      91              :  *  @param[in]  aLabel      An optional pointer to a NULL-terminated C string
      92              :  *                          indicating, for exception-style
      93              :  *                          assertions, the label that will be
      94              :  *                          branched to when the assertion expression
      95              :  *                          evaluates to false.
      96              :  *  @param[in]  aFile       A pointer to a NULL-terminated C string indicating
      97              :  *                          the file in which the exception
      98              :  *                          occurred. Typically this is and should be
      99              :  *                          \_\_FILE\_\_ from the C preprocessor.
     100              :  *  @param[in]  aLine       The line number in @a aFile on which the assertion
     101              :  *                          expression evaluated to false. Typically
     102              :  *                          this is and should be \_\_LINE\_\_ from the C
     103              :  *                          preprocessor.
     104              :  *  @param[in]  aMessage    An optional pointer to a NULL-terminated C string
     105              :  *                          containing a caller-specified message
     106              :  *                          further describing the assertion failure.
     107              :  *
     108              :  */
     109              : // clang-format off
     110              : #if !defined(NL_ASSERT_LOG)
     111              : #define NL_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)         \
     112              :     do                                                                                    \
     113              :     {                                                                                     \
     114              :         ChipLogError(NotSpecified,                                                       \
     115              :                       NL_ASSERT_LOG_FORMAT_DEFAULT,                                       \
     116              :                       aPrefix,                                                            \
     117              :                       (((aName) == 0) || (*(aName) == '\0')) ? "" : aName,                \
     118              :                       (((aName) == 0) || (*(aName) == '\0')) ? "" : ": ",                 \
     119              :                       aCondition,                                                         \
     120              :                       (((aMessage) == 0) ? "" : aMessage),                                \
     121              :                       (((aMessage) == 0) ? "" : ", "),                                    \
     122              :                       aFile,                                                              \
     123              :                       aLine);                                                             \
     124              :     } while (0)
     125              : #endif
     126              : // clang-format on
     127              : 
     128              : /**
     129              :  *  @} chip-specific nlassert.h Overrides
     130              :  *
     131              :  */
     132              : 
     133              : #include <nlassert.h>
     134              : 
     135              : /**
     136              :  *  @def ReturnErrorOnFailure(expr, ...)
     137              :  *
     138              :  *  @brief
     139              :  *    Returns the error code if the expression returns an error. For a CHIP_ERROR expression, this means any value other
     140              :  *    than CHIP_NO_ERROR. For an integer expression, this means non-zero.
     141              :  *
     142              :  *  Example usage:
     143              :  *
     144              :  *  @code
     145              :  *    ReturnErrorOnFailure(channel->SendMsg(msg), mState = Uninitialized);
     146              :  *  @endcode
     147              :  *
     148              :  *  @param[in]  expr        An expression to be tested.
     149              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     150              :  */
     151              : #define ReturnErrorOnFailure(expr, ...)                                                                                            \
     152              :     do                                                                                                                             \
     153              :     {                                                                                                                              \
     154              :         auto __err = (expr);                                                                                                       \
     155              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     156              :         {                                                                                                                          \
     157              :             __VA_ARGS__;                                                                                                           \
     158              :             return __err;                                                                                                          \
     159              :         }                                                                                                                          \
     160              :     } while (false)
     161              : 
     162              : /**
     163              :  *  @def ReturnErrorVariantOnFailure(expr)
     164              :  *
     165              :  *  @brief
     166              :  *    This is for use when the calling function returns a Variant type. It returns a CHIP_ERROR variant with the corresponding error
     167              :  *    code if the expression returns an error.
     168              :  *
     169              :  *  Example usage:
     170              :  *
     171              :  *  @code
     172              :  *    ReturnErrorVariantOnFailure(NextStep, ParseSigma1(tlvReader, parsedSigma1));
     173              :  *  @endcode
     174              :  *
     175              :  *  @param[in]  variantType   The Variant type that the calling function returns.
     176              :  *  @param[in]  expr          An expression to be tested.
     177              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     178              :  */
     179              : #define ReturnErrorVariantOnFailure(variantType, expr, ...)                                                                        \
     180              :     do                                                                                                                             \
     181              :     {                                                                                                                              \
     182              :         auto __err = (expr);                                                                                                       \
     183              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     184              :         {                                                                                                                          \
     185              :             __VA_ARGS__;                                                                                                           \
     186              :             return variantType::Create<CHIP_ERROR>(__err);                                                                         \
     187              :         }                                                                                                                          \
     188              :     } while (false)
     189              : 
     190              : /**
     191              :  *  @def ReturnLogErrorOnFailure(expr)
     192              :  *
     193              :  *  @brief
     194              :  *    Returns the error code if the expression returns something different
     195              :  *    than CHIP_NO_ERROR.
     196              :  *
     197              :  *  Example usage:
     198              :  *
     199              :  *  @code
     200              :  *    ReturnLogErrorOnFailure(channel->SendMsg(msg));
     201              :  *  @endcode
     202              :  *
     203              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     204              :  */
     205              : #define ReturnLogErrorOnFailure(expr)                                                                                              \
     206              :     do                                                                                                                             \
     207              :     {                                                                                                                              \
     208              :         CHIP_ERROR __err = (expr);                                                                                                 \
     209              :         if (__err != CHIP_NO_ERROR)                                                                                                \
     210              :         {                                                                                                                          \
     211              :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
     212              :             return __err;                                                                                                          \
     213              :         }                                                                                                                          \
     214              :     } while (false)
     215              : 
     216              : /**
     217              :  *  @def SuccessOrLog(expr, MOD, MSG, ...)
     218              :  *
     219              :  *  @brief
     220              :  *    If expr returns something other than CHIP_NO_ERROR, log a message for the specified module
     221              :  *    in the 'Error' category.
     222              :  *
     223              :  *  Example usage:
     224              :  *
     225              :  *  @code
     226              :  *    SuccessOrLog(channel->SendMsg(msg), Module, "Failure message: %s", param);
     227              :  *  @endcode
     228              :  *
     229              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     230              :  *  @param[in]  MOD         The log module to use.
     231              :  *  @param[in]  MSG         The log message format string.
     232              :  *  @param[in]  ...         Optional arguments for the log message.
     233              :  */
     234              : #define SuccessOrLog(expr, MOD, MSG, ...)                                                                                          \
     235              :     do                                                                                                                             \
     236              :     {                                                                                                                              \
     237              :         CHIP_ERROR __lerr = (expr);                                                                                                \
     238              :         if (!::chip::ChipError::IsSuccess(__lerr))                                                                                 \
     239              :         {                                                                                                                          \
     240              :             ChipLogFailure(__lerr, MOD, MSG, ##__VA_ARGS__);                                                                       \
     241              :         }                                                                                                                          \
     242              :     } while (false)
     243              : 
     244              : /**
     245              :  *  @def ReturnAndLogOnFailure(expr, MOD, MSG, ...)
     246              :  *
     247              :  *  @brief
     248              :  *    If expr returns something than CHIP_NO_ERROR, log a chip message for the specified module
     249              :  *    in the 'Error' category and return.
     250              :  *
     251              :  *  Example usage:
     252              :  *
     253              :  *  @code
     254              :  *    ReturnAndLogOnFailure(channel->SendMsg(msg), Module, "Failure message: %s", param);
     255              :  *  @endcode
     256              :  *
     257              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     258              :  *  @param[in]  MOD         The log module to use.
     259              :  *  @param[in]  MSG         The log message format string.
     260              :  *  @param[in]  ...         Optional arguments for the log message.
     261              :  */
     262              : #define ReturnAndLogOnFailure(expr, MOD, MSG, ...)                                                                                 \
     263              :     do                                                                                                                             \
     264              :     {                                                                                                                              \
     265              :         CHIP_ERROR __err = (expr);                                                                                                 \
     266              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     267              :         {                                                                                                                          \
     268              :             ChipLogFailure(__err, MOD, MSG, ##__VA_ARGS__);                                                                        \
     269              :             return;                                                                                                                \
     270              :         }                                                                                                                          \
     271              :     } while (false)
     272              : 
     273              : /**
     274              :  *  @def ReturnErrorAndLogOnFailure(expr, MOD, MSG, ...)
     275              :  *
     276              :  *  @brief
     277              :  *    If expr returns something than CHIP_NO_ERROR, log a chip message for the specified module
     278              :  *    in the 'Error' category and return the error.
     279              :  *
     280              :  *  Example usage:
     281              :  *
     282              :  *  @code
     283              :  *    ReturnErrorAndLogOnFailure(channel->SendMsg(msg), Module, "Failure message: %s", param);
     284              :  *  @endcode
     285              :  *
     286              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     287              :  *  @param[in]  MOD         The log module to use.
     288              :  *  @param[in]  MSG         The log message format string.
     289              :  *  @param[in]  ...         Optional arguments for the log message.
     290              :  */
     291              : #define ReturnErrorAndLogOnFailure(expr, MOD, MSG, ...)                                                                            \
     292              :     do                                                                                                                             \
     293              :     {                                                                                                                              \
     294              :         CHIP_ERROR __err = (expr);                                                                                                 \
     295              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     296              :         {                                                                                                                          \
     297              :             ChipLogFailure(__err, MOD, MSG, ##__VA_ARGS__);                                                                        \
     298              :             return __err;                                                                                                          \
     299              :         }                                                                                                                          \
     300              :     } while (false)
     301              : 
     302              : /**
     303              :  *  @def ReturnValueAndLogOnFailure(expr, value, MOD, MSG, ...)
     304              :  *
     305              :  *  @brief
     306              :  *    If expr returns something other than CHIP_NO_ERROR, log a message for the specified module
     307              :  *    in the 'Error' category and return the error.
     308              :  *
     309              :  *  Example usage:
     310              :  *
     311              :  *  @code
     312              :  *    ReturnValueAndLogOnFailure(channel->SendMsg(msg), false, Module, "Failure message: %s", param);
     313              :  *  @endcode
     314              :  *
     315              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     316              :  *  @param[in]  value       A value to return if @a expr is an error.
     317              :  *  @param[in]  MOD         The log module to use.
     318              :  *  @param[in]  MSG         The log message format string.
     319              :  *  @param[in]  ...         Optional arguments for the log message.
     320              :  */
     321              : #define ReturnValueAndLogOnFailure(expr, value, MOD, MSG, ...)                                                                     \
     322              :     do                                                                                                                             \
     323              :     {                                                                                                                              \
     324              :         CHIP_ERROR __err = (expr);                                                                                                 \
     325              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     326              :         {                                                                                                                          \
     327              :             ChipLogFailure(__err, MOD, MSG, ##__VA_ARGS__);                                                                        \
     328              :             return value;                                                                                                          \
     329              :         }                                                                                                                          \
     330              :     } while (false)
     331              : 
     332              : /**
     333              :  *  @def ReturnOnFailure(expr, ...)
     334              :  *
     335              :  *  @brief
     336              :  *    Returns if the expression returns an error. For a CHIP_ERROR expression, this means any value other
     337              :  *    than CHIP_NO_ERROR. For an integer expression, this means non-zero.
     338              :  *
     339              :  *  Example usage:
     340              :  *
     341              :  *  @code
     342              :  *    ReturnOnFailure(channel->SendMsg(msg), mState = Uninitialized);
     343              :  *  @endcode
     344              :  *
     345              :  *  @param[in]  expr        An expression to be tested.
     346              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     347              :  */
     348              : #define ReturnOnFailure(expr, ...)                                                                                                 \
     349              :     do                                                                                                                             \
     350              :     {                                                                                                                              \
     351              :         auto __err = (expr);                                                                                                       \
     352              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     353              :         {                                                                                                                          \
     354              :             __VA_ARGS__;                                                                                                           \
     355              :             return;                                                                                                                \
     356              :         }                                                                                                                          \
     357              :     } while (false)
     358              : 
     359              : /**
     360              :  *  @def ReturnValueOnFailure(expr, value, ...)
     361              :  *
     362              :  *  @brief
     363              :  *    Returns value if the expression returns an error. For a CHIP_ERROR expression, this means any value other
     364              :  *    than CHIP_NO_ERROR. For an integer expression, this means non-zero.
     365              :  *
     366              :  *  Example usage:
     367              :  *
     368              :  *  @code
     369              :  *    ReturnValueOnFailure(channel->SendMsg(msg), Status::Failure, mState = Uninitialized);
     370              :  *  @endcode
     371              :  *
     372              :  *  @param[in]  expr        An expression to be tested.
     373              :  *  @param[in]  value       A value to return if @a expr is an error.
     374              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     375              :  */
     376              : #define ReturnValueOnFailure(expr, value, ...)                                                                                     \
     377              :     do                                                                                                                             \
     378              :     {                                                                                                                              \
     379              :         auto __err = (expr);                                                                                                       \
     380              :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     381              :         {                                                                                                                          \
     382              :             __VA_ARGS__;                                                                                                           \
     383              :             return value;                                                                                                          \
     384              :         }                                                                                                                          \
     385              :     } while (false)
     386              : 
     387              : /**
     388              :  *  @def VerifyOrReturn(expr, ...)
     389              :  *
     390              :  *  @brief
     391              :  *    Returns from the void function if expression evaluates to false
     392              :  *
     393              :  *  Example usage:
     394              :  *
     395              :  *  @code
     396              :  *    VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
     397              :  *  @endcode
     398              :  *
     399              :  *  @param[in]  expr        A Boolean expression to be evaluated.
     400              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     401              :  */
     402              : #define VerifyOrReturn(expr, ...)                                                                                                  \
     403              :     do                                                                                                                             \
     404              :     {                                                                                                                              \
     405              :         if (!(expr))                                                                                                               \
     406              :         {                                                                                                                          \
     407              :             __VA_ARGS__;                                                                                                           \
     408              :             return;                                                                                                                \
     409              :         }                                                                                                                          \
     410              :     } while (false)
     411              : 
     412              : /**
     413              :  *  @def VerifyOrReturnError(expr, code, ...)
     414              :  *
     415              :  *  @brief
     416              :  *    Returns a specified error code if expression evaluates to false
     417              :  *
     418              :  *  Example usage:
     419              :  *
     420              :  *  @code
     421              :  *    VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     422              :  *  @endcode
     423              :  *
     424              :  *  @param[in]  expr        A Boolean expression to be evaluated.
     425              :  *  @param[in]  code        A value to return if @a expr is false.
     426              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     427              :  */
     428              : #define VerifyOrReturnError(expr, code, ...) VerifyOrReturnValue(expr, code, ##__VA_ARGS__)
     429              : 
     430              : /**
     431              :  *  @def VerifyOrReturnValue(expr, value, ...)
     432              :  *
     433              :  *  @brief
     434              :  *    Returns a specified value if expression evaluates to false
     435              :  *
     436              :  *  Example usage:
     437              :  *
     438              :  *  @code
     439              :  *    VerifyOrReturnError(param != nullptr, Foo());
     440              :  *  @endcode
     441              :  *
     442              :  *  @param[in]  expr        A Boolean expression to be evaluated.
     443              :  *  @param[in]  value       A value to return if @a expr is false.
     444              :  *  @param[in]  ...         Statements to execute before returning. Optional.
     445              :  */
     446              : #define VerifyOrReturnValue(expr, value, ...)                                                                                      \
     447              :     do                                                                                                                             \
     448              :     {                                                                                                                              \
     449              :         if (!(expr))                                                                                                               \
     450              :         {                                                                                                                          \
     451              :             __VA_ARGS__;                                                                                                           \
     452              :             return (value);                                                                                                        \
     453              :         }                                                                                                                          \
     454              :     } while (false)
     455              : 
     456              : /**
     457              :  *  @def VerifyOrReturnLogError(expr, code)
     458              :  *
     459              :  *  @brief
     460              :  *    Returns and print a specified error code if expression evaluates to false
     461              :  *
     462              :  *  Example usage:
     463              :  *
     464              :  *  @code
     465              :  *    VerifyOrReturnLogError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     466              :  *  @endcode
     467              :  *
     468              :  *  @param[in]  expr        A Boolean expression to be evaluated.
     469              :  *  @param[in]  code        A value to return if @a expr is false.
     470              :  */
     471              : #if CHIP_CONFIG_ERROR_SOURCE
     472              : #define VerifyOrReturnLogError(expr, code)                                                                                         \
     473              :     do                                                                                                                             \
     474              :     {                                                                                                                              \
     475              :         if (!(expr))                                                                                                               \
     476              :         {                                                                                                                          \
     477              :             auto __code = (code);                                                                                                  \
     478              :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__code), __FILE__, __LINE__);                                       \
     479              :             return __code;                                                                                                         \
     480              :         }                                                                                                                          \
     481              :     } while (false)
     482              : #else // CHIP_CONFIG_ERROR_SOURCE
     483              : #define VerifyOrReturnLogError(expr, code)                                                                                         \
     484              :     do                                                                                                                             \
     485              :     {                                                                                                                              \
     486              :         if (!(expr))                                                                                                               \
     487              :         {                                                                                                                          \
     488              :             auto __code = (code);                                                                                                  \
     489              :             ChipLogError(NotSpecified, "%s:%d false: %" CHIP_ERROR_FORMAT, #expr, __LINE__, __code.Format());                      \
     490              :             return __code;                                                                                                         \
     491              :         }                                                                                                                          \
     492              :     } while (false)
     493              : #endif // CHIP_CONFIG_ERROR_SOURCE
     494              : 
     495              : /**
     496              :  *  @def SuccessOrExit(error)
     497              :  *
     498              :  *  @brief
     499              :  *    This checks for the specified error, which is expected to
     500              :  *    commonly be successful (CHIP_NO_ERROR), and branches to
     501              :  *    the local label 'exit' if the status is unsuccessful.
     502              :  *
     503              :  *  Example Usage:
     504              :  *
     505              :  *  @code
     506              :  *  CHIP_ERROR TryHard()
     507              :  *  {
     508              :  *      CHIP_ERROR err;
     509              :  *
     510              :  *      err = TrySomething();
     511              :  *      SuccessOrExit(err);
     512              :  *
     513              :  *      err = TrySomethingElse();
     514              :  *      SuccessOrExit(err);
     515              :  *
     516              :  *  exit:
     517              :  *      return err;
     518              :  *  }
     519              :  *  @endcode
     520              :  *
     521              :  *  @param[in]  error  A ChipError object to be evaluated against success (CHIP_NO_ERROR).
     522              :  *
     523              :  */
     524              : #define SuccessOrExit(error) nlEXPECT(::chip::ChipError::IsSuccess((error)), exit)
     525              : 
     526              : /**
     527              :  *  @def SuccessOrExitAction(error, anAction)
     528              :  *
     529              :  *  @brief
     530              :  *    This checks for the specified error, which is expected to
     531              :  *    commonly be successful (CHIP_NO_ERROR), and both executes
     532              :  *    @a anAction and branches to the local label 'exit' if the
     533              :  *    status is unsuccessful.
     534              :  *
     535              :  *  @param[in]  error  A ChipError object to be evaluated against success (CHIP_NO_ERROR).
     536              :  */
     537              : #define SuccessOrExitAction(error, action) nlEXPECT_ACTION(::chip::ChipError::IsSuccess((error)), exit, action)
     538              : 
     539              : /**
     540              :  *  @def VerifyOrExit(aCondition, anAction)
     541              :  *
     542              :  *  @brief
     543              :  *    This checks for the specified condition, which is expected to
     544              :  *    commonly be true, and both executes @a anAction and branches to
     545              :  *    the local label 'exit' if the condition is false.
     546              :  *
     547              :  *  Example Usage:
     548              :  *
     549              :  *  @code
     550              :  *  CHIP_ERROR MakeBuffer(const uint8_t *& buf)
     551              :  *  {
     552              :  *      CHIP_ERROR err = CHIP_NO_ERROR;
     553              :  *
     554              :  *      buf = (uint8_t *)malloc(1024);
     555              :  *      VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
     556              :  *
     557              :  *      memset(buf, 0, 1024);
     558              :  *
     559              :  *  exit:
     560              :  *      return err;
     561              :  *  }
     562              :  *  @endcode
     563              :  *
     564              :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     565              :  *  @param[in]  anAction    An expression or block to execute when the
     566              :  *                          assertion fails.
     567              :  *
     568              :  */
     569              : #define VerifyOrExit(aCondition, anAction) nlEXPECT_ACTION(aCondition, exit, anAction)
     570              : 
     571              : /**
     572              :  *  @def ExitNow(...)
     573              :  *
     574              :  *  @brief
     575              :  *    This unconditionally executes @a ... and branches to the local
     576              :  *    label 'exit'.
     577              :  *
     578              :  *  @note The use of this interface implies neither success nor
     579              :  *        failure for the overall exit status of the enclosing function
     580              :  *        body.
     581              :  *
     582              :  *  Example Usage:
     583              :  *
     584              :  *  @code
     585              :  *  CHIP_ERROR ReadAll(Reader& reader)
     586              :  *  {
     587              :  *      CHIP_ERROR err;
     588              :  *
     589              :  *      while (true)
     590              :  *      {
     591              :  *          err = reader.ReadNext();
     592              :  *          if (err == CHIP_ERROR_AT_END)
     593              :  *              ExitNow(err = CHIP_NO_ERROR);
     594              :  *          SuccessOrExit(err);
     595              :  *          DoSomething();
     596              :  *      }
     597              :  *
     598              :  *  exit:
     599              :  *      return err;
     600              :  *  }
     601              :  *  @endcode
     602              :  *
     603              :  *  @param[in]  ...         Statements to execute. Optional.
     604              :  */
     605              : // clang-format off
     606              : #define ExitNow(...)                                                   \
     607              :     do {                                                               \
     608              :         __VA_ARGS__;                                                   \
     609              :         goto exit;                                                     \
     610              :     } while (0)
     611              : // clang-format on
     612              : 
     613              : /**
     614              :  *  @brief
     615              :  *    This is invoked when a #VerifyOrDie or #VerifyOrDieWithMsg
     616              :  *    assertion expression evaluates to false.
     617              :  *
     618              :  *    Developers may override and customize this by defining #chipDie
     619              :  *    before CodeUtils.h is included by the preprocessor.
     620              :  *
     621              :  *  Example Usage:
     622              :  *
     623              :  *  @code
     624              :  *  chipDie();
     625              :  *  @endcode
     626              :  *
     627              :  */
     628              : #ifndef chipAbort
     629              : extern "C" void chipAbort(void) __attribute((noreturn));
     630              : 
     631            0 : inline void chipAbort(void)
     632              : {
     633              :     while (true)
     634              :     {
     635              :         // NL_ASSERT_ABORT is redefined to be chipAbort, so not useful here.
     636            0 :         CHIP_CONFIG_ABORT();
     637              :     }
     638              : }
     639              : #endif // chipAbort
     640              : #ifndef chipDie
     641              : extern "C" void chipDie(void) __attribute((noreturn));
     642              : 
     643            0 : inline void chipDie(void)
     644              : {
     645            0 :     ChipLogError(NotSpecified, "chipDie chipDie chipDie");
     646            0 :     chipAbort();
     647              : }
     648              : #endif // chipDie
     649              : 
     650              : /**
     651              :  *  @def VerifyOrDie(aCondition)
     652              :  *
     653              :  *  @brief
     654              :  *    This checks for the specified condition, which is expected to
     655              :  *    commonly be true and forces an immediate abort if the condition
     656              :  *    is false.
     657              :  *
     658              :  *  Example Usage:
     659              :  *
     660              :  *  @code
     661              :  *  void FreeBuffer(const uint8_t *buf)
     662              :  *  {
     663              :  *      VerifyOrDie(buf != NULL);
     664              :  *      free(buf);
     665              :  *  }
     666              :  *  @endcode
     667              :  *
     668              :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     669              :  *
     670              :  *  @sa #VerifyOrDieWithMsg
     671              :  *  @sa #chipDie
     672              :  *
     673              :  */
     674              : #if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE && CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE_NO_COND
     675              : #define VerifyOrDie(aCondition)                                                                                                    \
     676              :     nlABORT_ACTION(aCondition, ChipLogError(Support, "VerifyOrDie failure at %s:%d", __FILE__, __LINE__))
     677              : #elif CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     678              : #define VerifyOrDie(aCondition)                                                                                                    \
     679              :     nlABORT_ACTION(aCondition, ChipLogError(Support, "VerifyOrDie failure at %s:%d: %s", __FILE__, __LINE__, #aCondition))
     680              : #else // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     681              : #define VerifyOrDie(aCondition) VerifyOrDieWithoutLogging(aCondition)
     682              : #endif // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     683              : 
     684              : /**
     685              :  *  @def SuccessOrDie(error)
     686              :  *
     687              :  *  @brief
     688              :  *    This checks for the specified error, which is expected to
     689              :  *    commonly be successful (CHIP_NO_ERROR), forces an immediate abort if the status
     690              :  *    is unsuccessful.
     691              :  *
     692              :  *
     693              :  *  Example Usage:
     694              :  *
     695              :  *  @code
     696              :  *  uint8_t* AllocateBuffer()
     697              :  *  {
     698              :  *      uint8_t* buffer;
     699              :  *      SuccessOrDie(ChipAllocateBuffer(buffer));
     700              :  *      return buffer;
     701              :  *  }
     702              :  *  @endcode
     703              :  *
     704              :  *  @param[in]  error  A ChipError object to be evaluated against success (CHIP_NO_ERROR).
     705              :  *
     706              :  */
     707              : #if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE && CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE_NO_COND
     708              : #define SuccessOrDie(error)                                                                                                        \
     709              :     do                                                                                                                             \
     710              :     {                                                                                                                              \
     711              :         auto __err = (error);                                                                                                      \
     712              :         nlABORT_ACTION(::chip::ChipError::IsSuccess(__err),                                                                        \
     713              :                        ChipLogError(Support, "SuccessOrDie failure %s at %s:%d", ErrorStr(__err), __FILE__, __LINE__));            \
     714              :     } while (false)
     715              : #elif CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     716              : #define SuccessOrDie(error)                                                                                                        \
     717              :     do                                                                                                                             \
     718              :     {                                                                                                                              \
     719              :         auto __err = (error);                                                                                                      \
     720              :         nlABORT_ACTION(                                                                                                            \
     721              :             ::chip::ChipError::IsSuccess(__err),                                                                                   \
     722              :             ChipLogError(Support, "SuccessOrDie failure %s at %s:%d: %s", ErrorStr(__err), __FILE__, __LINE__, #error));           \
     723              :     } while (false)
     724              : #else // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     725              : #define SuccessOrDie(error) VerifyOrDieWithoutLogging(::chip::ChipError::IsSuccess((error)))
     726              : #endif // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     727              : 
     728              : /**
     729              :  * @def VerifyOrDieWithObject(aCondition, aObject)
     730              :  *
     731              :  * Like VerifyOrDie(), but calls DumpObjectToLog()
     732              :  * on the provided object on failure before aborting
     733              :  * if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE is enabled.
     734              :  */
     735              : #if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     736              : #define VerifyOrDieWithObject(aCondition, aObject)                                                                                 \
     737              :     nlABORT_ACTION(aCondition, ::chip::DumpObjectToLog(aObject);                                                                   \
     738              :                    ChipLogError(Support, "VerifyOrDie failure at %s:%d: %s", __FILE__, __LINE__, #aCondition))
     739              : #else // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     740              : #define VerifyOrDieWithObject(aCondition, aObject) VerifyOrDieWithoutLogging(aCondition)
     741              : #endif // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     742              : 
     743              : /**
     744              :  *  @def VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)
     745              :  *
     746              :  *  @brief
     747              :  *    This checks for the specified condition, which is expected to
     748              :  *    commonly be true and both prints @a aMessage and forces an
     749              :  *    immediate abort if the condition is false.
     750              :  *
     751              :  *  Example Usage:
     752              :  *
     753              :  *  @code
     754              :  *  void FreeBuffer(const uint8_t *buf)
     755              :  *  {
     756              :  *      VerifyOrDieWithMsg(buf != NULL, MemoryManagement, "Invalid pointer passed to FreeBuffer");
     757              :  *      free(buf);
     758              :  *  }
     759              :  *  @endcode
     760              :  *
     761              :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     762              :  *  @param[in]  aModule     A chip LogModule short-hand mnemonic identifing
     763              :  *                          the logical section of code that is a
     764              :  *                          source the logged message.
     765              :  *  @param[in]  aMessage    A pointer to a NULL-terminated C string with
     766              :  *                          C Standard Library-style format specifiers
     767              :  *                          containing the log message to be formatted
     768              :  *                          and logged.
     769              :  *  @param[in]  ...         A variadic argument list whose elements should
     770              :  *                          correspond to the format specifiers in @a
     771              :  *                          aMessage.
     772              :  *
     773              :  *  @sa #VerifyOrDie
     774              :  *  @sa #chipDie
     775              :  *
     776              :  */
     777              : #define VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)                                                                     \
     778              :     nlABORT_ACTION(aCondition, ChipLogError(aModule, aMessage, ##__VA_ARGS__))
     779              : 
     780              : /**
     781              :  *  @def LogErrorOnFailure(expr)
     782              :  *
     783              :  *  @brief
     784              :  *    Logs a message if the expression returns something different than CHIP_NO_ERROR.
     785              :  *
     786              :  *  Example usage:
     787              :  *
     788              :  *  @code
     789              :  *    ReturnLogErrorOnFailure(channel->SendMsg(msg));
     790              :  *  @endcode
     791              :  *
     792              :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     793              :  */
     794              : #define LogErrorOnFailure(expr)                                                                                                    \
     795              :     do                                                                                                                             \
     796              :     {                                                                                                                              \
     797              :         CHIP_ERROR __err = (expr);                                                                                                 \
     798              :         if (__err != CHIP_NO_ERROR)                                                                                                \
     799              :         {                                                                                                                          \
     800              :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
     801              :         }                                                                                                                          \
     802              :     } while (false)
     803              : 
     804              : /**
     805              :  *  @def VerifyOrDo(expr, ...)
     806              :  *
     807              :  *  @brief
     808              :  *    do something if expression evaluates to false
     809              :  *
     810              :  *  Example usage:
     811              :  *
     812              :  * @code
     813              :  *    VerifyOrDo(param != nullptr, LogError("param is nullptr"));
     814              :  *  @endcode
     815              :  *
     816              :  *  @param[in]  expr        A Boolean expression to be evaluated.
     817              :  *  @param[in]  ...         Statements to execute.
     818              :  */
     819              : #define VerifyOrDo(expr, ...)                                                                                                      \
     820              :     do                                                                                                                             \
     821              :     {                                                                                                                              \
     822              :         if (!(expr))                                                                                                               \
     823              :         {                                                                                                                          \
     824              :             __VA_ARGS__;                                                                                                           \
     825              :         }                                                                                                                          \
     826              :     } while (false)
     827              : 
     828              : #if (__cplusplus >= 201103L)
     829              : 
     830              : #ifndef __FINAL
     831              : #define __FINAL final
     832              : #endif
     833              : 
     834              : #ifndef __OVERRIDE
     835              : #define __OVERRIDE override
     836              : #endif
     837              : 
     838              : #ifndef __CONSTEXPR
     839              : #define __CONSTEXPR constexpr
     840              : #endif
     841              : 
     842              : #else
     843              : 
     844              : #ifndef __FINAL
     845              : #define __FINAL
     846              : #endif
     847              : 
     848              : #ifndef __OVERRIDE
     849              : #define __OVERRIDE
     850              : #endif
     851              : 
     852              : #ifndef __CONSTEXPR
     853              : #define __CONSTEXPR constexpr
     854              : #endif
     855              : 
     856              : #endif // (__cplusplus >= 201103L)
     857              : 
     858              : #if ((__cplusplus >= 201703L) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__)) && (__clang_major__ >= 4))
     859              : #define CHECK_RETURN_VALUE [[nodiscard]]
     860              : #elif defined(__GNUC__) && (__GNUC__ >= 4)
     861              : #define CHECK_RETURN_VALUE __attribute__((warn_unused_result))
     862              : #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
     863              : #define CHECK_RETURN_VALUE _Check_return_
     864              : #else
     865              : #define CHECK_RETURN_VALUE
     866              : #endif
     867              : 
     868              : #if defined(__clang__)
     869              : #define FALLTHROUGH [[clang::fallthrough]]
     870              : #elif defined(__GNUC__)
     871              : #define FALLTHROUGH __attribute__((fallthrough))
     872              : #else
     873              : #define FALLTHROUGH (void) 0
     874              : #endif
     875              : 
     876              : /**
     877              :  * @def MATTER_ARRAY_SIZE(aArray)
     878              :  *
     879              :  * @brief
     880              :  *   Returns the size of an array in number of elements.
     881              :  *
     882              :  * Example Usage:
     883              :  *
     884              :  * @code
     885              :  * int numbers[10];
     886              :  * SortNumbers(numbers, MATTER_ARRAY_SIZE(numbers));
     887              :  * @endcode
     888              :  *
     889              :  * @return      The size of an array in number of elements.
     890              :  *
     891              :  * @note Clever template-based solutions seem to fail when MATTER_ARRAY_SIZE is used
     892              :  *       with a variable-length array argument, so we just do the C-compatible
     893              :  *       thing in C++ as well.
     894              :  */
     895              : #ifndef MATTER_ARRAY_SIZE
     896              : #define MATTER_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
     897              : #endif
     898              : 
     899              : /**
     900              :  * @brief Ensures that if `str` is NULL, a non-null `default_str_value` is provided
     901              :  *
     902              :  * @param str - null-terminated string pointer or nullptr
     903              :  * @param default_str_value - replacement value if `str` is nullptr
     904              :  * @return `str` if not null, otherwise `default_str_value`
     905              :  */
     906         5024 : inline const char * DefaultStringWhenNull(const char * str, const char * default_str_value)
     907              : {
     908         5024 :     return (str != nullptr) ? str : default_str_value;
     909              : }
     910              : 
     911              : /**
     912              :  * @brief Ensure that a string for a %s specifier is shown as "(null)" if null
     913              :  *
     914              :  * @param str - null-terminated string pointer or nullptr
     915              :  * @return `str` if not null, otherwise literal "(null)"
     916              :  */
     917         5024 : inline const char * StringOrNullMarker(const char * str)
     918              : {
     919         5024 :     return DefaultStringWhenNull(str, "(null)");
     920              : }
     921              : 
     922              : namespace chip {
     923              : 
     924              : /**
     925              :  * Utility for checking, at compile time if the array is constexpr, whether an
     926              :  * array is sorted.  Can be used for static_asserts.
     927              :  */
     928              : template <typename T>
     929              : constexpr bool ArrayIsSorted(const T * aArray, size_t aLength)
     930              : {
     931              :     if (aLength == 0 || aLength == 1)
     932              :     {
     933              :         return true;
     934              :     }
     935              : 
     936              :     if (aArray[0] > aArray[1])
     937              :     {
     938              :         return false;
     939              :     }
     940              : 
     941              :     return ArrayIsSorted(aArray + 1, aLength - 1);
     942              : }
     943              : 
     944              : template <typename T, size_t N>
     945              : constexpr bool ArrayIsSorted(const T (&aArray)[N])
     946              : {
     947              :     return ArrayIsSorted(aArray, N);
     948              : }
     949              : 
     950              : /**
     951              :  *  @def ScopeExit(fn)
     952              :  *
     953              :  *  @brief
     954              :  *    RAII to automatically release resources on scope exit (instead of depending on goto exit)
     955              :  *    See https://en.cppreference.com/w/cpp/experimental/scope_exit.html
     956              :  *    Use with ReturnOnFailure, ReturnLogErrorOnFailure, ReturnAndLogOnFailure and other such methods
     957              :  *    to return an error code result from a method call without needing to store in a local var
     958              :  *
     959              :  *  Example usage:
     960              :  *
     961              :  *  @code
     962              :  *  Resource * resource = GetResource();
     963              :  *  auto resourceHolder = ScopeExit([&] { resource->Release() });
     964              :  *  // If the call below fails, logs, returns the error code, and calls resourceHolder
     965              :  *  ReturnAndLogOnFailure(ProcessAndSaveResource(resource), Module, "Failure message: %s", param);
     966              :  *  resourceHolder->release(); // Cancel clean-up at end of successful method
     967              :  *  @endcode
     968              :  */
     969              : template <class F>
     970              : __attribute__((always_inline)) inline auto ScopeExit(F && fn)
     971              : {
     972          112 :     auto deleter = [f = std::forward<F>(fn)](void *) mutable { f(); };
     973          110 :     return std::unique_ptr<void, decltype(deleter)>(reinterpret_cast<void *>(1), std::move(deleter));
     974              : }
     975              : 
     976              : } // namespace chip
        

Generated by: LCOV version 2.0-1