Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / support / CodeUtils.h
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 #ifdef __cplusplus
30
31 #include <core/CHIPError.h>
32 #include <support/ErrorStr.h>
33 #include <support/logging/CHIPLogging.h>
34
35 /**
36  *  @name chip-specific nlassert.h Overrides
37  *
38  *  @{
39  *
40  */
41
42 /**
43  *  @def CHIP_ASSERT_ABORT()
44  *
45  *  @brief
46  *    This implements a chip-specific override for #CHIP_ASSERT_ABORT *
47  *    from nlassert.h.
48  *
49  */
50 #if !defined(CHIP_ASSERT_ABORT)
51 #define CHIP_ASSERT_ABORT() chipDie()
52 #endif
53
54 /**
55  *  @def CHIP_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)
56  *
57  *  @brief
58  *    This implements a chip-specific override for \c CHIP_ASSERT_LOG
59  *    from nlassert.h.
60  *
61  *  @param[in]  aPrefix     A pointer to a NULL-terminated C string printed
62  *                          at the beginning of the logged assertion
63  *                          message. Typically this is and should be
64  *                          \c CHIP_ASSERT_PREFIX_STRING.
65  *  @param[in]  aName       A pointer to a NULL-terminated C string printed
66  *                          following @a aPrefix that indicates what
67  *                          module, program, application or subsystem
68  *                          the assertion occurred in Typically this
69  *                          is and should be
70  *                          \c CHIP_ASSERT_COMPONENT_STRING.
71  *  @param[in]  aCondition  A pointer to a NULL-terminated C string indicating
72  *                          the expression that evaluated to false in
73  *                          the assertion. Typically this is a
74  *                          stringified version of the actual
75  *                          assertion expression.
76  *  @param[in]  aLabel      An optional pointer to a NULL-terminated C string
77  *                          indicating, for exception-style
78  *                          assertions, the label that will be
79  *                          branched to when the assertion expression
80  *                          evaluates to false.
81  *  @param[in]  aFile       A pointer to a NULL-terminated C string indicating
82  *                          the file in which the exception
83  *                          occurred. Typically this is and should be
84  *                          \_\_FILE\_\_ from the C preprocessor.
85  *  @param[in]  aLine       The line number in @a aFile on which the assertion
86  *                          expression evaluated to false. Typically
87  *                          this is and should be \_\_LINE\_\_ from the C
88  *                          preprocessor.
89  *  @param[in]  aMessage    An optional pointer to a NULL-terminated C string
90  *                          containing a caller-specified message
91  *                          further describing the assertion failure.
92  *
93  */
94 // clang-format off
95 #if !defined(CHIP_ASSERT_LOG)
96 #define CHIP_ASSERT_LOG(aPrefix, aName, aCondition, aLabel, aFile, aLine, aMessage)         \
97     do                                                                                    \
98     {                                                                                     \
99         ChipLogError(NotSpecified,                                                       \
100                       CHIP_ASSERT_LOG_FORMAT_DEFAULT,                                       \
101                       aPrefix,                                                            \
102                       (((aName) == 0) || (*(aName) == '\0')) ? "" : aName,                \
103                       (((aName) == 0) || (*(aName) == '\0')) ? "" : ": ",                 \
104                       aCondition,                                                         \
105                       (((aMessage) == 0) ? "" : aMessage),                                \
106                       (((aMessage) == 0) ? "" : ", "),                                    \
107                       aFile,                                                              \
108                       aLine);                                                             \
109     } while (0)
110 #endif
111 // clang-format on
112
113 /**
114  *  @} chip-specific nlassert.h Overrides
115  *
116  */
117
118 #include <nlassert.h>
119
120 namespace chip {
121
122 // Generic min() and max() functions
123 //
124 template <typename _T>
125 constexpr inline const _T & min(const _T & a, const _T & b)
126 {
127     if (b < a)
128         return b;
129
130     return a;
131 }
132
133 template <typename _T>
134 constexpr inline const _T & max(const _T & a, const _T & b)
135 {
136     if (a < b)
137         return b;
138
139     return a;
140 }
141
142 } // namespace chip
143
144 /**
145  *  @def IgnoreUnusedVariable(aVariable)
146  *
147  *  @brief
148  *    This casts the specified @a aVariable to void to quell any
149  *    compiler-issued unused variable warnings or errors.
150  *
151  *  @code
152  *  void foo (int err)
153  *  {
154  *      IgnoreUnusedVariable(err)
155  *  }
156  *  @endcode
157  *
158  */
159 #define IgnoreUnusedVariable(aVariable) ((void) (aVariable))
160
161 /**
162  *  @def ReturnErrorOnFailure(expr)
163  *
164  *  @brief
165  *    Returns the error code if the expression returns something different
166  *    than CHIP_NO_ERROR.
167  *
168  *  Example usage:
169  *
170  *  @code
171  *    ReturnErrorOnFailure(channel->SendMsg(msg));
172  *  @endcode
173  *
174  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
175  */
176 #define ReturnErrorOnFailure(expr)                                                                                                 \
177     do                                                                                                                             \
178     {                                                                                                                              \
179         CHIP_ERROR __err = (expr);                                                                                                 \
180         if (__err != CHIP_NO_ERROR)                                                                                                \
181         {                                                                                                                          \
182             return __err;                                                                                                          \
183         }                                                                                                                          \
184     } while (false)
185
186 /**
187  *  @def ReturnOnFailure(expr)
188  *
189  *  @brief
190  *    Returns if the expression returns something different than CHIP_NO_ERROR
191  *
192  *  Example usage:
193  *
194  *  @code
195  *    ReturnOnFailure(channel->SendMsg(msg));
196  *  @endcode
197  *
198  *  @param[in]  expr        A scalar expression to be evaluated against CHIP_NO_ERROR.
199  */
200 #define ReturnOnFailure(expr)                                                                                                      \
201     do                                                                                                                             \
202     {                                                                                                                              \
203         CHIP_ERROR __err = (expr);                                                                                                 \
204         if (__err != CHIP_NO_ERROR)                                                                                                \
205         {                                                                                                                          \
206             return;                                                                                                                \
207         }                                                                                                                          \
208     } while (false)
209
210 /**
211  *  @def VerifyOrReturn(expr, ...)
212  *
213  *  @brief
214  *    Returns from the void function if expression evaluates to false
215  *
216  *  Example usage:
217  *
218  * @code
219  *    VerifyOrReturn(param != nullptr, LogError("param is nullptr"));
220  *  @endcode
221  *
222  *  @param[in]  expr        A Boolean expression to be evaluated.
223  */
224 #define VerifyOrReturn(expr, ...)                                                                                                  \
225     do                                                                                                                             \
226     {                                                                                                                              \
227         if (!(expr))                                                                                                               \
228         {                                                                                                                          \
229             __VA_ARGS__;                                                                                                           \
230             return;                                                                                                                \
231         }                                                                                                                          \
232     } while (false)
233
234 /**
235  *  @def VerifyOrReturnError(expr, code)
236  *
237  *  @brief
238  *    Returns a specified error code if expression evaluates to false
239  *
240  *  Example usage:
241  *
242  *  @code
243  *    VerifyOrReturnError(param != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
244  *  @endcode
245  *
246  *  @param[in]  expr        A Boolean expression to be evaluated.
247  *  @param[in]  code        A value to return if @a expr is false.
248  */
249 #define VerifyOrReturnError(expr, code)                                                                                            \
250     do                                                                                                                             \
251     {                                                                                                                              \
252         if (!(expr))                                                                                                               \
253         {                                                                                                                          \
254             return code;                                                                                                           \
255         }                                                                                                                          \
256     } while (false)
257
258 /**
259  *  @def ReturnErrorCodeIf(expr, code)
260  *
261  *  @brief
262  *    Returns a specified error code if expression evaluates to true
263  *
264  *  Example usage:
265  *
266  *  @code
267  *    ReturnErrorCodeIf(state == kInitialized, CHIP_NO_ERROR);
268  *    ReturnErrorCodeIf(state == kInitialized, CHIP_ERROR_INVALID_STATE);
269  *  @endcode
270  *
271  *  @param[in]  expr        A Boolean expression to be evaluated.
272  *  @param[in]  code        A value to return if @a expr is false.
273  */
274 #define ReturnErrorCodeIf(expr, code)                                                                                              \
275     do                                                                                                                             \
276     {                                                                                                                              \
277         if (expr)                                                                                                                  \
278         {                                                                                                                          \
279             return code;                                                                                                           \
280         }                                                                                                                          \
281     } while (false)
282
283 /**
284  *  @def SuccessOrExit(aStatus)
285  *
286  *  @brief
287  *    This checks for the specified status, which is expected to
288  *    commonly be successful (CHIP_NO_ERROR), and branches to
289  *    the local label 'exit' if the status is unsuccessful.
290  *
291  *  Example Usage:
292  *
293  *  @code
294  *  CHIP_ERROR TryHard()
295  *  {
296  *      CHIP_ERROR err;
297  *
298  *      err = TrySomething();
299  *      SuccessOrExit(err);
300  *
301  *      err = TrySomethingElse();
302  *      SuccessOrExit(err);
303  *
304  *  exit:
305  *      return err;
306  *  }
307  *  @endcode
308  *
309  *  @param[in]  aStatus     A scalar status to be evaluated against zero (0).
310  *
311  */
312 #define SuccessOrExit(aStatus) nlEXPECT((aStatus) == CHIP_NO_ERROR, exit)
313
314 /**
315  *  @def VerifyOrExit(aCondition, anAction)
316  *
317  *  @brief
318  *    This checks for the specified condition, which is expected to
319  *    commonly be true, and both executes @a anAction and branches to
320  *    the local label 'exit' if the condition is false.
321  *
322  *  Example Usage:
323  *
324  *  @code
325  *  CHIP_ERROR MakeBuffer(const uint8_t *& buf)
326  *  {
327  *      CHIP_ERROR err = CHIP_NO_ERROR;
328  *
329  *      buf = (uint8_t *)malloc(1024);
330  *      VerifyOrExit(buf != NULL, err = CHIP_ERROR_NO_MEMORY);
331  *
332  *      memset(buf, 0, 1024);
333  *
334  *  exit:
335  *      return err;
336  *  }
337  *  @endcode
338  *
339  *  @param[in]  aCondition  A Boolean expression to be evaluated.
340  *  @param[in]  anAction    An expression or block to execute when the
341  *                          assertion fails.
342  *
343  */
344 #define VerifyOrExit(aCondition, anAction) nlEXPECT_ACTION(aCondition, exit, anAction)
345
346 /**
347  *  @def ExitNow(...)
348  *
349  *  @brief
350  *    This unconditionally executes @a ... and branches to the local
351  *    label 'exit'.
352  *
353  *  @note The use of this interface implies neither success nor
354  *        failure for the overall exit status of the enclosing function
355  *        body.
356  *
357  *  Example Usage:
358  *
359  *  @code
360  *  CHIP_ERROR ReadAll(Reader& reader)
361  *  {
362  *      CHIP_ERROR err;
363  *
364  *      while (true)
365  *      {
366  *          err = reader.ReadNext();
367  *          if (err == CHIP_ERROR_AT_END)
368  *              ExitNow(err = CHIP_NO_ERROR);
369  *          SuccessOrExit(err);
370  *          DoSomething();
371  *      }
372  *
373  *  exit:
374  *      return err;
375  *  }
376  *  @endcode
377  *
378  *  @param[in]  ...         An optional expression or block to execute
379  *                          when the assertion fails.
380  *
381  */
382 // clang-format off
383 #define ExitNow(...)                                                   \
384     do {                                                               \
385         __VA_ARGS__;                                                   \
386         goto exit;                                                     \
387     } while (0)
388 // clang-format on
389
390 /**
391  *  @brief
392  *    This is invoked when a #VerifyOrDie or #VerifyOrDieWithMsg
393  *    assertion expression evaluates to false.
394  *
395  *    Developers may override and customize this by defining #chipDie
396  *    before CodeUtils.h is included by the preprocessor.
397  *
398  *  Example Usage:
399  *
400  *  @code
401  *  chipDie();
402  *  @endcode
403  *
404  */
405 #ifndef chipDie
406 extern "C" void chipDie(void) __attribute((noreturn));
407
408 inline void chipDie(void)
409 {
410     ChipLogError(NotSpecified, "chipDie chipDie chipDie");
411
412     while (true)
413     {
414         // CHIP_ASSERT_ABORT is redefined to be chipDie, so not useful here.
415         abort();
416     }
417 }
418 #endif // chipDie
419
420 /**
421  *  @def VerifyOrDie(aCondition)
422  *
423  *  @brief
424  *    This checks for the specified condition, which is expected to
425  *    commonly be true and forces an immediate abort if the condition
426  *    is false.
427  *
428  *  Example Usage:
429  *
430  *  @code
431  *  void FreeBuffer(const uint8_t *buf)
432  *  {
433  *      VerifyOrDie(buf != NULL);
434  *      free(buf);
435  *  }
436  *  @endcode
437  *
438  *  @param[in]  aCondition  A Boolean expression to be evaluated.
439  *
440  *  @sa #VerifyOrDieWithMsg
441  *  @sa #chipDie
442  *
443  */
444 #define VerifyOrDie(aCondition) nlABORT(aCondition)
445
446 /**
447  *  @def VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)
448  *
449  *  @brief
450  *    This checks for the specified condition, which is expected to
451  *    commonly be true and both prints @a aMessage and forces an
452  *    immediate abort if the condition is false.
453  *
454  *  Example Usage:
455  *
456  *  @code
457  *  void FreeBuffer(const uint8_t *buf)
458  *  {
459  *      VerifyOrDieWithMsg(buf != NULL, MemoryManagement, "Invalid pointer passed to FreeBuffer");
460  *      free(buf);
461  *  }
462  *  @endcode
463  *
464  *  @param[in]  aCondition  A Boolean expression to be evaluated.
465  *  @param[in]  aModule     A chip LogModule short-hand mnemonic identifing
466  *                          the logical section of code that is a
467  *                          source the logged message.
468  *  @param[in]  aMessage    A pointer to a NULL-terminated C string with
469  *                          C Standard Library-style format specifiers
470  *                          containing the log message to be formatted
471  *                          and logged.
472  *  @param[in]  ...         A variadic argument list whose elements should
473  *                          correspond to the format specifiers in @a
474  *                          aMessage.
475  *
476  *  @sa #VerifyOrDie
477  *  @sa #chipDie
478  *
479  */
480 #define VerifyOrDieWithMsg(aCondition, aModule, aMessage, ...)                                                                     \
481     nlABORT_ACTION(aCondition, ChipLogDetail(aModule, aMessage, ##__VA_ARGS__))
482
483 #if (__cplusplus >= 201103L)
484
485 #ifndef __FINAL
486 #define __FINAL final
487 #endif
488
489 #ifndef __OVERRIDE
490 #define __OVERRIDE override
491 #endif
492
493 #ifndef __CONSTEXPR
494 #define __CONSTEXPR constexpr
495 #endif
496
497 #else
498
499 #ifndef __FINAL
500 #define __FINAL
501 #endif
502
503 #ifndef __OVERRIDE
504 #define __OVERRIDE
505 #endif
506
507 #ifndef __CONSTEXPR
508 #define __CONSTEXPR constexpr
509 #endif
510
511 #endif // (__cplusplus >= 201103L)
512
513 #if ((__cplusplus >= 201703L) || (defined(__GNUC__) && (__GNUC__ >= 7)) || (defined(__clang__)) && (__clang_major__ >= 4))
514 #define CHECK_RETURN_VALUE [[nodiscard]]
515 #elif defined(__GNUC__) && (__GNUC__ >= 4)
516 #define CHECK_RETURN_VALUE __attribute__((warn_unused_result))
517 #elif defined(_MSC_VER) && (_MSC_VER >= 1700)
518 #define CHECK_RETURN_VALUE _Check_return_
519 #else
520 #define CHECK_RETURN_VALUE
521 #endif
522
523 #if defined(__clang__)
524 #define FALLTHROUGH [[clang::fallthrough]]
525 #else
526 #define FALLTHROUGH (void) 0
527 #endif
528
529 #endif // __cplusplus
530
531 /**
532  * @def ArraySize(aArray)
533  *
534  * @brief
535  *   Returns the size of an array in number of elements.
536  *
537  * Example Usage:
538  *
539  * @code
540  * int numbers[10];
541  * SortNumbers(numbers, ArraySize(numbers));
542  * @endcode
543  *
544  * @return      The size of an array in number of elements.
545  *
546  * @note Clever template-based solutions seem to fail when ArraySize is used
547  *       with a variable-length array argument, so we just do the C-compatible
548  *       thing in C++ as well.
549  */
550 #define ArraySize(a) (sizeof(a) / sizeof((a)[0]))