LCOV - code coverage report
Current view: top level - lib/support - CodeUtils.h (source / functions) Hit Total Coverage
Test: lcov_final.info Lines: 8 13 61.5 %
Date: 2024-02-15 08:20:41 Functions: 6 10 60.0 %

          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/VerificationMacrosNoLogging.h>
      33             : #include <lib/support/logging/TextOnlyLogging.h>
      34             : 
      35             : /**
      36             :  * Base-level abnormal termination.
      37             :  *
      38             :  * Terminate the program immediately, without invoking destructors, atexit callbacks, etc.
      39             :  * Used to implement the default `chipDie()`.
      40             :  *
      41             :  * @note
      42             :  *  This should never be invoked directly by code outside this file.
      43             :  */
      44             : #if !defined(CHIP_CONFIG_ABORT)
      45             : #define CHIP_CONFIG_ABORT() abort()
      46             : #endif
      47             : 
      48             : /**
      49             :  *  @name chip-specific nlassert.h Overrides
      50             :  *
      51             :  *  @{
      52             :  *
      53             :  */
      54             : 
      55             : /**
      56             :  *  @def NL_ASSERT_ABORT()
      57             :  *
      58             :  *  @brief
      59             :  *    This implements a chip-specific override for #NL_ASSERT_ABORT *
      60             :  *    from nlassert.h.
      61             :  *
      62             :  */
      63             : #if !defined(NL_ASSERT_ABORT)
      64             : #define NL_ASSERT_ABORT() chipAbort()
      65             : #endif
      66             : 
      67             : /**
      68             :  *  @def NL_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)
      69             :  *
      70             :  *  @brief
      71             :  *    This implements a chip-specific override for \c NL_ASSERT_LOG
      72             :  *    from nlassert.h.
      73             :  *
      74             :  *  @param[in]  aPrefix     A pointer to a NULL-terminated C string printed
      75             :  *                          at the beginning of the logged assertion
      76             :  *                          message. Typically this is and should be
      77             :  *                          \c NL_ASSERT_PREFIX_STRING.
      78             :  *  @param[in]  aName       A pointer to a NULL-terminated C string printed
      79             :  *                          following @a aPrefix that indicates what
      80             :  *                          module, program, application or subsystem
      81             :  *                          the assertion occurred in Typically this
      82             :  *                          is and should be
      83             :  *                          \c NL_ASSERT_COMPONENT_STRING.
      84             :  *  @param[in]  aCondition  A pointer to a NULL-terminated C string indicating
      85             :  *                          the expression that evaluated to false in
      86             :  *                          the assertion. Typically this is a
      87             :  *                          stringified version of the actual
      88             :  *                          assertion expression.
      89             :  *  @param[in]  aLabel      An optional pointer to a NULL-terminated C string
      90             :  *                          indicating, for exception-style
      91             :  *                          assertions, the label that will be
      92             :  *                          branched to when the assertion expression
      93             :  *                          evaluates to false.
      94             :  *  @param[in]  aFile       A pointer to a NULL-terminated C string indicating
      95             :  *                          the file in which the exception
      96             :  *                          occurred. Typically this is and should be
      97             :  *                          \_\_FILE\_\_ from the C preprocessor.
      98             :  *  @param[in]  aLine       The line number in @a aFile on which the assertion
      99             :  *                          expression evaluated to false. Typically
     100             :  *                          this is and should be \_\_LINE\_\_ from the C
     101             :  *                          preprocessor.
     102             :  *  @param[in]  aMessage    An optional pointer to a NULL-terminated C string
     103             :  *                          containing a caller-specified message
     104             :  *                          further describing the assertion failure.
     105             :  *
     106             :  */
     107             : // clang-format off
     108             : #if !defined(NL_ASSERT_LOG)
     109             : #define NL_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)         \
     110             :     do                                                                                    \
     111             :     {                                                                                     \
     112             :         ChipLogError(NotSpecified,                                                       \
     113             :                       NL_ASSERT_LOG_FORMAT_DEFAULT,                                       \
     114             :                       aPrefix,                                                            \
     115             :                       (((aName) == 0) || (*(aName) == '\0')) ? "" : aName,                \
     116             :                       (((aName) == 0) || (*(aName) == '\0')) ? "" : ": ",                 \
     117             :                       aCondition,                                                         \
     118             :                       (((aMessage) == 0) ? "" : aMessage),                                \
     119             :                       (((aMessage) == 0) ? "" : ", "),                                    \
     120             :                       aFile,                                                              \
     121             :                       aLine);                                                             \
     122             :     } while (0)
     123             : #endif
     124             : // clang-format on
     125             : 
     126             : /**
     127             :  *  @} chip-specific nlassert.h Overrides
     128             :  *
     129             :  */
     130             : 
     131             : #include <nlassert.h>
     132             : 
     133             : namespace chip {
     134             : 
     135             : // Generic min() and max() functions
     136             : //
     137             : template <typename _T>
     138       10053 : constexpr inline const _T & min(const _T & a, const _T & b)
     139             : {
     140       10053 :     if (b < a)
     141        9906 :         return b;
     142             : 
     143         147 :     return a;
     144             : }
     145             : 
     146             : template <typename _T>
     147             : constexpr inline const _T & max(const _T & a, const _T & b)
     148             : {
     149             :     if (a < b)
     150             :         return b;
     151             : 
     152             :     return a;
     153             : }
     154             : 
     155             : } // namespace chip
     156             : 
     157             : /**
     158             :  *  @def ReturnErrorOnFailure(expr)
     159             :  *
     160             :  *  @brief
     161             :  *    Returns the error code if the expression returns an error. For a CHIP_ERROR expression, this means any value other
     162             :  *    than CHIP_NO_ERROR. For an integer expression, this means non-zero.
     163             :  *
     164             :  *  Example usage:
     165             :  *
     166             :  *  @code
     167             :  *    ReturnErrorOnFailure(channel->SendMsg(msg));
     168             :  *  @endcode
     169             :  *
     170             :  *  @param[in]  expr        An expression to be tested.
     171             :  */
     172             : #define ReturnErrorOnFailure(expr)                                                                                                 \
     173             :     do                                                                                                                             \
     174             :     {                                                                                                                              \
     175             :         auto __err = (expr);                                                                                                       \
     176             :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     177             :         {                                                                                                                          \
     178             :             return __err;                                                                                                          \
     179             :         }                                                                                                                          \
     180             :     } while (false)
     181             : 
     182             : /**
     183             :  *  @def ReturnLogErrorOnFailure(expr)
     184             :  *
     185             :  *  @brief
     186             :  *    Returns the error code if the expression returns something different
     187             :  *    than CHIP_NO_ERROR.
     188             :  *
     189             :  *  Example usage:
     190             :  *
     191             :  *  @code
     192             :  *    ReturnLogErrorOnFailure(channel->SendMsg(msg));
     193             :  *  @endcode
     194             :  *
     195             :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     196             :  */
     197             : #define ReturnLogErrorOnFailure(expr)                                                                                              \
     198             :     do                                                                                                                             \
     199             :     {                                                                                                                              \
     200             :         CHIP_ERROR __err = (expr);                                                                                                 \
     201             :         if (__err != CHIP_NO_ERROR)                                                                                                \
     202             :         {                                                                                                                          \
     203             :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
     204             :             return __err;                                                                                                          \
     205             :         }                                                                                                                          \
     206             :     } while (false)
     207             : 
     208             : /**
     209             :  *  @def ReturnOnFailure(expr)
     210             :  *
     211             :  *  @brief
     212             :  *    Returns if the expression returns an error. For a CHIP_ERROR expression, this means any value other
     213             :  *    than CHIP_NO_ERROR. For an integer expression, this means non-zero.
     214             :  *
     215             :  *  Example usage:
     216             :  *
     217             :  *  @code
     218             :  *    ReturnOnFailure(channel->SendMsg(msg));
     219             :  *  @endcode
     220             :  *
     221             :  *  @param[in]  expr        An expression to be tested.
     222             :  */
     223             : #define ReturnOnFailure(expr)                                                                                                      \
     224             :     do                                                                                                                             \
     225             :     {                                                                                                                              \
     226             :         auto __err = (expr);                                                                                                       \
     227             :         if (!::chip::ChipError::IsSuccess(__err))                                                                                  \
     228             :         {                                                                                                                          \
     229             :             return;                                                                                                                \
     230             :         }                                                                                                                          \
     231             :     } while (false)
     232             : 
     233             : /**
     234             :  *  @def VerifyOrReturn(expr, ...)
     235             :  *
     236             :  *  @brief
     237             :  *    Returns from the void function if expression evaluates to false
     238             :  *
     239             :  *  Example usage:
     240             :  *
     241             :  *  @code
     242             :  *    VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
     243             :  *  @endcode
     244             :  *
     245             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     246             :  *  @param[in]  ...         Statements to execute before returning. Optional.
     247             :  */
     248             : #define VerifyOrReturn(expr, ...)                                                                                                  \
     249             :     do                                                                                                                             \
     250             :     {                                                                                                                              \
     251             :         if (!(expr))                                                                                                               \
     252             :         {                                                                                                                          \
     253             :             __VA_ARGS__;                                                                                                           \
     254             :             return;                                                                                                                \
     255             :         }                                                                                                                          \
     256             :     } while (false)
     257             : 
     258             : /**
     259             :  *  @def VerifyOrReturnError(expr, code, ...)
     260             :  *
     261             :  *  @brief
     262             :  *    Returns a specified error code if expression evaluates to false
     263             :  *
     264             :  *  Example usage:
     265             :  *
     266             :  *  @code
     267             :  *    VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     268             :  *  @endcode
     269             :  *
     270             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     271             :  *  @param[in]  code        A value to return if @a expr is false.
     272             :  *  @param[in]  ...         Statements to execute before returning. Optional.
     273             :  */
     274             : #define VerifyOrReturnError(expr, code, ...) VerifyOrReturnValue(expr, code, ##__VA_ARGS__)
     275             : 
     276             : /**
     277             :  *  @def VerifyOrReturnValue(expr, value, ...)
     278             :  *
     279             :  *  @brief
     280             :  *    Returns a specified value if expression evaluates to false
     281             :  *
     282             :  *  Example usage:
     283             :  *
     284             :  *  @code
     285             :  *    VerifyOrReturnError(param != nullptr, Foo());
     286             :  *  @endcode
     287             :  *
     288             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     289             :  *  @param[in]  value       A value to return if @a expr is false.
     290             :  *  @param[in]  ...         Statements to execute before returning. Optional.
     291             :  */
     292             : #define VerifyOrReturnValue(expr, value, ...)                                                                                      \
     293             :     do                                                                                                                             \
     294             :     {                                                                                                                              \
     295             :         if (!(expr))                                                                                                               \
     296             :         {                                                                                                                          \
     297             :             __VA_ARGS__;                                                                                                           \
     298             :             return (value);                                                                                                        \
     299             :         }                                                                                                                          \
     300             :     } while (false)
     301             : 
     302             : /**
     303             :  *  @def VerifyOrReturnLogError(expr, code)
     304             :  *
     305             :  *  @brief
     306             :  *    Returns and print a specified error code if expression evaluates to false
     307             :  *
     308             :  *  Example usage:
     309             :  *
     310             :  *  @code
     311             :  *    VerifyOrReturnLogError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
     312             :  *  @endcode
     313             :  *
     314             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     315             :  *  @param[in]  code        A value to return if @a expr is false.
     316             :  */
     317             : #if CHIP_CONFIG_ERROR_SOURCE
     318             : #define VerifyOrReturnLogError(expr, code)                                                                                         \
     319             :     do                                                                                                                             \
     320             :     {                                                                                                                              \
     321             :         if (!(expr))                                                                                                               \
     322             :         {                                                                                                                          \
     323             :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(code), __FILE__, __LINE__);                                         \
     324             :             return code;                                                                                                           \
     325             :         }                                                                                                                          \
     326             :     } while (false)
     327             : #else // CHIP_CONFIG_ERROR_SOURCE
     328             : #define VerifyOrReturnLogError(expr, code)                                                                                         \
     329             :     do                                                                                                                             \
     330             :     {                                                                                                                              \
     331             :         if (!(expr))                                                                                                               \
     332             :         {                                                                                                                          \
     333             :             ChipLogError(NotSpecified, "%s:%d false: %" CHIP_ERROR_FORMAT, #expr, __LINE__, code.Format());                        \
     334             :             return code;                                                                                                           \
     335             :         }                                                                                                                          \
     336             :     } while (false)
     337             : #endif // CHIP_CONFIG_ERROR_SOURCE
     338             : 
     339             : /**
     340             :  *  @def ReturnErrorCodeIf(expr, code)
     341             :  *
     342             :  *  @brief
     343             :  *    Returns a specified error code if expression evaluates to true
     344             :  *
     345             :  *  Example usage:
     346             :  *
     347             :  *  @code
     348             :  *    ReturnErrorCodeIf(state == kInitialized, CHIP_NO_ERROR);
     349             :  *    ReturnErrorCodeIf(state == kInitialized, CHIP_ERROR_INCORRECT_STATE);
     350             :  *  @endcode
     351             :  *
     352             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     353             :  *  @param[in]  code        A value to return if @a expr is false.
     354             :  */
     355             : #define ReturnErrorCodeIf(expr, code)                                                                                              \
     356             :     do                                                                                                                             \
     357             :     {                                                                                                                              \
     358             :         if (expr)                                                                                                                  \
     359             :         {                                                                                                                          \
     360             :             return code;                                                                                                           \
     361             :         }                                                                                                                          \
     362             :     } while (false)
     363             : 
     364             : /**
     365             :  *  @def SuccessOrExit(aStatus)
     366             :  *
     367             :  *  @brief
     368             :  *    This checks for the specified status, which is expected to
     369             :  *    commonly be successful (CHIP_NO_ERROR), and branches to
     370             :  *    the local label 'exit' if the status is unsuccessful.
     371             :  *
     372             :  *  Example Usage:
     373             :  *
     374             :  *  @code
     375             :  *  CHIP_ERROR TryHard()
     376             :  *  {
     377             :  *      CHIP_ERROR err;
     378             :  *
     379             :  *      err = TrySomething();
     380             :  *      SuccessOrExit(err);
     381             :  *
     382             :  *      err = TrySomethingElse();
     383             :  *      SuccessOrExit(err);
     384             :  *
     385             :  *  exit:
     386             :  *      return err;
     387             :  *  }
     388             :  *  @endcode
     389             :  *
     390             :  *  @param[in]  aStatus     A scalar status to be evaluated against zero (0).
     391             :  *
     392             :  */
     393             : #define SuccessOrExit(aStatus) nlEXPECT(::chip::ChipError::IsSuccess((aStatus)), exit)
     394             : 
     395             : /**
     396             :  *  @def VerifyOrExit(aCondition, anAction)
     397             :  *
     398             :  *  @brief
     399             :  *    This checks for the specified condition, which is expected to
     400             :  *    commonly be true, and both executes @a anAction and branches to
     401             :  *    the local label 'exit' if the condition is false.
     402             :  *
     403             :  *  Example Usage:
     404             :  *
     405             :  *  @code
     406             :  *  CHIP_ERROR MakeBuffer(const uint8_t *& buf)
     407             :  *  {
     408             :  *      CHIP_ERROR err = CHIP_NO_ERROR;
     409             :  *
     410             :  *      buf = (uint8_t *)malloc(1024);
     411             :  *      VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
     412             :  *
     413             :  *      memset(buf, 0, 1024);
     414             :  *
     415             :  *  exit:
     416             :  *      return err;
     417             :  *  }
     418             :  *  @endcode
     419             :  *
     420             :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     421             :  *  @param[in]  anAction    An expression or block to execute when the
     422             :  *                          assertion fails.
     423             :  *
     424             :  */
     425             : #define VerifyOrExit(aCondition, anAction) nlEXPECT_ACTION(aCondition, exit, anAction)
     426             : 
     427             : /**
     428             :  *  @def ExitNow(...)
     429             :  *
     430             :  *  @brief
     431             :  *    This unconditionally executes @a ... and branches to the local
     432             :  *    label 'exit'.
     433             :  *
     434             :  *  @note The use of this interface implies neither success nor
     435             :  *        failure for the overall exit status of the enclosing function
     436             :  *        body.
     437             :  *
     438             :  *  Example Usage:
     439             :  *
     440             :  *  @code
     441             :  *  CHIP_ERROR ReadAll(Reader& reader)
     442             :  *  {
     443             :  *      CHIP_ERROR err;
     444             :  *
     445             :  *      while (true)
     446             :  *      {
     447             :  *          err = reader.ReadNext();
     448             :  *          if (err == CHIP_ERROR_AT_END)
     449             :  *              ExitNow(err = CHIP_NO_ERROR);
     450             :  *          SuccessOrExit(err);
     451             :  *          DoSomething();
     452             :  *      }
     453             :  *
     454             :  *  exit:
     455             :  *      return err;
     456             :  *  }
     457             :  *  @endcode
     458             :  *
     459             :  *  @param[in]  ...         Statements to execute. Optional.
     460             :  */
     461             : // clang-format off
     462             : #define ExitNow(...)                                                   \
     463             :     do {                                                               \
     464             :         __VA_ARGS__;                                                   \
     465             :         goto exit;                                                     \
     466             :     } while (0)
     467             : // clang-format on
     468             : 
     469             : /**
     470             :  *  @brief
     471             :  *    This is invoked when a #VerifyOrDie or #VerifyOrDieWithMsg
     472             :  *    assertion expression evaluates to false.
     473             :  *
     474             :  *    Developers may override and customize this by defining #chipDie
     475             :  *    before CodeUtils.h is included by the preprocessor.
     476             :  *
     477             :  *  Example Usage:
     478             :  *
     479             :  *  @code
     480             :  *  chipDie();
     481             :  *  @endcode
     482             :  *
     483             :  */
     484             : #ifndef chipAbort
     485             : extern "C" void chipAbort(void) __attribute((noreturn));
     486             : 
     487           0 : inline void chipAbort(void)
     488             : {
     489             :     while (true)
     490             :     {
     491             :         // NL_ASSERT_ABORT is redefined to be chipAbort, so not useful here.
     492           0 :         CHIP_CONFIG_ABORT();
     493             :     }
     494             : }
     495             : #endif // chipAbort
     496             : #ifndef chipDie
     497             : extern "C" void chipDie(void) __attribute((noreturn));
     498             : 
     499           0 : inline void chipDie(void)
     500             : {
     501           0 :     ChipLogError(NotSpecified, "chipDie chipDie chipDie");
     502           0 :     chipAbort();
     503             : }
     504             : #endif // chipDie
     505             : 
     506             : /**
     507             :  *  @def VerifyOrDie(aCondition)
     508             :  *
     509             :  *  @brief
     510             :  *    This checks for the specified condition, which is expected to
     511             :  *    commonly be true and forces an immediate abort if the condition
     512             :  *    is false.
     513             :  *
     514             :  *  Example Usage:
     515             :  *
     516             :  *  @code
     517             :  *  void FreeBuffer(const uint8_t *buf)
     518             :  *  {
     519             :  *      VerifyOrDie(buf != NULL);
     520             :  *      free(buf);
     521             :  *  }
     522             :  *  @endcode
     523             :  *
     524             :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     525             :  *
     526             :  *  @sa #VerifyOrDieWithMsg
     527             :  *  @sa #chipDie
     528             :  *
     529             :  */
     530             : #if CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     531             : #define VerifyOrDie(aCondition)                                                                                                    \
     532             :     nlABORT_ACTION(aCondition, ChipLogDetail(Support, "VerifyOrDie failure at %s:%d: %s", __FILE__, __LINE__, #aCondition))
     533             : #else // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     534             : #define VerifyOrDie(aCondition) VerifyOrDieWithoutLogging(aCondition)
     535             : #endif // CHIP_CONFIG_VERBOSE_VERIFY_OR_DIE
     536             : 
     537             : /**
     538             :  *  @def VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)
     539             :  *
     540             :  *  @brief
     541             :  *    This checks for the specified condition, which is expected to
     542             :  *    commonly be true and both prints @a aMessage and forces an
     543             :  *    immediate abort if the condition is false.
     544             :  *
     545             :  *  Example Usage:
     546             :  *
     547             :  *  @code
     548             :  *  void FreeBuffer(const uint8_t *buf)
     549             :  *  {
     550             :  *      VerifyOrDieWithMsg(buf != NULL, MemoryManagement, "Invalid pointer passed to FreeBuffer");
     551             :  *      free(buf);
     552             :  *  }
     553             :  *  @endcode
     554             :  *
     555             :  *  @param[in]  aCondition  A Boolean expression to be evaluated.
     556             :  *  @param[in]  aModule     A chip LogModule short-hand mnemonic identifing
     557             :  *                          the logical section of code that is a
     558             :  *                          source the logged message.
     559             :  *  @param[in]  aMessage    A pointer to a NULL-terminated C string with
     560             :  *                          C Standard Library-style format specifiers
     561             :  *                          containing the log message to be formatted
     562             :  *                          and logged.
     563             :  *  @param[in]  ...         A variadic argument list whose elements should
     564             :  *                          correspond to the format specifiers in @a
     565             :  *                          aMessage.
     566             :  *
     567             :  *  @sa #VerifyOrDie
     568             :  *  @sa #chipDie
     569             :  *
     570             :  */
     571             : #define VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)                                                                     \
     572             :     nlABORT_ACTION(aCondition, ChipLogDetail(aModule, aMessage, ##__VA_ARGS__))
     573             : 
     574             : /**
     575             :  *  @def LogErrorOnFailure(expr)
     576             :  *
     577             :  *  @brief
     578             :  *    Logs a message if the expression returns something different than CHIP_NO_ERROR.
     579             :  *
     580             :  *  Example usage:
     581             :  *
     582             :  *  @code
     583             :  *    ReturnLogErrorOnFailure(channel->SendMsg(msg));
     584             :  *  @endcode
     585             :  *
     586             :  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
     587             :  */
     588             : #define LogErrorOnFailure(expr)                                                                                                    \
     589             :     do                                                                                                                             \
     590             :     {                                                                                                                              \
     591             :         CHIP_ERROR __err = (expr);                                                                                                 \
     592             :         if (__err != CHIP_NO_ERROR)                                                                                                \
     593             :         {                                                                                                                          \
     594             :             ChipLogError(NotSpecified, "%s at %s:%d", ErrorStr(__err), __FILE__, __LINE__);                                        \
     595             :         }                                                                                                                          \
     596             :     } while (false)
     597             : 
     598             : /**
     599             :  *  @def VerifyOrDo(expr, ...)
     600             :  *
     601             :  *  @brief
     602             :  *    do something if expression evaluates to false
     603             :  *
     604             :  *  Example usage:
     605             :  *
     606             :  * @code
     607             :  *    VerifyOrDo(param != nullptr, LogError("param is nullptr"));
     608             :  *  @endcode
     609             :  *
     610             :  *  @param[in]  expr        A Boolean expression to be evaluated.
     611             :  *  @param[in]  ...         Statements to execute.
     612             :  */
     613             : #define VerifyOrDo(expr, ...)                                                                                                      \
     614             :     do                                                                                                                             \
     615             :     {                                                                                                                              \
     616             :         if (!(expr))                                                                                                               \
     617             :         {                                                                                                                          \
     618             :             __VA_ARGS__;                                                                                                           \
     619             :         }                                                                                                                          \
     620             :     } while (false)
     621             : 
     622             : #if (__cplusplus >= 201103L)
     623             : 
     624             : #ifndef __FINAL
     625             : #define __FINAL final
     626             : #endif
     627             : 
     628             : #ifndef __OVERRIDE
     629             : #define __OVERRIDE override
     630             : #endif
     631             : 
     632             : #ifndef __CONSTEXPR
     633             : #define __CONSTEXPR constexpr
     634             : #endif
     635             : 
     636             : #else
     637             : 
     638             : #ifndef __FINAL
     639             : #define __FINAL
     640             : #endif
     641             : 
     642             : #ifndef __OVERRIDE
     643             : #define __OVERRIDE
     644             : #endif
     645             : 
     646             : #ifndef __CONSTEXPR
     647             : #define __CONSTEXPR constexpr
     648             : #endif
     649             : 
     650             : #endif // (__cplusplus >= 201103L)
     651             : 
     652             : #if ((__cplusplus >= 201703L) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__)) && (__clang_major__ >= 4))
     653             : #define CHECK_RETURN_VALUE [[nodiscard]]
     654             : #elif defined(__GNUC__) && (__GNUC__ >= 4)
     655             : #define CHECK_RETURN_VALUE __attribute__((warn_unused_result))
     656             : #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
     657             : #define CHECK_RETURN_VALUE _Check_return_
     658             : #else
     659             : #define CHECK_RETURN_VALUE
     660             : #endif
     661             : 
     662             : #if defined(__clang__)
     663             : #define FALLTHROUGH [[clang::fallthrough]]
     664             : #elif defined(__GNUC__)
     665             : #define FALLTHROUGH __attribute__((fallthrough))
     666             : #else
     667             : #define FALLTHROUGH (void) 0
     668             : #endif
     669             : 
     670             : /**
     671             :  * @def ArraySize(aArray)
     672             :  *
     673             :  * @brief
     674             :  *   Returns the size of an array in number of elements.
     675             :  *
     676             :  * Example Usage:
     677             :  *
     678             :  * @code
     679             :  * int numbers[10];
     680             :  * SortNumbers(numbers, ArraySize(numbers));
     681             :  * @endcode
     682             :  *
     683             :  * @return      The size of an array in number of elements.
     684             :  *
     685             :  * @note Clever template-based solutions seem to fail when ArraySize is used
     686             :  *       with a variable-length array argument, so we just do the C-compatible
     687             :  *       thing in C++ as well.
     688             :  */
     689             : #define ArraySize(a) (sizeof(a) / sizeof((a)[0]))
     690             : 
     691             : /**
     692             :  * @brief Ensures that if `str` is NULL, a non-null `default_str_value` is provided
     693             :  *
     694             :  * @param str - null-terminated string pointer or nullptr
     695             :  * @param default_str_value - replacement value if `str` is nullptr
     696             :  * @return `str` if not null, otherwise `default_str_value`
     697             :  */
     698        3637 : inline const char * DefaultStringWhenNull(const char * str, const char * default_str_value)
     699             : {
     700        3637 :     return (str != nullptr) ? str : default_str_value;
     701             : }
     702             : 
     703             : /**
     704             :  * @brief Ensure that a string for a %s specifier is shown as "(null)" if null
     705             :  *
     706             :  * @param str - null-terminated string pointer or nullptr
     707             :  * @return `str` if not null, otherwise literal "(null)"
     708             :  */
     709        3637 : inline const char * StringOrNullMarker(const char * str)
     710             : {
     711        3637 :     return DefaultStringWhenNull(str, "(null)");
     712             : }
     713             : 
     714             : namespace chip {
     715             : 
     716             : /**
     717             :  * Utility for checking, at compile time if the array is constexpr, whether an
     718             :  * array is sorted.  Can be used for static_asserts.
     719             :  */
     720             : 
     721             : template <typename T>
     722             : constexpr bool ArrayIsSorted(const T * aArray, size_t aLength)
     723             : {
     724             :     if (aLength == 0 || aLength == 1)
     725             :     {
     726             :         return true;
     727             :     }
     728             : 
     729             :     if (aArray[0] > aArray[1])
     730             :     {
     731             :         return false;
     732             :     }
     733             : 
     734             :     return ArrayIsSorted(aArray + 1, aLength - 1);
     735             : }
     736             : 
     737             : template <typename T, size_t N>
     738             : constexpr bool ArrayIsSorted(const T (&aArray)[N])
     739             : {
     740             :     return ArrayIsSorted(aArray, N);
     741             : }
     742             : 
     743             : } // namespace chip

Generated by: LCOV version 1.14