From 64ded3fba41e6ad038a67a06cf78faf4ffaa753b Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Wed, 16 Dec 2020 21:13:13 -0500 Subject: [PATCH] Add C++ interface for the libbabeltrace2 `bt_integer_range_set_*` API This patch adds C++ wrappers for Babeltrace 2 integer range set objects. The four new available types are: * `bt2::UnsignedIntegerRange` * `bt2::ConstUnsignedIntegerRange` * `bt2::SignedIntegerRange` * `bt2::ConstSignedIntegerRange` Implicitly convert from a mutable integer range set to a constant integer range set with converting constructors and assignment operators. All classes have the `Shared` type alias which is what the shared() method returns. You can also implicitly convert from a shared mutable integer range set to a shared constant integer range set. The corresponding integer range type of any integer range set type `T` is `T::Range`. Borrow an integer range by index from the set with operator[](): auto myRange = myRangeSet[3]; Get the number of integer ranges in the set with the size() method. Compare compatible integer range sets with operator==() and operator!=(). Create a shared integer range set with the static create() methods, for example: auto myRangeSet = bt2::SignedIntegerRangeSet::create(); Those methods can throw a `LibMemoryError` instance. Signed-off-by: Philippe Proulx Change-Id: I14f00e9a020ec8f429bf632132e030ff4cc881a6 Reviewed-on: https://review.lttng.org/c/babeltrace/+/4599 --- src/cpp-common/bt2/integer-range-set.hpp | 231 +++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 src/cpp-common/bt2/integer-range-set.hpp diff --git a/src/cpp-common/bt2/integer-range-set.hpp b/src/cpp-common/bt2/integer-range-set.hpp new file mode 100644 index 00000000..52fc540d --- /dev/null +++ b/src/cpp-common/bt2/integer-range-set.hpp @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2020 Philippe Proulx + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BABELTRACE_CPP_COMMON_BT2_INTEGER_RANGE_SET_HPP +#define BABELTRACE_CPP_COMMON_BT2_INTEGER_RANGE_SET_HPP + +#include +#include +#include + +#include "internal/borrowed-obj.hpp" +#include "internal/utils.hpp" +#include "integer-range.hpp" +#include "lib-error.hpp" + +namespace bt2 { + +namespace internal { + +template +struct IntegerRangeSetRefFuncs; + +template <> +struct IntegerRangeSetRefFuncs final +{ + static void get(const bt_integer_range_set_unsigned * const libObjPtr) + { + bt_integer_range_set_unsigned_get_ref(libObjPtr); + } + + static void put(const bt_integer_range_set_unsigned * const libObjPtr) + { + bt_integer_range_set_unsigned_get_ref(libObjPtr); + } +}; + +template <> +struct IntegerRangeSetRefFuncs final +{ + static void get(const bt_integer_range_set_signed * const libObjPtr) + { + bt_integer_range_set_signed_get_ref(libObjPtr); + } + + static void put(const bt_integer_range_set_signed * const libObjPtr) + { + bt_integer_range_set_signed_get_ref(libObjPtr); + } +}; + +template +struct CommonIntegerRangeSetSpec; + +// Functions specific to unsigned integer range sets +template <> +struct CommonIntegerRangeSetSpec final +{ + static std::uint64_t size(const bt_integer_range_set_unsigned * const libRangePtr) noexcept + { + return bt_integer_range_set_get_range_count( + bt_integer_range_set_unsigned_as_range_set_const(libRangePtr)); + } + + static const bt_integer_range_unsigned * + rangeByIndex(const bt_integer_range_set_unsigned * const libRangePtr, + const std::uint64_t index) noexcept + { + return bt_integer_range_set_unsigned_borrow_range_by_index_const(libRangePtr, index); + } + + static bool isEqual(const bt_integer_range_set_unsigned * const libRangePtrA, + const bt_integer_range_set_unsigned * const libRangePtrB) noexcept + { + return static_cast( + bt_integer_range_set_unsigned_is_equal(libRangePtrA, libRangePtrB)); + } + + static bt_integer_range_set_add_range_status + addRange(bt_integer_range_set_unsigned * const libRangePtr, const std::uint64_t lower, + const std::uint64_t upper) noexcept + { + return bt_integer_range_set_unsigned_add_range(libRangePtr, lower, upper); + } + + static bt_integer_range_set_unsigned *create() noexcept + { + return bt_integer_range_set_unsigned_create(); + } +}; + +// Functions specific to signed integer range sets +template <> +struct CommonIntegerRangeSetSpec final +{ + static std::uint64_t size(const bt_integer_range_set_signed * const libRangePtr) noexcept + { + return bt_integer_range_set_get_range_count( + bt_integer_range_set_signed_as_range_set_const(libRangePtr)); + } + + static const bt_integer_range_signed * + rangeByIndex(const bt_integer_range_set_signed * const libRangePtr, + const std::uint64_t index) noexcept + { + return bt_integer_range_set_signed_borrow_range_by_index_const(libRangePtr, index); + } + + static bool isEqual(const bt_integer_range_set_signed * const libRangePtrA, + const bt_integer_range_set_signed * const libRangePtrB) noexcept + { + return static_cast(bt_integer_range_set_signed_is_equal(libRangePtrA, libRangePtrB)); + } + + static bt_integer_range_set_add_range_status + addRange(bt_integer_range_set_signed * const libRangePtr, const std::int64_t lower, + const std::int64_t upper) noexcept + { + return bt_integer_range_set_signed_add_range(libRangePtr, lower, upper); + } + + static bt_integer_range_set_signed *create() noexcept + { + return bt_integer_range_set_signed_create(); + } +}; + +} // namespace internal + +template +class CommonIntegerRangeSet final : public internal::BorrowedObj +{ + // Allow operator==() to call `other._libObjPtr()` + friend class CommonIntegerRangeSet; + friend class CommonIntegerRangeSet; + friend class CommonIntegerRangeSet; + friend class CommonIntegerRangeSet; + +private: + using typename internal::BorrowedObj::_ThisBorrowedObj; + using typename internal::BorrowedObj::_LibObjPtr; + using _ConstLibObjT = typename std::add_const::type; + using _RefFuncs = internal::IntegerRangeSetRefFuncs<_ConstLibObjT>; + using _Spec = internal::CommonIntegerRangeSetSpec<_ConstLibObjT>; + using _ThisCommonIntegerRangeSet = CommonIntegerRangeSet; + +public: + using Shared = internal::SharedObj<_ThisCommonIntegerRangeSet, LibObjT, _RefFuncs>; + + using Range = typename std::conditional< + std::is_same<_ConstLibObjT, const bt_integer_range_set_unsigned>::value, + ConstUnsignedIntegerRange, ConstSignedIntegerRange>::type; + + using Value = typename Range::Value; + + explicit CommonIntegerRangeSet(const _LibObjPtr libObjPtr) noexcept : + _ThisBorrowedObj {libObjPtr} + { + } + + static Shared create() + { + const auto libObjPtr = _Spec::create(); + + internal::validateCreatedObjPtr(libObjPtr); + return Shared {_ThisCommonIntegerRangeSet {libObjPtr}}; + } + + template + CommonIntegerRangeSet(const CommonIntegerRangeSet& rangeSet) noexcept : + _ThisBorrowedObj {rangeSet} + { + } + + template + _ThisCommonIntegerRangeSet& + operator=(const CommonIntegerRangeSet& rangeSet) noexcept + { + _ThisBorrowedObj::operator=(rangeSet); + return *this; + } + + template + bool operator==(const CommonIntegerRangeSet& other) const noexcept + { + return _Spec::isEqual(this->_libObjPtr(), other._libObjPtr()); + } + + template + bool operator!=(const CommonIntegerRangeSet& other) const noexcept + { + return !(*this == other); + } + + void addRange(const Value lower, const Value upper) + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + const auto status = _Spec::addRange(this->_libObjPtr(), lower, upper); + + if (status == BT_INTEGER_RANGE_SET_ADD_RANGE_STATUS_MEMORY_ERROR) { + throw LibMemoryError {}; + } + } + + std::uint64_t size() const noexcept + { + return _Spec::size(this->_libObjPtr()); + } + + Range operator[](const std::uint64_t index) const noexcept + { + return Range {_Spec::rangeByIndex(this->_libObjPtr(), index)}; + } + + Shared shared() const noexcept + { + return Shared {*this}; + } +}; + +using UnsignedIntegerRangeSet = CommonIntegerRangeSet; +using ConstUnsignedIntegerRangeSet = CommonIntegerRangeSet; +using SignedIntegerRangeSet = CommonIntegerRangeSet; +using ConstSignedIntegerRangeSet = CommonIntegerRangeSet; + +} // namespace bt2 + +#endif // BABELTRACE_CPP_COMMON_BT2_INTEGER_RANGE_SET_HPP -- 2.34.1