libcamera: flags: Add type-safe enum-based flags
Add a Flags template class that provide type-safe bitwise operators on enum values. This allows using enum types for bit fields, without giving away type-safety as usually done when storing combined flags in integer variables. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Reviewed-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org>
This commit is contained in:
parent
a792512496
commit
87c18aab8c
4 changed files with 389 additions and 0 deletions
195
include/libcamera/base/flags.h
Normal file
195
include/libcamera/base/flags.h
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020, Google Inc.
|
||||||
|
*
|
||||||
|
* flags.h - Type-safe enum-based bitfields
|
||||||
|
*/
|
||||||
|
#ifndef __LIBCAMERA_BASE_FLAGS_H__
|
||||||
|
#define __LIBCAMERA_BASE_FLAGS_H__
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
class Flags
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static_assert(std::is_enum<E>::value,
|
||||||
|
"Flags<> template parameter must be an enum");
|
||||||
|
|
||||||
|
using Type = std::underlying_type_t<E>;
|
||||||
|
|
||||||
|
constexpr Flags()
|
||||||
|
: value_(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags(E flag)
|
||||||
|
: value_(static_cast<Type>(flag))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator&=(E flag)
|
||||||
|
{
|
||||||
|
value_ &= static_cast<Type>(flag);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator&=(Flags other)
|
||||||
|
{
|
||||||
|
value_ &= other.value_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator|=(E flag)
|
||||||
|
{
|
||||||
|
value_ |= static_cast<Type>(flag);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator|=(Flags other)
|
||||||
|
{
|
||||||
|
value_ |= other.value_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator^=(E flag)
|
||||||
|
{
|
||||||
|
value_ ^= static_cast<Type>(flag);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags &operator^=(Flags other)
|
||||||
|
{
|
||||||
|
value_ ^= other.value_;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(E flag)
|
||||||
|
{
|
||||||
|
return value_ == static_cast<Type>(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator==(Flags other)
|
||||||
|
{
|
||||||
|
return value_ == static_cast<Type>(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(E flag)
|
||||||
|
{
|
||||||
|
return value_ != static_cast<Type>(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!=(Flags other)
|
||||||
|
{
|
||||||
|
return value_ != static_cast<Type>(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit operator Type() const
|
||||||
|
{
|
||||||
|
return value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr explicit operator bool() const
|
||||||
|
{
|
||||||
|
return !!value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator&(E flag) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ & static_cast<Type>(flag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator&(Flags other) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ & other.value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator|(E flag) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ | static_cast<Type>(flag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator|(Flags other) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ | other.value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator^(E flag) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ ^ static_cast<Type>(flag)));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator^(Flags other) const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(value_ ^ other.value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr Flags operator~() const
|
||||||
|
{
|
||||||
|
return Flags(static_cast<E>(~value_));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool operator!() const
|
||||||
|
{
|
||||||
|
return !value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef __DOXYGEN__
|
||||||
|
template<typename E>
|
||||||
|
struct flags_enable_operators {
|
||||||
|
static const bool enable = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
typename std::enable_if_t<flags_enable_operators<E>::enable, Flags<E>>
|
||||||
|
operator|(E lhs, E rhs)
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<E>;
|
||||||
|
return Flags<E>(static_cast<E>(static_cast<type>(lhs) | static_cast<type>(rhs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
typename std::enable_if_t<flags_enable_operators<E>::enable, Flags<E>>
|
||||||
|
operator&(E lhs, E rhs)
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<E>;
|
||||||
|
return Flags<E>(static_cast<E>(static_cast<type>(lhs) & static_cast<type>(rhs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
typename std::enable_if_t<flags_enable_operators<E>::enable, Flags<E>>
|
||||||
|
operator^(E lhs, E rhs)
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<E>;
|
||||||
|
return Flags<E>(static_cast<E>(static_cast<type>(lhs) ^ static_cast<type>(rhs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
typename std::enable_if_t<flags_enable_operators<E>::enable, Flags<E>>
|
||||||
|
operator~(E rhs)
|
||||||
|
{
|
||||||
|
using type = std::underlying_type_t<E>;
|
||||||
|
return Flags<E>(static_cast<E>(~static_cast<type>(rhs)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LIBCAMERA_FLAGS_ENABLE_OPERATORS(_enum) \
|
||||||
|
template<> \
|
||||||
|
struct flags_enable_operators<_enum> { \
|
||||||
|
static const bool enable = true; \
|
||||||
|
};
|
||||||
|
|
||||||
|
#else /* __DOXYGEN__ */
|
||||||
|
|
||||||
|
#define LIBCAMERA_FLAGS_ENABLE_OPERATORS(_enum)
|
||||||
|
|
||||||
|
#endif /* __DOXYGEN__ */
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
||||||
|
|
||||||
|
#endif /* __LIBCAMERA_BASE_FLAGS_H__ */
|
|
@ -9,6 +9,7 @@ libcamera_base_headers = files([
|
||||||
'event_dispatcher_poll.h',
|
'event_dispatcher_poll.h',
|
||||||
'event_notifier.h',
|
'event_notifier.h',
|
||||||
'file.h',
|
'file.h',
|
||||||
|
'flags.h',
|
||||||
'log.h',
|
'log.h',
|
||||||
'message.h',
|
'message.h',
|
||||||
'object.h',
|
'object.h',
|
||||||
|
|
192
src/libcamera/base/flags.cpp
Normal file
192
src/libcamera/base/flags.cpp
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020, Google Inc.
|
||||||
|
*
|
||||||
|
* flags.cpp - Type-safe enum-based bitfields
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libcamera/base/flags.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \file base/flags.h
|
||||||
|
* \brief Enum-based bit fields
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace libcamera {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \class Flags
|
||||||
|
* \brief Type-safe container for enum-based bitfields
|
||||||
|
*
|
||||||
|
* The Flags template class provides type-safe bitwise operators on enum values.
|
||||||
|
* It allows using enum types for bitfields, while preventing unsafe casts from
|
||||||
|
* integer types and mixing of flags from different enum types.
|
||||||
|
*
|
||||||
|
* To use the Flags class, declare an enum containing the desired bit flags, and
|
||||||
|
* use the Flags<enum> class to store bitfields based on the enum. If bitwise
|
||||||
|
* operators on the underlying enum are also desired, they can be enabled with
|
||||||
|
* the LIBCAMERA_FLAGS_ENABLE_OPERATORS(enum) macro.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \typedef Flags::Type
|
||||||
|
* \brief The underlying data type of the enum
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags::Flags()
|
||||||
|
* \brief Construct a Flags instance with a zero value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags::Flags(E flag)
|
||||||
|
* \brief Construct a Flags instance storing the \a flag
|
||||||
|
* \param[in] flag The initial value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator&=(E flag)
|
||||||
|
* \brief Store the bitwise AND of this Flags and the \a flag in this Flags
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator&=(Flags other)
|
||||||
|
* \brief Store the bitwise AND of this Flags and the \a other Flags in this Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator|=(E flag)
|
||||||
|
* \brief Store the bitwise OR of this Flags and the \a flag in this Flags
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator|=(Flags other)
|
||||||
|
* \brief Store the bitwise OR of this Flags and the \a other Flags in this Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator^=(E flag)
|
||||||
|
* \brief Store the bitwise XOR of this Flags and the \a flag in this Flags
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags &Flags::operator^=(Flags other)
|
||||||
|
* \brief Store the bitwise XOR of this Flags and the \a other Flags in this Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A reference to this Flags
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bool Flags::operator==(E flag)
|
||||||
|
* \brief Compare flags for equality
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return True if the Flags and \a flag are equal, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bool Flags::operator==(Flags other)
|
||||||
|
* \brief Compare flags for equality
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return True if the Flags and \a other are equal, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bool Flags::operator!=(E flag)
|
||||||
|
* \brief Compare flags for non-equality
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return True if the Flags and \a flag are not equal, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bool Flags::operator!=(Flags other)
|
||||||
|
* \brief Compare flags for non-equality
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return True if the Flags and \a other are not equal, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags::operator Type() const
|
||||||
|
* \brief Convert the Flags to the underlying integer type
|
||||||
|
* \return The Flags value as an integer
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags::operator bool() const
|
||||||
|
* \brief Convert the Flags to a boolean
|
||||||
|
* \return True if at least one flag is set, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator&(E flag) const
|
||||||
|
* \brief Compute the bitwise AND of this Flags and the \a flag
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A Flags containing the result of the AND operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator&(Flags other) const
|
||||||
|
* \brief Compute the bitwise AND of this Flags and the \a other Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A Flags containing the result of the AND operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator|(E flag) const
|
||||||
|
* \brief Compute the bitwise OR of this Flags and the \a flag
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A Flags containing the result of the OR operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator|(Flags other) const
|
||||||
|
* \brief Compute the bitwise OR of this Flags and the \a other Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A Flags containing the result of the OR operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator^(E flag) const
|
||||||
|
* \brief Compute the bitwise XOR of this Flags and the \a flag
|
||||||
|
* \param[in] flag The second operand
|
||||||
|
* \return A Flags containing the result of the XOR operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator^(Flags other) const
|
||||||
|
* \brief Compute the bitwise XOR of this Flags and the \a other Flags
|
||||||
|
* \param[in] other The second operand
|
||||||
|
* \return A Flags containing the result of the XOR operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn Flags Flags::operator~() const
|
||||||
|
* \brief Compute the bitwise NOT of this Flags
|
||||||
|
* \return A Flags containing the result of the NOT operation
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn bool Flags::operator!() const
|
||||||
|
* \brief Check if flags are set
|
||||||
|
* \return True if no flags is set, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \def LIBCAMERA_FLAGS_ENABLE_OPERATORS(enum)
|
||||||
|
* \brief Enable bitwise operations on the \a enum enumeration
|
||||||
|
*
|
||||||
|
* This macro enables the bitwise AND, OR, XOR and NOT operators on the given
|
||||||
|
* \a enum. This allows the enum values to be safely used in bitwise operations
|
||||||
|
* with the Flags<> class.
|
||||||
|
*/
|
||||||
|
|
||||||
|
} /* namespace libcamera */
|
|
@ -7,6 +7,7 @@ libcamera_base_sources = files([
|
||||||
'event_dispatcher_poll.cpp',
|
'event_dispatcher_poll.cpp',
|
||||||
'event_notifier.cpp',
|
'event_notifier.cpp',
|
||||||
'file.cpp',
|
'file.cpp',
|
||||||
|
'flags.cpp',
|
||||||
'log.cpp',
|
'log.cpp',
|
||||||
'message.cpp',
|
'message.cpp',
|
||||||
'object.cpp',
|
'object.cpp',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue