Add C++ interface for the libbabeltrace2 `bt_field` API
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 18 Dec 2020 04:27:10 +0000 (23:27 -0500)
committerPhilippe Proulx <eeppeliteloop@gmail.com>
Fri, 28 Jan 2022 16:22:26 +0000 (11:22 -0500)
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 <eeppeliteloop@gmail.com>
Change-Id: Ic8886033befc38366f3ee676e0c779640420a72f
Reviewed-on: https://review.lttng.org/c/babeltrace/+/4629

src/cpp-common/bt2/field.hpp [new file with mode: 0644]

diff --git a/src/cpp-common/bt2/field.hpp b/src/cpp-common/bt2/field.hpp
new file mode 100644 (file)
index 0000000..c62368e
--- /dev/null
@@ -0,0 +1,1371 @@
+/*
+ * Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
+#define BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
+
+#include <type_traits>
+#include <cstdint>
+#include <babeltrace2/babeltrace.h>
+
+#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 <typename LibObjT>
+class CommonBoolField;
+
+template <typename LibObjT>
+class CommonBitArrayField;
+
+template <typename LibObjT>
+class CommonUnsignedIntegerField;
+
+template <typename LibObjT>
+class CommonSignedIntegerField;
+
+template <typename LibObjT>
+class CommonUnsignedEnumerationField;
+
+template <typename LibObjT>
+class CommonSignedEnumerationField;
+
+template <typename LibObjT>
+class CommonSinglePrecisionRealField;
+
+template <typename LibObjT>
+class CommonDoublePrecisionRealField;
+
+template <typename LibObjT>
+class CommonStringField;
+
+template <typename LibObjT>
+class CommonStructureField;
+
+template <typename LibObjT>
+class CommonArrayField;
+
+template <typename LibObjT>
+class CommonDynamicArrayField;
+
+template <typename LibObjT>
+class CommonOptionField;
+
+template <typename LibObjT>
+class CommonVariantField;
+
+namespace internal {
+
+template <typename LibObjT>
+struct CommonFieldSpec;
+
+// Functions specific to mutable fields
+template <>
+struct CommonFieldSpec<bt_field> 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<const bt_field> final
+{
+    static const bt_field_class *cls(const bt_field * const libObjPtr) noexcept
+    {
+        return bt_field_borrow_class_const(libObjPtr);
+    }
+};
+
+} // namespace internal
+
+template <typename LibObjT>
+class CommonField : public internal::BorrowedObj<LibObjT>
+{
+private:
+    using typename internal::BorrowedObj<LibObjT>::_ThisBorrowedObj;
+
+protected:
+    using typename internal::BorrowedObj<LibObjT>::_LibObjPtr;
+    using _ThisCommonField = CommonField<LibObjT>;
+
+public:
+    using Class =
+        typename std::conditional<std::is_const<LibObjT>::value, ConstFieldClass, FieldClass>::type;
+
+    explicit CommonField(const _LibObjPtr libObjPtr) noexcept : _ThisBorrowedObj {libObjPtr}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonField(const CommonField<OtherLibObjT>& val) noexcept : _ThisBorrowedObj {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    _ThisCommonField& operator=(const CommonField<OtherLibObjT>& val) noexcept
+    {
+        _ThisBorrowedObj::operator=(val);
+        return *this;
+    }
+
+    FieldClassType classType() const noexcept
+    {
+        return static_cast<FieldClassType>(bt_field_get_class_type(this->_libObjPtr()));
+    }
+
+    ConstFieldClass cls() const noexcept
+    {
+        return ConstFieldClass {internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::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<LibObjT> asBool() const noexcept;
+    CommonBitArrayField<LibObjT> asBitArray() const noexcept;
+    CommonUnsignedIntegerField<LibObjT> asUnsignedInteger() const noexcept;
+    CommonSignedIntegerField<LibObjT> asSignedInteger() const noexcept;
+    CommonUnsignedEnumerationField<LibObjT> asUnsignedEnumeration() const noexcept;
+    CommonSignedEnumerationField<LibObjT> asSignedEnumeration() const noexcept;
+    CommonSinglePrecisionRealField<LibObjT> asSinglePrecisionReal() const noexcept;
+    CommonDoublePrecisionRealField<LibObjT> asDoublePrecisionReal() const noexcept;
+    CommonStringField<LibObjT> asString() const noexcept;
+    CommonStructureField<LibObjT> asStructure() const noexcept;
+    CommonArrayField<LibObjT> asArray() const noexcept;
+    CommonDynamicArrayField<LibObjT> asDynamicArray() const noexcept;
+    CommonOptionField<LibObjT> asOption() const noexcept;
+    CommonVariantField<LibObjT> asVariant() const noexcept;
+};
+
+using Field = CommonField<bt_field>;
+using ConstField = CommonField<const bt_field>;
+
+template <typename LibObjT>
+class CommonBoolField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+public:
+    using Value = bool;
+
+    explicit CommonBoolField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isBool());
+    }
+
+    template <typename OtherLibObjT>
+    CommonBoolField(const CommonBoolField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonBoolField<LibObjT>& operator=(const CommonBoolField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    CommonBoolField<LibObjT>& operator=(const Value val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+
+        bt_field_bool_set_value(this->_libObjPtr(), static_cast<bt_bool>(val));
+        return *this;
+    }
+
+    Value value() const noexcept
+    {
+        return static_cast<Value>(bt_field_bool_get_value(this->_libObjPtr()));
+    }
+
+    operator Value() const noexcept
+    {
+        return this->value();
+    }
+};
+
+using BoolField = CommonBoolField<bt_field>;
+using ConstBoolField = CommonBoolField<const bt_field>;
+
+template <typename LibObjT>
+class CommonBitArrayField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+public:
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstBitArrayFieldClass,
+                                            BitArrayFieldClass>::type;
+
+    explicit CommonBitArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isBitArray());
+    }
+
+    template <typename OtherLibObjT>
+    CommonBitArrayField(const CommonBitArrayField<OtherLibObjT>& val) noexcept :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonBitArrayField<LibObjT>& operator=(const CommonBitArrayField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstBitArrayFieldClass cls() const noexcept
+    {
+        return ConstBitArrayFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+    }
+
+    CommonBitArrayField<LibObjT>& operator=(const std::uint64_t bits) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bool>(this->valueAsInteger() & (1ULL << index));
+    }
+};
+
+using BitArrayField = CommonBitArrayField<bt_field>;
+using ConstBitArrayField = CommonBitArrayField<const bt_field>;
+
+template <typename LibObjT>
+class CommonUnsignedIntegerField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+protected:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using _ThisCommonUnsignedIntegerField = CommonUnsignedIntegerField<LibObjT>;
+
+public:
+    using Value = std::uint64_t;
+
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstIntegerFieldClass,
+                                            IntegerFieldClass>::type;
+
+    explicit CommonUnsignedIntegerField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isUnsignedInteger());
+    }
+
+    template <typename OtherLibObjT>
+    CommonUnsignedIntegerField(const CommonUnsignedIntegerField<OtherLibObjT>& val) noexcept :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    _ThisCommonUnsignedIntegerField&
+    operator=(const CommonUnsignedIntegerField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstIntegerFieldClass cls() const noexcept
+    {
+        return ConstIntegerFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+    }
+
+    CommonUnsignedIntegerField<LibObjT>& operator=(const Value val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bt_field>;
+using ConstUnsignedIntegerField = CommonUnsignedIntegerField<const bt_field>;
+
+template <typename LibObjT>
+class CommonSignedIntegerField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+protected:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using _ThisCommonSignedIntegerField = CommonSignedIntegerField<LibObjT>;
+
+public:
+    using Value = std::uint64_t;
+
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstIntegerFieldClass,
+                                            IntegerFieldClass>::type;
+
+    explicit CommonSignedIntegerField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isSignedInteger());
+    }
+
+    template <typename OtherLibObjT>
+    CommonSignedIntegerField(const CommonSignedIntegerField<OtherLibObjT>& val) noexcept :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    _ThisCommonSignedIntegerField&
+    operator=(const CommonSignedIntegerField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstIntegerFieldClass cls() const noexcept
+    {
+        return ConstIntegerFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+    }
+
+    CommonSignedIntegerField<LibObjT>& operator=(const Value val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bt_field>;
+using ConstSignedIntegerField = CommonSignedIntegerField<const bt_field>;
+
+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 <typename LibObjT>
+class CommonUnsignedEnumerationField final : public CommonUnsignedIntegerField<LibObjT>
+{
+private:
+    using typename CommonUnsignedIntegerField<LibObjT>::_ThisCommonUnsignedIntegerField;
+    using typename CommonField<LibObjT>::_LibObjPtr;
+
+public:
+    using Class =
+        typename std::conditional<std::is_const<LibObjT>::value, ConstUnsignedEnumerationFieldClass,
+                                  UnsignedEnumerationFieldClass>::type;
+
+    explicit CommonUnsignedEnumerationField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonUnsignedIntegerField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isUnsignedEnumeration());
+    }
+
+    template <typename OtherLibObjT>
+    CommonUnsignedEnumerationField(const CommonUnsignedEnumerationField<OtherLibObjT>& val) noexcept
+        :
+        _ThisCommonUnsignedIntegerField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonUnsignedEnumerationField<LibObjT>&
+    operator=(const CommonUnsignedEnumerationField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonUnsignedIntegerField::operator=(val);
+        return *this;
+    }
+
+    ConstUnsignedEnumerationFieldClass cls() const noexcept
+    {
+        return ConstUnsignedEnumerationFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::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<bt_field>;
+using ConstUnsignedEnumerationField = CommonUnsignedEnumerationField<const bt_field>;
+
+template <typename LibObjT>
+class CommonSignedEnumerationField final : public CommonSignedIntegerField<LibObjT>
+{
+private:
+    using typename CommonSignedIntegerField<LibObjT>::_ThisCommonSignedIntegerField;
+    using typename CommonField<LibObjT>::_LibObjPtr;
+
+public:
+    using Class =
+        typename std::conditional<std::is_const<LibObjT>::value, ConstSignedEnumerationFieldClass,
+                                  SignedEnumerationFieldClass>::type;
+
+    explicit CommonSignedEnumerationField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonSignedIntegerField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isSignedEnumeration());
+    }
+
+    template <typename OtherLibObjT>
+    CommonSignedEnumerationField(const CommonSignedEnumerationField<OtherLibObjT>& val) noexcept :
+        _ThisCommonSignedIntegerField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonSignedEnumerationField<LibObjT>&
+    operator=(const CommonSignedEnumerationField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonSignedIntegerField::operator=(val);
+        return *this;
+    }
+
+    ConstSignedEnumerationFieldClass cls() const noexcept
+    {
+        return ConstSignedEnumerationFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::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<bt_field>;
+using ConstSignedEnumerationField = CommonSignedEnumerationField<const bt_field>;
+
+template <typename LibObjT>
+class CommonSinglePrecisionRealField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+public:
+    using Value = float;
+
+    explicit CommonSinglePrecisionRealField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isSinglePrecisionReal());
+    }
+
+    template <typename OtherLibObjT>
+    CommonSinglePrecisionRealField(const CommonSinglePrecisionRealField<OtherLibObjT>& val) noexcept
+        :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonSinglePrecisionRealField<LibObjT>&
+    operator=(const CommonSinglePrecisionRealField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    CommonSinglePrecisionRealField<LibObjT>& operator=(const Value val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bt_field>;
+using ConstSinglePrecisionRealField = CommonSinglePrecisionRealField<const bt_field>;
+
+template <typename LibObjT>
+class CommonDoublePrecisionRealField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+public:
+    using Value = double;
+
+    explicit CommonDoublePrecisionRealField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isDoublePrecisionReal());
+    }
+
+    template <typename OtherLibObjT>
+    CommonDoublePrecisionRealField(const CommonDoublePrecisionRealField<OtherLibObjT>& val) noexcept
+        :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonDoublePrecisionRealField<LibObjT>&
+    operator=(const CommonDoublePrecisionRealField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    CommonDoublePrecisionRealField<LibObjT>& operator=(const Value val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bt_field>;
+using ConstDoublePrecisionRealField = CommonDoublePrecisionRealField<const bt_field>;
+
+template <typename LibObjT>
+class CommonStringField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+
+public:
+    explicit CommonStringField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isString());
+    }
+
+    template <typename OtherLibObjT>
+    CommonStringField(const CommonStringField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonStringField<LibObjT>& operator=(const CommonStringField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    CommonStringField<LibObjT>& operator=(const char * const val) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<LibObjT>& operator=(const std::string& val) noexcept
+    {
+        return *this = val.data();
+    }
+
+    void clear() noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::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<bt_field>;
+using ConstStringField = CommonStringField<const bt_field>;
+
+namespace internal {
+
+template <typename LibObjT>
+struct CommonStructureFieldSpec;
+
+// Functions specific to mutable structure fields
+template <>
+struct CommonStructureFieldSpec<bt_field> 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<const bt_field> 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 <typename LibObjT>
+class CommonStructureField final : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+    using _Spec = internal::CommonStructureFieldSpec<LibObjT>;
+
+public:
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstStructureFieldClass,
+                                            StructureFieldClass>::type;
+
+    explicit CommonStructureField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isStructure());
+    }
+
+    template <typename OtherLibObjT>
+    CommonStructureField(const CommonStructureField<OtherLibObjT>& val) noexcept :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonStructureField<LibObjT>& operator=(const CommonStructureField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstStructureFieldClass cls() const noexcept
+    {
+        return ConstStructureFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::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<const bt_field>::memberFieldByIndex(
+            this->_libObjPtr(), index)};
+    }
+
+    CommonField<LibObjT> operator[](const std::uint64_t index) noexcept
+    {
+        return CommonField<LibObjT> {_Spec::memberFieldByIndex(this->_libObjPtr(), index)};
+    }
+
+    nonstd::optional<ConstField> operator[](const char * const name) const noexcept
+    {
+        const auto libObjPtr =
+            internal::CommonStructureFieldSpec<const bt_field>::memberFieldByName(
+                this->_libObjPtr(), name);
+
+        if (libObjPtr) {
+            return ConstField {libObjPtr};
+        }
+
+        return nonstd::nullopt;
+    }
+
+    nonstd::optional<ConstField> operator[](const std::string& name) const noexcept
+    {
+        return (*this)[name.data()];
+    }
+
+    nonstd::optional<CommonField<LibObjT>> operator[](const char * const name) noexcept
+    {
+        const auto libObjPtr = _Spec::memberFieldByName(this->_libObjPtr(), name);
+
+        if (libObjPtr) {
+            return CommonField<LibObjT> {libObjPtr};
+        }
+
+        return nonstd::nullopt;
+    }
+
+    nonstd::optional<CommonField<LibObjT>> operator[](const std::string& name) noexcept
+    {
+        return (*this)[name.data()];
+    }
+};
+
+using StructureField = CommonStructureField<bt_field>;
+using ConstStructureField = CommonStructureField<const bt_field>;
+
+namespace internal {
+
+template <typename LibObjT>
+struct CommonArrayFieldSpec;
+
+// Functions specific to mutable array fields
+template <>
+struct CommonArrayFieldSpec<bt_field> 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<const bt_field> 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 <typename LibObjT>
+class CommonArrayField : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_ThisCommonField;
+    using _Spec = internal::CommonArrayFieldSpec<LibObjT>;
+
+protected:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using _ThisCommonArrayField = CommonArrayField<LibObjT>;
+
+public:
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstArrayFieldClass,
+                                            ArrayFieldClass>::type;
+
+    explicit CommonArrayField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isArray());
+    }
+
+    template <typename OtherLibObjT>
+    CommonArrayField(const CommonArrayField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    _ThisCommonArrayField& operator=(const CommonArrayField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstArrayFieldClass cls() const noexcept
+    {
+        return ConstArrayFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::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<const bt_field>::elementFieldByIndex(
+            this->_libObjPtr(), index)};
+    }
+
+    CommonField<LibObjT> operator[](const std::uint64_t index) noexcept
+    {
+        return CommonField<LibObjT> {_Spec::elementFieldByIndex(this->_libObjPtr(), index)};
+    }
+};
+
+using ArrayField = CommonArrayField<bt_field>;
+using ConstArrayField = CommonArrayField<const bt_field>;
+
+template <typename LibObjT>
+class CommonDynamicArrayField : public CommonArrayField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonArrayField<LibObjT>::_ThisCommonArrayField;
+
+public:
+    explicit CommonDynamicArrayField(const _LibObjPtr libObjPtr) noexcept :
+        _ThisCommonArrayField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isDynamicArray());
+    }
+
+    template <typename OtherLibObjT>
+    CommonDynamicArrayField(const CommonDynamicArrayField<OtherLibObjT>& val) noexcept :
+        _ThisCommonArrayField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonDynamicArrayField<LibObjT>&
+    operator=(const CommonDynamicArrayField<OtherLibObjT>& 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<LibObjT>::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<bt_field>;
+using ConstDynamicArrayField = CommonDynamicArrayField<const bt_field>;
+
+namespace internal {
+
+template <typename LibObjT>
+struct CommonOptionFieldSpec;
+
+// Functions specific to mutable option fields
+template <>
+struct CommonOptionFieldSpec<bt_field> 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<const bt_field> final
+{
+    static const bt_field *field(const bt_field * const libObjPtr) noexcept
+    {
+        return bt_field_option_borrow_field_const(libObjPtr);
+    }
+};
+
+} // namespace internal
+
+template <typename LibObjT>
+class CommonOptionField : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+    using _Spec = internal::CommonOptionFieldSpec<LibObjT>;
+
+public:
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstOptionFieldClass,
+                                            OptionFieldClass>::type;
+
+    explicit CommonOptionField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isOption());
+    }
+
+    template <typename OtherLibObjT>
+    CommonOptionField(const CommonOptionField<OtherLibObjT>& val) noexcept : _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonOptionField<LibObjT>& operator=(const CommonOptionField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstOptionFieldClass cls() const noexcept
+    {
+        return ConstOptionFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+    }
+
+    void hasField(const bool hasField) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+
+        bt_field_option_set_has_field(this->_libObjPtr(), static_cast<bt_bool>(hasField));
+    }
+
+    bool hasField() const noexcept
+    {
+        return this->field();
+    }
+
+    nonstd::optional<ConstField> field() const noexcept
+    {
+        const auto libObjPtr =
+            internal::CommonOptionFieldSpec<const bt_field>::field(this->_libObjPtr());
+
+        if (libObjPtr) {
+            return ConstField {libObjPtr};
+        }
+
+        return nonstd::nullopt;
+    }
+
+    nonstd::optional<CommonField<LibObjT>> field() noexcept
+    {
+        const auto libObjPtr = _Spec::field(this->_libObjPtr());
+
+        if (libObjPtr) {
+            return CommonField<LibObjT> {libObjPtr};
+        }
+
+        return nonstd::nullopt;
+    }
+};
+
+using OptionField = CommonOptionField<bt_field>;
+using ConstOptionField = CommonOptionField<const bt_field>;
+
+namespace internal {
+
+template <typename LibObjT>
+struct CommonVariantFieldSpec;
+
+// Functions specific to mutable variant fields
+template <>
+struct CommonVariantFieldSpec<bt_field> 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<const bt_field> 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 <typename LibObjT>
+class CommonVariantField : public CommonField<LibObjT>
+{
+private:
+    using typename CommonField<LibObjT>::_LibObjPtr;
+    using typename CommonField<LibObjT>::_ThisCommonField;
+    using _Spec = internal::CommonVariantFieldSpec<LibObjT>;
+
+public:
+    using Class = typename std::conditional<std::is_const<LibObjT>::value, ConstVariantFieldClass,
+                                            VariantFieldClass>::type;
+
+    explicit CommonVariantField(const _LibObjPtr libObjPtr) noexcept : _ThisCommonField {libObjPtr}
+    {
+        BT_ASSERT_DBG(this->isVariant());
+    }
+
+    template <typename OtherLibObjT>
+    CommonVariantField(const CommonVariantField<OtherLibObjT>& val) noexcept :
+        _ThisCommonField {val}
+    {
+    }
+
+    template <typename OtherLibObjT>
+    CommonVariantField<LibObjT>& operator=(const CommonVariantField<OtherLibObjT>& val) noexcept
+    {
+        _ThisCommonField::operator=(val);
+        return *this;
+    }
+
+    ConstVariantFieldClass cls() const noexcept
+    {
+        return ConstVariantFieldClass {
+            internal::CommonFieldSpec<const bt_field>::cls(this->_libObjPtr())};
+    }
+
+    Class cls() noexcept
+    {
+        return Class {internal::CommonFieldSpec<LibObjT>::cls(this->_libObjPtr())};
+    }
+
+    void selectOption(const std::uint64_t index) noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+
+        static_cast<void>(bt_field_variant_select_option_by_index(this->_libObjPtr(), index));
+    }
+
+    ConstField selectedOptionField() const noexcept
+    {
+        return ConstField {internal::CommonVariantFieldSpec<const bt_field>::selectedOptionField(
+            this->_libObjPtr())};
+    }
+
+    CommonField<LibObjT> selectedOptionField() noexcept
+    {
+        return CommonField<LibObjT> {_Spec::selectedOptionField(this->_libObjPtr())};
+    }
+
+    std::uint64_t selectedOptionIndex() const noexcept
+    {
+        return bt_field_variant_get_selected_option_index(this->_libObjPtr());
+    }
+};
+
+using VariantField = CommonVariantField<bt_field>;
+using ConstVariantField = CommonVariantField<const bt_field>;
+
+template <typename LibObjT>
+CommonBoolField<LibObjT> CommonField<LibObjT>::asBool() const noexcept
+{
+    BT_ASSERT_DBG(this->isBool());
+    return CommonBoolField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonBitArrayField<LibObjT> CommonField<LibObjT>::asBitArray() const noexcept
+{
+    BT_ASSERT_DBG(this->isBitArray());
+    return CommonBitArrayField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonUnsignedIntegerField<LibObjT> CommonField<LibObjT>::asUnsignedInteger() const noexcept
+{
+    BT_ASSERT_DBG(this->isUnsignedInteger());
+    return CommonUnsignedIntegerField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonSignedIntegerField<LibObjT> CommonField<LibObjT>::asSignedInteger() const noexcept
+{
+    BT_ASSERT_DBG(this->isSignedInteger());
+    return CommonSignedIntegerField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonUnsignedEnumerationField<LibObjT> CommonField<LibObjT>::asUnsignedEnumeration() const noexcept
+{
+    BT_ASSERT_DBG(this->isUnsignedEnumeration());
+    return CommonUnsignedEnumerationField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonSignedEnumerationField<LibObjT> CommonField<LibObjT>::asSignedEnumeration() const noexcept
+{
+    BT_ASSERT_DBG(this->isSignedEnumeration());
+    return CommonSignedEnumerationField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonSinglePrecisionRealField<LibObjT> CommonField<LibObjT>::asSinglePrecisionReal() const noexcept
+{
+    BT_ASSERT_DBG(this->isSinglePrecisionReal());
+    return CommonSinglePrecisionRealField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonDoublePrecisionRealField<LibObjT> CommonField<LibObjT>::asDoublePrecisionReal() const noexcept
+{
+    BT_ASSERT_DBG(this->isDoublePrecisionReal());
+    return CommonDoublePrecisionRealField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonStringField<LibObjT> CommonField<LibObjT>::asString() const noexcept
+{
+    BT_ASSERT_DBG(this->isString());
+    return CommonStringField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonStructureField<LibObjT> CommonField<LibObjT>::asStructure() const noexcept
+{
+    BT_ASSERT_DBG(this->isStructure());
+    return CommonStructureField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonArrayField<LibObjT> CommonField<LibObjT>::asArray() const noexcept
+{
+    BT_ASSERT_DBG(this->isArray());
+    return CommonArrayField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonDynamicArrayField<LibObjT> CommonField<LibObjT>::asDynamicArray() const noexcept
+{
+    BT_ASSERT_DBG(this->isDynamicArray());
+    return CommonDynamicArrayField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonOptionField<LibObjT> CommonField<LibObjT>::asOption() const noexcept
+{
+    BT_ASSERT_DBG(this->isOption());
+    return CommonOptionField<LibObjT> {this->_libObjPtr()};
+}
+
+template <typename LibObjT>
+CommonVariantField<LibObjT> CommonField<LibObjT>::asVariant() const noexcept
+{
+    BT_ASSERT_DBG(this->isVariant());
+    return CommonVariantField<LibObjT> {this->_libObjPtr()};
+}
+
+} // namespace bt2
+
+#endif // BABELTRACE_CPP_COMMON_BT2_FIELD_HPP
This page took 0.035761 seconds and 4 git commands to generate.