diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2020-07-12 23:27:07 +0300 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2021-08-03 10:55:20 +0300 |
commit | 87c18aab8c32d4ec07ea166721ae847b72f7418a (patch) | |
tree | 508e952724332655ed7568951e2b705a819329c3 /include | |
parent | a792512496abbf756354cecc7b564e9733ea3fda (diff) |
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>
Diffstat (limited to 'include')
-rw-r--r-- | include/libcamera/base/flags.h | 195 | ||||
-rw-r--r-- | include/libcamera/base/meson.build | 1 |
2 files changed, 196 insertions, 0 deletions
diff --git a/include/libcamera/base/flags.h b/include/libcamera/base/flags.h new file mode 100644 index 00000000..adec549d --- /dev/null +++ b/include/libcamera/base/flags.h @@ -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__ */ diff --git a/include/libcamera/base/meson.build b/include/libcamera/base/meson.build index 7c499b55..9feb4b93 100644 --- a/include/libcamera/base/meson.build +++ b/include/libcamera/base/meson.build @@ -9,6 +9,7 @@ libcamera_base_headers = files([ 'event_dispatcher_poll.h', 'event_notifier.h', 'file.h', + 'flags.h', 'log.h', 'message.h', 'object.h', |