/* * Copyright (c) 2017, The OpenThread Authors. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holder nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * @file * This file includes utility macros for coding. */ #ifndef OTBR_COMMON_CODE_UTILS_HPP_ #define OTBR_COMMON_CODE_UTILS_HPP_ #include "openthread-br/config.h" #ifndef OTBR_LOG_TAG #define OTBR_LOG_TAG "UTILS" #endif #include #include #include #include "common/logging.hpp" /** * This aligns the pointer to @p aAlignType. * * @param[in] aMem A pointer to arbitrary memory. * @param[in] aAlignType The type to align with and convert the pointer to this type. * * @returns A pointer to aligned memory. */ #define OTBR_ALIGNED(aMem, aAlignType) \ reinterpret_cast( \ ((reinterpret_cast(aMem) + sizeof(aAlignType) - 1) / sizeof(aAlignType)) * sizeof(aAlignType)) // Allocate the structure using "raw" storage. #define OT_DEFINE_ALIGNED_VAR(name, size, align_type) \ align_type name[(((size) + (sizeof(align_type) - 1)) / sizeof(align_type))] #ifndef CONTAINING_RECORD #define BASE 0x1 #define myoffsetof(s, m) (((size_t) & (((s *)BASE)->m)) - BASE) #define CONTAINING_RECORD(address, type, field) ((type *)((uint8_t *)(address)-myoffsetof(type, field))) #endif /* CONTAINING_RECORD */ /** * This checks for the specified status, which is expected to * commonly be successful, and branches to the local label 'exit' if * the status is unsuccessful. * * @param[in] aStatus A scalar status to be evaluated against zero (0). */ #define SuccessOrExit(aStatus, ...) \ do \ { \ if ((aStatus) != 0) \ { \ __VA_ARGS__; \ goto exit; \ } \ } while (false) /** * This macro verifies a given error status to be successful (compared against value zero (0)), otherwise, it emits a * given error messages and exits the program. * * @param[in] aStatus A scalar error status to be evaluated against zero (0). * @param[in] aMessage A message (text string) to print on failure. */ #define SuccessOrDie(aStatus, aMessage) \ do \ { \ if ((aStatus) != 0) \ { \ otbrLogEmerg("FAILED %s:%d - %d: %s", __FILE__, __LINE__, aStatus, aMessage); \ exit(-1); \ } \ } while (false) /** * This checks for the specified condition, which is expected to * commonly be true, and both executes @a ... and branches to the * local label 'exit' if the condition is false. * * @param[in] aCondition A Boolean expression to be evaluated. * @param[in] ... An expression or block to execute when the * assertion fails. */ #define VerifyOrExit(aCondition, ...) \ do \ { \ if (!(aCondition)) \ { \ __VA_ARGS__; \ goto exit; \ } \ } while (false) /** * This macro checks for the specified condition, which is expected to commonly be true, * and both prints the message and terminates the program if the condition is false. * * @param[in] aCondition The condition to verify * @param[in] aMessage A message (text string) to print on failure. */ #define VerifyOrDie(aCondition, aMessage) \ do \ { \ if (!(aCondition)) \ { \ otbrLogEmerg("FAILED %s:%d - %s", __FILE__, __LINE__, aMessage); \ exit(-1); \ } \ } while (false) /** * This macro prints the message and terminates the program. * * @param[in] aMessage A message (text string) to print. */ #define DieNow(aMessage) \ do \ { \ otbrLogEmerg("FAILED %s:%d - %s", __FILE__, __LINE__, aMessage); \ exit(-1); \ } while (false) /** * This unconditionally executes @a ... and branches to the local * label 'exit'. * * @note The use of this interface implies neither success nor * failure for the overall exit status of the enclosing * function body. * * @param[in] ... An optional expression or block to execute * when the assertion fails. */ #define ExitNow(...) \ do \ { \ __VA_ARGS__; \ goto exit; \ } while (false) #define OTBR_NOOP #define OTBR_UNUSED_VARIABLE(variable) ((void)(variable)) template std::unique_ptr MakeUnique(Args &&...args) { return std::unique_ptr(new T(std::forward(args)...)); } /** * This method converts 8 uint8_t bytes into uint64_t using big-endian. * * @param[in] aValue The input 8 uint8_t bytes. * @returns The converted uint64_t. */ uint64_t ConvertOpenThreadUint64(const uint8_t *aValue); /** * This class makes any class that derives from it non-copyable. It is intended to be used as a private base class. */ class NonCopyable { public: NonCopyable(const NonCopyable &) = delete; NonCopyable &operator=(const NonCopyable &) = delete; protected: NonCopyable(void) = default; }; template class Optional { public: constexpr Optional(void) = default; Optional(T aValue) { SetValue(aValue); } ~Optional(void) { ClearValue(); } Optional(const Optional &aOther) { AssignFrom(aOther); } Optional &operator=(const Optional &aOther) { AssignFrom(aOther); } constexpr const T *operator->(void) const { return &GetValue(); } constexpr const T &operator*(void) const { return GetValue(); } constexpr bool HasValue(void) const { return mHasValue; } private: T &GetValue(void) const { assert(mHasValue); return *const_cast(reinterpret_cast(&mStorage)); } void ClearValue(void) { if (mHasValue) { GetValue().~T(); mHasValue = false; } } void SetValue(const T &aValue) { ClearValue(); new (&mStorage) T(aValue); mHasValue = true; } void AssignFrom(const Optional &aOther) { ClearValue(); if (aOther.mHasValue) { SetValue(aOther.GetValue()); } } alignas(T) unsigned char mStorage[sizeof(T)]; bool mHasValue = false; }; #endif // OTBR_COMMON_CODE_UTILS_HPP_