blob: f6d2620faf240bca651f16b318147b7c49d5cd57 [file]
/*
* 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 <assert.h>
#include <memory>
#include <stdlib.h>
#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<aAlignType>( \
((reinterpret_cast<unsigned long>(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 <typename T, typename... Args> std::unique_ptr<T> MakeUnique(Args &&...args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(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 <typename T> 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<T *>(reinterpret_cast<const T *>(&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_