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