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