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 */
57 #define OTBR_ALIGNED(aMem, aAlignType) \
58 reinterpret_cast<aAlignType>( \
59 ((reinterpret_cast<unsigned long>(aMem) + sizeof(aAlignType) - 1) / sizeof(aAlignType)) * sizeof(aAlignType))
60
61 // Allocate the structure using "raw" storage.
62 #define OT_DEFINE_ALIGNED_VAR(name, size, align_type) \
63 align_type name[(((size) + (sizeof(align_type) - 1)) / sizeof(align_type))]
64
65 #ifndef CONTAINING_RECORD
66 #define BASE 0x1
67 #define myoffsetof(s, m) (((size_t) & (((s *)BASE)->m)) - BASE)
68 #define CONTAINING_RECORD(address, type, field) ((type *)((uint8_t *)(address)-myoffsetof(type, field)))
69 #endif /* CONTAINING_RECORD */
70
71 /**
72 * This checks for the specified status, which is expected to
73 * commonly be successful, and branches to the local label 'exit' if
74 * the status is unsuccessful.
75 *
76 * @param[in] aStatus A scalar status to be evaluated against zero (0).
77 *
78 */
79 #define SuccessOrExit(aStatus, ...) \
80 do \
81 { \
82 if ((aStatus) != 0) \
83 { \
84 __VA_ARGS__; \
85 goto exit; \
86 } \
87 } while (false)
88
89 /**
90 * This macro verifies a given error status to be successful (compared against value zero (0)), otherwise, it emits a
91 * given error messages and exits the program.
92 *
93 * @param[in] aStatus A scalar error status to be evaluated against zero (0).
94 * @param[in] aMessage A message (text string) to print on failure.
95 *
96 */
97 #define SuccessOrDie(aStatus, aMessage) \
98 do \
99 { \
100 if ((aStatus) != 0) \
101 { \
102 otbrLogEmerg("FAILED %s:%d - %d: %s", __FILE__, __LINE__, aStatus, aMessage); \
103 exit(-1); \
104 } \
105 } while (false)
106
107 /**
108 * This checks for the specified condition, which is expected to
109 * commonly be true, and both executes @a ... and branches to the
110 * local label 'exit' if the condition is false.
111 *
112 * @param[in] aCondition A Boolean expression to be evaluated.
113 * @param[in] ... An expression or block to execute when the
114 * assertion fails.
115 *
116 */
117 #define VerifyOrExit(aCondition, ...) \
118 do \
119 { \
120 if (!(aCondition)) \
121 { \
122 __VA_ARGS__; \
123 goto exit; \
124 } \
125 } while (false)
126
127 /**
128 * This macro checks for the specified condition, which is expected to commonly be true,
129 * and both prints the message and terminates the program if the condition is false.
130 *
131 * @param[in] aCondition The condition to verify
132 * @param[in] aMessage A message (text string) to print on failure.
133 *
134 */
135 #define VerifyOrDie(aCondition, aMessage) \
136 do \
137 { \
138 if (!(aCondition)) \
139 { \
140 otbrLogEmerg("FAILED %s:%d - %s", __FILE__, __LINE__, aMessage); \
141 exit(-1); \
142 } \
143 } while (false)
144
145 /**
146 * This unconditionally executes @a ... and branches to the local
147 * label 'exit'.
148 *
149 * @note The use of this interface implies neither success nor
150 * failure for the overall exit status of the enclosing
151 * function body.
152 *
153 * @param[in] ... An optional expression or block to execute
154 * when the assertion fails.
155 *
156 */
157 #define ExitNow(...) \
158 do \
159 { \
160 __VA_ARGS__; \
161 goto exit; \
162 } while (false)
163
164 #define OTBR_NOOP
165 #define OTBR_UNUSED_VARIABLE(variable) ((void)(variable))
166
MakeUnique(Args &&...args)167 template <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args &&...args)
168 {
169 return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
170 }
171
172 /**
173 * This method converts 8 uint8_t bytes into uint64_t using big-endian.
174 *
175 * @param[in] aValue The input 8 uint8_t bytes.
176 * @returns The converted uint64_t.
177 */
178 uint64_t ConvertOpenThreadUint64(const uint8_t *aValue);
179
180 /**
181 * This class makes any class that derives from it non-copyable. It is intended to be used as a private base class.
182 *
183 */
184 class NonCopyable
185 {
186 public:
187 NonCopyable(const NonCopyable &) = delete;
188 NonCopyable &operator=(const NonCopyable &) = delete;
189
190 protected:
191 NonCopyable(void) = default;
192 };
193
194 template <typename T> class Optional
195 {
196 public:
197 constexpr Optional(void) = default;
198
Optional(T aValue)199 Optional(T aValue) { SetValue(aValue); }
200
~Optional(void)201 ~Optional(void) { ClearValue(); }
202
Optional(const Optional & aOther)203 Optional(const Optional &aOther) { AssignFrom(aOther); }
204
operator =(const Optional & aOther)205 Optional &operator=(const Optional &aOther) { AssignFrom(aOther); }
206
operator ->(void) const207 constexpr const T *operator->(void) const { return &GetValue(); }
208
operator *(void) const209 constexpr const T &operator*(void) const { return GetValue(); }
210
HasValue(void) const211 constexpr bool HasValue(void) const { return mHasValue; }
212
213 private:
GetValue(void) const214 T &GetValue(void) const
215 {
216 assert(mHasValue);
217 return *const_cast<T *>(reinterpret_cast<const T *>(&mStorage));
218 }
219
ClearValue(void)220 void ClearValue(void)
221 {
222 if (mHasValue)
223 {
224 GetValue().~T();
225 mHasValue = false;
226 }
227 }
228
SetValue(const T & aValue)229 void SetValue(const T &aValue)
230 {
231 ClearValue();
232 new (&mStorage) T(aValue);
233 mHasValue = true;
234 }
235
AssignFrom(const Optional & aOther)236 void AssignFrom(const Optional &aOther)
237 {
238 ClearValue();
239 if (aOther.mHasValue)
240 {
241 SetValue(aOther.GetValue());
242 }
243 }
244
245 alignas(T) unsigned char mStorage[sizeof(T)];
246 bool mHasValue = false;
247 };
248
249 #endif // OTBR_COMMON_CODE_UTILS_HPP_
250