From a1e3187822e3320ce83e37a0e30bc68e176112d4 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Thu, 17 Dec 2020 23:27:10 -0500 Subject: [PATCH] Add C++ interface for the libbabeltrace2 `bt_field` API This patch adds C++ wrappers for Babeltrace 2 field objects. The class hierarchy is: Field BoolField BitArrayField UnsignedIntegerField UnsignedEnumerationField SignedIntegerField SignedEnumerationField SinglePrecisionRealField DoublePrecisionRealField StringField StructureField ArrayField DynamicArrayField OptionField VariantField ConstField ConstBoolField ConstBitArrayField ConstUnsignedIntegerField ConstUnsignedEnumerationField ConstSignedIntegerField ConstSignedEnumerationField ConstSinglePrecisionRealField ConstDoublePrecisionRealField ConstStringField ConstStructureField ConstArrayField ConstDynamicArrayField ConstOptionField ConstVariantField EnumerationFieldClassMappingLabels Implicitly convert from a mutable field to a constant field with converting constructors and assignment operators. Those new template classes follow the approach of other wrappers in `src/cpp-common/bt2`. Each specialized field type has a cls() method which returns a corresponding specialized field class type instance. Signed-off-by: Philippe Proulx Change-Id: Ic8886033befc38366f3ee676e0c779640420a72f Reviewed-on: https://review.lttng.org/c/babeltrace/+/4629 --- src/cpp-common/bt2/field.hpp | 1371 ++++++++++++++++++++++++++++++++++ 1 file changed, 1371 insertions(+) create mode 100644 src/cpp-common/bt2/field.hpp diff --git a/src/cpp-common/bt2/field.hpp b/src/cpp-common/bt2/field.hpp new file mode 100644 index 00000000..c62368e5 --- /dev/null +++ b/src/cpp-common/bt2/field.hpp @@ -0,0 +1,1371 @@ +/* + * Copyright (c) 2020 Philippe Proulx + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BABELTRACE_CPP_COMMON_BT2_FIELD_HPP +#define BABELTRACE_CPP_COMMON_BT2_FIELD_HPP + +#include +#include +#include + +#include "common/assert.h" +#include "internal/borrowed-obj.hpp" +#include "cpp-common/optional.hpp" +#include "cpp-common/string_view.hpp" +#include "field-class.hpp" + +namespace bt2 { + +template +class CommonBoolField; + +template +class CommonBitArrayField; + +template +class CommonUnsignedIntegerField; + +template +class CommonSignedIntegerField; + +template +class CommonUnsignedEnumerationField; + +template +class CommonSignedEnumerationField; + +template +class CommonSinglePrecisionRealField; + +template +class CommonDoublePrecisionRealField; + +template +class CommonStringField; + +template +class CommonStructureField; + +template +class CommonArrayField; + +template +class CommonDynamicArrayField; + +template +class CommonOptionField; + +template +class CommonVariantField; + +namespace internal { + +template +struct CommonFieldSpec; + +// Functions specific to mutable fields +template <> +struct CommonFieldSpec final +{ + static bt_field_class *cls(bt_field * const libObjPtr) noexcept + { + return bt_field_borrow_class(libObjPtr); + } +}; + +// Functions specific to constant fields +template <> +struct CommonFieldSpec final +{ + static const bt_field_class *cls(const bt_field * const libObjPtr) noexcept + { + return bt_field_borrow_class_const(libObjPtr); + } +}; + +} // namespace internal + +template +class CommonField : public internal::BorrowedObj +{ +private: + using typename internal::BorrowedObj::_ThisBorrowedObj; + +protected: + using typename internal::BorrowedObj::_LibObjPtr; + using _ThisCommonField = CommonField; + +public: + using Class = + typename std::conditional::value, ConstFieldClass, FieldClass>::type; + + explicit CommonField(const _LibObjPtr libObjPtr) noexcept : _ThisBorrowedObj {libObjPtr} + { + } + + template + CommonField(const CommonField& val) noexcept : _ThisBorrowedObj {val} + { + } + + template + _ThisCommonField& operator=(const CommonField& val) noexcept + { + _ThisBorrowedObj::operator=(val); + return *this; + } + + FieldClassType classType() const noexcept + { + return static_cast(bt_field_get_class_type(this->_libObjPtr())); + } + + ConstFieldClass cls() const noexcept + { + return ConstFieldClass {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + bool isBool() const noexcept + { + return this->cls().isBool(); + } + + bool isBitArray() const noexcept + { + return this->cls().isBitArray(); + } + + bool isUnsignedInteger() const noexcept + { + return this->cls().isUnsignedInteger(); + } + + bool isSignedInteger() const noexcept + { + return this->cls().isSignedInteger(); + } + + bool isUnsignedEnumeration() const noexcept + { + return this->cls().isUnsignedEnumeration(); + } + + bool isSignedEnumeration() const noexcept + { + return this->cls().isSignedEnumeration(); + } + + bool isSinglePrecisionReal() const noexcept + { + return this->cls().isSinglePrecisionReal(); + } + + bool isDoublePrecisionReal() const noexcept + { + return this->cls().isDoublePrecisionReal(); + } + + bool isString() const noexcept + { + return this->cls().isString(); + } + + bool isStructure() const noexcept + { + return this->cls().isStructure(); + } + + bool isArray() const noexcept + { + return this->cls().isArray(); + } + + bool isDynamicArray() const noexcept + { + return this->cls().isDynamicArray(); + } + + bool isOption() const noexcept + { + return this->cls().isOption(); + } + + bool isVariant() const noexcept + { + return this->cls().isVariant(); + } + + CommonBoolField asBool() const noexcept; + CommonBitArrayField asBitArray() const noexcept; + CommonUnsignedIntegerField asUnsignedInteger() const noexcept; + CommonSignedIntegerField asSignedInteger() const noexcept; + CommonUnsignedEnumerationField asUnsignedEnumeration() const noexcept; + CommonSignedEnumerationField asSignedEnumeration() const noexcept; + CommonSinglePrecisionRealField asSinglePrecisionReal() const noexcept; + CommonDoublePrecisionRealField asDoublePrecisionReal() const noexcept; + CommonStringField asString() const noexcept; + CommonStructureField asStructure() const noexcept; + CommonArrayField asArray() const noexcept; + CommonDynamicArrayField asDynamicArray() const noexcept; + CommonOptionField asOption() const noexcept; + CommonVariantField asVariant() const noexcept; +}; + +using Field = CommonField; +using ConstField = CommonField; + +template +class CommonBoolField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + +public: + using Value = bool; + + explicit CommonBoolField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isBool()); + } + + template + CommonBoolField(const CommonBoolField& val) noexcept : _ThisCommonField {val} + { + } + + template + CommonBoolField& operator=(const CommonBoolField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + CommonBoolField& operator=(const Value val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_bool_set_value(this->_libObjPtr(), static_cast(val)); + return *this; + } + + Value value() const noexcept + { + return static_cast(bt_field_bool_get_value(this->_libObjPtr())); + } + + operator Value() const noexcept + { + return this->value(); + } +}; + +using BoolField = CommonBoolField; +using ConstBoolField = CommonBoolField; + +template +class CommonBitArrayField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + +public: + using Class = typename std::conditional::value, ConstBitArrayFieldClass, + BitArrayFieldClass>::type; + + explicit CommonBitArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isBitArray()); + } + + template + CommonBitArrayField(const CommonBitArrayField& val) noexcept : + _ThisCommonField {val} + { + } + + template + CommonBitArrayField& operator=(const CommonBitArrayField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstBitArrayFieldClass cls() const noexcept + { + return ConstBitArrayFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + CommonBitArrayField& operator=(const std::uint64_t bits) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_bit_array_set_value_as_integer(this->_libObjPtr(), bits); + return *this; + } + + std::uint64_t valueAsInteger() const noexcept + { + return bt_field_bit_array_get_value_as_integer(this->_libObjPtr()); + } + + bool bitValue(const std::uint64_t index) const noexcept + { + BT_ASSERT_DBG(index < this->cls().length()); + return static_cast(this->valueAsInteger() & (1ULL << index)); + } +}; + +using BitArrayField = CommonBitArrayField; +using ConstBitArrayField = CommonBitArrayField; + +template +class CommonUnsignedIntegerField final : public CommonField +{ +private: + using typename CommonField::_ThisCommonField; + +protected: + using typename CommonField::_LibObjPtr; + using _ThisCommonUnsignedIntegerField = CommonUnsignedIntegerField; + +public: + using Value = std::uint64_t; + + using Class = typename std::conditional::value, ConstIntegerFieldClass, + IntegerFieldClass>::type; + + explicit CommonUnsignedIntegerField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isUnsignedInteger()); + } + + template + CommonUnsignedIntegerField(const CommonUnsignedIntegerField& val) noexcept : + _ThisCommonField {val} + { + } + + template + _ThisCommonUnsignedIntegerField& + operator=(const CommonUnsignedIntegerField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstIntegerFieldClass cls() const noexcept + { + return ConstIntegerFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + CommonUnsignedIntegerField& operator=(const Value val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_integer_unsigned_set_value(this->_libObjPtr(), val); + return *this; + } + + Value value() const noexcept + { + return bt_field_integer_unsigned_get_value(this->_libObjPtr()); + } + + operator Value() const noexcept + { + return this->value(); + } +}; + +using UnsignedIntegerField = CommonUnsignedIntegerField; +using ConstUnsignedIntegerField = CommonUnsignedIntegerField; + +template +class CommonSignedIntegerField final : public CommonField +{ +private: + using typename CommonField::_ThisCommonField; + +protected: + using typename CommonField::_LibObjPtr; + using _ThisCommonSignedIntegerField = CommonSignedIntegerField; + +public: + using Value = std::uint64_t; + + using Class = typename std::conditional::value, ConstIntegerFieldClass, + IntegerFieldClass>::type; + + explicit CommonSignedIntegerField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isSignedInteger()); + } + + template + CommonSignedIntegerField(const CommonSignedIntegerField& val) noexcept : + _ThisCommonField {val} + { + } + + template + _ThisCommonSignedIntegerField& + operator=(const CommonSignedIntegerField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstIntegerFieldClass cls() const noexcept + { + return ConstIntegerFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + CommonSignedIntegerField& operator=(const Value val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_integer_signed_set_value(this->_libObjPtr(), val); + return *this; + } + + Value value() const noexcept + { + return bt_field_integer_signed_get_value(this->_libObjPtr()); + } + + operator Value() const noexcept + { + return this->value(); + } +}; + +using SignedIntegerField = CommonSignedIntegerField; +using ConstSignedIntegerField = CommonSignedIntegerField; + +class EnumerationFieldClassMappingLabels +{ +public: + explicit EnumerationFieldClassMappingLabels( + const bt_field_class_enumeration_mapping_label_array labels, const std::uint64_t size) : + _mLabels {labels}, + _mSize {size} + { + } + + EnumerationFieldClassMappingLabels(const EnumerationFieldClassMappingLabels&) noexcept = + default; + + EnumerationFieldClassMappingLabels& + operator=(const EnumerationFieldClassMappingLabels&) noexcept = default; + + std::uint64_t size() const noexcept + { + return _mSize; + } + + bpstd::string_view operator[](const std::uint64_t index) const noexcept + { + return _mLabels[index]; + } + +private: + bt_field_class_enumeration_mapping_label_array _mLabels; + std::uint64_t _mSize; +}; + +template +class CommonUnsignedEnumerationField final : public CommonUnsignedIntegerField +{ +private: + using typename CommonUnsignedIntegerField::_ThisCommonUnsignedIntegerField; + using typename CommonField::_LibObjPtr; + +public: + using Class = + typename std::conditional::value, ConstUnsignedEnumerationFieldClass, + UnsignedEnumerationFieldClass>::type; + + explicit CommonUnsignedEnumerationField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonUnsignedIntegerField {libObjPtr} + { + BT_ASSERT_DBG(this->isUnsignedEnumeration()); + } + + template + CommonUnsignedEnumerationField(const CommonUnsignedEnumerationField& val) noexcept + : + _ThisCommonUnsignedIntegerField {val} + { + } + + template + CommonUnsignedEnumerationField& + operator=(const CommonUnsignedEnumerationField& val) noexcept + { + _ThisCommonUnsignedIntegerField::operator=(val); + return *this; + } + + ConstUnsignedEnumerationFieldClass cls() const noexcept + { + return ConstUnsignedEnumerationFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + EnumerationFieldClassMappingLabels labels() const + { + bt_field_class_enumeration_mapping_label_array labelArray; + std::uint64_t count; + const auto status = bt_field_enumeration_unsigned_get_mapping_labels(this->_libObjPtr(), + &labelArray, &count); + + if (status == BT_FIELD_ENUMERATION_GET_MAPPING_LABELS_STATUS_MEMORY_ERROR) { + throw LibMemoryError {}; + } + + return EnumerationFieldClassMappingLabels {labelArray, count}; + } +}; + +using UnsignedEnumerationField = CommonUnsignedEnumerationField; +using ConstUnsignedEnumerationField = CommonUnsignedEnumerationField; + +template +class CommonSignedEnumerationField final : public CommonSignedIntegerField +{ +private: + using typename CommonSignedIntegerField::_ThisCommonSignedIntegerField; + using typename CommonField::_LibObjPtr; + +public: + using Class = + typename std::conditional::value, ConstSignedEnumerationFieldClass, + SignedEnumerationFieldClass>::type; + + explicit CommonSignedEnumerationField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonSignedIntegerField {libObjPtr} + { + BT_ASSERT_DBG(this->isSignedEnumeration()); + } + + template + CommonSignedEnumerationField(const CommonSignedEnumerationField& val) noexcept : + _ThisCommonSignedIntegerField {val} + { + } + + template + CommonSignedEnumerationField& + operator=(const CommonSignedEnumerationField& val) noexcept + { + _ThisCommonSignedIntegerField::operator=(val); + return *this; + } + + ConstSignedEnumerationFieldClass cls() const noexcept + { + return ConstSignedEnumerationFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + EnumerationFieldClassMappingLabels labels() const + { + bt_field_class_enumeration_mapping_label_array labelArray; + std::uint64_t count; + const auto status = + bt_field_enumeration_signed_get_mapping_labels(this->_libObjPtr(), &labelArray, &count); + + if (status == BT_FIELD_ENUMERATION_GET_MAPPING_LABELS_STATUS_MEMORY_ERROR) { + throw LibMemoryError {}; + } + + return EnumerationFieldClassMappingLabels {labelArray, count}; + } +}; + +using SignedEnumerationField = CommonSignedEnumerationField; +using ConstSignedEnumerationField = CommonSignedEnumerationField; + +template +class CommonSinglePrecisionRealField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + +public: + using Value = float; + + explicit CommonSinglePrecisionRealField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isSinglePrecisionReal()); + } + + template + CommonSinglePrecisionRealField(const CommonSinglePrecisionRealField& val) noexcept + : + _ThisCommonField {val} + { + } + + template + CommonSinglePrecisionRealField& + operator=(const CommonSinglePrecisionRealField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + CommonSinglePrecisionRealField& operator=(const Value val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_real_single_precision_set_value(this->_libObjPtr(), val); + return *this; + } + + Value value() const noexcept + { + return bt_field_real_single_precision_get_value(this->_libObjPtr()); + } + + operator Value() const noexcept + { + return this->value(); + } +}; + +using SinglePrecisionRealField = CommonSinglePrecisionRealField; +using ConstSinglePrecisionRealField = CommonSinglePrecisionRealField; + +template +class CommonDoublePrecisionRealField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + +public: + using Value = double; + + explicit CommonDoublePrecisionRealField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isDoublePrecisionReal()); + } + + template + CommonDoublePrecisionRealField(const CommonDoublePrecisionRealField& val) noexcept + : + _ThisCommonField {val} + { + } + + template + CommonDoublePrecisionRealField& + operator=(const CommonDoublePrecisionRealField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + CommonDoublePrecisionRealField& operator=(const Value val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_real_single_precision_set_value(this->_libObjPtr(), val); + return *this; + } + + Value value() const noexcept + { + return bt_field_real_single_precision_get_value(this->_libObjPtr()); + } + + operator Value() const noexcept + { + return this->value(); + } +}; + +using DoublePrecisionRealField = CommonDoublePrecisionRealField; +using ConstDoublePrecisionRealField = CommonDoublePrecisionRealField; + +template +class CommonStringField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + +public: + explicit CommonStringField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isString()); + } + + template + CommonStringField(const CommonStringField& val) noexcept : _ThisCommonField {val} + { + } + + template + CommonStringField& operator=(const CommonStringField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + CommonStringField& operator=(const char * const val) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + const auto status = bt_field_string_set_value(this->_libObjPtr(), val); + + if (status == BT_FIELD_STRING_SET_VALUE_STATUS_MEMORY_ERROR) { + throw LibMemoryError {}; + } + + return *this; + } + + CommonStringField& operator=(const std::string& val) noexcept + { + return *this = val.data(); + } + + void clear() noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_string_clear(this->_libObjPtr()); + } + + bpstd::string_view value() const noexcept + { + return bt_field_string_get_value(this->_libObjPtr()); + } +}; + +using StringField = CommonStringField; +using ConstStringField = CommonStringField; + +namespace internal { + +template +struct CommonStructureFieldSpec; + +// Functions specific to mutable structure fields +template <> +struct CommonStructureFieldSpec final +{ + static bt_field *memberFieldByIndex(bt_field * const libObjPtr, + const std::uint64_t index) noexcept + { + return bt_field_structure_borrow_member_field_by_index(libObjPtr, index); + } + + static bt_field *memberFieldByName(bt_field * const libObjPtr, const char * const name) noexcept + { + return bt_field_structure_borrow_member_field_by_name(libObjPtr, name); + } +}; + +// Functions specific to constant structure fields +template <> +struct CommonStructureFieldSpec final +{ + static const bt_field *memberFieldByIndex(const bt_field * const libObjPtr, + const std::uint64_t index) noexcept + { + return bt_field_structure_borrow_member_field_by_index_const(libObjPtr, index); + } + + static const bt_field *memberFieldByName(const bt_field * const libObjPtr, + const char * const name) noexcept + { + return bt_field_structure_borrow_member_field_by_name_const(libObjPtr, name); + } +}; + +} // namespace internal + +template +class CommonStructureField final : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + using _Spec = internal::CommonStructureFieldSpec; + +public: + using Class = typename std::conditional::value, ConstStructureFieldClass, + StructureFieldClass>::type; + + explicit CommonStructureField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isStructure()); + } + + template + CommonStructureField(const CommonStructureField& val) noexcept : + _ThisCommonField {val} + { + } + + template + CommonStructureField& operator=(const CommonStructureField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstStructureFieldClass cls() const noexcept + { + return ConstStructureFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + std::uint64_t size() const noexcept + { + return this->cls().size(); + } + + ConstField operator[](const std::uint64_t index) const noexcept + { + return ConstField {internal::CommonStructureFieldSpec::memberFieldByIndex( + this->_libObjPtr(), index)}; + } + + CommonField operator[](const std::uint64_t index) noexcept + { + return CommonField {_Spec::memberFieldByIndex(this->_libObjPtr(), index)}; + } + + nonstd::optional operator[](const char * const name) const noexcept + { + const auto libObjPtr = + internal::CommonStructureFieldSpec::memberFieldByName( + this->_libObjPtr(), name); + + if (libObjPtr) { + return ConstField {libObjPtr}; + } + + return nonstd::nullopt; + } + + nonstd::optional operator[](const std::string& name) const noexcept + { + return (*this)[name.data()]; + } + + nonstd::optional> operator[](const char * const name) noexcept + { + const auto libObjPtr = _Spec::memberFieldByName(this->_libObjPtr(), name); + + if (libObjPtr) { + return CommonField {libObjPtr}; + } + + return nonstd::nullopt; + } + + nonstd::optional> operator[](const std::string& name) noexcept + { + return (*this)[name.data()]; + } +}; + +using StructureField = CommonStructureField; +using ConstStructureField = CommonStructureField; + +namespace internal { + +template +struct CommonArrayFieldSpec; + +// Functions specific to mutable array fields +template <> +struct CommonArrayFieldSpec final +{ + static bt_field *elementFieldByIndex(bt_field * const libObjPtr, + const std::uint64_t index) noexcept + { + return bt_field_array_borrow_element_field_by_index(libObjPtr, index); + } +}; + +// Functions specific to constant array fields +template <> +struct CommonArrayFieldSpec final +{ + static const bt_field *elementFieldByIndex(const bt_field * const libObjPtr, + const std::uint64_t index) noexcept + { + return bt_field_array_borrow_element_field_by_index_const(libObjPtr, index); + } +}; + +} // namespace internal + +template +class CommonArrayField : public CommonField +{ +private: + using typename CommonField::_ThisCommonField; + using _Spec = internal::CommonArrayFieldSpec; + +protected: + using typename CommonField::_LibObjPtr; + using _ThisCommonArrayField = CommonArrayField; + +public: + using Class = typename std::conditional::value, ConstArrayFieldClass, + ArrayFieldClass>::type; + + explicit CommonArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isArray()); + } + + template + CommonArrayField(const CommonArrayField& val) noexcept : _ThisCommonField {val} + { + } + + template + _ThisCommonArrayField& operator=(const CommonArrayField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstArrayFieldClass cls() const noexcept + { + return ConstArrayFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + std::uint64_t length() const noexcept + { + return bt_field_array_get_length(this->_libObjPtr()); + } + + ConstField operator[](const std::uint64_t index) const noexcept + { + return ConstField {internal::CommonArrayFieldSpec::elementFieldByIndex( + this->_libObjPtr(), index)}; + } + + CommonField operator[](const std::uint64_t index) noexcept + { + return CommonField {_Spec::elementFieldByIndex(this->_libObjPtr(), index)}; + } +}; + +using ArrayField = CommonArrayField; +using ConstArrayField = CommonArrayField; + +template +class CommonDynamicArrayField : public CommonArrayField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonArrayField::_ThisCommonArrayField; + +public: + explicit CommonDynamicArrayField(const _LibObjPtr libObjPtr) noexcept : + _ThisCommonArrayField {libObjPtr} + { + BT_ASSERT_DBG(this->isDynamicArray()); + } + + template + CommonDynamicArrayField(const CommonDynamicArrayField& val) noexcept : + _ThisCommonArrayField {val} + { + } + + template + CommonDynamicArrayField& + operator=(const CommonDynamicArrayField& val) noexcept + { + _ThisCommonArrayField::operator=(val); + return *this; + } + + std::uint64_t length() const noexcept + { + return _ThisCommonArrayField::length(); + } + + void length(const std::uint64_t length) + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + const auto status = bt_field_array_dynamic_set_length(this->_libObjPtr(), length); + + if (status == BT_FIELD_DYNAMIC_ARRAY_SET_LENGTH_STATUS_MEMORY_ERROR) { + throw LibMemoryError {}; + } + } +}; + +using DynamicArrayField = CommonDynamicArrayField; +using ConstDynamicArrayField = CommonDynamicArrayField; + +namespace internal { + +template +struct CommonOptionFieldSpec; + +// Functions specific to mutable option fields +template <> +struct CommonOptionFieldSpec final +{ + static bt_field *field(bt_field * const libObjPtr) noexcept + { + return bt_field_option_borrow_field(libObjPtr); + } +}; + +// Functions specific to constant option fields +template <> +struct CommonOptionFieldSpec final +{ + static const bt_field *field(const bt_field * const libObjPtr) noexcept + { + return bt_field_option_borrow_field_const(libObjPtr); + } +}; + +} // namespace internal + +template +class CommonOptionField : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + using _Spec = internal::CommonOptionFieldSpec; + +public: + using Class = typename std::conditional::value, ConstOptionFieldClass, + OptionFieldClass>::type; + + explicit CommonOptionField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isOption()); + } + + template + CommonOptionField(const CommonOptionField& val) noexcept : _ThisCommonField {val} + { + } + + template + CommonOptionField& operator=(const CommonOptionField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstOptionFieldClass cls() const noexcept + { + return ConstOptionFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + void hasField(const bool hasField) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + bt_field_option_set_has_field(this->_libObjPtr(), static_cast(hasField)); + } + + bool hasField() const noexcept + { + return this->field(); + } + + nonstd::optional field() const noexcept + { + const auto libObjPtr = + internal::CommonOptionFieldSpec::field(this->_libObjPtr()); + + if (libObjPtr) { + return ConstField {libObjPtr}; + } + + return nonstd::nullopt; + } + + nonstd::optional> field() noexcept + { + const auto libObjPtr = _Spec::field(this->_libObjPtr()); + + if (libObjPtr) { + return CommonField {libObjPtr}; + } + + return nonstd::nullopt; + } +}; + +using OptionField = CommonOptionField; +using ConstOptionField = CommonOptionField; + +namespace internal { + +template +struct CommonVariantFieldSpec; + +// Functions specific to mutable variant fields +template <> +struct CommonVariantFieldSpec final +{ + static bt_field *selectedOptionField(bt_field * const libObjPtr) noexcept + { + return bt_field_variant_borrow_selected_option_field(libObjPtr); + } +}; + +// Functions specific to constant variant fields +template <> +struct CommonVariantFieldSpec final +{ + static const bt_field *selectedOptionField(const bt_field * const libObjPtr) noexcept + { + return bt_field_variant_borrow_selected_option_field_const(libObjPtr); + } +}; + +} // namespace internal + +template +class CommonVariantField : public CommonField +{ +private: + using typename CommonField::_LibObjPtr; + using typename CommonField::_ThisCommonField; + using _Spec = internal::CommonVariantFieldSpec; + +public: + using Class = typename std::conditional::value, ConstVariantFieldClass, + VariantFieldClass>::type; + + explicit CommonVariantField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr} + { + BT_ASSERT_DBG(this->isVariant()); + } + + template + CommonVariantField(const CommonVariantField& val) noexcept : + _ThisCommonField {val} + { + } + + template + CommonVariantField& operator=(const CommonVariantField& val) noexcept + { + _ThisCommonField::operator=(val); + return *this; + } + + ConstVariantFieldClass cls() const noexcept + { + return ConstVariantFieldClass { + internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + Class cls() noexcept + { + return Class {internal::CommonFieldSpec::cls(this->_libObjPtr())}; + } + + void selectOption(const std::uint64_t index) noexcept + { + static_assert(!std::is_const::value, "`LibObjT` must NOT be `const`."); + + static_cast(bt_field_variant_select_option_by_index(this->_libObjPtr(), index)); + } + + ConstField selectedOptionField() const noexcept + { + return ConstField {internal::CommonVariantFieldSpec::selectedOptionField( + this->_libObjPtr())}; + } + + CommonField selectedOptionField() noexcept + { + return CommonField {_Spec::selectedOptionField(this->_libObjPtr())}; + } + + std::uint64_t selectedOptionIndex() const noexcept + { + return bt_field_variant_get_selected_option_index(this->_libObjPtr()); + } +}; + +using VariantField = CommonVariantField; +using ConstVariantField = CommonVariantField; + +template +CommonBoolField CommonField::asBool() const noexcept +{ + BT_ASSERT_DBG(this->isBool()); + return CommonBoolField {this->_libObjPtr()}; +} + +template +CommonBitArrayField CommonField::asBitArray() const noexcept +{ + BT_ASSERT_DBG(this->isBitArray()); + return CommonBitArrayField {this->_libObjPtr()}; +} + +template +CommonUnsignedIntegerField CommonField::asUnsignedInteger() const noexcept +{ + BT_ASSERT_DBG(this->isUnsignedInteger()); + return CommonUnsignedIntegerField {this->_libObjPtr()}; +} + +template +CommonSignedIntegerField CommonField::asSignedInteger() const noexcept +{ + BT_ASSERT_DBG(this->isSignedInteger()); + return CommonSignedIntegerField {this->_libObjPtr()}; +} + +template +CommonUnsignedEnumerationField CommonField::asUnsignedEnumeration() const noexcept +{ + BT_ASSERT_DBG(this->isUnsignedEnumeration()); + return CommonUnsignedEnumerationField {this->_libObjPtr()}; +} + +template +CommonSignedEnumerationField CommonField::asSignedEnumeration() const noexcept +{ + BT_ASSERT_DBG(this->isSignedEnumeration()); + return CommonSignedEnumerationField {this->_libObjPtr()}; +} + +template +CommonSinglePrecisionRealField CommonField::asSinglePrecisionReal() const noexcept +{ + BT_ASSERT_DBG(this->isSinglePrecisionReal()); + return CommonSinglePrecisionRealField {this->_libObjPtr()}; +} + +template +CommonDoublePrecisionRealField CommonField::asDoublePrecisionReal() const noexcept +{ + BT_ASSERT_DBG(this->isDoublePrecisionReal()); + return CommonDoublePrecisionRealField {this->_libObjPtr()}; +} + +template +CommonStringField CommonField::asString() const noexcept +{ + BT_ASSERT_DBG(this->isString()); + return CommonStringField {this->_libObjPtr()}; +} + +template +CommonStructureField CommonField::asStructure() const noexcept +{ + BT_ASSERT_DBG(this->isStructure()); + return CommonStructureField {this->_libObjPtr()}; +} + +template +CommonArrayField CommonField::asArray() const noexcept +{ + BT_ASSERT_DBG(this->isArray()); + return CommonArrayField {this->_libObjPtr()}; +} + +template +CommonDynamicArrayField CommonField::asDynamicArray() const noexcept +{ + BT_ASSERT_DBG(this->isDynamicArray()); + return CommonDynamicArrayField {this->_libObjPtr()}; +} + +template +CommonOptionField CommonField::asOption() const noexcept +{ + BT_ASSERT_DBG(this->isOption()); + return CommonOptionField {this->_libObjPtr()}; +} + +template +CommonVariantField CommonField::asVariant() const noexcept +{ + BT_ASSERT_DBG(this->isVariant()); + return CommonVariantField {this->_libObjPtr()}; +} + +} // namespace bt2 + +#endif // BABELTRACE_CPP_COMMON_BT2_FIELD_HPP -- 2.34.1