doc/api/libbabeltrace2/DoxygenLayout.xml: use `topics` tab
[babeltrace.git] / src / cpp-common / bt2 / value.hpp
index 4b34a16ebf2038a57d944e47662b862d529935ba..9f7fdff5cc883b312e8fc71cf495d369a54507ca 100644 (file)
@@ -7,41 +7,45 @@
 #ifndef BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
 #define BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
 
-#include <type_traits>
 #include <cstdint>
 #include <functional>
+#include <type_traits>
+
 #include <babeltrace2/babeltrace.h>
 
 #include "common/assert.h"
 #include "common/common.h"
-#include "internal/borrowed-obj.hpp"
-#include "internal/shared-obj.hpp"
+#include "cpp-common/bt2c/c-string-view.hpp"
+#include "cpp-common/vendor/wise-enum/wise_enum.h"
+
+#include "borrowed-object-iterator.hpp"
+#include "borrowed-object.hpp"
+#include "exc.hpp"
 #include "internal/utils.hpp"
-#include "cpp-common/optional.hpp"
-#include "cpp-common/string_view.hpp"
-#include "lib-error.hpp"
+#include "optional-borrowed-object.hpp"
+#include "raw-value-proxy.hpp"
+#include "shared-object.hpp"
 
 namespace bt2 {
-
 namespace internal {
 
 struct ValueRefFuncs final
 {
-    static void get(const bt_value * const libObjPtr)
+    static void get(const bt_value * const libObjPtr) noexcept
     {
         bt_value_get_ref(libObjPtr);
     }
 
-    static void put(const bt_value * const libObjPtr)
+    static void put(const bt_value * const libObjPtr) noexcept
     {
         bt_value_put_ref(libObjPtr);
     }
 };
 
-template <typename ObjT, typename LibObjT>
-using SharedValue = internal::SharedObj<ObjT, LibObjT, internal::ValueRefFuncs>;
+} /* namespace internal */
 
-} // namespace internal
+template <typename ObjT, typename LibObjT>
+using SharedValue = SharedObject<ObjT, LibObjT, internal::ValueRefFuncs>;
 
 template <typename LibObjT>
 class CommonNullValue;
@@ -67,86 +71,81 @@ class CommonArrayValue;
 template <typename LibObjT>
 class CommonMapValue;
 
-enum class ValueType
-{
-    NUL = BT_VALUE_TYPE_NULL,
-    BOOL = BT_VALUE_TYPE_BOOL,
-    UNSIGNED_INTEGER = BT_VALUE_TYPE_UNSIGNED_INTEGER,
-    SIGNED_INTEGER = BT_VALUE_TYPE_SIGNED_INTEGER,
-    REAL = BT_VALUE_TYPE_REAL,
-    STRING = BT_VALUE_TYPE_STRING,
-    ARRAY = BT_VALUE_TYPE_ARRAY,
-    MAP = BT_VALUE_TYPE_MAP,
-};
-
-template <typename LibObjT>
-class CommonClockClass;
+/* clang-format off */
 
-template <typename LibObjT>
-class CommonFieldClass;
+WISE_ENUM_CLASS(ValueType,
+    (Null, BT_VALUE_TYPE_NULL),
+    (Bool, BT_VALUE_TYPE_BOOL),
+    (UnsignedInteger, BT_VALUE_TYPE_UNSIGNED_INTEGER),
+    (SignedInteger, BT_VALUE_TYPE_SIGNED_INTEGER),
+    (Real, BT_VALUE_TYPE_REAL),
+    (String, BT_VALUE_TYPE_STRING),
+    (Array, BT_VALUE_TYPE_ARRAY),
+    (Map, BT_VALUE_TYPE_MAP));
 
-template <typename LibObjT>
-class CommonTraceClass;
+/* clang-format on */
 
-template <typename LibObjT>
-class CommonStreamClass;
+template <typename ValueObjT>
+class CommonValueRawValueProxy final
+{
+public:
+    explicit CommonValueRawValueProxy(const ValueObjT obj) : _mObj {obj}
+    {
+    }
 
-template <typename LibObjT>
-class CommonEventClass;
+    CommonValueRawValueProxy& operator=(bool rawVal) noexcept;
+    CommonValueRawValueProxy& operator=(std::int64_t rawVal) noexcept;
+    CommonValueRawValueProxy& operator=(std::uint64_t rawVal) noexcept;
+    CommonValueRawValueProxy& operator=(double rawVal) noexcept;
+    CommonValueRawValueProxy& operator=(const char *rawVal);
+    CommonValueRawValueProxy& operator=(bt2c::CStringView rawVal);
+    operator bool() const noexcept;
+    operator std::int64_t() const noexcept;
+    operator std::uint64_t() const noexcept;
+    operator double() const noexcept;
+    operator bt2c::CStringView() const noexcept;
 
-template <typename LibObjT>
-class CommonStream;
+private:
+    ValueObjT _mObj;
+};
 
 template <typename LibObjT>
-class CommonValue : public internal::BorrowedObj<LibObjT>
+class CommonValue : public BorrowedObject<LibObjT>
 {
-    // Allow append() to call `val._libObjPtr()`
-    friend class CommonArrayValue<bt_value>;
-
-    // Allow insert() to call `val._libObjPtr()`
-    friend class CommonMapValue<bt_value>;
-
-    // Allow userAttributes() to call `val._libObjPtr()`
-    friend class CommonClockClass<bt_clock_class>;
-    friend class CommonFieldClass<bt_field_class>;
-    friend class CommonTraceClass<bt_trace_class>;
-    friend class CommonStreamClass<bt_stream_class>;
-    friend class CommonEventClass<bt_event_class>;
-    friend class CommonStream<bt_stream>;
-
-    // Allow operator==() to call `other._libObjPtr()`
-    friend class CommonValue<bt_value>;
-    friend class CommonValue<const bt_value>;
-
 private:
-    using typename internal::BorrowedObj<LibObjT>::_ThisBorrowedObj;
+    using typename BorrowedObject<LibObjT>::_ThisBorrowedObject;
 
 protected:
-    using typename internal::BorrowedObj<LibObjT>::_LibObjPtr;
     using _ThisCommonValue = CommonValue<LibObjT>;
 
 public:
-    using Shared = internal::SharedValue<CommonValue<LibObjT>, LibObjT>;
+    using typename BorrowedObject<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonValue<LibObjT>, LibObjT>;
 
-    explicit CommonValue(const _LibObjPtr libObjPtr) noexcept : _ThisBorrowedObj {libObjPtr}
+    explicit CommonValue(const LibObjPtr libObjPtr) noexcept : _ThisBorrowedObject {libObjPtr}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonValue(const CommonValue<OtherLibObjT>& val) noexcept : _ThisBorrowedObj {val}
+    CommonValue(const CommonValue<OtherLibObjT> val) noexcept : _ThisBorrowedObject {val}
     {
     }
 
     template <typename OtherLibObjT>
-    _ThisCommonValue& operator=(const CommonValue<OtherLibObjT>& val) noexcept
+    _ThisCommonValue operator=(const CommonValue<OtherLibObjT> val) noexcept
     {
-        _ThisBorrowedObj::operator=(val);
+        _ThisBorrowedObject::operator=(val);
         return *this;
     }
 
+    CommonValue<const bt_value> asConst() const noexcept
+    {
+        return CommonValue<const bt_value> {*this};
+    }
+
     ValueType type() const noexcept
     {
-        return static_cast<ValueType>(bt_value_get_type(this->_libObjPtr()));
+        return static_cast<ValueType>(bt_value_get_type(this->libObjPtr()));
     }
 
     bool isNull() const noexcept
@@ -195,20 +194,86 @@ public:
     }
 
     template <typename OtherLibObjT>
-    bool operator==(const CommonValue<OtherLibObjT>& other) const noexcept
+    bool operator==(const CommonValue<OtherLibObjT> other) const noexcept
     {
-        return static_cast<bool>(bt_value_is_equal(this->_libObjPtr(), other._libObjPtr()));
+        return static_cast<bool>(bt_value_is_equal(this->libObjPtr(), other.libObjPtr()));
     }
 
     template <typename OtherLibObjT>
-    bool operator!=(const CommonValue<OtherLibObjT>& other) const noexcept
+    bool operator!=(const CommonValue<OtherLibObjT> other) const noexcept
     {
         return !(*this == other);
     }
 
+    CommonValueRawValueProxy<CommonValue> operator*() const noexcept
+    {
+        return CommonValueRawValueProxy<CommonValue> {*this};
+    }
+
+    std::uint64_t arrayLength() const noexcept
+    {
+        return this->asArray().length();
+    }
+
+    bool arrayIsEmpty() const noexcept
+    {
+        return this->asArray().isEmpty();
+    }
+
+    CommonValue<LibObjT> operator[](const std::uint64_t index) const noexcept
+    {
+        return this->asArray()[index];
+    }
+
+    template <typename T>
+    void append(T&& elem) const
+    {
+        this->asArray().append(std::forward<T>(elem));
+    }
+
+    CommonArrayValue<bt_value> appendEmptyArray() const;
+    CommonMapValue<bt_value> appendEmptyMap() const;
+
+    std::uint64_t mapLength() const noexcept
+    {
+        return this->asMap().length();
+    }
+
+    bool mapIsEmpty() const noexcept
+    {
+        return this->asMap().isEmpty();
+    }
+
+    template <typename KeyT>
+    OptionalBorrowedObject<CommonValue<LibObjT>> operator[](KeyT&& key) const noexcept
+    {
+        return this->asMap()[std::forward<KeyT>(key)];
+    }
+
+    template <typename KeyT>
+    bool hasEntry(KeyT&& key) const noexcept
+    {
+        return this->asMap().hasEntry(std::forward<KeyT>(key));
+    }
+
+    template <typename KeyT, typename ValT>
+    void insert(KeyT&& key, ValT&& val) const
+    {
+        this->asMap().insert(std::forward<KeyT>(key), std::forward<ValT>(val));
+    }
+
+    CommonArrayValue<bt_value> insertEmptyArray(bt2c::CStringView key) const;
+    CommonMapValue<bt_value> insertEmptyMap(bt2c::CStringView key) const;
+
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
+    }
+
+    template <typename ValueT>
+    ValueT as() const noexcept
+    {
+        return ValueT {this->libObjPtr()};
     }
 
     CommonNullValue<LibObjT> asNull() const noexcept;
@@ -223,13 +288,111 @@ public:
 protected:
     bool _libTypeIs(const bt_value_type type) const noexcept
     {
-        return bt_value_type_is(bt_value_get_type(this->_libObjPtr()), type);
+        return bt_value_type_is(bt_value_get_type(this->libObjPtr()), type);
     }
 };
 
 using Value = CommonValue<bt_value>;
 using ConstValue = CommonValue<const bt_value>;
 
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const bool rawVal) noexcept
+{
+    _mObj.asBool().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const std::int64_t rawVal) noexcept
+{
+    _mObj.asSignedInteger().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const std::uint64_t rawVal) noexcept
+{
+    _mObj.asUnsignedInteger().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const double rawVal) noexcept
+{
+    _mObj.asReal().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const char * const rawVal)
+{
+    _mObj.asString().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>&
+CommonValueRawValueProxy<ValueObjT>::operator=(const bt2c::CStringView rawVal)
+{
+    _mObj.asString().value(rawVal);
+    return *this;
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>::operator bool() const noexcept
+{
+    return _mObj.asBool().value();
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>::operator std::int64_t() const noexcept
+{
+    return _mObj.asSignedInteger().value();
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>::operator std::uint64_t() const noexcept
+{
+    return _mObj.asUnsignedInteger().value();
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>::operator double() const noexcept
+{
+    return _mObj.asReal().value();
+}
+
+template <typename ValueObjT>
+CommonValueRawValueProxy<ValueObjT>::operator bt2c::CStringView() const noexcept
+{
+    return _mObj.asString().value();
+}
+
+namespace internal {
+
+struct ValueTypeDescr
+{
+    using Const = ConstValue;
+    using NonConst = Value;
+};
+
+template <>
+struct TypeDescr<Value> : public ValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstValue> : public ValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonNullValue final : public CommonValue<LibObjT>
 {
@@ -237,51 +400,76 @@ private:
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonNullValue<LibObjT>, LibObjT>;
+    using Shared = SharedValue<CommonNullValue<LibObjT>, LibObjT>;
 
     CommonNullValue() noexcept : _ThisCommonValue {bt_value_null}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonNullValue(const CommonNullValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonNullValue(const CommonNullValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonNullValue<LibObjT>& operator=(const CommonNullValue<OtherLibObjT>& val) noexcept
+    CommonNullValue<LibObjT> operator=(const CommonNullValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
+    CommonNullValue<const bt_value> asConst() const noexcept
+    {
+        return CommonNullValue<const bt_value> {*this};
+    }
+
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
 using NullValue = CommonNullValue<bt_value>;
 using ConstNullValue = CommonNullValue<const bt_value>;
 
+namespace internal {
+
+struct NullValueTypeDescr
+{
+    using Const = ConstNullValue;
+    using NonConst = NullValue;
+};
+
+template <>
+struct TypeDescr<NullValue> : public NullValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstNullValue> : public NullValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonBoolValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonBoolValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonBoolValue<LibObjT>, LibObjT>;
     using Value = bool;
 
-    explicit CommonBoolValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
+    explicit CommonBoolValue(const LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isBool());
     }
 
     template <typename OtherLibObjT>
-    CommonBoolValue(const CommonBoolValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonBoolValue(const CommonBoolValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
@@ -290,55 +478,80 @@ public:
         const auto libObjPtr = bt_value_bool_create_init(static_cast<bt_bool>(rawVal));
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonBoolValue<LibObjT> {libObjPtr}};
+        return CommonBoolValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonBoolValue<LibObjT>& operator=(const CommonBoolValue<OtherLibObjT>& val) noexcept
+    CommonBoolValue<LibObjT> operator=(const CommonBoolValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    CommonBoolValue<LibObjT>& operator=(const Value rawVal) noexcept
+    CommonBoolValue<const bt_value> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonBoolValue<const bt_value> {*this};
+    }
 
-        bt_value_bool_set(this->_libObjPtr(), static_cast<bt_bool>(rawVal));
-        return *this;
+    RawValueProxy<CommonBoolValue> operator*() const noexcept
+    {
+        return RawValueProxy<CommonBoolValue> {*this};
     }
 
     Value value() const noexcept
     {
-        return static_cast<Value>(bt_value_bool_get(this->_libObjPtr()));
+        return static_cast<Value>(bt_value_bool_get(this->libObjPtr()));
     }
 
-    operator Value() const noexcept
+    CommonBoolValue value(const Value val) const noexcept
     {
-        return this->value();
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstBoolValue`.");
+
+        bt_value_bool_set(this->libObjPtr(), static_cast<bt_bool>(val));
+        return *this;
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
 using BoolValue = CommonBoolValue<bt_value>;
 using ConstBoolValue = CommonBoolValue<const bt_value>;
 
+namespace internal {
+
+struct BoolValueTypeDescr
+{
+    using Const = ConstBoolValue;
+    using NonConst = BoolValue;
+};
+
+template <>
+struct TypeDescr<BoolValue> : public BoolValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstBoolValue> : public BoolValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonUnsignedIntegerValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonUnsignedIntegerValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonUnsignedIntegerValue<LibObjT>, LibObjT>;
     using Value = std::uint64_t;
 
-    explicit CommonUnsignedIntegerValue(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonUnsignedIntegerValue(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isUnsignedInteger());
@@ -349,62 +562,88 @@ public:
         const auto libObjPtr = bt_value_integer_unsigned_create_init(rawVal);
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonUnsignedIntegerValue<LibObjT> {libObjPtr}};
+        return CommonUnsignedIntegerValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonUnsignedIntegerValue(const CommonUnsignedIntegerValue<OtherLibObjT>& val) noexcept :
+    CommonUnsignedIntegerValue(const CommonUnsignedIntegerValue<OtherLibObjT> val) noexcept :
         _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonUnsignedIntegerValue<LibObjT>&
-    operator=(const CommonUnsignedIntegerValue<OtherLibObjT>& val) noexcept
+    CommonUnsignedIntegerValue<LibObjT>
+    operator=(const CommonUnsignedIntegerValue<OtherLibObjT> val) noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
-
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    CommonUnsignedIntegerValue<LibObjT>& operator=(const Value rawVal) noexcept
+    CommonUnsignedIntegerValue<const bt_value> asConst() const noexcept
     {
-        bt_value_integer_unsigned_set(this->_libObjPtr(), rawVal);
-        return *this;
+        return CommonUnsignedIntegerValue<const bt_value> {*this};
     }
 
-    Value value() const noexcept
+    RawValueProxy<CommonUnsignedIntegerValue> operator*() const noexcept
     {
-        return bt_value_integer_unsigned_get(this->_libObjPtr());
+        return RawValueProxy<CommonUnsignedIntegerValue> {*this};
+    }
+
+    CommonUnsignedIntegerValue value(const Value val) const noexcept
+    {
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstUnsignedIntegerValue`.");
+
+        bt_value_integer_unsigned_set(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_value_integer_unsigned_get(this->libObjPtr());
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
 using UnsignedIntegerValue = CommonUnsignedIntegerValue<bt_value>;
 using ConstUnsignedIntegerValue = CommonUnsignedIntegerValue<const bt_value>;
 
+namespace internal {
+
+struct UnsignedIntegerValueTypeDescr
+{
+    using Const = ConstUnsignedIntegerValue;
+    using NonConst = UnsignedIntegerValue;
+};
+
+template <>
+struct TypeDescr<UnsignedIntegerValue> : public UnsignedIntegerValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstUnsignedIntegerValue> : public UnsignedIntegerValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonSignedIntegerValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonSignedIntegerValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonSignedIntegerValue<LibObjT>, LibObjT>;
     using Value = std::int64_t;
 
-    explicit CommonSignedIntegerValue(const _LibObjPtr libObjPtr) noexcept :
+    explicit CommonSignedIntegerValue(const LibObjPtr libObjPtr) noexcept :
         _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isSignedInteger());
@@ -415,62 +654,88 @@ public:
         const auto libObjPtr = bt_value_integer_signed_create_init(rawVal);
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonSignedIntegerValue<LibObjT> {libObjPtr}};
+        return CommonSignedIntegerValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonSignedIntegerValue(const CommonSignedIntegerValue<OtherLibObjT>& val) noexcept :
+    CommonSignedIntegerValue(const CommonSignedIntegerValue<OtherLibObjT> val) noexcept :
         _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonSignedIntegerValue<LibObjT>&
-    operator=(const CommonSignedIntegerValue<OtherLibObjT>& val) noexcept
+    CommonSignedIntegerValue<LibObjT>
+    operator=(const CommonSignedIntegerValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    CommonSignedIntegerValue<LibObjT>& operator=(const Value rawVal) noexcept
+    CommonSignedIntegerValue<const bt_value> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonSignedIntegerValue<const bt_value> {*this};
+    }
 
-        bt_value_integer_signed_set(this->_libObjPtr(), rawVal);
-        return *this;
+    RawValueProxy<CommonSignedIntegerValue> operator*() const noexcept
+    {
+        return RawValueProxy<CommonSignedIntegerValue> {*this};
     }
 
-    Value value() const noexcept
+    CommonSignedIntegerValue value(const Value val) const noexcept
     {
-        return bt_value_integer_signed_get(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstSignedIntegerValue`.");
+
+        bt_value_integer_signed_set(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_value_integer_signed_get(this->libObjPtr());
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
 using SignedIntegerValue = CommonSignedIntegerValue<bt_value>;
 using ConstSignedIntegerValue = CommonSignedIntegerValue<const bt_value>;
 
+namespace internal {
+
+struct SignedIntegerValueTypeDescr
+{
+    using Const = ConstSignedIntegerValue;
+    using NonConst = SignedIntegerValue;
+};
+
+template <>
+struct TypeDescr<SignedIntegerValue> : public SignedIntegerValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstSignedIntegerValue> : public SignedIntegerValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonRealValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonRealValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonRealValue<LibObjT>, LibObjT>;
     using Value = double;
 
-    explicit CommonRealValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
+    explicit CommonRealValue(const LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isReal());
     }
@@ -480,114 +745,141 @@ public:
         const auto libObjPtr = bt_value_real_create_init(rawVal);
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonRealValue<LibObjT> {libObjPtr}};
+        return CommonRealValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonRealValue(const CommonRealValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonRealValue(const CommonRealValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonRealValue<LibObjT>& operator=(const CommonRealValue<OtherLibObjT>& val) noexcept
+    CommonRealValue<LibObjT> operator=(const CommonRealValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    CommonRealValue<LibObjT>& operator=(const Value rawVal) noexcept
+    CommonRealValue<const bt_value> asConst() const noexcept
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        return CommonRealValue<const bt_value> {*this};
+    }
 
-        bt_value_real_set(this->_libObjPtr(), rawVal);
-        return *this;
+    RawValueProxy<CommonRealValue> operator*() const noexcept
+    {
+        return RawValueProxy<CommonRealValue> {*this};
     }
 
-    Value value() const noexcept
+    CommonRealValue value(const Value val) const noexcept
     {
-        return bt_value_real_get(this->_libObjPtr());
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstRealValue`.");
+
+        bt_value_real_set(this->libObjPtr(), val);
+        return *this;
     }
 
-    operator Value() const noexcept
+    Value value() const noexcept
     {
-        return this->value();
+        return bt_value_real_get(this->libObjPtr());
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
 using RealValue = CommonRealValue<bt_value>;
 using ConstRealValue = CommonRealValue<const bt_value>;
 
+namespace internal {
+
+struct RealValueTypeDescr
+{
+    using Const = ConstRealValue;
+    using NonConst = RealValue;
+};
+
+template <>
+struct TypeDescr<RealValue> : public RealValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstRealValue> : public RealValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
 template <typename LibObjT>
 class CommonStringValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonStringValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonStringValue<LibObjT>, LibObjT>;
+    using Value = bt2c::CStringView;
 
-    explicit CommonStringValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
+    explicit CommonStringValue(const LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isString());
     }
 
-    static Shared create(const char * const rawVal = "")
+    static Shared create(const bt2c::CStringView rawVal = "")
     {
         const auto libObjPtr = bt_value_string_create_init(rawVal);
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonStringValue<LibObjT> {libObjPtr}};
-    }
-
-    static Shared create(const std::string& rawVal)
-    {
-        return CommonStringValue<LibObjT>::create(rawVal.data());
+        return CommonStringValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonStringValue(const CommonStringValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonStringValue(const CommonStringValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonStringValue<LibObjT>& operator=(const CommonStringValue<OtherLibObjT>& val) noexcept
+    CommonStringValue<LibObjT> operator=(const CommonStringValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    CommonStringValue<LibObjT>& operator=(const char * const rawVal)
+    CommonStringValue<const bt_value> asConst() const noexcept
+    {
+        return CommonStringValue<const bt_value> {*this};
+    }
+
+    RawValueProxy<CommonStringValue> operator*() const noexcept
+    {
+        return RawValueProxy<CommonStringValue> {*this};
+    }
+
+    CommonStringValue value(const Value val) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value,
+                      "Not available with `bt2::ConstStringValue`.");
 
-        const auto status = bt_value_string_set(this->_libObjPtr(), rawVal);
+        const auto status = bt_value_string_set(this->libObjPtr(), *val);
 
         if (status == BT_VALUE_STRING_SET_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
 
         return *this;
     }
 
-    CommonStringValue<LibObjT>& operator=(const std::string& rawVal) noexcept
-    {
-        return *this = rawVal.data();
-    }
-
-    bpstd::string_view value() const noexcept
+    Value value() const noexcept
     {
-        return bt_value_string_get(this->_libObjPtr());
+        return bt_value_string_get(this->libObjPtr());
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 };
 
@@ -596,10 +888,26 @@ using ConstStringValue = CommonStringValue<const bt_value>;
 
 namespace internal {
 
+struct StringValueTypeDescr
+{
+    using Const = ConstStringValue;
+    using NonConst = StringValue;
+};
+
+template <>
+struct TypeDescr<StringValue> : public StringValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstStringValue> : public StringValueTypeDescr
+{
+};
+
 template <typename LibObjT>
 struct CommonArrayValueSpec;
 
-// Functions specific to mutable array values
+/* Functions specific to mutable array values */
 template <>
 struct CommonArrayValueSpec<bt_value> final
 {
@@ -609,7 +917,7 @@ struct CommonArrayValueSpec<bt_value> final
     }
 };
 
-// Functions specific to constant array values
+/* Functions specific to constant array values */
 template <>
 struct CommonArrayValueSpec<const bt_value> final
 {
@@ -620,19 +928,20 @@ struct CommonArrayValueSpec<const bt_value> final
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonArrayValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonArrayValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonArrayValue<LibObjT>, LibObjT>;
+    using Iterator = BorrowedObjectIterator<CommonArrayValue<LibObjT>>;
 
-    explicit CommonArrayValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
+    explicit CommonArrayValue(const LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isArray());
     }
@@ -642,153 +951,167 @@ public:
         const auto libObjPtr = bt_value_array_create();
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonArrayValue<LibObjT> {libObjPtr}};
+        return CommonArrayValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonArrayValue(const CommonArrayValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonArrayValue(const CommonArrayValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonArrayValue<LibObjT>& operator=(const CommonArrayValue<OtherLibObjT>& val) noexcept
+    CommonArrayValue<LibObjT> operator=(const CommonArrayValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
+    CommonArrayValue<const bt_value> asConst() const noexcept
+    {
+        return CommonArrayValue<const bt_value> {*this};
+    }
+
     std::uint64_t length() const noexcept
     {
-        return bt_value_array_get_length(this->_libObjPtr());
+        return bt_value_array_get_length(this->libObjPtr());
     }
 
-    bool isEmpty() const noexcept
+    Iterator begin() const noexcept
     {
-        return this->length() == 0;
+        return Iterator {*this, 0};
+    }
+
+    Iterator end() const noexcept
+    {
+        return Iterator {*this, this->length()};
     }
 
-    ConstValue operator[](const std::uint64_t index) const noexcept
+    bool isEmpty() const noexcept
     {
-        return ConstValue {internal::CommonArrayValueSpec<const bt_value>::elementByIndex(
-            this->_libObjPtr(), index)};
+        return this->length() == 0;
     }
 
-    CommonValue<LibObjT> operator[](const std::uint64_t index) noexcept
+    CommonValue<LibObjT> operator[](const std::uint64_t index) const noexcept
     {
         return CommonValue<LibObjT> {
-            internal::CommonArrayValueSpec<LibObjT>::elementByIndex(this->_libObjPtr(), index)};
+            internal::CommonArrayValueSpec<LibObjT>::elementByIndex(this->libObjPtr(), index)};
     }
 
-    void append(const Value& val)
+    CommonArrayValue append(const Value val) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
-        const auto status = bt_value_array_append_element(this->_libObjPtr(), val._libObjPtr());
+        const auto status = bt_value_array_append_element(this->libObjPtr(), val.libObjPtr());
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const bool rawVal)
+    CommonArrayValue append(const bool rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
         const auto status =
-            bt_value_array_append_bool_element(this->_libObjPtr(), static_cast<bt_bool>(rawVal));
+            bt_value_array_append_bool_element(this->libObjPtr(), static_cast<bt_bool>(rawVal));
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const std::uint64_t rawVal)
+    CommonArrayValue append(const std::uint64_t rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
         const auto status =
-            bt_value_array_append_unsigned_integer_element(this->_libObjPtr(), rawVal);
+            bt_value_array_append_unsigned_integer_element(this->libObjPtr(), rawVal);
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const std::int64_t rawVal)
+    CommonArrayValue append(const std::int64_t rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
-        const auto status =
-            bt_value_array_append_signed_integer_element(this->_libObjPtr(), rawVal);
+        const auto status = bt_value_array_append_signed_integer_element(this->libObjPtr(), rawVal);
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const double rawVal)
+    CommonArrayValue append(const double rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
-        const auto status = bt_value_array_append_real_element(this->_libObjPtr(), rawVal);
+        const auto status = bt_value_array_append_real_element(this->libObjPtr(), rawVal);
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const char * const rawVal)
+    CommonArrayValue append(const char * const rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
-        const auto status = bt_value_array_append_string_element(this->_libObjPtr(), rawVal);
+        const auto status = bt_value_array_append_string_element(this->libObjPtr(), rawVal);
 
         this->_handleAppendLibStatus(status);
+        return *this;
     }
 
-    void append(const std::string& rawVal)
+    CommonArrayValue append(const bt2c::CStringView rawVal) const
     {
-        this->append(rawVal.data());
+        return this->append(rawVal.data());
     }
 
-    CommonArrayValue<bt_value> appendEmptyArray();
-    CommonMapValue<bt_value> appendEmptyMap();
+    CommonArrayValue<bt_value> appendEmptyArray() const;
+    CommonMapValue<bt_value> appendEmptyMap() const;
 
-    void operator+=(const Value& val)
+    void operator+=(const Value val) const
     {
         this->append(val);
     }
 
-    void operator+=(const bool rawVal)
+    void operator+=(const bool rawVal) const
     {
         this->append(rawVal);
     }
 
-    void operator+=(const std::uint64_t rawVal)
+    void operator+=(const std::uint64_t rawVal) const
     {
         this->append(rawVal);
     }
 
-    void operator+=(const std::int64_t rawVal)
+    void operator+=(const std::int64_t rawVal) const
     {
         this->append(rawVal);
     }
 
-    void operator+=(const double rawVal)
+    void operator+=(const double rawVal) const
     {
         this->append(rawVal);
     }
 
-    void operator+=(const char * const rawVal)
+    void operator+=(const char * const rawVal) const
     {
         this->append(rawVal);
     }
 
-    void operator+=(const std::string& rawVal)
+    void operator+=(const bt2c::CStringView rawVal) const
     {
         this->append(rawVal);
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 
 private:
     void _handleAppendLibStatus(const bt_value_array_append_element_status status) const
     {
         if (status == BT_VALUE_ARRAY_APPEND_ELEMENT_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
     }
 };
@@ -798,13 +1121,29 @@ using ConstArrayValue = CommonArrayValue<const bt_value>;
 
 namespace internal {
 
+struct ArrayValueTypeDescr
+{
+    using Const = ConstArrayValue;
+    using NonConst = ArrayValue;
+};
+
+template <>
+struct TypeDescr<ArrayValue> : public ArrayValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstArrayValue> : public ArrayValueTypeDescr
+{
+};
+
 /*
  * Type of a user function passed to `CommonMapValue<ObjT>::forEach()`.
  *
  * First argument is the entry's key, second is its value.
  */
 template <typename ObjT>
-using CommonMapValueForEachUserFunc = std::function<void(const bpstd::string_view&, ObjT)>;
+using CommonMapValueForEachUserFunc = std::function<void(bt2c::CStringView, ObjT)>;
 
 /*
  * Template of a function to be passed to bt_value_map_foreach_entry()
@@ -814,7 +1153,7 @@ using CommonMapValueForEachUserFunc = std::function<void(const bpstd::string_vie
  * `CommonMapValueForEachUserFunc<ObjT>` (the user function to call).
  *
  * This function catches any exception which the user function throws
- * and returns the `ErrorStatus` value. If there's no execption, this
+ * and returns the `ErrorStatus` value. If there's no exception, this
  * function returns the `OkStatus` value.
  */
 template <typename ObjT, typename LibObjT, typename LibStatusT, int OkStatus, int ErrorStatus>
@@ -835,7 +1174,7 @@ LibStatusT mapValueForEachLibFunc(const char * const key, LibObjT * const libObj
 template <typename LibObjT>
 struct CommonMapValueSpec;
 
-// Functions specific to mutable map values
+/* Functions specific to mutable map values */
 template <>
 struct CommonMapValueSpec<bt_value> final
 {
@@ -859,14 +1198,14 @@ struct CommonMapValueSpec<bt_value> final
             return;
         case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_USER_ERROR:
         case BT_VALUE_MAP_FOREACH_ENTRY_STATUS_ERROR:
-            throw LibError {};
+            throw Error {};
         default:
             bt_common_abort();
         }
     }
 };
 
-// Functions specific to constant map values
+/* Functions specific to constant map values */
 template <>
 struct CommonMapValueSpec<const bt_value> final
 {
@@ -892,26 +1231,26 @@ struct CommonMapValueSpec<const bt_value> final
             return;
         case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_USER_ERROR:
         case BT_VALUE_MAP_FOREACH_ENTRY_CONST_STATUS_ERROR:
-            throw LibError {};
+            throw Error {};
         default:
             bt_common_abort();
         }
     }
 };
 
-} // namespace internal
+} /* namespace internal */
 
 template <typename LibObjT>
 class CommonMapValue final : public CommonValue<LibObjT>
 {
 private:
-    using typename CommonValue<LibObjT>::_LibObjPtr;
     using typename CommonValue<LibObjT>::_ThisCommonValue;
 
 public:
-    using Shared = internal::SharedValue<CommonMapValue<LibObjT>, LibObjT>;
+    using typename CommonValue<LibObjT>::LibObjPtr;
+    using Shared = SharedValue<CommonMapValue<LibObjT>, LibObjT>;
 
-    explicit CommonMapValue(const _LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
+    explicit CommonMapValue(const LibObjPtr libObjPtr) noexcept : _ThisCommonValue {libObjPtr}
     {
         BT_ASSERT_DBG(this->isMap());
     }
@@ -921,197 +1260,135 @@ public:
         const auto libObjPtr = bt_value_map_create();
 
         internal::validateCreatedObjPtr(libObjPtr);
-        return Shared {CommonMapValue<LibObjT> {libObjPtr}};
+        return CommonMapValue::Shared::createWithoutRef(libObjPtr);
     }
 
     template <typename OtherLibObjT>
-    CommonMapValue(const CommonMapValue<OtherLibObjT>& val) noexcept : _ThisCommonValue {val}
+    CommonMapValue(const CommonMapValue<OtherLibObjT> val) noexcept : _ThisCommonValue {val}
     {
     }
 
     template <typename OtherLibObjT>
-    CommonMapValue<LibObjT>& operator=(const CommonMapValue<OtherLibObjT>& val) noexcept
+    CommonMapValue<LibObjT> operator=(const CommonMapValue<OtherLibObjT> val) noexcept
     {
         _ThisCommonValue::operator=(val);
         return *this;
     }
 
-    std::uint64_t size() const noexcept
+    CommonMapValue<const bt_value> asConst() const noexcept
     {
-        return bt_value_map_get_size(this->_libObjPtr());
+        return CommonMapValue<const bt_value> {*this};
     }
 
-    bool isEmpty() const noexcept
-    {
-        return this->size() == 0;
-    }
-
-    nonstd::optional<ConstValue> operator[](const char * const key) const noexcept
-    {
-        const auto libObjPtr =
-            internal::CommonMapValueSpec<const bt_value>::entryByKey(this->_libObjPtr(), key);
-
-        if (!libObjPtr) {
-            return nonstd::nullopt;
-        }
-
-        return ConstValue {libObjPtr};
-    }
-
-    nonstd::optional<ConstValue> operator[](const std::string& key) const noexcept
-    {
-        return (*this)[key.data()];
-    }
-
-    nonstd::optional<CommonValue<LibObjT>> operator[](const char * const key) noexcept
+    std::uint64_t length() const noexcept
     {
-        const auto libObjPtr =
-            internal::CommonMapValueSpec<LibObjT>::entryByKey(this->_libObjPtr(), key);
-
-        if (!libObjPtr) {
-            return nonstd::nullopt;
-        }
-
-        return CommonValue<LibObjT> {libObjPtr};
+        return bt_value_map_get_size(this->libObjPtr());
     }
 
-    nonstd::optional<CommonValue<LibObjT>> operator[](const std::string& key) noexcept
+    bool isEmpty() const noexcept
     {
-        return (*this)[key.data()];
+        return this->length() == 0;
     }
 
-    bool hasEntry(const char * const key) const noexcept
+    OptionalBorrowedObject<CommonValue<LibObjT>>
+    operator[](const bt2c::CStringView key) const noexcept
     {
-        return static_cast<bool>(bt_value_map_has_entry(this->_libObjPtr(), key));
+        return internal::CommonMapValueSpec<LibObjT>::entryByKey(this->libObjPtr(), key);
     }
 
-    bool hasEntry(const std::string& key) const noexcept
+    bool hasEntry(const bt2c::CStringView key) const noexcept
     {
-        return this->hasEntry(key.data());
+        return static_cast<bool>(bt_value_map_has_entry(this->libObjPtr(), key));
     }
 
-    void insert(const char * const key, const Value& val)
+    CommonMapValue insert(const bt2c::CStringView key, const Value val) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
-        const auto status = bt_value_map_insert_entry(this->_libObjPtr(), key, val._libObjPtr());
+        const auto status = bt_value_map_insert_entry(this->libObjPtr(), key, val.libObjPtr());
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const std::string& key, const Value& val)
-    {
-        this->insert(key.data(), val);
-    }
-
-    void insert(const char * const key, const bool rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const bool rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
         const auto status =
-            bt_value_map_insert_bool_entry(this->_libObjPtr(), key, static_cast<bt_bool>(rawVal));
+            bt_value_map_insert_bool_entry(this->libObjPtr(), key, static_cast<bt_bool>(rawVal));
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const std::string& key, const bool rawVal)
-    {
-        this->insert(key.data(), rawVal);
-    }
-
-    void insert(const char * const key, const std::uint64_t rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const std::uint64_t rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
         const auto status =
-            bt_value_map_insert_unsigned_integer_entry(this->_libObjPtr(), key, rawVal);
+            bt_value_map_insert_unsigned_integer_entry(this->libObjPtr(), key, rawVal);
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const std::string& key, const std::uint64_t rawVal)
-    {
-        this->insert(key.data(), rawVal);
-    }
-
-    void insert(const char * const key, const std::int64_t rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const std::int64_t rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
         const auto status =
-            bt_value_map_insert_signed_integer_entry(this->_libObjPtr(), key, rawVal);
+            bt_value_map_insert_signed_integer_entry(this->libObjPtr(), key, rawVal);
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const std::string& key, const std::int64_t rawVal)
-    {
-        this->insert(key.data(), rawVal);
-    }
-
-    void insert(const char * const key, const double rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const double rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
-        const auto status = bt_value_map_insert_real_entry(this->_libObjPtr(), key, rawVal);
+        const auto status = bt_value_map_insert_real_entry(this->libObjPtr(), key, rawVal);
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const std::string& key, const double rawVal)
-    {
-        this->insert(key.data(), rawVal);
-    }
-
-    void insert(const char * const key, const char * const rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const char *rawVal) const
     {
-        static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+        static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
-        const auto status = bt_value_map_insert_string_entry(this->_libObjPtr(), key, rawVal);
+        const auto status = bt_value_map_insert_string_entry(this->libObjPtr(), key, rawVal);
 
         this->_handleInsertLibStatus(status);
+        return *this;
     }
 
-    void insert(const char * const key, const std::string& rawVal)
-    {
-        this->insert(key, rawVal.data());
-    }
-
-    void insert(const std::string& key, const char * const rawVal)
-    {
-        this->insert(key.data(), rawVal);
-    }
-
-    void insert(const std::string& key, const std::string& rawVal)
+    CommonMapValue insert(const bt2c::CStringView key, const bt2c::CStringView rawVal) const
     {
-        this->insert(key.data(), rawVal.data());
+        return this->insert(key, rawVal.data());
     }
 
-    CommonArrayValue<bt_value> insertEmptyArray(const char *key);
-    CommonArrayValue<bt_value> insertEmptyArray(const std::string& key);
-    CommonMapValue<bt_value> insertEmptyMap(const char *key);
-    CommonMapValue<bt_value> insertEmptyMap(const std::string& key);
-
-    void forEach(const internal::CommonMapValueForEachUserFunc<ConstValue>& func) const
-    {
-        internal::CommonMapValueSpec<const bt_value>::forEach(this->_libObjPtr(), func);
-    }
+    CommonArrayValue<bt_value> insertEmptyArray(bt2c::CStringView key) const;
+    CommonMapValue<bt_value> insertEmptyMap(bt2c::CStringView key) const;
 
-    void forEach(const internal::CommonMapValueForEachUserFunc<CommonValue<LibObjT>>& func)
+    CommonMapValue
+    forEach(const internal::CommonMapValueForEachUserFunc<CommonValue<LibObjT>>& func) const
     {
-        internal::CommonMapValueSpec<LibObjT>::forEach(this->_libObjPtr(), func);
+        internal::CommonMapValueSpec<LibObjT>::forEach(this->libObjPtr(), func);
+        return *this;
     }
 
     Shared shared() const noexcept
     {
-        return Shared {*this};
+        return Shared::createWithRef(*this);
     }
 
 private:
     void _handleInsertLibStatus(const bt_value_map_insert_entry_status status) const
     {
         if (status == BT_VALUE_MAP_INSERT_ENTRY_STATUS_MEMORY_ERROR) {
-            throw LibMemoryError {};
+            throw MemoryError {};
         }
     }
 };
@@ -1119,123 +1396,147 @@ private:
 using MapValue = CommonMapValue<bt_value>;
 using ConstMapValue = CommonMapValue<const bt_value>;
 
+namespace internal {
+
+struct MapValueTypeDescr
+{
+    using Const = ConstMapValue;
+    using NonConst = MapValue;
+};
+
+template <>
+struct TypeDescr<MapValue> : public MapValueTypeDescr
+{
+};
+
+template <>
+struct TypeDescr<ConstMapValue> : public MapValueTypeDescr
+{
+};
+
+} /* namespace internal */
+
+template <typename LibObjT>
+ArrayValue CommonValue<LibObjT>::appendEmptyArray() const
+{
+    return this->asArray().appendEmptyArray();
+}
+
+template <typename LibObjT>
+MapValue CommonValue<LibObjT>::appendEmptyMap() const
+{
+    return this->asArray().appendEmptyMap();
+}
+
+template <typename LibObjT>
+ArrayValue CommonValue<LibObjT>::insertEmptyArray(const bt2c::CStringView key) const
+{
+    return this->asMap().insertEmptyArray(key);
+}
+
+template <typename LibObjT>
+MapValue CommonValue<LibObjT>::insertEmptyMap(const bt2c::CStringView key) const
+{
+    return this->asMap().insertEmptyMap(key);
+}
+
 template <typename LibObjT>
 CommonNullValue<LibObjT> CommonValue<LibObjT>::asNull() const noexcept
 {
     BT_ASSERT_DBG(this->isNull());
-    return CommonNullValue<LibObjT> {this->_libObjPtr()};
+    return CommonNullValue<LibObjT> {};
 }
 
 template <typename LibObjT>
 CommonBoolValue<LibObjT> CommonValue<LibObjT>::asBool() const noexcept
 {
-    BT_ASSERT_DBG(this->isBool());
-    return CommonBoolValue<LibObjT> {this->_libObjPtr()};
+    return CommonBoolValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonSignedIntegerValue<LibObjT> CommonValue<LibObjT>::asSignedInteger() const noexcept
 {
-    BT_ASSERT_DBG(this->isSignedInteger());
-    return CommonSignedIntegerValue<LibObjT> {this->_libObjPtr()};
+    return CommonSignedIntegerValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonUnsignedIntegerValue<LibObjT> CommonValue<LibObjT>::asUnsignedInteger() const noexcept
 {
-    BT_ASSERT_DBG(this->isUnsignedInteger());
-    return CommonUnsignedIntegerValue<LibObjT> {this->_libObjPtr()};
+    return CommonUnsignedIntegerValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonRealValue<LibObjT> CommonValue<LibObjT>::asReal() const noexcept
 {
-    BT_ASSERT_DBG(this->isReal());
-    return CommonRealValue<LibObjT> {this->_libObjPtr()};
+    return CommonRealValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonStringValue<LibObjT> CommonValue<LibObjT>::asString() const noexcept
 {
-    BT_ASSERT_DBG(this->isString());
-    return CommonStringValue<LibObjT> {this->_libObjPtr()};
+    return CommonStringValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonArrayValue<LibObjT> CommonValue<LibObjT>::asArray() const noexcept
 {
-    BT_ASSERT_DBG(this->isArray());
-    return CommonArrayValue<LibObjT> {this->_libObjPtr()};
+    return CommonArrayValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
 CommonMapValue<LibObjT> CommonValue<LibObjT>::asMap() const noexcept
 {
-    BT_ASSERT_DBG(this->isMap());
-    return CommonMapValue<LibObjT> {this->_libObjPtr()};
+    return CommonMapValue<LibObjT> {this->libObjPtr()};
 }
 
 template <typename LibObjT>
-ArrayValue CommonArrayValue<LibObjT>::appendEmptyArray()
+ArrayValue CommonArrayValue<LibObjT>::appendEmptyArray() const
 {
-    static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+    static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
     bt_value *libElemPtr;
-    const auto status = bt_value_array_append_empty_array_element(this->_libObjPtr(), &libElemPtr);
+    const auto status = bt_value_array_append_empty_array_element(this->libObjPtr(), &libElemPtr);
 
     this->_handleAppendLibStatus(status);
     return ArrayValue {libElemPtr};
 }
 
 template <typename LibObjT>
-MapValue CommonArrayValue<LibObjT>::appendEmptyMap()
+MapValue CommonArrayValue<LibObjT>::appendEmptyMap() const
 {
-    static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+    static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstArrayValue`.");
 
     bt_value *libElemPtr;
-    const auto status = bt_value_array_append_empty_map_element(this->_libObjPtr(), &libElemPtr);
+    const auto status = bt_value_array_append_empty_map_element(this->libObjPtr(), &libElemPtr);
 
     this->_handleAppendLibStatus(status);
     return MapValue {libElemPtr};
 }
 
 template <typename LibObjT>
-ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const char * const key)
+ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const bt2c::CStringView key) const
 {
-    static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+    static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
     bt_value *libEntryPtr;
-    const auto status =
-        bt_value_map_insert_empty_array_entry(this->_libObjPtr(), key, &libEntryPtr);
+    const auto status = bt_value_map_insert_empty_array_entry(this->libObjPtr(), key, &libEntryPtr);
 
     this->_handleInsertLibStatus(status);
     return ArrayValue {libEntryPtr};
 }
 
 template <typename LibObjT>
-ArrayValue CommonMapValue<LibObjT>::insertEmptyArray(const std::string& key)
+MapValue CommonMapValue<LibObjT>::insertEmptyMap(const bt2c::CStringView key) const
 {
-    return this->insertEmptyArray(key.data());
-}
-
-template <typename LibObjT>
-MapValue CommonMapValue<LibObjT>::insertEmptyMap(const char * const key)
-{
-    static_assert(!std::is_const<LibObjT>::value, "`LibObjT` must NOT be `const`.");
+    static_assert(!std::is_const<LibObjT>::value, "Not available with `bt2::ConstMapValue`.");
 
     bt_value *libEntryPtr;
-    const auto status = bt_value_map_insert_empty_map_entry(this->_libObjPtr(), key, &libEntryPtr);
+    const auto status = bt_value_map_insert_empty_map_entry(this->libObjPtr(), key, &libEntryPtr);
 
     this->_handleInsertLibStatus(status);
     return MapValue {libEntryPtr};
 }
 
-template <typename LibObjT>
-MapValue CommonMapValue<LibObjT>::insertEmptyMap(const std::string& key)
-{
-    return this->insertEmptyMap(key.data());
-}
-
 inline BoolValue::Shared createValue(const bool rawVal)
 {
     return BoolValue::create(rawVal);
@@ -1261,11 +1562,11 @@ inline StringValue::Shared createValue(const char * const rawVal)
     return StringValue::create(rawVal);
 }
 
-inline StringValue::Shared createValue(const std::string& rawVal)
+inline StringValue::Shared createValue(const bt2c::CStringView rawVal)
 {
     return StringValue::create(rawVal);
 }
 
-} // namespace bt2
+} /* namespace bt2 */
 
-#endif // BABELTRACE_CPP_COMMON_BT2_VALUE_HPP
+#endif /* BABELTRACE_CPP_COMMON_BT2_VALUE_HPP */
This page took 0.044834 seconds and 4 git commands to generate.