xref: /aosp_15_r20/external/ot-br-posix/src/common/code_utils.hpp (revision 4a64e381480ef79f0532b2421e44e6ee336b8e0d)
1 /*
2  *    Copyright (c) 2017, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 /**
30  * @file
31  * This file includes utility macros for coding.
32  */
33 #ifndef OTBR_COMMON_CODE_UTILS_HPP_
34 #define OTBR_COMMON_CODE_UTILS_HPP_
35 
36 #include "openthread-br/config.h"
37 
38 #ifndef OTBR_LOG_TAG
39 #define OTBR_LOG_TAG "UTILS"
40 #endif
41 
42 #include <assert.h>
43 #include <memory>
44 #include <stdlib.h>
45 
46 #include "common/logging.hpp"
47 
48 /**
49  *  This aligns the pointer to @p aAlignType.
50  *
51  *  @param[in] aMem        A pointer to arbitrary memory.
52  *  @param[in] aAlignType  The type to align with and convert the pointer to this type.
53  *
54  *  @returns A pointer to aligned memory.
55  */
56 #define OTBR_ALIGNED(aMem, aAlignType) \
57     reinterpret_cast<aAlignType>(      \
58         ((reinterpret_cast<unsigned long>(aMem) + sizeof(aAlignType) - 1) / sizeof(aAlignType)) * sizeof(aAlignType))
59 
60 // Allocate the structure using "raw" storage.
61 #define OT_DEFINE_ALIGNED_VAR(name, size, align_type) \
62     align_type name[(((size) + (sizeof(align_type) - 1)) / sizeof(align_type))]
63 
64 #ifndef CONTAINING_RECORD
65 #define BASE 0x1
66 #define myoffsetof(s, m) (((size_t) & (((s *)BASE)->m)) - BASE)
67 #define CONTAINING_RECORD(address, type, field) ((type *)((uint8_t *)(address)-myoffsetof(type, field)))
68 #endif /* CONTAINING_RECORD */
69 
70 /**
71  *  This checks for the specified status, which is expected to
72  *  commonly be successful, and branches to the local label 'exit' if
73  *  the status is unsuccessful.
74  *
75  *  @param[in] aStatus  A scalar status to be evaluated against zero (0).
76  */
77 #define SuccessOrExit(aStatus, ...) \
78     do                              \
79     {                               \
80         if ((aStatus) != 0)         \
81         {                           \
82             __VA_ARGS__;            \
83             goto exit;              \
84         }                           \
85     } while (false)
86 
87 /**
88  * This macro verifies a given error status to be successful (compared against value zero (0)), otherwise, it emits a
89  * given error messages and exits the program.
90  *
91  * @param[in] aStatus   A scalar error status to be evaluated against zero (0).
92  * @param[in] aMessage  A message (text string) to print on failure.
93  */
94 #define SuccessOrDie(aStatus, aMessage)                                                   \
95     do                                                                                    \
96     {                                                                                     \
97         if ((aStatus) != 0)                                                               \
98         {                                                                                 \
99             otbrLogEmerg("FAILED %s:%d - %d: %s", __FILE__, __LINE__, aStatus, aMessage); \
100             exit(-1);                                                                     \
101         }                                                                                 \
102     } while (false)
103 
104 /**
105  *  This checks for the specified condition, which is expected to
106  *  commonly be true, and both executes @a ... and branches to the
107  *  local label 'exit' if the condition is false.
108  *
109  *  @param[in] aCondition  A Boolean expression to be evaluated.
110  *  @param[in] ...         An expression or block to execute when the
111  *                         assertion fails.
112  */
113 #define VerifyOrExit(aCondition, ...) \
114     do                                \
115     {                                 \
116         if (!(aCondition))            \
117         {                             \
118             __VA_ARGS__;              \
119             goto exit;                \
120         }                             \
121     } while (false)
122 
123 /**
124  * This macro checks for the specified condition, which is expected to commonly be true,
125  * and both prints the message and terminates the program if the condition is false.
126  *
127  * @param[in] aCondition  The condition to verify
128  * @param[in] aMessage    A message (text string) to print on failure.
129  */
130 #define VerifyOrDie(aCondition, aMessage)                                    \
131     do                                                                       \
132     {                                                                        \
133         if (!(aCondition))                                                   \
134         {                                                                    \
135             otbrLogEmerg("FAILED %s:%d - %s", __FILE__, __LINE__, aMessage); \
136             exit(-1);                                                        \
137         }                                                                    \
138     } while (false)
139 
140 /**
141  * This macro prints the message and terminates the program.
142  *
143  * @param[in] aMessage    A message (text string) to print.
144  */
145 #define DieNow(aMessage)                                                 \
146     do                                                                   \
147     {                                                                    \
148         otbrLogEmerg("FAILED %s:%d - %s", __FILE__, __LINE__, aMessage); \
149         exit(-1);                                                        \
150     } while (false)
151 
152 /**
153  *  This unconditionally executes @a ... and branches to the local
154  *  label 'exit'.
155  *
156  *  @note The use of this interface implies neither success nor
157  *        failure for the overall exit status of the enclosing
158  *        function body.
159  *
160  *  @param[in] ...  An optional expression or block to execute
161  *                  when the assertion fails.
162  */
163 #define ExitNow(...) \
164     do               \
165     {                \
166         __VA_ARGS__; \
167         goto exit;   \
168     } while (false)
169 
170 #define OTBR_NOOP
171 #define OTBR_UNUSED_VARIABLE(variable) ((void)(variable))
172 
MakeUnique(Args &&...args)173 template <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args &&...args)
174 {
175     return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
176 }
177 
178 /**
179  * This method converts 8 uint8_t bytes into uint64_t using big-endian.
180  *
181  * @param[in] aValue  The input 8 uint8_t bytes.
182  * @returns The converted uint64_t.
183  */
184 uint64_t ConvertOpenThreadUint64(const uint8_t *aValue);
185 
186 /**
187  * This class makes any class that derives from it non-copyable. It is intended to be used as a private base class.
188  */
189 class NonCopyable
190 {
191 public:
192     NonCopyable(const NonCopyable &)            = delete;
193     NonCopyable &operator=(const NonCopyable &) = delete;
194 
195 protected:
196     NonCopyable(void) = default;
197 };
198 
199 template <typename T> class Optional
200 {
201 public:
202     constexpr Optional(void) = default;
203 
Optional(T aValue)204     Optional(T aValue) { SetValue(aValue); }
205 
~Optional(void)206     ~Optional(void) { ClearValue(); }
207 
Optional(const Optional & aOther)208     Optional(const Optional &aOther) { AssignFrom(aOther); }
209 
operator =(const Optional & aOther)210     Optional &operator=(const Optional &aOther) { AssignFrom(aOther); }
211 
operator ->(void) const212     constexpr const T *operator->(void) const { return &GetValue(); }
213 
operator *(void) const214     constexpr const T &operator*(void) const { return GetValue(); }
215 
HasValue(void) const216     constexpr bool HasValue(void) const { return mHasValue; }
217 
218 private:
GetValue(void) const219     T &GetValue(void) const
220     {
221         assert(mHasValue);
222         return *const_cast<T *>(reinterpret_cast<const T *>(&mStorage));
223     }
224 
ClearValue(void)225     void ClearValue(void)
226     {
227         if (mHasValue)
228         {
229             GetValue().~T();
230             mHasValue = false;
231         }
232     }
233 
SetValue(const T & aValue)234     void SetValue(const T &aValue)
235     {
236         ClearValue();
237         new (&mStorage) T(aValue);
238         mHasValue = true;
239     }
240 
AssignFrom(const Optional & aOther)241     void AssignFrom(const Optional &aOther)
242     {
243         ClearValue();
244         if (aOther.mHasValue)
245         {
246             SetValue(aOther.GetValue());
247         }
248     }
249 
250     alignas(T) unsigned char mStorage[sizeof(T)];
251     bool mHasValue = false;
252 };
253 
254 #endif // OTBR_COMMON_CODE_UTILS_HPP_
255