--- /dev/null
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright 2022-2024 Philippe Proulx <pproulx@efficios.com>
+ */
+
+#ifndef BABELTRACE_PLUGINS_CTF_COMMON_METADATA_CTF_IR_HPP
+#define BABELTRACE_PLUGINS_CTF_COMMON_METADATA_CTF_IR_HPP
+
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <utility>
+#include <vector>
+
+#include "common/assert.h"
+#include "cpp-common/bt2/clock-class.hpp"
+#include "cpp-common/bt2/field-class.hpp"
+#include "cpp-common/bt2/trace-ir.hpp"
+#include "cpp-common/bt2c/data-len.hpp"
+#include "cpp-common/bt2s/make-unique.hpp"
+#include "cpp-common/bt2s/optional.hpp"
+#include "cpp-common/vendor/wise-enum/wise_enum.h"
+
+#include "int-range-set.hpp"
+
+namespace ctf {
+namespace ir {
+
+/*
+ * This is the common CTF IR API, that is, the intermediate
+ * representation of CTF metadata objects for the whole `ctf` plugin.
+ *
+ * CLASS HIERARCHY
+ * ━━━━━━━━━━━━━━━
+ * The class hierarchy (omitting template parameters) is as such:
+ *
+ * TraceCls
+ * DataStreamCls
+ * EventRecordCls
+ * ClkCls
+ * FieldLoc
+ * StructFieldMemberCls
+ * VariantFcOpt
+ * Fc
+ * FixedLenBitArrayFc
+ * FixedLenBitMapFc
+ * FixedLenBoolFc
+ * FixedLenFloatFc
+ * FixedLenIntFc
+ * FixedLenUIntFc
+ * FixedLenSIntFc
+ * VarLengthIntFc
+ * VarLengthUIntFc
+ * VarLengthSIntFc
+ * StrFc
+ * NullTerminatedStrFc
+ * NonNullTerminatedStrFc
+ * StaticLenStrFc
+ * DynLenStrFc
+ * BlobFc
+ * StaticLenBlobFc
+ * DynLenBlobFc
+ * ArrayFc
+ * StaticLenArrayFc
+ * DynLenArrayFc
+ * StructFc
+ * OptionalFc
+ * OptionalWithBoolSelFc
+ * OptionalWithIntSelFc
+ * OptionalWithUIntSelFc
+ * OptionalWithSIntSelFc
+ * VariantFc
+ * VariantWithUIntSelFc
+ * VariantWithSIntSelFc
+ *
+ * The `FcVisitor` and `ConstFcVisitor` base classes are available to
+ * visit field classes through the virtual Fc::accept() methods.
+ *
+ * Each class template has the `UserMixinsT` template parameter.
+ *
+ * USER MIXINS
+ * ━━━━━━━━━━━
+ * `UserMixinsT` is expected to be a user mixin container, a type which
+ * defines the following nested types (user mixins):
+ *
+ * • `ClkCls`
+ * • `DataStreamCls`
+ * • `DynLenArrayFc`
+ * • `DynLenBlobFc`
+ * • `DynLenStrFc`
+ * • `EventRecordCls`
+ * • `Fc`
+ * • `FieldLoc`
+ * • `FixedLenBitArrayFc`
+ * • `FixedLenBitMapFc`
+ * • `FixedLenBoolFc`
+ * • `FixedLenIntFc`
+ * • `FixedLenUIntFc`
+ * • `OptionalFc`
+ * • `OptionalWithBoolSelFc`
+ * • `OptionalWithSIntSelFc`
+ * • `OptionalWithUIntSelFc`
+ * • `StaticLenArrayFc`
+ * • `StaticLenBlobFc`
+ * • `StaticLenStrFc`
+ * • `StructFc`
+ * • `StructFieldMemberCls`
+ * • `TraceCls`
+ * • `VariantFcOpt`
+ * • `VariantWithSIntSelFc`
+ * • `VariantWithUIntSelFc`
+ * • `VarLenIntFc`
+ * • `VarLenUIntFc`
+ *
+ * Most class templates inherit a given user mixin. For example,
+ * `FixedLenBoolFc` inherits `UserMixinsT::FixedLenBoolFc`. This makes
+ * it possible for the user to inject data and methods into the class
+ * while keeping the hierarchy and common features.
+ *
+ * A class template which inherits a user mixin M has a constructor
+ * which accepts an instance of M by value to initialize this part of
+ * the object.
+ *
+ * If a class template C which inherits a user mixin also inherits
+ * another class template inheriting another user mixin, then the
+ * constructor of C accepts both mixins. For example,
+ * FixedLenUIntFc::FixedLenUIntFc() accepts three mixins: field class,
+ * fixed-length bit array field class, and fixed-length integer
+ * field class.
+ *
+ * A mixin must be copy-constructible to make the Fc::clone()
+ * method work.
+ *
+ * The API offers `DefUserMixins` which defines empty user mixins to act
+ * as a base user mixin container structure.
+ *
+ * USAGE
+ * ━━━━━
+ * This is how you would use this API:
+ *
+ * • Define your own user mixin container structure which inherits
+ * `DefUserMixins`, defining the user mixins you need to add data and
+ * methods to specific common classes.
+ *
+ * • Define aliases for each `ctf::ir` type you need, using your user
+ * mixin container structure as the `UserMixinsT` template parameter
+ * when needed.
+ *
+ * • Create convenient object creation functions to construct specific
+ * CTF IR objects from parameters, hiding the internal user
+ * mixin details.
+ */
+
+template <typename UserMixinsT>
+class FixedLenBitArrayFc;
+
+template <typename UserMixinsT>
+class FixedLenBitMapFc;
+
+template <typename UserMixinsT>
+class FixedLenBoolFc;
+
+template <typename UserMixinsT>
+class FixedLenFloatFc;
+
+template <typename UserMixinsT>
+class FixedLenIntFc;
+
+template <typename UserMixinsT>
+class FixedLenUIntFc;
+
+template <typename UserMixinsT>
+class FixedLenSIntFc;
+
+template <typename UserMixinsT>
+class VarLenIntFc;
+
+template <typename UserMixinsT>
+class VarLenSIntFc;
+
+template <typename UserMixinsT>
+class VarLenUIntFc;
+
+template <typename UserMixinsT>
+class StrFc;
+
+template <typename UserMixinsT>
+class NullTerminatedStrFc;
+
+template <typename UserMixinsT>
+class NonNullTerminatedStrFc;
+
+template <typename UserMixinsT>
+class StaticLenStrFc;
+
+template <typename UserMixinsT>
+class DynLenStrFc;
+
+template <typename UserMixinsT>
+class BlobFc;
+
+template <typename UserMixinsT>
+class StaticLenBlobFc;
+
+template <typename UserMixinsT>
+class DynLenBlobFc;
+
+template <typename UserMixinsT>
+class ArrayFc;
+
+template <typename UserMixinsT>
+class StaticLenArrayFc;
+
+template <typename UserMixinsT>
+class DynLenArrayFc;
+
+template <typename UserMixinsT>
+class StructFc;
+
+template <typename UserMixinsT>
+class OptionalFc;
+
+template <typename UserMixinsT>
+class OptionalWithBoolSelFc;
+
+template <typename UserMixinsT>
+class OptionalWithUIntSelFc;
+
+template <typename UserMixinsT>
+class OptionalWithSIntSelFc;
+
+template <typename UserMixinsT>
+class VariantWithUIntSelFc;
+
+template <typename UserMixinsT>
+class VariantWithSIntSelFc;
+
+/*
+ * Visitor of `Fc<UserMixinsT>`.
+ *
+ * See `ConstFcVisitor` which visits `const Fc<UserMixinsT>`.
+ */
+template <typename UserMixinsT>
+class FcVisitor
+{
+protected:
+ explicit FcVisitor() = default;
+
+public:
+ virtual ~FcVisitor() = default;
+
+ virtual void visit(FixedLenBitArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(FixedLenBitMapFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(FixedLenBoolFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(FixedLenFloatFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(FixedLenUIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(FixedLenSIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(VarLenSIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(VarLenUIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(NullTerminatedStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(StaticLenStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(DynLenStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(StaticLenBlobFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(DynLenBlobFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(StaticLenArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(DynLenArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(StructFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(OptionalWithBoolSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(OptionalWithUIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(OptionalWithSIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(VariantWithUIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(VariantWithSIntSelFc<UserMixinsT>&)
+ {
+ }
+};
+
+/*
+ * Visitor of `const Fc<UserMixinsT>`.
+ *
+ * See `FcVisitor` which visits `Fc<UserMixinsT>`.
+ */
+template <typename UserMixinsT>
+class ConstFcVisitor
+{
+protected:
+ explicit ConstFcVisitor() = default;
+
+public:
+ virtual ~ConstFcVisitor() = default;
+
+ virtual void visit(const FixedLenBitArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const FixedLenBitMapFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const FixedLenBoolFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const FixedLenFloatFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const FixedLenUIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const FixedLenSIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const VarLenSIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const VarLenUIntFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const NullTerminatedStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const StaticLenStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const DynLenStrFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const StaticLenBlobFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const DynLenBlobFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const StaticLenArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const DynLenArrayFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const StructFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const OptionalWithBoolSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const OptionalWithUIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const OptionalWithSIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const VariantWithUIntSelFc<UserMixinsT>&)
+ {
+ }
+
+ virtual void visit(const VariantWithSIntSelFc<UserMixinsT>&)
+ {
+ }
+};
+
+namespace internal {
+
+/* clang-format off */
+
+/*
+ * To make the Fc<UserMixinsT>::isXyz() methods more efficient, `FcType`
+ * enumerators (below) are bitwise compositions of `FcTypeTraits` values
+ * (traits/features). The isXyz() methods only check if specific bits of
+ * the field class type are set.
+ */
+struct FcTypeTraits final
+{
+ enum {
+ FixedOrStaticLen = 1 << 0,
+ VarOrDynLen = 1 << 1,
+ BitArray = 1 << 2,
+ BitMap = 1 << 3,
+ Bool = 1 << 4,
+ Int = 1 << 5,
+ UInt = (1 << 6) | Int,
+ SInt = (1 << 7) | Int,
+ Float = 1 << 8,
+ Str = 1 << 9,
+ NullTerminated = 1 << 10,
+ NonNullTerminated = 1 << 11,
+ Blob = 1 << 12,
+ Array = 1 << 13,
+ Struct = 1 << 14,
+ BoolSel = 1 << 15,
+ IntSel = 1 << 16,
+ UIntSel = (1 << 17) | IntSel,
+ SIntSel = (1 << 18) | IntSel,
+ Optional = 1 << 19,
+ Variant = 1 << 20,
+ };
+};
+
+/* clang-format on */
+
+} /* namespace internal */
+
+/* clang-format off */
+
+/*
+ * Field class type.
+ */
+WISE_ENUM_CLASS(FcType,
+ (FixedLenBitArray, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray),
+
+ (FixedLenBitMap, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray |
+ internal::FcTypeTraits::BitMap),
+
+ (FixedLenBool, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray |
+ internal::FcTypeTraits::Bool),
+
+ (FixedLenUInt, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray |
+ internal::FcTypeTraits::UInt),
+
+ (FixedLenSInt, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray |
+ internal::FcTypeTraits::SInt),
+
+ (FixedLenFloat, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray |
+ internal::FcTypeTraits::Float),
+
+ (VarLenUInt, internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::UInt),
+
+ (VarLenSInt, internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::SInt),
+
+ (NullTerminatedStr, internal::FcTypeTraits::NullTerminated |
+ internal::FcTypeTraits::Str),
+
+ (StaticLenStr, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::NonNullTerminated |
+ internal::FcTypeTraits::Str),
+
+ (DynLenStr, internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::NonNullTerminated |
+ internal::FcTypeTraits::Str),
+
+ (StaticLenBlob, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::Blob),
+
+ (DynLenBlob, internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::Blob),
+
+ (StaticLenArray, internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::Array),
+
+ (DynLenArray, internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::Array),
+
+ (Struct, internal::FcTypeTraits::Struct),
+
+ (OptionalWithBoolSel, internal::FcTypeTraits::Optional |
+ internal::FcTypeTraits::BoolSel),
+
+ (OptionalWithUIntSel, internal::FcTypeTraits::Optional |
+ internal::FcTypeTraits::UIntSel),
+
+ (OptionalWithSIntSel, internal::FcTypeTraits::Optional |
+ internal::FcTypeTraits::SIntSel),
+
+ (VariantWithUIntSel, internal::FcTypeTraits::Variant |
+ internal::FcTypeTraits::UIntSel),
+
+ (VariantWithSIntSel, internal::FcTypeTraits::Variant |
+ internal::FcTypeTraits::SIntSel)
+)
+
+/* clang-format on */
+
+/*
+ * Optional attributes.
+ */
+using OptAttrs = bt2::ConstMapValue::Shared;
+
+namespace internal {
+
+/*
+ * Internal mixin for classes with an optional equivalent libbabeltrace2
+ * class.
+ */
+template <typename ClsT>
+class WithLibCls
+{
+public:
+ /*
+ * Equivalent libbabeltrace2 class (borrowed).
+ */
+ const bt2::OptionalBorrowedObject<ClsT> libCls() const noexcept
+ {
+ return _mLibCls;
+ }
+
+ /*
+ * Equivalent libbabeltrace2 class (borrowed).
+ */
+ bt2::OptionalBorrowedObject<ClsT> libCls() noexcept
+ {
+ return _mLibCls;
+ }
+
+ /*
+ * Sets the equivalent libbabeltrace2 class to `libCls` (borrowed).
+ */
+ void libCls(const ClsT libCls) noexcept
+ {
+ _mLibCls = libCls;
+ }
+
+private:
+ /* Equivalent libbabeltrace2 class (borrowed) */
+ bt2::OptionalBorrowedObject<ClsT> _mLibCls;
+};
+
+/*
+ * Internal mixin for classes with attributes.
+ */
+class WithAttrsMixin
+{
+protected:
+ explicit WithAttrsMixin(OptAttrs attrs) : _mAttrs {std::move(attrs)}
+ {
+ }
+
+public:
+ /*
+ * Attributes of this object.
+ */
+ const OptAttrs& attrs() const noexcept
+ {
+ return _mAttrs;
+ }
+
+protected:
+ /*
+ * Moves the attributes to the caller.
+ */
+ OptAttrs _takeAttrs() noexcept
+ {
+ return std::move(_mAttrs);
+ }
+
+private:
+ /* Attributes of this object */
+ OptAttrs _mAttrs;
+};
+
+} /* namespace internal */
+
+/*
+ * Field class base.
+ *
+ * Specific properties:
+ *
+ * • Alignment of instances.
+ * • Attributes.
+ */
+template <typename UserMixinsT>
+class Fc :
+ public internal::WithAttrsMixin,
+ public internal::WithLibCls<bt2::FieldClass>,
+ public UserMixinsT::Fc
+{
+public:
+ using Type = FcType;
+ using UP = std::unique_ptr<Fc>;
+
+protected:
+ explicit Fc(const FcType type, typename UserMixinsT::Fc mixin, const unsigned int align,
+ OptAttrs&& attrs) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::Fc {std::move(mixin)}, _mType {type}, _mAlign {align}
+ {
+ }
+
+public:
+ /* Disable copy/move operations to make this API simpler */
+ Fc(const Fc&) = delete;
+ Fc(Fc&&) = delete;
+ Fc& operator=(const Fc&) = delete;
+ Fc& operator=(Fc&&) = delete;
+
+ virtual ~Fc() = default;
+
+ Type type() const noexcept
+ {
+ return _mType;
+ }
+
+ /*
+ * Alignment (bits) of instances of this field class.
+ */
+ unsigned int align() const noexcept
+ {
+ return _mAlign;
+ }
+
+ /*
+ * Moves the attributes of this field class to the caller.
+ */
+ OptAttrs takeAttrs() noexcept
+ {
+ return this->_takeAttrs();
+ }
+
+ /*
+ * Clones this field class and returns the clone.
+ */
+ virtual UP clone() const = 0;
+
+ /*
+ * Accepts a visitor to visit this field class.
+ */
+ virtual void accept(FcVisitor<UserMixinsT>&) = 0;
+
+ /*
+ * Accepts a visitor to visit this constant field class.
+ */
+ virtual void accept(ConstFcVisitor<UserMixinsT>&) const = 0;
+
+ /* Casting methods below */
+ FixedLenBitArrayFc<UserMixinsT>& asFixedLenBitArray() noexcept;
+ const FixedLenBitArrayFc<UserMixinsT>& asFixedLenBitArray() const noexcept;
+ FixedLenBitMapFc<UserMixinsT>& asFixedLenBitMap() noexcept;
+ const FixedLenBitMapFc<UserMixinsT>& asFixedLenBitMap() const noexcept;
+ FixedLenBoolFc<UserMixinsT>& asFixedLenBool() noexcept;
+ const FixedLenBoolFc<UserMixinsT>& asFixedLenBool() const noexcept;
+ FixedLenFloatFc<UserMixinsT>& asFixedLenFloat() noexcept;
+ const FixedLenFloatFc<UserMixinsT>& asFixedLenFloat() const noexcept;
+ FixedLenIntFc<UserMixinsT>& asFixedLenInt() noexcept;
+ const FixedLenIntFc<UserMixinsT>& asFixedLenInt() const noexcept;
+ FixedLenSIntFc<UserMixinsT>& asFixedLenSInt() noexcept;
+ const FixedLenSIntFc<UserMixinsT>& asFixedLenSInt() const noexcept;
+ FixedLenUIntFc<UserMixinsT>& asFixedLenUInt() noexcept;
+ const FixedLenUIntFc<UserMixinsT>& asFixedLenUInt() const noexcept;
+ VarLenIntFc<UserMixinsT>& asVarLenInt() noexcept;
+ const VarLenIntFc<UserMixinsT>& asVarLenInt() const noexcept;
+ VarLenUIntFc<UserMixinsT>& asVarLenUInt() noexcept;
+ const VarLenUIntFc<UserMixinsT>& asVarLenUInt() const noexcept;
+ VarLenSIntFc<UserMixinsT>& asVarLenSInt() noexcept;
+ const VarLenSIntFc<UserMixinsT>& asVarLenSInt() const noexcept;
+ StrFc<UserMixinsT>& asStr() noexcept;
+ const StrFc<UserMixinsT>& asStr() const noexcept;
+ NullTerminatedStrFc<UserMixinsT>& asNullTerminatedStr() noexcept;
+ const NullTerminatedStrFc<UserMixinsT>& asNullTerminatedStr() const noexcept;
+ NonNullTerminatedStrFc<UserMixinsT>& asNonNullTerminatedStr() noexcept;
+ const NonNullTerminatedStrFc<UserMixinsT>& asNonNullTerminatedStr() const noexcept;
+ StaticLenStrFc<UserMixinsT>& asStaticLenStr() noexcept;
+ const StaticLenStrFc<UserMixinsT>& asStaticLenStr() const noexcept;
+ DynLenStrFc<UserMixinsT>& asDynLenStr() noexcept;
+ const DynLenStrFc<UserMixinsT>& asDynLenStr() const noexcept;
+ BlobFc<UserMixinsT>& asBlob() noexcept;
+ const BlobFc<UserMixinsT>& asBlob() const noexcept;
+ StaticLenBlobFc<UserMixinsT>& asStaticLenBlob() noexcept;
+ const StaticLenBlobFc<UserMixinsT>& asStaticLenBlob() const noexcept;
+ DynLenBlobFc<UserMixinsT>& asDynLenBlob() noexcept;
+ const DynLenBlobFc<UserMixinsT>& asDynLenBlob() const noexcept;
+ ArrayFc<UserMixinsT>& asArray() noexcept;
+ const ArrayFc<UserMixinsT>& asArray() const noexcept;
+ StaticLenArrayFc<UserMixinsT>& asStaticLenArray() noexcept;
+ const StaticLenArrayFc<UserMixinsT>& asStaticLenArray() const noexcept;
+ DynLenArrayFc<UserMixinsT>& asDynLenArray() noexcept;
+ const DynLenArrayFc<UserMixinsT>& asDynLenArray() const noexcept;
+ StructFc<UserMixinsT>& asStruct() noexcept;
+ const StructFc<UserMixinsT>& asStruct() const noexcept;
+ OptionalFc<UserMixinsT>& asOptional() noexcept;
+ const OptionalFc<UserMixinsT>& asOptional() const noexcept;
+ OptionalWithBoolSelFc<UserMixinsT>& asOptionalWithBoolSel() noexcept;
+ const OptionalWithBoolSelFc<UserMixinsT>& asOptionalWithBoolSel() const noexcept;
+ OptionalWithUIntSelFc<UserMixinsT>& asOptionalWithUIntSel() noexcept;
+ const OptionalWithUIntSelFc<UserMixinsT>& asOptionalWithUIntSel() const noexcept;
+ OptionalWithSIntSelFc<UserMixinsT>& asOptionalWithSIntSel() noexcept;
+ const OptionalWithSIntSelFc<UserMixinsT>& asOptionalWithSIntSel() const noexcept;
+ VariantWithUIntSelFc<UserMixinsT>& asVariantWithUIntSel() noexcept;
+ const VariantWithUIntSelFc<UserMixinsT>& asVariantWithUIntSel() const noexcept;
+ VariantWithSIntSelFc<UserMixinsT>& asVariantWithSIntSel() noexcept;
+ const VariantWithSIntSelFc<UserMixinsT>& asVariantWithSIntSel() const noexcept;
+
+ bool isFixedLenBitArray() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::BitArray);
+ }
+
+ bool isFixedLenBitMap() const noexcept
+ {
+ return _mType == Type::FixedLenBitMap;
+ }
+
+ bool isFixedLenBool() const noexcept
+ {
+ return _mType == Type::FixedLenBool;
+ }
+
+ bool isFixedLenFloat() const noexcept
+ {
+ return _mType == Type::FixedLenFloat;
+ }
+
+ bool isInt() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Int);
+ }
+
+ bool isUInt() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::UInt);
+ }
+
+ bool isSInt() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::SInt);
+ }
+
+ bool isFixedLenInt() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::FixedOrStaticLen |
+ internal::FcTypeTraits::Int);
+ }
+
+ bool isFixedLenUInt() const noexcept
+ {
+ return _mType == Type::FixedLenUInt;
+ }
+
+ bool isFixedLenSInt() const noexcept
+ {
+ return _mType == Type::FixedLenSInt;
+ }
+
+ bool isVarLenInt() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::VarOrDynLen |
+ internal::FcTypeTraits::Int);
+ }
+
+ bool isVarLenUInt() const noexcept
+ {
+ return _mType == Type::VarLenUInt;
+ }
+
+ bool isVarLenSInt() const noexcept
+ {
+ return _mType == Type::VarLenSInt;
+ }
+
+ bool isStr() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Str);
+ }
+
+ bool isNullTerminatedStr() const noexcept
+ {
+ return _mType == Type::NullTerminatedStr;
+ }
+
+ bool isNonNullTerminatedStr() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::NonNullTerminated);
+ }
+
+ bool isStaticLenStr() const noexcept
+ {
+ return _mType == Type::StaticLenStr;
+ }
+
+ bool isDynLenStr() const noexcept
+ {
+ return _mType == Type::DynLenStr;
+ }
+
+ bool isBlob() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Blob);
+ }
+
+ bool isStaticLenBlob() const noexcept
+ {
+ return _mType == Type::StaticLenBlob;
+ }
+
+ bool isDynLenBlob() const noexcept
+ {
+ return _mType == Type::DynLenBlob;
+ }
+
+ bool isArray() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Array);
+ }
+
+ bool isStaticLenArray() const noexcept
+ {
+ return _mType == Type::StaticLenArray;
+ }
+
+ bool isDynLenArray() const noexcept
+ {
+ return _mType == Type::DynLenArray;
+ }
+
+ bool isStruct() const noexcept
+ {
+ return _mType == Type::Struct;
+ }
+
+ bool isOptional() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Optional);
+ }
+
+ bool isOptionalWithBoolSel() const noexcept
+ {
+ return _mType == Type::OptionalWithBoolSel;
+ }
+
+ bool isOptionalWithIntSel() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Optional |
+ internal::FcTypeTraits::IntSel);
+ }
+
+ bool isOptionalWithUIntSel() const noexcept
+ {
+ return _mType == Type::OptionalWithUIntSel;
+ }
+
+ bool isOptionalWithSIntSel() const noexcept
+ {
+ return _mType == Type::OptionalWithSIntSel;
+ }
+
+ bool isVariant() const noexcept
+ {
+ return this->_hasTypeTrait(internal::FcTypeTraits::Variant);
+ }
+
+ bool isVariantWithUIntSel() const noexcept
+ {
+ return _mType == Type::VariantWithUIntSel;
+ }
+
+ bool isVariantWithSIntSel() const noexcept
+ {
+ return _mType == Type::VariantWithSIntSel;
+ }
+
+private:
+ /*
+ * Returns whether or not this field class has the type trait
+ * `typeTrait` (one or more bitwise-OR combined `FcTypeTraits`
+ * enumerators).
+ */
+ bool _hasTypeTrait(const int typeTrait) const noexcept
+ {
+ return (static_cast<int>(_mType) & typeTrait) == typeTrait;
+ }
+
+ /* Type of this field class */
+ Type _mType;
+
+ /* Alignment (bits) of instances of this field class */
+ unsigned int _mAlign;
+};
+
+/* clang-format off */
+
+/*
+ * Byte order.
+ */
+WISE_ENUM_CLASS(ByteOrder,
+ /* Big-endian */
+ Big,
+
+ /* Little-endian */
+ Little
+)
+
+/*
+ * Bit order.
+ */
+WISE_ENUM_CLASS(BitOrder,
+ /* First to last */
+ FirstToLast,
+
+ /* Last to first */
+ LastToFirst
+)
+
+/* clang-format on */
+
+/*
+ * Fixed-length bit array field class.
+ *
+ * Specific properties over `Fc<UserMixinsT>`:
+ *
+ * • Length of instances.
+ * • Byte order of instances.
+ * • Bit order of instances.
+ */
+template <typename UserMixinsT>
+class FixedLenBitArrayFc : public Fc<UserMixinsT>, public UserMixinsT::FixedLenBitArrayFc
+{
+protected:
+ explicit FixedLenBitArrayFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc mixin,
+ const unsigned int align, const bt2c::DataLen len,
+ const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder,
+ OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), align, std::move(attrs)},
+ UserMixinsT::FixedLenBitArrayFc(std::move(mixin)), _mLen {len}, _mByteOrder {byteOrder},
+ _mBitOrder {bitOrder ? *bitOrder :
+ (byteOrder == ByteOrder::Big ? BitOrder::LastToFirst :
+ BitOrder::FirstToLast)}
+ {
+ using namespace bt2c::literals::datalen;
+
+ BT_ASSERT(len > 0_bits && len <= 64_bits);
+ BT_ASSERT(align > 0);
+ }
+
+public:
+ explicit FixedLenBitArrayFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc mixin,
+ const unsigned int align, const bt2c::DataLen len,
+ const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ OptAttrs attrs = OptAttrs {}) :
+ FixedLenBitArrayFc {FcType::FixedLenBitArray,
+ std::move(fcMixin),
+ std::move(mixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ std::move(attrs)}
+ {
+ }
+
+ /*
+ * Length of instances of this field class.
+ */
+ const bt2c::DataLen len() const noexcept
+ {
+ return _mLen;
+ }
+
+ /*
+ * Byte order of instances of this field class.
+ */
+ ByteOrder byteOrder() const noexcept
+ {
+ return _mByteOrder;
+ }
+
+ /*
+ * Bit order of instances of this field class.
+ */
+ BitOrder bitOrder() const noexcept
+ {
+ return _mBitOrder;
+ }
+
+ /*
+ * Returns whether or not the bits of instances of a fixed-length
+ * bit array field class having the byte order `byteOrder` and the
+ * bit order `bitOrder` (deduced from `byteOrder` if
+ * `bt2s::nullopt`) are reversed, that is, in an unnatural way.
+ */
+ static bool isRev(const ByteOrder byteOrder, const bt2s::optional<BitOrder>& bitOrder) noexcept
+ {
+ if (!bitOrder) {
+ return false;
+ }
+
+ return (byteOrder == ByteOrder::Big && *bitOrder == BitOrder::FirstToLast) ||
+ (byteOrder == ByteOrder::Little && *bitOrder == BitOrder::LastToFirst);
+ }
+
+ /*
+ * Like isRev() above, but using the properties of this field class.
+ */
+ bool isRev() const noexcept
+ {
+ return FixedLenBitArrayFc::isRev(_mByteOrder, _mBitOrder);
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenBitArrayFc>(*this, *this, this->align(), _mLen,
+ _mByteOrder, _mBitOrder, this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+
+private:
+ /* Length of instances of this field class */
+ bt2c::DataLen _mLen;
+
+ /* Byte order of instances of this field class */
+ ByteOrder _mByteOrder;
+
+ /* Bit order of instances of this field class */
+ BitOrder _mBitOrder;
+};
+
+/*
+ * Fixed-length bit map field class.
+ *
+ * Specific property over `FixedLenBitArrayFc<UserMixinsT>`:
+ *
+ * • Flags of instances.
+ */
+template <typename UserMixinsT>
+class FixedLenBitMapFc final :
+ public FixedLenBitArrayFc<UserMixinsT>,
+ public UserMixinsT::FixedLenBitMapFc
+{
+public:
+ using Flags = std::unordered_map<std::string, UIntRangeSet>;
+
+ explicit FixedLenBitMapFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ typename UserMixinsT::FixedLenBitMapFc mixin,
+ const unsigned int align, const bt2c::DataLen len,
+ const ByteOrder byteOrder, Flags flags,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ OptAttrs attrs = OptAttrs {}) :
+ FixedLenBitArrayFc<UserMixinsT> {FcType::FixedLenBitMap,
+ std::move(fcMixin),
+ std::move(fixedLenBitArrayFcMixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ std::move(attrs)},
+ UserMixinsT::FixedLenBitMapFc(std::move(mixin)), _mFlags {std::move(flags)}
+ {
+ BT_ASSERT(!_mFlags.empty());
+ }
+
+ /*
+ * Flags of this fixed-length bit map field class.
+ */
+ const Flags& flags() const noexcept
+ {
+ return _mFlags;
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenBitMapFc>(*this, *this, *this, this->align(), this->len(),
+ this->byteOrder(), _mFlags, this->bitOrder(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+
+private:
+ Flags _mFlags;
+};
+
+/*
+ * Fixed-length boolean field class.
+ */
+template <typename UserMixinsT>
+class FixedLenBoolFc final :
+ public FixedLenBitArrayFc<UserMixinsT>,
+ public UserMixinsT::FixedLenBoolFc
+{
+public:
+ explicit FixedLenBoolFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ typename UserMixinsT::FixedLenBoolFc mixin, const unsigned int align,
+ const bt2c::DataLen len, const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ OptAttrs attrs = OptAttrs {}) :
+ FixedLenBitArrayFc<UserMixinsT> {FcType::FixedLenBool,
+ std::move(fcMixin),
+ std::move(fixedLenBitArrayFcMixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ std::move(attrs)},
+ UserMixinsT::FixedLenBoolFc {std::move(mixin)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenBoolFc>(*this, *this, *this, this->align(), this->len(),
+ this->byteOrder(), this->bitOrder(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Fixed-length floating-point number field class.
+ */
+template <typename UserMixinsT>
+class FixedLenFloatFc final : public FixedLenBitArrayFc<UserMixinsT>
+{
+public:
+ explicit FixedLenFloatFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ const unsigned int align, const bt2c::DataLen len,
+ const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ OptAttrs attrs = OptAttrs {}) :
+ FixedLenBitArrayFc<UserMixinsT> {FcType::FixedLenFloat,
+ std::move(fcMixin),
+ std::move(fixedLenBitArrayFcMixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ std::move(attrs)}
+ {
+ using namespace bt2c::literals::datalen;
+
+ BT_ASSERT(len == 32_bits || len == 64_bits);
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenFloatFc>(*this, *this, this->align(), this->len(),
+ this->byteOrder(), this->bitOrder(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/* clang-format off */
+
+/*
+ * Display base.
+ */
+WISE_ENUM_CLASS(DispBase,
+ /* Binary */
+ (Bin, 2),
+
+ /* Octal */
+ (Oct, 8),
+
+ /* Decimal */
+ (Dec, 10),
+
+ /* Hexadecimal */
+ (Hex, 16)
+)
+
+/* clang-format on */
+
+namespace internal {
+
+/*
+ * Internal mixin for integer field classes with a preferred display
+ * base.
+ */
+class WithPrefDispBaseMixin
+{
+protected:
+ explicit WithPrefDispBaseMixin(const DispBase prefDispBase) : _mPrefDispBase {prefDispBase}
+ {
+ }
+
+public:
+ /*
+ * Preferred display base of instances of this field class.
+ */
+ DispBase prefDispBase() const noexcept
+ {
+ return _mPrefDispBase;
+ }
+
+private:
+ /* Preferred display base of instances of this field class */
+ DispBase _mPrefDispBase;
+};
+
+/*
+ * Internal mixin for integer field classes with mappings.
+ */
+template <typename MappingRangeSetT>
+class WithMappingsMixin
+{
+public:
+ using Mappings = std::unordered_map<std::string, MappingRangeSetT>;
+ using Val = typename MappingRangeSetT::Val;
+
+protected:
+ explicit WithMappingsMixin(Mappings&& mappings) : _mMappings {std::move(mappings)}
+ {
+ }
+
+public:
+ /*
+ * Mappings of instances of this integer field class.
+ */
+ const Mappings& mappings() const noexcept
+ {
+ return _mMappings;
+ }
+
+private:
+ /* Mappings of instances of this integer field class */
+ Mappings _mMappings;
+};
+
+} /* namespace internal */
+
+/*
+ * Fixed-length integer field class base.
+ *
+ * Specific property over `FixedLenBitArrayFc<UserMixinsT>`:
+ *
+ * • Preferred display base of instances.
+ */
+template <typename UserMixinsT>
+class FixedLenIntFc :
+ public FixedLenBitArrayFc<UserMixinsT>,
+ public internal::WithPrefDispBaseMixin,
+ public UserMixinsT::FixedLenIntFc
+{
+protected:
+ explicit FixedLenIntFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ typename UserMixinsT::FixedLenIntFc mixin, const unsigned int align,
+ const bt2c::DataLen len, const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder, const DispBase prefDispBase,
+ OptAttrs&& attrs) :
+ FixedLenBitArrayFc<UserMixinsT> {
+ type, std::move(fcMixin), std::move(fixedLenBitArrayFcMixin), align, len, byteOrder,
+ bitOrder, std::move(attrs)},
+ internal::WithPrefDispBaseMixin {prefDispBase},
+ UserMixinsT::FixedLenIntFc {std::move(mixin)}
+ {
+ }
+};
+
+/* clang-format off */
+
+/*
+ * Unsigned integer field role.
+ */
+WISE_ENUM_CLASS(UIntFieldRole,
+ /* Packet magic number */
+ (PktMagicNumber, 1 << 1),
+
+ /* Data stream class ID */
+ (DataStreamClsId, 1 << 2),
+
+ /* Data stream ID */
+ (DataStreamId, 1 << 3),
+
+ /* Total length of packet */
+ (PktTotalLen, 1 << 4),
+
+ /* Content length of packet */
+ (PktContentLen, 1 << 5),
+
+ /* Default clock timestamp */
+ (DefClkTs, 1 << 6),
+
+ /* Default clock timestamp at end of packet */
+ (PktEndDefClkTs, 1 << 7),
+
+ /* Discarded event record counter snapshot */
+ (DiscEventRecordCounterSnap, 1 << 8),
+
+ /* Packet sequence number */
+ (PktSeqNum, 1 << 9),
+
+ /* Event record class ID */
+ (EventRecordClsId, 1 << 10)
+)
+
+/* clang-format on */
+
+/*
+ * Set of unsigned integer field roles.
+ */
+using UIntFieldRoles = std::set<UIntFieldRole>;
+
+namespace internal {
+
+/*
+ * Internal mixin for unsigned integer field class classes.
+ */
+class UIntFcMixin
+{
+protected:
+ explicit UIntFcMixin(UIntFieldRoles roles) : _mRoles {std::move(roles)}
+ {
+ }
+
+public:
+ /*
+ * Roles of instances of this unsigned integer field class.
+ */
+ const UIntFieldRoles& roles() const noexcept
+ {
+ return _mRoles;
+ }
+
+ /*
+ * Returns whether or not the instances of this field class have the
+ * role `role`.
+ */
+ bool hasRole(const UIntFieldRole role) const noexcept
+ {
+ return _mRoles.count(role) == 1;
+ }
+
+private:
+ /* Roles of instances of this unsigned integer field class */
+ UIntFieldRoles _mRoles;
+};
+
+} /* namespace internal */
+
+/*
+ * Fixed-length unsigned integer field class.
+ *
+ * Specific properties over `FixedLenIntFc<UserMixinsT>`:
+ *
+ * • Mappings.
+ * • Roles of instances.
+ */
+template <typename UserMixinsT>
+class FixedLenUIntFc final :
+ public FixedLenIntFc<UserMixinsT>,
+ public internal::WithMappingsMixin<UIntRangeSet>,
+ public internal::UIntFcMixin,
+ public UserMixinsT::FixedLenUIntFc
+{
+public:
+ using typename internal::WithMappingsMixin<UIntRangeSet>::Mappings;
+
+ explicit FixedLenUIntFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ typename UserMixinsT::FixedLenIntFc fixedLenIntFcMixin,
+ typename UserMixinsT::FixedLenUIntFc mixin, const unsigned int align,
+ const bt2c::DataLen len, const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ const DispBase prefDispBase = DispBase::Dec, Mappings mappings = {},
+ UIntFieldRoles roles = {}, OptAttrs attrs = OptAttrs {}) :
+ FixedLenIntFc<UserMixinsT> {FcType::FixedLenUInt,
+ std::move(fcMixin),
+ std::move(fixedLenBitArrayFcMixin),
+ std::move(fixedLenIntFcMixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ prefDispBase,
+ std::move(attrs)},
+ internal::WithMappingsMixin<UIntRangeSet> {std::move(mappings)},
+ internal::UIntFcMixin {std::move(roles)}, UserMixinsT::FixedLenUIntFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenUIntFc>(
+ *this, *this, *this, *this, this->align(), this->len(), this->byteOrder(),
+ this->bitOrder(), this->prefDispBase(), this->mappings(), this->roles(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Fixed-length signed integer field class.
+ *
+ * Specific property over `FixedLenIntFc<UserMixinsT>`:
+ *
+ * • Mappings.
+ */
+template <typename UserMixinsT>
+class FixedLenSIntFc final :
+ public FixedLenIntFc<UserMixinsT>,
+ public internal::WithMappingsMixin<SIntRangeSet>
+{
+public:
+ using typename internal::WithMappingsMixin<SIntRangeSet>::Mappings;
+
+ explicit FixedLenSIntFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::FixedLenBitArrayFc fixedLenBitArrayFcMixin,
+ typename UserMixinsT::FixedLenIntFc fixedLenIntFcMixin,
+ const unsigned int align, const bt2c::DataLen len,
+ const ByteOrder byteOrder,
+ const bt2s::optional<BitOrder>& bitOrder = bt2s::nullopt,
+ const DispBase prefDispBase = DispBase::Dec, Mappings mappings = {},
+ OptAttrs attrs = OptAttrs {}) :
+ FixedLenIntFc<UserMixinsT> {FcType::FixedLenSInt,
+ std::move(fcMixin),
+ std::move(fixedLenBitArrayFcMixin),
+ std::move(fixedLenIntFcMixin),
+ align,
+ len,
+ byteOrder,
+ bitOrder,
+ prefDispBase,
+ std::move(attrs)},
+ internal::WithMappingsMixin<SIntRangeSet> {std::move(mappings)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<FixedLenSIntFc>(
+ *this, *this, *this, this->align(), this->len(), this->byteOrder(), this->bitOrder(),
+ this->prefDispBase(), this->mappings(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Variable-length integer field class base.
+ */
+template <typename UserMixinsT>
+class VarLenIntFc :
+ public Fc<UserMixinsT>,
+ public internal::WithPrefDispBaseMixin,
+ public UserMixinsT::VarLenIntFc
+{
+protected:
+ explicit VarLenIntFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VarLenIntFc mixin, const DispBase prefDispBase,
+ OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), 8, std::move(attrs)},
+ internal::WithPrefDispBaseMixin {prefDispBase}, UserMixinsT::VarLenIntFc {std::move(mixin)}
+ {
+ }
+};
+
+/*
+ * Variable-length unsigned integer field class.
+ *
+ * Specific properties over `VarLenIntFc<UserMixinsT>`:
+ *
+ * • Mappings.
+ * • Roles of instances.
+ */
+template <typename UserMixinsT>
+class VarLenUIntFc final :
+ public VarLenIntFc<UserMixinsT>,
+ public internal::WithMappingsMixin<UIntRangeSet>,
+ public internal::UIntFcMixin,
+ public UserMixinsT::VarLenUIntFc
+{
+public:
+ using typename internal::WithMappingsMixin<UIntRangeSet>::Mappings;
+
+ explicit VarLenUIntFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VarLenIntFc varLenIntFcMixin,
+ typename UserMixinsT::VarLenUIntFc mixin, const DispBase prefDispBase,
+ Mappings mappings = {}, UIntFieldRoles roles = {},
+ OptAttrs attrs = OptAttrs {}) :
+ VarLenIntFc<UserMixinsT> {FcType::VarLenUInt, std::move(fcMixin),
+ std::move(varLenIntFcMixin), prefDispBase, std::move(attrs)},
+ internal::WithMappingsMixin<UIntRangeSet> {std::move(mappings)},
+ internal::UIntFcMixin {std::move(roles)}, UserMixinsT::VarLenUIntFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<VarLenUIntFc>(*this, *this, *this, this->prefDispBase(),
+ this->mappings(), this->roles(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Variable-length signed integer field class.
+ *
+ * Specific property over `VarLenIntFc<UserMixinsT>`:
+ *
+ * • Mappings.
+ */
+template <typename UserMixinsT>
+class VarLenSIntFc final :
+ public VarLenIntFc<UserMixinsT>,
+ public internal::WithMappingsMixin<SIntRangeSet>
+{
+public:
+ using typename internal::WithMappingsMixin<SIntRangeSet>::Mappings;
+
+ explicit VarLenSIntFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VarLenIntFc varLenIntFcMixin,
+ const DispBase prefDispBase, Mappings mappings = {},
+ OptAttrs attrs = OptAttrs {}) :
+ VarLenIntFc<UserMixinsT> {FcType::VarLenSInt, std::move(fcMixin),
+ std::move(varLenIntFcMixin), prefDispBase, std::move(attrs)},
+ internal::WithMappingsMixin<SIntRangeSet> {std::move(mappings)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<VarLenSIntFc>(*this, *this, this->prefDispBase(), this->mappings(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/* clang-format off */
+
+/*
+ * String encoding.
+ */
+WISE_ENUM_CLASS(StrEncoding,
+ /* UTF-8 */
+ Utf8,
+
+ /* UTF-16BE */
+ Utf16Be,
+
+ /* UTF-16LE */
+ Utf16Le,
+
+ /* UTF-32BE */
+ Utf32Be,
+
+ /* UTF-32LE */
+ Utf32Le
+)
+
+/* clang-format on */
+
+/*
+ * String field class base.
+ *
+ * Specific property over `Fc<UserMixinsT>`:
+ *
+ * • Encoding of instances.
+ */
+template <typename UserMixinsT>
+class StrFc : public Fc<UserMixinsT>
+{
+protected:
+ explicit StrFc(const FcType type, typename UserMixinsT::Fc fcMixin, const StrEncoding encoding,
+ OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), 8, std::move(attrs)},
+ _mEncoding {encoding}
+ {
+ }
+
+public:
+ /*
+ * Encoding of instances of this string field class.
+ */
+ StrEncoding encoding() const noexcept
+ {
+ return _mEncoding;
+ }
+
+private:
+ /* Encoding of instances of this string field class */
+ StrEncoding _mEncoding;
+};
+
+/*
+ * Null-terminated string field class.
+ */
+template <typename UserMixinsT>
+class NullTerminatedStrFc final : public StrFc<UserMixinsT>
+{
+public:
+ explicit NullTerminatedStrFc(typename UserMixinsT::Fc fcMixin,
+ const StrEncoding encoding = StrEncoding::Utf8,
+ OptAttrs attrs = OptAttrs {}) :
+ StrFc<UserMixinsT> {FcType::NullTerminatedStr, std::move(fcMixin), encoding,
+ std::move(attrs)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<NullTerminatedStrFc>(*this, this->encoding(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/* clang-format off */
+
+/*
+ * Scope.
+ */
+WISE_ENUM_CLASS(Scope,
+ /* Packet header */
+ PktHeader,
+
+ /* Packet context */
+ PktCtx,
+
+ /* Event record header */
+ EventRecordHeader,
+
+ /* Common event record context */
+ CommonEventRecordCtx,
+
+ /* Specific event record context */
+ SpecEventRecordCtx,
+
+ /* Event record payload */
+ EventRecordPayload
+)
+
+/* clang-format on */
+
+/*
+ * Field location.
+ *
+ * A field location may be:
+ *
+ * Absolute:
+ * Has an origin and no `bt2s::nullopt` items.
+ *
+ * Relative:
+ * Has no origin and may contain `bt2s::nullopt` items.
+ *
+ * A `bt2s::nullopt` item means "go to parent structure field"
+ * (CTF 2 strategy).
+ */
+template <typename UserMixinsT>
+class FieldLoc final : public UserMixinsT::FieldLoc
+{
+public:
+ using Items = std::vector<bt2s::optional<std::string>>;
+
+ explicit FieldLoc(typename UserMixinsT::FieldLoc mixin, bt2s::optional<Scope> origin,
+ Items items) :
+ UserMixinsT::FieldLoc {std::move(mixin)},
+ _mOrigin {std::move(origin)}, _mItems {std::move(items)}
+ {
+ }
+
+ /*
+ * Origin of this field location, or `bt2s::nullopt` if it's a
+ * relative field location.
+ */
+ const bt2s::optional<Scope>& origin() const noexcept
+ {
+ return _mOrigin;
+ }
+
+ /*
+ * Path item of this field location.
+ */
+ const Items& items() const noexcept
+ {
+ return _mItems;
+ }
+
+ Items::const_reference operator[](const Items::size_type index) const noexcept
+ {
+ return _mItems[index];
+ }
+
+ Items::size_type size() const noexcept
+ {
+ return _mItems.size();
+ }
+
+ Items::const_iterator begin() const noexcept
+ {
+ return _mItems.begin();
+ }
+
+ Items::const_iterator end() const noexcept
+ {
+ return _mItems.end();
+ }
+
+private:
+ /* Origin of this field location */
+ bt2s::optional<Scope> _mOrigin;
+
+ /* Path items of this field location */
+ Items _mItems;
+};
+
+namespace internal {
+
+/*
+ * Internal mixin for static-length field class classes.
+ */
+class StaticLenFcMixin
+{
+protected:
+ explicit StaticLenFcMixin(const std::size_t len) : _mLen {len}
+ {
+ }
+
+public:
+ /*
+ * Length (bytes or elements) of instances of this field class.
+ */
+ std::size_t len() const noexcept
+ {
+ return _mLen;
+ }
+
+private:
+ /* Length of instances of this field class */
+ std::size_t _mLen;
+};
+
+/*
+ * Internal mixin for dynamic-length field class classes.
+ */
+template <typename UserMixinsT>
+class DynLenFcMixin
+{
+protected:
+ explicit DynLenFcMixin(FieldLoc<UserMixinsT> lenFieldLoc) :
+ _mLenFieldLoc {std::move(lenFieldLoc)}
+ {
+ }
+
+public:
+ /*
+ * Length field location of instances of this field class.
+ */
+ const FieldLoc<UserMixinsT>& lenFieldLoc() const noexcept
+ {
+ return _mLenFieldLoc;
+ }
+
+ /*
+ * Sets the length field location of instances of this field class
+ * to `loc`.
+ */
+ void lenFieldLoc(FieldLoc<UserMixinsT> loc) noexcept
+ {
+ _mLenFieldLoc = std::move(loc);
+ }
+
+private:
+ /* Length field location of instances of this field class */
+ FieldLoc<UserMixinsT> _mLenFieldLoc;
+};
+
+} /* namespace internal */
+
+/*
+ * Non-null-terminated string field class base.
+ */
+template <typename UserMixinsT>
+class NonNullTerminatedStrFc : public StrFc<UserMixinsT>
+{
+protected:
+ explicit NonNullTerminatedStrFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ const StrEncoding strEncoding, OptAttrs&& attrs) :
+ StrFc<UserMixinsT> {type, std::move(fcMixin), strEncoding, std::move(attrs)}
+ {
+ }
+};
+
+/*
+ * Static-length string field class.
+ *
+ * Specific property over `NonNullTerminatedStrFc<UserMixinsT>`:
+ *
+ * • Length (number of bytes) of instances.
+ */
+template <typename UserMixinsT>
+class StaticLenStrFc final :
+ public NonNullTerminatedStrFc<UserMixinsT>,
+ public internal::StaticLenFcMixin,
+ public UserMixinsT::StaticLenStrFc
+{
+public:
+ explicit StaticLenStrFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::StaticLenStrFc mixin, const std::size_t len,
+ const StrEncoding encoding = StrEncoding::Utf8,
+ OptAttrs attrs = OptAttrs {}) :
+ NonNullTerminatedStrFc<UserMixinsT> {FcType::StaticLenStr, std::move(fcMixin), encoding,
+ std::move(attrs)},
+ internal::StaticLenFcMixin {len}, UserMixinsT::StaticLenStrFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<StaticLenStrFc>(*this, *this, this->len(), this->encoding(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Dynamic-length string field class.
+ *
+ * Specific property over `NonNullTerminatedStrFc<UserMixinsT>`:
+ *
+ * • Length field location of instances.
+ */
+template <typename UserMixinsT>
+class DynLenStrFc final :
+ public NonNullTerminatedStrFc<UserMixinsT>,
+ public internal::DynLenFcMixin<UserMixinsT>,
+ public UserMixinsT::DynLenStrFc
+{
+public:
+ explicit DynLenStrFc(typename UserMixinsT::Fc fcMixin, typename UserMixinsT::DynLenStrFc mixin,
+ FieldLoc<UserMixinsT> lenFieldLoc,
+ const StrEncoding encoding = StrEncoding::Utf8,
+ OptAttrs attrs = OptAttrs {}) :
+ NonNullTerminatedStrFc<UserMixinsT> {FcType::DynLenStr, std::move(fcMixin), encoding,
+ std::move(attrs)},
+ internal::DynLenFcMixin<UserMixinsT> {std::move(lenFieldLoc)},
+ UserMixinsT::DynLenStrFc {std::move(mixin)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<DynLenStrFc>(*this, *this, this->lenFieldLoc(), this->encoding(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+extern const char * const defaultBlobMediaType;
+
+/*
+ * BLOB field class base.
+ *
+ * Specific property over `Fc<UserMixinsT>`:
+ *
+ * • Media type of instances.
+ */
+template <typename UserMixinsT>
+class BlobFc : public Fc<UserMixinsT>
+{
+protected:
+ explicit BlobFc(const FcType type, typename UserMixinsT::Fc fcMixin, std::string&& mediaType,
+ OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), 8, std::move(attrs)},
+ _mMediaType {std::move(mediaType)}
+ {
+ }
+
+public:
+ /*
+ * Media type of instances of this field class.
+ */
+ const std::string& mediaType() const noexcept
+ {
+ return _mMediaType;
+ }
+
+private:
+ /* Media type of instances of this field class */
+ std::string _mMediaType;
+};
+
+/*
+ * Static-length BLOB field class.
+ *
+ * Specific properties over `BlobFc<UserMixinsT>`:
+ *
+ * • Length (number of bytes) of instances.
+ *
+ * • Whether or not instances have the "metadata stream UUID" role.
+ */
+template <typename UserMixinsT>
+class StaticLenBlobFc final :
+ public BlobFc<UserMixinsT>,
+ public internal::StaticLenFcMixin,
+ public UserMixinsT::StaticLenBlobFc
+{
+public:
+ explicit StaticLenBlobFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::StaticLenBlobFc mixin, const std::size_t len,
+ std::string mediaType = defaultBlobMediaType,
+ const bool hasMetadataStreamUuidRole = false,
+ OptAttrs attrs = OptAttrs {}) :
+ BlobFc<UserMixinsT> {FcType::StaticLenBlob, std::move(fcMixin), std::move(mediaType),
+ std::move(attrs)},
+ internal::StaticLenFcMixin {len}, UserMixinsT::StaticLenBlobFc(std::move(mixin)),
+ _mHasMetadataStreamUuidRole {hasMetadataStreamUuidRole}
+ {
+ }
+
+ bool hasMetadataStreamUuidRole() const noexcept
+ {
+ return _mHasMetadataStreamUuidRole;
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<StaticLenBlobFc>(*this, *this, this->len(), this->mediaType(),
+ _mHasMetadataStreamUuidRole, this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+
+private:
+ bool _mHasMetadataStreamUuidRole;
+};
+
+/*
+ * Dynamic-length BLOB field class.
+ *
+ * Specific property over `BlobFc<UserMixinsT>`:
+ *
+ * • Length field location of instances.
+ */
+template <typename UserMixinsT>
+class DynLenBlobFc final :
+ public BlobFc<UserMixinsT>,
+ public internal::DynLenFcMixin<UserMixinsT>,
+ public UserMixinsT::DynLenBlobFc
+{
+public:
+ explicit DynLenBlobFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::DynLenBlobFc mixin,
+ FieldLoc<UserMixinsT> lenFieldLoc,
+ std::string mediaType = defaultBlobMediaType,
+ OptAttrs attrs = OptAttrs {}) :
+ BlobFc<UserMixinsT> {FcType::DynLenBlob, std::move(fcMixin), std::move(mediaType),
+ std::move(attrs)},
+ internal::DynLenFcMixin<UserMixinsT> {std::move(lenFieldLoc)},
+ UserMixinsT::DynLenBlobFc {std::move(mixin)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<DynLenBlobFc>(*this, *this, this->lenFieldLoc(), this->mediaType(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Array field class base.
+ *
+ * Specific properties over `Fc<UserMixinsT>`:
+ *
+ * • Class of element fields.
+ * • Minimum alignment of instances.
+ */
+template <typename UserMixinsT>
+class ArrayFc : public Fc<UserMixinsT>
+{
+protected:
+ explicit ArrayFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename Fc<UserMixinsT>::UP&& elemFc, const unsigned int minAlign,
+ OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), ArrayFc::_effectiveAlign(*elemFc, minAlign),
+ std::move(attrs)},
+ _mElemFc {std::move(elemFc)}, _mMinAlign {minAlign}
+ {
+ BT_ASSERT(_mElemFc);
+ }
+
+public:
+ /*
+ * Class of the element fields of instances of this field class.
+ */
+ const Fc<UserMixinsT>& elemFc() const noexcept
+ {
+ return *_mElemFc;
+ }
+
+ /*
+ * Class of the element fields of instances of this field class.
+ */
+ Fc<UserMixinsT>& elemFc() noexcept
+ {
+ return *_mElemFc;
+ }
+
+ /*
+ * Sets the class of the element fields of instances of this field
+ * class.
+ */
+ void elemFc(typename Fc<UserMixinsT>::UP elemFc) noexcept
+ {
+ _mElemFc = std::move(elemFc);
+ }
+
+ /*
+ * Moves the class of the element fields of instances of this field
+ * class to the caller.
+ */
+ typename Fc<UserMixinsT>::UP takeElemFc() noexcept
+ {
+ return std::move(_mElemFc);
+ }
+
+ /*
+ * Minimum alignment (bits) of instances of this field class.
+ */
+ unsigned int minAlign() const noexcept
+ {
+ return _mMinAlign;
+ }
+
+private:
+ /*
+ * Returns the effective alignment of an array field of which:
+ *
+ * • The minimum alignment is `minAlign` bits.
+ * • The elements are instances of `elemFc`.
+ */
+ static unsigned int _effectiveAlign(const Fc<UserMixinsT>& elemFc,
+ const unsigned int minAlign) noexcept
+ {
+ return std::max(elemFc.align(), minAlign);
+ }
+
+ /* Class of the element fields of instances of this field class */
+ typename Fc<UserMixinsT>::UP _mElemFc;
+
+ /* Minimum alignment (bits) of instances of this field class */
+ unsigned int _mMinAlign;
+};
+
+/*
+ * Static-length array field class.
+ *
+ * Specific property over `ArrayFc<UserMixinsT>`:
+ *
+ * • Length (number of elements) of instances.
+ */
+template <typename UserMixinsT>
+class StaticLenArrayFc final :
+ public ArrayFc<UserMixinsT>,
+ public internal::StaticLenFcMixin,
+ public UserMixinsT::StaticLenArrayFc
+{
+public:
+ explicit StaticLenArrayFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::StaticLenArrayFc mixin, const std::size_t len,
+ typename Fc<UserMixinsT>::UP elemFc, const unsigned int minAlign = 1,
+ OptAttrs attrs = OptAttrs {}) :
+ ArrayFc<UserMixinsT> {FcType::StaticLenArray, std::move(fcMixin), std::move(elemFc),
+ minAlign, std::move(attrs)},
+ internal::StaticLenFcMixin {len}, UserMixinsT::StaticLenArrayFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<StaticLenArrayFc>(
+ *this, *this, this->len(), this->elemFc().clone(), this->minAlign(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Dynamic-length array field class.
+ *
+ * Specific property over `ArrayFc<UserMixinsT>`:
+ *
+ * • Length field location of instances.
+ */
+template <typename UserMixinsT>
+class DynLenArrayFc final :
+ public ArrayFc<UserMixinsT>,
+ public internal::DynLenFcMixin<UserMixinsT>,
+ public UserMixinsT::DynLenArrayFc
+{
+public:
+ explicit DynLenArrayFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::DynLenArrayFc mixin,
+ FieldLoc<UserMixinsT> lenFieldLoc, typename Fc<UserMixinsT>::UP elemFc,
+ const unsigned int minAlign = 1, OptAttrs attrs = OptAttrs {}) :
+ ArrayFc<UserMixinsT> {FcType::DynLenArray, std::move(fcMixin), std::move(elemFc), minAlign,
+ std::move(attrs)},
+ internal::DynLenFcMixin<UserMixinsT> {std::move(lenFieldLoc)},
+ UserMixinsT::DynLenArrayFc {std::move(mixin)}
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<DynLenArrayFc>(*this, *this, this->lenFieldLoc(),
+ this->elemFc().clone(), this->minAlign(),
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Structure field member class.
+ */
+template <typename UserMixinsT>
+class StructFieldMemberCls final :
+ public internal::WithAttrsMixin,
+ public UserMixinsT::StructFieldMemberCls
+{
+public:
+ explicit StructFieldMemberCls(typename UserMixinsT::StructFieldMemberCls mixin,
+ std::string name, typename Fc<UserMixinsT>::UP fc,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::StructFieldMemberCls(std::move(mixin)), _mName {std::move(name)},
+ _mFc {std::move(fc)}
+ {
+ BT_ASSERT(_mFc);
+ }
+
+ /*
+ * Builds a member class from `other`, cloning its field class.
+ */
+ StructFieldMemberCls(const StructFieldMemberCls& other) :
+ internal::WithAttrsMixin {other.attrs()}, UserMixinsT::StructFieldMemberCls(other),
+ _mName {other.name()}, _mFc {other.fc().clone()}
+ {
+ }
+
+ /*
+ * Name of this member class.
+ */
+ const std::string& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * Field class of this member class.
+ */
+ const Fc<UserMixinsT>& fc() const noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Field class of this member class.
+ */
+ Fc<UserMixinsT>& fc() noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Moves the field class of this member class to the caller.
+ */
+ typename Fc<UserMixinsT>::UP takeFc() noexcept
+ {
+ return std::move(_mFc);
+ }
+
+ /*
+ * Sets the field class of this member class.
+ */
+ void fc(typename Fc<UserMixinsT>::UP fc) noexcept
+ {
+ _mFc = std::move(fc);
+ }
+
+private:
+ std::string _mName;
+ typename Fc<UserMixinsT>::UP _mFc;
+};
+
+/*
+ * Structure field class.
+ *
+ * Specific properties over `Fc<UserMixinsT>`:
+ *
+ * • Minimum alignment of instances.
+ * • Classes of members of instances.
+ */
+template <typename UserMixinsT>
+class StructFc final : public Fc<UserMixinsT>, public UserMixinsT::StructFc
+{
+public:
+ using MemberClasses = std::vector<StructFieldMemberCls<UserMixinsT>>;
+
+ explicit StructFc(typename UserMixinsT::Fc fcMixin, typename UserMixinsT::StructFc mixin,
+ MemberClasses memberClasses = {}, const unsigned int minAlign = 1,
+ OptAttrs attrs = OptAttrs {}) :
+ Fc<UserMixinsT> {FcType::Struct, std::move(fcMixin),
+ StructFc::_effectiveAlign(memberClasses, minAlign), std::move(attrs)},
+ UserMixinsT::StructFc(std::move(mixin)), _mMemberClasses {std::move(memberClasses)},
+ _mMinAlign {minAlign}
+ {
+ }
+
+ /*
+ * Classes of members of instances of this field class.
+ */
+ const MemberClasses& memberClasses() const noexcept
+ {
+ return _mMemberClasses;
+ }
+
+ typename MemberClasses::const_reference
+ operator[](const typename MemberClasses::size_type index) const noexcept
+ {
+ return _mMemberClasses[index];
+ }
+
+ typename MemberClasses::reference
+ operator[](const typename MemberClasses::size_type index) noexcept
+ {
+ return _mMemberClasses[index];
+ }
+
+ const typename MemberClasses::value_type *operator[](const std::string& name) const noexcept
+ {
+ return this->_memberClsByName<const typename MemberClasses::value_type>(*this, name);
+ }
+
+ typename MemberClasses::value_type *operator[](const std::string& name) noexcept
+ {
+ return this->_memberClsByName<typename MemberClasses::value_type>(*this, name);
+ }
+
+ typename MemberClasses::size_type size() const noexcept
+ {
+ return _mMemberClasses.size();
+ }
+
+ bool isEmpty() const noexcept
+ {
+ return _mMemberClasses.empty();
+ }
+
+ typename MemberClasses::const_iterator begin() const noexcept
+ {
+ return _mMemberClasses.begin();
+ }
+
+ typename MemberClasses::iterator begin() noexcept
+ {
+ return _mMemberClasses.begin();
+ }
+
+ typename MemberClasses::const_iterator end() const noexcept
+ {
+ return _mMemberClasses.end();
+ }
+
+ typename MemberClasses::iterator end() noexcept
+ {
+ return _mMemberClasses.end();
+ }
+
+ typename MemberClasses::const_reverse_iterator rbegin() const noexcept
+ {
+ return _mMemberClasses.rbegin();
+ }
+
+ typename MemberClasses::reverse_iterator rbegin() noexcept
+ {
+ return _mMemberClasses.rbegin();
+ }
+
+ typename MemberClasses::const_reverse_iterator rend() const noexcept
+ {
+ return _mMemberClasses.rend();
+ }
+
+ typename MemberClasses::reverse_iterator rend() noexcept
+ {
+ return _mMemberClasses.rend();
+ }
+
+ /*
+ * Minimum alignment (bits) of instances of this field class.
+ */
+ unsigned int minAlign() const noexcept
+ {
+ return _mMinAlign;
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<StructFc>(*this, *this, _mMemberClasses, _mMinAlign,
+ this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+
+private:
+ /*
+ * Returns the effective alignment of a structure field of which:
+ *
+ * • The minimum alignment is `minAlign` bits.
+ * • The members are instances of `memberClasses`.
+ */
+ static unsigned int _effectiveAlign(const MemberClasses& memberClasses,
+ const unsigned int minAlign) noexcept
+ {
+ auto align = minAlign;
+
+ for (auto& memberCls : memberClasses) {
+ align = std::max(align, memberCls.fc().align());
+ }
+
+ return align;
+ }
+
+ template <typename ValT, typename StructFcT>
+ static ValT *_memberClsByName(StructFcT& structFc, const std::string& name) noexcept
+ {
+ for (auto& memberCls : structFc._mMemberClasses) {
+ if (memberCls.name() == name) {
+ return &memberCls;
+ }
+ }
+
+ return nullptr;
+ }
+
+ /* Classes of members of instances of this field class */
+ MemberClasses _mMemberClasses;
+
+ /* Minimum alignment (bits) of instances of this field class */
+ unsigned int _mMinAlign;
+};
+
+/*
+ * Optional field class base.
+ *
+ * Specific properties over `Fc<UserMixinsT>`:
+ *
+ * • Selector field location of instances.
+ * • Optional field of instances.
+ */
+template <typename UserMixinsT>
+class OptionalFc : public Fc<UserMixinsT>, public UserMixinsT::OptionalFc
+{
+protected:
+ explicit OptionalFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::OptionalFc mixin, typename Fc<UserMixinsT>::UP&& fc,
+ FieldLoc<UserMixinsT>&& selFieldLoc, OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), 1, std::move(attrs)},
+ UserMixinsT::OptionalFc {std::move(mixin)}, _mSelFieldLoc {std::move(selFieldLoc)},
+ _mFc {std::move(fc)}
+ {
+ }
+
+public:
+ /*
+ * Selector field location of instances of this field class.
+ */
+ const FieldLoc<UserMixinsT>& selFieldLoc() const noexcept
+ {
+ return _mSelFieldLoc;
+ }
+
+ /*
+ * Sets the selector field location of instances of this field class
+ * to `loc`.
+ */
+ void selFieldLoc(FieldLoc<UserMixinsT> loc) noexcept
+ {
+ _mSelFieldLoc = std::move(loc);
+ }
+
+ /*
+ * Moves the selector field location of instances of this field
+ * class to the caller.
+ */
+ FieldLoc<UserMixinsT> takeSelFieldLoc() noexcept
+ {
+ return std::move(_mSelFieldLoc);
+ }
+
+ /*
+ * Class of the optional field of instances of this field class.
+ */
+ const Fc<UserMixinsT>& fc() const noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Class of the optional field of instances of this field class.
+ */
+ Fc<UserMixinsT>& fc() noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Sets the class of the optional field of instances of this field
+ * class.
+ */
+ void fc(typename Fc<UserMixinsT>::UP fc) noexcept
+ {
+ _mFc = std::move(fc);
+ }
+
+ /*
+ * Moves the class of the optional field of instances of this field
+ * class to the caller.
+ */
+ typename Fc<UserMixinsT>::UP takeFc() noexcept
+ {
+ return std::move(_mFc);
+ }
+
+private:
+ /* Selector field location of instances of this field class */
+ FieldLoc<UserMixinsT> _mSelFieldLoc;
+
+ /* Class of the optional field of instances of this field class */
+ typename Fc<UserMixinsT>::UP _mFc;
+};
+
+/*
+ * Class of optional fields with a boolean selector.
+ */
+template <typename UserMixinsT>
+class OptionalWithBoolSelFc final :
+ public OptionalFc<UserMixinsT>,
+ public UserMixinsT::OptionalWithBoolSelFc
+{
+public:
+ /* Selector value type */
+ using SelVal = bool;
+
+ explicit OptionalWithBoolSelFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::OptionalFc optionalFcMixin,
+ typename UserMixinsT::OptionalWithBoolSelFc mixin,
+ typename Fc<UserMixinsT>::UP fc,
+ FieldLoc<UserMixinsT> selFieldLoc,
+ OptAttrs attrs = OptAttrs {}) :
+ OptionalFc<UserMixinsT> {FcType::OptionalWithBoolSel, std::move(fcMixin),
+ std::move(optionalFcMixin), std::move(fc),
+ std::move(selFieldLoc), std::move(attrs)},
+ UserMixinsT::OptionalWithBoolSelFc(std::move(mixin))
+ {
+ }
+
+ /*
+ * Returns whether or not an instance of this field class is enabled
+ * by the selector value `selVal`.
+ */
+ bool isEnabledBySelVal(const bool selVal) const noexcept
+ {
+ return selVal;
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<OptionalWithBoolSelFc>(*this, *this, *this, this->fc().clone(),
+ this->selFieldLoc(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Base class of optional fields with an integer selector.
+ *
+ * `IntRangeSetT` is the integer selector range set type.
+ *
+ * Specific property over `OptionalFc<UserMixinsT>`:
+ *
+ * • Selector field ranges which enable an instance.
+ */
+template <typename UserMixinsT, typename IntRangeSetT>
+class OptionalWithIntSelFc :
+ public OptionalFc<UserMixinsT>,
+ public UserMixinsT::OptionalWithIntSelFc
+{
+public:
+ /* Integer selector range set type */
+ using SelFieldRanges = IntRangeSetT;
+
+ /* Selector value type */
+ using SelVal = typename IntRangeSetT::Val;
+
+protected:
+ explicit OptionalWithIntSelFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::OptionalFc optionalFcMixin,
+ typename UserMixinsT::OptionalWithIntSelFc mixin,
+ typename Fc<UserMixinsT>::UP&& fc,
+ FieldLoc<UserMixinsT>&& selFieldLoc,
+ IntRangeSetT&& selFieldRanges, OptAttrs&& attrs) :
+ OptionalFc<UserMixinsT> {type, std::move(fcMixin), std::move(optionalFcMixin),
+ std::move(fc), std::move(selFieldLoc), std::move(attrs)},
+ UserMixinsT::OptionalWithIntSelFc(std::move(mixin)),
+ _mSelFieldRanges {std::move(selFieldRanges)}
+ {
+ }
+
+public:
+ /*
+ * Integer selector field ranges which enable an instance of this
+ * field class.
+ */
+ const IntRangeSetT& selFieldRanges() const noexcept
+ {
+ return _mSelFieldRanges;
+ }
+
+ /*
+ * Returns whether or not an instance of this field class is
+ * enabled by the selector value `selVal`.
+ */
+ bool isEnabledBySelVal(const SelVal selVal) const noexcept
+ {
+ return _mSelFieldRanges.contains(selVal);
+ }
+
+private:
+ /* Integer selector field ranges */
+ IntRangeSetT _mSelFieldRanges;
+};
+
+/*
+ * Class of optional fields with an unsigned integer selector.
+ */
+template <typename UserMixinsT>
+class OptionalWithUIntSelFc final :
+ public OptionalWithIntSelFc<UserMixinsT, UIntRangeSet>,
+ public UserMixinsT::OptionalWithUIntSelFc
+{
+public:
+ explicit OptionalWithUIntSelFc(
+ typename UserMixinsT::Fc fcMixin, typename UserMixinsT::OptionalFc optionalFcMixin,
+ typename UserMixinsT::OptionalWithIntSelFc optionalWithIntSelFcMixin,
+ typename UserMixinsT::OptionalWithUIntSelFc mixin, typename Fc<UserMixinsT>::UP fc,
+ FieldLoc<UserMixinsT> selFieldLoc, UIntRangeSet selFieldRanges,
+ OptAttrs attrs = OptAttrs {}) :
+ OptionalWithIntSelFc<UserMixinsT, UIntRangeSet> {FcType::OptionalWithUIntSel,
+ std::move(fcMixin),
+ std::move(optionalFcMixin),
+ std::move(optionalWithIntSelFcMixin),
+ std::move(fc),
+ std::move(selFieldLoc),
+ std::move(selFieldRanges),
+ std::move(attrs)},
+ UserMixinsT::OptionalWithUIntSelFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<OptionalWithUIntSelFc>(*this, *this, *this, *this,
+ this->fc().clone(), this->selFieldLoc(),
+ this->selFieldRanges(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Class of optional fields with a signed integer selector.
+ */
+template <typename UserMixinsT>
+class OptionalWithSIntSelFc final :
+ public OptionalWithIntSelFc<UserMixinsT, SIntRangeSet>,
+ public UserMixinsT::OptionalWithSIntSelFc
+{
+public:
+ explicit OptionalWithSIntSelFc(
+ typename UserMixinsT::Fc fcMixin, typename UserMixinsT::OptionalFc optionalFcMixin,
+ typename UserMixinsT::OptionalWithIntSelFc optionalWithIntSelFcMixin,
+ typename UserMixinsT::OptionalWithSIntSelFc mixin, typename Fc<UserMixinsT>::UP fc,
+ FieldLoc<UserMixinsT> selFieldLoc, SIntRangeSet selFieldRanges,
+ OptAttrs attrs = OptAttrs {}) :
+ OptionalWithIntSelFc<UserMixinsT, SIntRangeSet> {FcType::OptionalWithSIntSel,
+ std::move(fcMixin),
+ std::move(optionalFcMixin),
+ std::move(optionalWithIntSelFcMixin),
+ std::move(fc),
+ std::move(selFieldLoc),
+ std::move(selFieldRanges),
+ std::move(attrs)},
+ UserMixinsT::OptionalWithSIntSelFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<OptionalWithSIntSelFc>(*this, *this, *this, *this,
+ this->fc().clone(), this->selFieldLoc(),
+ this->selFieldRanges(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Variant field class option.
+ *
+ * `IntRangeSetT` is the integer selector range set type.
+ */
+template <typename UserMixinsT, typename IntRangeSetT>
+class VariantFcOpt final : public internal::WithAttrsMixin, public UserMixinsT::VariantFcOpt
+{
+public:
+ /* Integer selector range set type */
+ using SelFieldRanges = IntRangeSetT;
+
+ /* Selector value type */
+ using SelVal = typename IntRangeSetT::Val;
+
+ explicit VariantFcOpt(typename UserMixinsT::VariantFcOpt mixin, typename Fc<UserMixinsT>::UP fc,
+ IntRangeSetT selFieldRanges, bt2s::optional<std::string> name,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::VariantFcOpt(std::move(mixin)), _mName {std::move(name)}, _mFc {std::move(fc)},
+ _mSelFieldRanges {std::move(selFieldRanges)}
+ {
+ BT_ASSERT(_mFc);
+ }
+
+ /*
+ * Builds a variant field class option from `other`, cloning its
+ * field class.
+ */
+ VariantFcOpt(const VariantFcOpt& other) :
+ internal::WithAttrsMixin {other.attrs()}, UserMixinsT::VariantFcOpt(other),
+ _mName {other.name()}, _mFc {other.fc().clone()}, _mSelFieldRanges {other.selFieldRanges()}
+ {
+ }
+
+ /*
+ * Name of this variant field class option.
+ */
+ const bt2s::optional<std::string>& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * Moves the name of this variant field class option to the caller.
+ */
+ typename bt2s::optional<std::string> takeName() noexcept
+ {
+ return std::move(_mName);
+ }
+
+ /*
+ * Field class of this variant field class option.
+ */
+ const Fc<UserMixinsT>& fc() const noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Name of this variant field class option.
+ */
+ Fc<UserMixinsT>& fc() noexcept
+ {
+ return *_mFc;
+ }
+
+ /*
+ * Moves the field class of this variant field class option to the
+ * caller.
+ */
+ typename Fc<UserMixinsT>::UP takeFc() noexcept
+ {
+ return std::move(_mFc);
+ }
+
+ /*
+ * Sets the field class of this variant field class option.
+ */
+ void fc(typename Fc<UserMixinsT>::UP fc) noexcept
+ {
+ _mFc = std::move(fc);
+ }
+
+ /*
+ * Integer selector field ranges which select this variant field
+ * class option.
+ */
+ const IntRangeSetT& selFieldRanges() const noexcept
+ {
+ return _mSelFieldRanges;
+ }
+
+ /*
+ * Moves the attributes of this variant field class option to
+ * the caller.
+ */
+ OptAttrs takeAttrs() noexcept
+ {
+ return this->_takeAttrs();
+ }
+
+private:
+ bt2s::optional<std::string> _mName;
+ typename Fc<UserMixinsT>::UP _mFc;
+ IntRangeSetT _mSelFieldRanges;
+};
+
+/*
+ * Variant field class base.
+ *
+ * `IntRangeSetT` is the integer selector range set type.
+ *
+ * Specific properties over `Fc<UserMixinsT>`:
+ *
+ * • Selector field location of instances.
+ * • Options.
+ */
+template <typename UserMixinsT, typename IntRangeSetT>
+class VariantFc : public Fc<UserMixinsT>, public UserMixinsT::VariantFc
+{
+public:
+ /* Option type */
+ using Opt = VariantFcOpt<UserMixinsT, IntRangeSetT>;
+
+ /* Type of options */
+ using Opts = std::vector<Opt>;
+
+ /* Integer selector range set type */
+ using SelFieldRanges = typename Opt::SelFieldRanges;
+
+ /* Selector value type */
+ using SelVal = typename Opt::SelVal;
+
+protected:
+ explicit VariantFc(const FcType type, typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VariantFc mixin, Opts&& opts,
+ FieldLoc<UserMixinsT>&& selFieldLoc, OptAttrs&& attrs) :
+ Fc<UserMixinsT> {type, std::move(fcMixin), 1, std::move(attrs)},
+ UserMixinsT::VariantFc {std::move(mixin)}, _mOpts {std::move(opts)},
+ _mSelFieldLoc {std::move(selFieldLoc)}
+ {
+ }
+
+public:
+ /*
+ * Selector field location of instances of this field class.
+ */
+ const FieldLoc<UserMixinsT>& selFieldLoc() const noexcept
+ {
+ return _mSelFieldLoc;
+ }
+
+ /*
+ * Sets the selector field location of instances of this field class
+ * to `loc`.
+ */
+ void selFieldLoc(FieldLoc<UserMixinsT> loc) noexcept
+ {
+ _mSelFieldLoc = std::move(loc);
+ }
+
+ /*
+ * Moves the selector field location of instances of this field
+ * class to the caller.
+ */
+ FieldLoc<UserMixinsT> takeSelFieldLoc() noexcept
+ {
+ return std::move(_mSelFieldLoc);
+ }
+
+ /*
+ * Options of this field class.
+ */
+ const Opts& opts() const noexcept
+ {
+ return _mOpts;
+ }
+
+ /*
+ * Options of this field class.
+ */
+ Opts& opts() noexcept
+ {
+ return _mOpts;
+ }
+
+ typename Opts::const_reference operator[](const typename Opts::size_type index) const noexcept
+ {
+ return _mOpts[index];
+ }
+
+ typename Opts::reference operator[](const typename Opts::size_type index) noexcept
+ {
+ return _mOpts[index];
+ }
+
+ const typename Opts::value_type *operator[](const std::string& name) const noexcept
+ {
+ return this->_optByName<const typename Opts::value_type>(*this, name);
+ }
+
+ typename Opts::value_type *operator[](const std::string& name) noexcept
+ {
+ return this->_optByName<typename Opts::value_type>(*this, name);
+ }
+
+ typename Opts::size_type size() const noexcept
+ {
+ return _mOpts.size();
+ }
+
+ typename Opts::const_iterator begin() const noexcept
+ {
+ return _mOpts.begin();
+ }
+
+ typename Opts::iterator begin() noexcept
+ {
+ return _mOpts.begin();
+ }
+
+ typename Opts::const_iterator end() const noexcept
+ {
+ return _mOpts.end();
+ }
+
+ typename Opts::iterator end() noexcept
+ {
+ return _mOpts.end();
+ }
+
+ /*
+ * Returns the option of this field class which the selector value
+ * `selVal` selects, or `nullptr` if none.
+ */
+ typename Opts::const_iterator findOptBySelVal(const SelVal selVal) const noexcept
+ {
+ return std::find_if(_mOpts.begin(), _mOpts.end(), [selVal](const Opt& opt) {
+ return opt.selFieldRanges().contains(selVal);
+ });
+ }
+
+private:
+ template <typename ValT, typename VarFcT>
+ static ValT *_optByName(VarFcT& varFc, const std::string& name) noexcept
+ {
+ for (auto& opt : varFc._mOpts) {
+ if (opt.name() && *opt.name() == name) {
+ return &opt;
+ }
+ }
+
+ return nullptr;
+ }
+
+ /* Options of this field class */
+ Opts _mOpts;
+
+ /* Selector field location of instances of this field class */
+ FieldLoc<UserMixinsT> _mSelFieldLoc;
+};
+
+/*
+ * Class of variant fields with an unsigned integer selector.
+ */
+template <typename UserMixinsT>
+class VariantWithUIntSelFc final :
+ public VariantFc<UserMixinsT, UIntRangeSet>,
+ public UserMixinsT::VariantWithUIntSelFc
+{
+public:
+ explicit VariantWithUIntSelFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VariantFc variantFcMixin,
+ typename UserMixinsT::VariantWithUIntSelFc mixin,
+ typename VariantFc<UserMixinsT, UIntRangeSet>::Opts opts,
+ FieldLoc<UserMixinsT> selFieldLoc, OptAttrs attrs = OptAttrs {}) :
+ VariantFc<UserMixinsT, UIntRangeSet> {FcType::VariantWithUIntSel, std::move(fcMixin),
+ std::move(variantFcMixin), std::move(opts),
+ std::move(selFieldLoc), std::move(attrs)},
+ UserMixinsT::VariantWithUIntSelFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<VariantWithUIntSelFc>(*this, *this, *this, this->opts(),
+ this->selFieldLoc(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+/*
+ * Class of variant fields with a signed integer selector.
+ */
+template <typename UserMixinsT>
+class VariantWithSIntSelFc final :
+ public VariantFc<UserMixinsT, SIntRangeSet>,
+ public UserMixinsT::VariantWithSIntSelFc
+{
+public:
+ explicit VariantWithSIntSelFc(typename UserMixinsT::Fc fcMixin,
+ typename UserMixinsT::VariantFc variantFcMixin,
+ typename UserMixinsT::VariantWithSIntSelFc mixin,
+ typename VariantFc<UserMixinsT, SIntRangeSet>::Opts opts,
+ FieldLoc<UserMixinsT> selFieldLoc, OptAttrs attrs = OptAttrs {}) :
+ VariantFc<UserMixinsT, SIntRangeSet> {FcType::VariantWithSIntSel, std::move(fcMixin),
+ std::move(variantFcMixin), std::move(opts),
+ std::move(selFieldLoc), std::move(attrs)},
+ UserMixinsT::VariantWithSIntSelFc(std::move(mixin))
+ {
+ }
+
+ typename Fc<UserMixinsT>::UP clone() const override
+ {
+ return bt2s::make_unique<VariantWithSIntSelFc>(*this, *this, *this, this->opts(),
+ this->selFieldLoc(), this->attrs());
+ }
+
+ void accept(FcVisitor<UserMixinsT>& visitor) override
+ {
+ visitor.visit(*this);
+ }
+
+ void accept(ConstFcVisitor<UserMixinsT>& visitor) const override
+ {
+ visitor.visit(*this);
+ }
+};
+
+template <typename UserMixinsT>
+FixedLenBitArrayFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBitArray() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBitArray());
+ return static_cast<FixedLenBitArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenBitArrayFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBitArray() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBitArray());
+ return static_cast<const FixedLenBitArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenBitMapFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBitMap() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBitMap());
+ return static_cast<FixedLenBitMapFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenBitMapFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBitMap() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBitMap());
+ return static_cast<const FixedLenBitMapFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenBoolFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBool() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBool());
+ return static_cast<FixedLenBoolFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenBoolFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenBool() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenBool());
+ return static_cast<const FixedLenBoolFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenFloatFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenFloat() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenFloat());
+ return static_cast<FixedLenFloatFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenFloatFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenFloat() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenFloat());
+ return static_cast<const FixedLenFloatFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenInt() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenInt());
+ return static_cast<FixedLenIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenInt());
+ return static_cast<const FixedLenIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenSIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenSInt() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenSInt());
+ return static_cast<FixedLenSIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenSIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenSInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenSInt());
+ return static_cast<const FixedLenSIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+FixedLenUIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenUInt() noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenUInt());
+ return static_cast<FixedLenUIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const FixedLenUIntFc<UserMixinsT>& Fc<UserMixinsT>::asFixedLenUInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isFixedLenUInt());
+ return static_cast<const FixedLenUIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+VarLenIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenInt() noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenInt());
+ return static_cast<VarLenIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const VarLenIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenInt());
+ return static_cast<const VarLenIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+VarLenSIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenSInt() noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenSInt());
+ return static_cast<VarLenSIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const VarLenSIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenSInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenSInt());
+ return static_cast<const VarLenSIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+VarLenUIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenUInt() noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenUInt());
+ return static_cast<VarLenUIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const VarLenUIntFc<UserMixinsT>& Fc<UserMixinsT>::asVarLenUInt() const noexcept
+{
+ BT_ASSERT_DBG(this->isVarLenUInt());
+ return static_cast<const VarLenUIntFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+NullTerminatedStrFc<UserMixinsT>& Fc<UserMixinsT>::asNullTerminatedStr() noexcept
+{
+ BT_ASSERT_DBG(this->isNullTerminatedStr());
+ return static_cast<NullTerminatedStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const NullTerminatedStrFc<UserMixinsT>& Fc<UserMixinsT>::asNullTerminatedStr() const noexcept
+{
+ BT_ASSERT_DBG(this->isNullTerminatedStr());
+ return static_cast<const NullTerminatedStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+NonNullTerminatedStrFc<UserMixinsT>& Fc<UserMixinsT>::asNonNullTerminatedStr() noexcept
+{
+ BT_ASSERT_DBG(this->isNonNullTerminatedStr());
+ return static_cast<NonNullTerminatedStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const NonNullTerminatedStrFc<UserMixinsT>& Fc<UserMixinsT>::asNonNullTerminatedStr() const noexcept
+{
+ BT_ASSERT_DBG(this->isNonNullTerminatedStr());
+ return static_cast<const NonNullTerminatedStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+StrFc<UserMixinsT>& Fc<UserMixinsT>::asStr() noexcept
+{
+ BT_ASSERT_DBG(this->isStr());
+ return static_cast<StrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const StrFc<UserMixinsT>& Fc<UserMixinsT>::asStr() const noexcept
+{
+ BT_ASSERT_DBG(this->isStr());
+ return static_cast<const StrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+StaticLenStrFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenStr() noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenStr());
+ return static_cast<StaticLenStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const StaticLenStrFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenStr() const noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenStr());
+ return static_cast<const StaticLenStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+DynLenStrFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenStr() noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenStr());
+ return static_cast<DynLenStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const DynLenStrFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenStr() const noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenStr());
+ return static_cast<const DynLenStrFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+BlobFc<UserMixinsT>& Fc<UserMixinsT>::asBlob() noexcept
+{
+ BT_ASSERT_DBG(this->isBlob());
+ return static_cast<BlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const BlobFc<UserMixinsT>& Fc<UserMixinsT>::asBlob() const noexcept
+{
+ BT_ASSERT_DBG(this->isBlob());
+ return static_cast<const BlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+StaticLenBlobFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenBlob() noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenBlob());
+ return static_cast<StaticLenBlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const StaticLenBlobFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenBlob() const noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenBlob());
+ return static_cast<const StaticLenBlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+DynLenBlobFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenBlob() noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenBlob());
+ return static_cast<DynLenBlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const DynLenBlobFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenBlob() const noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenBlob());
+ return static_cast<const DynLenBlobFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+ArrayFc<UserMixinsT>& Fc<UserMixinsT>::asArray() noexcept
+{
+ BT_ASSERT_DBG(this->isArray());
+ return static_cast<ArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const ArrayFc<UserMixinsT>& Fc<UserMixinsT>::asArray() const noexcept
+{
+ BT_ASSERT_DBG(this->isArray());
+ return static_cast<const ArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+StaticLenArrayFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenArray() noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenArray());
+ return static_cast<StaticLenArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const StaticLenArrayFc<UserMixinsT>& Fc<UserMixinsT>::asStaticLenArray() const noexcept
+{
+ BT_ASSERT_DBG(this->isStaticLenArray());
+ return static_cast<const StaticLenArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+DynLenArrayFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenArray() noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenArray());
+ return static_cast<DynLenArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const DynLenArrayFc<UserMixinsT>& Fc<UserMixinsT>::asDynLenArray() const noexcept
+{
+ BT_ASSERT_DBG(this->isDynLenArray());
+ return static_cast<const DynLenArrayFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+StructFc<UserMixinsT>& Fc<UserMixinsT>::asStruct() noexcept
+{
+ BT_ASSERT_DBG(this->isStruct());
+ return static_cast<StructFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const StructFc<UserMixinsT>& Fc<UserMixinsT>::asStruct() const noexcept
+{
+ BT_ASSERT_DBG(this->isStruct());
+ return static_cast<const StructFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+OptionalFc<UserMixinsT>& Fc<UserMixinsT>::asOptional() noexcept
+{
+ BT_ASSERT_DBG(this->isOptional());
+ return static_cast<OptionalFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const OptionalFc<UserMixinsT>& Fc<UserMixinsT>::asOptional() const noexcept
+{
+ BT_ASSERT_DBG(this->isOptional());
+ return static_cast<const OptionalFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+OptionalWithBoolSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithBoolSel() noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithBoolSel());
+ return static_cast<OptionalWithBoolSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const OptionalWithBoolSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithBoolSel() const noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithBoolSel());
+ return static_cast<const OptionalWithBoolSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+OptionalWithUIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithUIntSel() noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithUIntSel());
+ return static_cast<OptionalWithUIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const OptionalWithUIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithUIntSel() const noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithUIntSel());
+ return static_cast<const OptionalWithUIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+OptionalWithSIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithSIntSel() noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithSIntSel());
+ return static_cast<OptionalWithSIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const OptionalWithSIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asOptionalWithSIntSel() const noexcept
+{
+ BT_ASSERT_DBG(this->isOptionalWithSIntSel());
+ return static_cast<const OptionalWithSIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+VariantWithUIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asVariantWithUIntSel() noexcept
+{
+ BT_ASSERT_DBG(this->isVariantWithUIntSel());
+ return static_cast<VariantWithUIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const VariantWithUIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asVariantWithUIntSel() const noexcept
+{
+ BT_ASSERT_DBG(this->isVariantWithUIntSel());
+ return static_cast<const VariantWithUIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+VariantWithSIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asVariantWithSIntSel() noexcept
+{
+ BT_ASSERT_DBG(this->isVariantWithSIntSel());
+ return static_cast<VariantWithSIntSelFc<UserMixinsT>&>(*this);
+}
+
+template <typename UserMixinsT>
+const VariantWithSIntSelFc<UserMixinsT>& Fc<UserMixinsT>::asVariantWithSIntSel() const noexcept
+{
+ BT_ASSERT_DBG(this->isVariantWithSIntSel());
+ return static_cast<const VariantWithSIntSelFc<UserMixinsT>&>(*this);
+}
+
+/*
+ * Clock offset (seconds and cycles).
+ */
+class ClkOffset final
+{
+public:
+ explicit ClkOffset(const long long seconds = 0, const unsigned long long cycles = 0) noexcept :
+ _mSeconds {seconds}, _mCycles {cycles}
+ {
+ }
+
+ /*
+ * Seconds part of this clock offset offset.
+ */
+ long long seconds() const noexcept
+ {
+ return _mSeconds;
+ }
+
+ /*
+ * Cycles part of this clock offset offset.
+ */
+ unsigned long long cycles() const noexcept
+ {
+ return _mCycles;
+ }
+
+private:
+ /* Seconds part of this clock offset offset */
+ long long _mSeconds;
+
+ /* Cycles part of this clock offset offset */
+ unsigned long long _mCycles;
+};
+
+/*
+ * Clock origin (namespace, name, and unique ID).
+ */
+class ClkOrigin final
+{
+public:
+ /*
+ * Builds a clock origin having the (optional) namespace `ns`, the
+ * name `name`, and the unique ID `uid`.
+ */
+ explicit ClkOrigin(bt2s::optional<std::string> ns, std::string name, std::string uid) :
+ _mNs {std::move(ns)}, _mName {std::move(name)}, _mUid {std::move(uid)}
+ {
+ }
+
+ /*
+ * Builds a Unix epoch clock origin.
+ */
+ explicit ClkOrigin() : ClkOrigin {_unixEpochNs, _unixEpochName, _unixEpochUid}
+ {
+ }
+
+ /*
+ * Namespace.
+ */
+ const bt2s::optional<std::string>& ns() const noexcept
+ {
+ return _mNs;
+ }
+
+ /*
+ * Name.
+ */
+ const std::string& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * Unique ID.
+ */
+ const std::string& uid() const noexcept
+ {
+ return _mUid;
+ }
+
+ /*
+ * Returns whether or not this clock origin is the Unix epoch.
+ */
+ bool isUnixEpoch() const noexcept
+ {
+ return _mNs == _unixEpochNs && _mName == _unixEpochName && _mUid == _unixEpochUid;
+ }
+
+private:
+ /* Internal Unix epoch origin namespace, name, and unique ID */
+ static const char * const _unixEpochNs;
+ static const char * const _unixEpochName;
+ static const char * const _unixEpochUid;
+
+ /* Namespace */
+ bt2s::optional<std::string> _mNs;
+
+ /* Name */
+ std::string _mName;
+
+ /* Unique ID */
+ std::string _mUid;
+};
+
+/*
+ * Clock class.
+ */
+template <typename UserMixinsT>
+class ClkCls final :
+ public internal::WithAttrsMixin,
+ public internal::WithLibCls<bt2::ClockClass>,
+ public UserMixinsT::ClkCls
+{
+public:
+ /* Shared pointer to a clock class */
+ using SP = std::shared_ptr<ClkCls>;
+
+ explicit ClkCls(typename UserMixinsT::ClkCls mixin, std::string id,
+ const unsigned long long freq, bt2s::optional<std::string> ns = bt2s::nullopt,
+ bt2s::optional<std::string> name = bt2s::nullopt,
+ bt2s::optional<std::string> uid = bt2s::nullopt,
+ const ClkOffset& offsetFromOrigin = ClkOffset {},
+ bt2s::optional<ClkOrigin> origin = ClkOrigin {},
+ bt2s::optional<std::string> descr = bt2s::nullopt,
+ bt2s::optional<unsigned long long> precision = bt2s::nullopt,
+ bt2s::optional<unsigned long long> accuracy = bt2s::nullopt,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::ClkCls {std::move(mixin)}, _mId {std::move(id)}, _mNs {std::move(ns)},
+ _mName {std::move(name)}, _mUid {std::move(uid)}, _mFreq {freq},
+ _mOffsetFromOrigin {offsetFromOrigin}, _mOrigin {std::move(origin)},
+ _mDescr {std::move(descr)}, _mPrecision {std::move(precision)},
+ _mAccuracy {std::move(accuracy)}
+ {
+ BT_ASSERT(_mFreq > 0);
+ BT_ASSERT(_mOffsetFromOrigin.cycles() < _mFreq);
+ }
+
+ /*
+ * Unique ID of this clock class within its trace class.
+ */
+ const std::string& id() const noexcept
+ {
+ return _mId;
+ }
+
+ /*
+ * Namespace of instances of this clock class.
+ */
+ const bt2s::optional<std::string>& ns() const noexcept
+ {
+ return _mNs;
+ }
+
+ /*
+ * Name of instances of this clock class.
+ */
+ const bt2s::optional<std::string>& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * UID of instances of this clock class.
+ */
+ const bt2s::optional<std::string>& uid() const noexcept
+ {
+ return _mUid;
+ }
+
+ /*
+ * Frequency (Hz) of instances of this clock class.
+ */
+ unsigned long long freq() const noexcept
+ {
+ return _mFreq;
+ }
+
+ /*
+ * Offset from origin of instances of this clock class.
+ */
+ const ClkOffset& offsetFromOrigin() const noexcept
+ {
+ return _mOffsetFromOrigin;
+ }
+
+ /*
+ * Sets the offset from origin of instances of this clock class.
+ */
+ void offsetFromOrigin(const ClkOffset& offsetFromOrigin) noexcept
+ {
+ _mOffsetFromOrigin = offsetFromOrigin;
+ }
+
+ /*
+ * Origin of instances of this clock class.
+ */
+ const bt2s::optional<ClkOrigin>& origin() const noexcept
+ {
+ return _mOrigin;
+ }
+
+ /*
+ * Sets the origin of instances of this clock class.
+ */
+ void origin(bt2s::optional<ClkOrigin> origin) noexcept
+ {
+ _mOrigin = std::move(origin);
+ }
+
+ /*
+ * Description of instances of this clock class.
+ */
+ const bt2s::optional<std::string>& descr() const noexcept
+ {
+ return _mDescr;
+ }
+
+ /*
+ * Precision (cycles) of instances of this clock class.
+ */
+ const bt2s::optional<unsigned long long>& precision() const noexcept
+ {
+ return _mPrecision;
+ }
+
+ /*
+ * Accuracy (cycles) of instances of this clock class.
+ */
+ const bt2s::optional<unsigned long long>& accuracy() const noexcept
+ {
+ return _mAccuracy;
+ }
+
+private:
+ /* Unique ID of this clock class within its trace class */
+ std::string _mId;
+
+ /* Namespace of instances of this clock class */
+ bt2s::optional<std::string> _mNs;
+
+ /* Name of instances of this clock class */
+ bt2s::optional<std::string> _mName;
+
+ /* UID of instances of this clock class */
+ bt2s::optional<std::string> _mUid;
+
+ /* Frequency (Hz) of instances of this clock class */
+ unsigned long long _mFreq;
+
+ /* Offset from origin of instances of this clock class */
+ ClkOffset _mOffsetFromOrigin;
+
+ /* Origin of instances of this clock class */
+ bt2s::optional<ClkOrigin> _mOrigin;
+
+ /* Description of instances of this clock class */
+ bt2s::optional<std::string> _mDescr;
+
+ /* Precision (cycles) of instances of this clock class */
+ bt2s::optional<unsigned long long> _mPrecision;
+
+ /* Accuracy (cycles) of instances of this clock class */
+ bt2s::optional<unsigned long long> _mAccuracy;
+};
+
+/*
+ * Event record class.
+ */
+template <typename UserMixinsT>
+class EventRecordCls final :
+ public internal::WithAttrsMixin,
+ public internal::WithLibCls<bt2::EventClass>,
+ public UserMixinsT::EventRecordCls
+{
+public:
+ /* Unique pointer to an event record class */
+ using UP = std::unique_ptr<EventRecordCls>;
+
+ explicit EventRecordCls(typename UserMixinsT::EventRecordCls mixin, const unsigned long long id,
+ bt2s::optional<std::string> ns = bt2s::nullopt,
+ bt2s::optional<std::string> name = bt2s::nullopt,
+ bt2s::optional<std::string> uid = bt2s::nullopt,
+ typename StructFc<UserMixinsT>::UP specCtxFc = nullptr,
+ typename StructFc<UserMixinsT>::UP payloadFc = nullptr,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::EventRecordCls(std::move(mixin)), _mId {id}, _mNs {std::move(ns)},
+ _mName {std::move(name)}, _mUid {std::move(uid)}, _mSpecCtxFc {std::move(specCtxFc)},
+ _mPayloadFc {std::move(payloadFc)}
+ {
+ }
+
+ /*
+ * ID of this event record class.
+ */
+ unsigned long long id() const noexcept
+ {
+ return _mId;
+ }
+
+ /*
+ * Namespace of instances of this event record class.
+ */
+ const bt2s::optional<std::string>& ns() const noexcept
+ {
+ return _mNs;
+ }
+
+ /*
+ * Name of instances of this event record class.
+ */
+ const bt2s::optional<std::string>& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * UID of instances of this event record class.
+ */
+ const bt2s::optional<std::string>& uid() const noexcept
+ {
+ return _mUid;
+ }
+
+ /*
+ * Class of the specific context field of instances of this event
+ * record class.
+ */
+ const StructFc<UserMixinsT> *specCtxFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mSpecCtxFc.get());
+ }
+
+ /*
+ * Class of the specific context field of instances of this event
+ * record class.
+ */
+ StructFc<UserMixinsT> *specCtxFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mSpecCtxFc.get());
+ }
+
+ /*
+ * Class of the payload field of instances of this event record
+ * class.
+ */
+ const StructFc<UserMixinsT> *payloadFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPayloadFc.get());
+ }
+
+ /*
+ * Class of the payload field of instances of this event record
+ * class.
+ */
+ StructFc<UserMixinsT> *payloadFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPayloadFc.get());
+ }
+
+private:
+ /* ID of this event record class */
+ unsigned long long _mId;
+
+ /* Namespace of instances of this event record class */
+ bt2s::optional<std::string> _mNs;
+
+ /* Name of instances of this event record class */
+ bt2s::optional<std::string> _mName;
+
+ /* UID of instances of this event record class */
+ bt2s::optional<std::string> _mUid;
+
+ /*
+ * Class of the specific context field of instances of this event
+ * record class.
+ */
+ typename StructFc<UserMixinsT>::UP _mSpecCtxFc;
+
+ /*
+ * Class of the payload field of instances of this event record
+ * class.
+ */
+ typename StructFc<UserMixinsT>::UP _mPayloadFc;
+};
+
+namespace internal {
+
+/*
+ * Less-than functor working on numeric IDs of unique pointers to
+ * `ObjT`.
+ */
+template <typename ObjT>
+struct ObjUpIdLt final
+{
+ bool operator()(const typename ObjT::UP& objA, const typename ObjT::UP& objB) const noexcept
+ {
+ return objA->id() < objB->id();
+ }
+};
+
+} /* namespace internal */
+
+/*
+ * Data stream class.
+ */
+template <typename UserMixinsT>
+class DataStreamCls final :
+ public internal::WithAttrsMixin,
+ public internal::WithLibCls<bt2::StreamClass>,
+ public UserMixinsT::DataStreamCls
+{
+public:
+ /* Unique pointer to a data stream class */
+ using UP = std::unique_ptr<DataStreamCls>;
+
+ /* Event record class set */
+ using EventRecordClsSet = std::set<typename EventRecordCls<UserMixinsT>::UP,
+ internal::ObjUpIdLt<EventRecordCls<UserMixinsT>>>;
+
+ explicit DataStreamCls(typename UserMixinsT::DataStreamCls mixin, const unsigned long long id,
+ bt2s::optional<std::string> ns = bt2s::nullopt,
+ bt2s::optional<std::string> name = bt2s::nullopt,
+ bt2s::optional<std::string> uid = bt2s::nullopt,
+ typename StructFc<UserMixinsT>::UP pktCtxFc = nullptr,
+ typename StructFc<UserMixinsT>::UP eventRecordHeaderFc = nullptr,
+ typename StructFc<UserMixinsT>::UP commonEventRecordCtxFc = nullptr,
+ typename ClkCls<UserMixinsT>::SP defClkCls = nullptr,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::DataStreamCls(std::move(mixin)), _mId {id}, _mNs {std::move(ns)},
+ _mName {std::move(name)}, _mUid {std::move(uid)}, _mPktCtxFc {std::move(pktCtxFc)},
+ _mEventRecordHeaderFc {std::move(eventRecordHeaderFc)},
+ _mCommonEventRecordCtxFc {std::move(commonEventRecordCtxFc)},
+ _mDefClkCls {std::move(defClkCls)}
+ {
+ }
+
+ /*
+ * ID of this data stream class.
+ */
+ unsigned long long id() const noexcept
+ {
+ return _mId;
+ }
+
+ /*
+ * Namespace of instances of this data stream class.
+ */
+ const bt2s::optional<std::string>& ns() const noexcept
+ {
+ return _mNs;
+ }
+
+ /*
+ * Name of instances of this data stream class.
+ */
+ const bt2s::optional<std::string>& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * UID of instances of this data stream class.
+ */
+ const bt2s::optional<std::string>& uid() const noexcept
+ {
+ return _mUid;
+ }
+
+ /*
+ * Class of the packet context field of instances of this data
+ * stream class.
+ */
+ const StructFc<UserMixinsT> *pktCtxFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPktCtxFc.get());
+ }
+
+ /*
+ * Class of the context field of packets which are part of instances
+ * of this data stream class.
+ */
+ StructFc<UserMixinsT> *pktCtxFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPktCtxFc.get());
+ }
+
+ /*
+ * Class of the context field of packets which are part of instances
+ * of this data stream class.
+ */
+ const StructFc<UserMixinsT> *eventRecordHeaderFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mEventRecordHeaderFc.get());
+ }
+
+ /*
+ * Class of the header field of event records which are part of
+ * instances of this data stream class.
+ */
+ StructFc<UserMixinsT> *eventRecordHeaderFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mEventRecordHeaderFc.get());
+ }
+
+ /*
+ * Class of the header field of event records which are part of
+ * instances of this data stream class.
+ */
+ const StructFc<UserMixinsT> *commonEventRecordCtxFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mCommonEventRecordCtxFc.get());
+ }
+
+ /*
+ * Class of the common context field of event records which are part
+ * of instances of this data stream class.
+ */
+ StructFc<UserMixinsT> *commonEventRecordCtxFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mCommonEventRecordCtxFc.get());
+ }
+
+ /*
+ * Class of the common context field of event records which are part
+ * of instances of this data stream class.
+ */
+ const ClkCls<UserMixinsT> *defClkCls() const noexcept
+ {
+ return _mDefClkCls.get();
+ }
+
+ /*
+ * Class of the default clock of instances of this data stream
+ * class.
+ */
+ ClkCls<UserMixinsT> *defClkCls() noexcept
+ {
+ return _mDefClkCls.get();
+ }
+
+ /*
+ * Event record classes of this data stream class.
+ */
+ const EventRecordClsSet& eventRecordClasses() const noexcept
+ {
+ return _mEventRecordClasses;
+ }
+
+ /*
+ * Adds the event record class `eventRecordCls` to the set of event
+ * record classes of this data stream class.
+ */
+ void addEventRecordCls(typename EventRecordCls<UserMixinsT>::UP eventRecordCls)
+ {
+ BT_ASSERT_DBG(eventRecordCls);
+ _mEventRecordClsIdMap[eventRecordCls->id()] = eventRecordCls.get();
+ _mEventRecordClasses.emplace(std::move(eventRecordCls));
+ }
+
+ const EventRecordCls<UserMixinsT> *operator[](const unsigned long long id) const noexcept
+ {
+ return this->_eventRecordClsById<const EventRecordCls<UserMixinsT>>(*this, id);
+ }
+
+ EventRecordCls<UserMixinsT> *operator[](const unsigned long long id) noexcept
+ {
+ return this->_eventRecordClsById<EventRecordCls<UserMixinsT>>(*this, id);
+ }
+
+ typename EventRecordClsSet::size_type size() const noexcept
+ {
+ return _mEventRecordClasses.size();
+ }
+
+ typename EventRecordClsSet::const_iterator begin() const noexcept
+ {
+ return _mEventRecordClasses.begin();
+ }
+
+ typename EventRecordClsSet::iterator begin() noexcept
+ {
+ return _mEventRecordClasses.begin();
+ }
+
+ typename EventRecordClsSet::const_iterator end() const noexcept
+ {
+ return _mEventRecordClasses.end();
+ }
+
+ typename EventRecordClsSet::iterator end() noexcept
+ {
+ return _mEventRecordClasses.end();
+ }
+
+private:
+ using _EventRecordClsByIdMap =
+ std::unordered_map<unsigned long long, EventRecordCls<UserMixinsT> *>;
+
+ template <typename ValT, typename DataStreamClsT>
+ static ValT *_eventRecordClsById(DataStreamClsT& dataStreamCls,
+ const unsigned long long id) noexcept
+ {
+ const auto it = dataStreamCls._mEventRecordClsIdMap.find(id);
+
+ if (it == dataStreamCls._mEventRecordClsIdMap.end()) {
+ return nullptr;
+ }
+
+ return it->second;
+ }
+
+ /* ID of this data stream class */
+ unsigned long long _mId;
+
+ /* Event record classes of this data stream class */
+ EventRecordClsSet _mEventRecordClasses;
+
+ /* Map of event record class ID to event record class */
+ _EventRecordClsByIdMap _mEventRecordClsIdMap;
+
+ /* Namespace of instances of this data stream class */
+ bt2s::optional<std::string> _mNs;
+
+ /* Name of instances of this data stream class */
+ bt2s::optional<std::string> _mName;
+
+ /* UID of instances of this data stream class */
+ bt2s::optional<std::string> _mUid;
+
+ /*
+ * Class of the context field of packets which are part of instances
+ * of this data stream class.
+ */
+ typename Fc<UserMixinsT>::UP _mPktCtxFc;
+
+ /*
+ * Class of the header field of event records which are part of
+ * instances of this data stream class.
+ */
+ typename Fc<UserMixinsT>::UP _mEventRecordHeaderFc;
+
+ /*
+ * Class of the common context field of event records which are part
+ * of instances of this data stream class.
+ */
+ typename Fc<UserMixinsT>::UP _mCommonEventRecordCtxFc;
+
+ /*
+ * Class of the default clock of instances of this data stream
+ * class.
+ */
+ typename ClkCls<UserMixinsT>::SP _mDefClkCls;
+};
+
+/*
+ * Trace class.
+ */
+template <typename UserMixinsT>
+class TraceCls final :
+ public internal::WithAttrsMixin,
+ public internal::WithLibCls<bt2::TraceClass>,
+ public UserMixinsT::TraceCls
+{
+public:
+ /* Data stream class set */
+ using DataStreamClsSet = std::set<typename DataStreamCls<UserMixinsT>::UP,
+ internal::ObjUpIdLt<DataStreamCls<UserMixinsT>>>;
+
+ explicit TraceCls(typename UserMixinsT::TraceCls mixin,
+ bt2s::optional<std::string> ns = bt2s::nullopt,
+ bt2s::optional<std::string> name = bt2s::nullopt,
+ bt2s::optional<std::string> uid = bt2s::nullopt,
+ bt2::ConstMapValue::Shared env = bt2::ConstMapValue::Shared {},
+ typename Fc<UserMixinsT>::UP pktHeaderFc = nullptr,
+ OptAttrs attrs = OptAttrs {}) :
+ internal::WithAttrsMixin {std::move(attrs)},
+ UserMixinsT::TraceCls {std::move(mixin)}, _mNs {std::move(ns)}, _mName {std::move(name)},
+ _mUid {std::move(uid)}, _mEnv {std::move(env)}, _mPktHeaderFc {std::move(pktHeaderFc)}
+ {
+ BT_ASSERT(!_mPktHeaderFc || _mPktHeaderFc->isStruct());
+ }
+
+ /*
+ * Namespace of instances of this trace class.
+ */
+ const bt2s::optional<std::string>& ns() const noexcept
+ {
+ return _mNs;
+ }
+
+ /*
+ * Name of instances of this trace class.
+ */
+ const bt2s::optional<std::string>& name() const noexcept
+ {
+ return _mName;
+ }
+
+ /*
+ * UID of instances of this trace class.
+ */
+ const bt2s::optional<std::string>& uid() const noexcept
+ {
+ return _mUid;
+ }
+
+ /*
+ * Environment of instances of this trace class.
+ */
+ const bt2::ConstMapValue::Shared& env() const noexcept
+ {
+ return _mEnv;
+ }
+
+ /*
+ * Class of the header field of packets which are part of instances
+ * of this data stream class.
+ */
+ const StructFc<UserMixinsT> *pktHeaderFc() const noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPktHeaderFc.get());
+ }
+
+ /*
+ * Class of the header field of packets which are part of instances
+ * of this data stream class.
+ */
+ StructFc<UserMixinsT> *pktHeaderFc() noexcept
+ {
+ return static_cast<StructFc<UserMixinsT> *>(_mPktHeaderFc.get());
+ }
+
+ /*
+ * Data stream classes of this trace class.
+ */
+ const DataStreamClsSet& dataStreamClasses() const noexcept
+ {
+ return _mDataStreamClasses;
+ }
+
+ /*
+ * Adds the data stream class `dataStreamCls` to the set of data
+ * stream classes of this trace class.
+ */
+ void addDataStreamCls(typename DataStreamCls<UserMixinsT>::UP dataStreamCls)
+ {
+ BT_ASSERT_DBG(dataStreamCls);
+ _mDataStreamClsIdMap[dataStreamCls->id()] = dataStreamCls.get();
+ _mDataStreamClasses.emplace(std::move(dataStreamCls));
+ }
+
+ const DataStreamCls<UserMixinsT> *operator[](const unsigned long long id) const noexcept
+ {
+ return this->_dataStreamClsById<const DataStreamCls<UserMixinsT>>(*this, id);
+ }
+
+ DataStreamCls<UserMixinsT> *operator[](const unsigned long long id) noexcept
+ {
+ return this->_dataStreamClsById<DataStreamCls<UserMixinsT>>(*this, id);
+ }
+
+ typename DataStreamClsSet::size_type size() const noexcept
+ {
+ return _mDataStreamClasses.size();
+ }
+
+ typename DataStreamClsSet::const_iterator begin() const noexcept
+ {
+ return _mDataStreamClasses.begin();
+ }
+
+ typename DataStreamClsSet::iterator begin() noexcept
+ {
+ return _mDataStreamClasses.begin();
+ }
+
+ typename DataStreamClsSet::const_iterator end() const noexcept
+ {
+ return _mDataStreamClasses.end();
+ }
+
+ typename DataStreamClsSet::iterator end() noexcept
+ {
+ return _mDataStreamClasses.end();
+ }
+
+private:
+ using _DataStreamClsByIdMap =
+ std::unordered_map<unsigned long long, DataStreamCls<UserMixinsT> *>;
+
+ template <typename ValT, typename TraceClsT>
+ static ValT *_dataStreamClsById(TraceClsT& traceCls, const unsigned long long id) noexcept
+ {
+ const auto it = traceCls._mDataStreamClsIdMap.find(id);
+
+ if (it == traceCls._mDataStreamClsIdMap.end()) {
+ return nullptr;
+ }
+
+ return it->second;
+ }
+
+ /* Data stream classes of this trace class */
+ DataStreamClsSet _mDataStreamClasses;
+
+ /* Map of data stream class ID to data stream class */
+ _DataStreamClsByIdMap _mDataStreamClsIdMap;
+
+ /* Namespace of instances of this trace class */
+ bt2s::optional<std::string> _mNs;
+
+ /* Name of instances of this trace class */
+ bt2s::optional<std::string> _mName;
+
+ /* UID of instances of this trace class */
+ bt2s::optional<std::string> _mUid;
+
+ /* Environment of instances of this trace class */
+ bt2::ConstMapValue::Shared _mEnv;
+
+ /*
+ * Class of the header field of packets which are part of instances
+ * of this data stream class.
+ */
+ typename Fc<UserMixinsT>::UP _mPktHeaderFc;
+};
+
+/*
+ * Default user mixins.
+ */
+struct DefUserMixins
+{
+ struct FieldLoc
+ {
+ };
+
+ struct Fc
+ {
+ };
+
+ struct FixedLenBitArrayFc
+ {
+ };
+
+ struct FixedLenBitMapFc
+ {
+ };
+
+ struct FixedLenBoolFc
+ {
+ };
+
+ struct FixedLenIntFc
+ {
+ };
+
+ struct FixedLenUIntFc
+ {
+ };
+
+ struct VarLenIntFc
+ {
+ };
+
+ struct VarLenUIntFc
+ {
+ };
+
+ struct StaticLenStrFc
+ {
+ };
+
+ struct DynLenStrFc
+ {
+ };
+
+ struct StaticLenBlobFc
+ {
+ };
+
+ struct DynLenBlobFc
+ {
+ };
+
+ struct StaticLenArrayFc
+ {
+ };
+
+ struct DynLenArrayFc
+ {
+ };
+
+ struct StructFieldMemberCls
+ {
+ };
+
+ struct StructFc
+ {
+ };
+
+ struct OptionalFc
+ {
+ };
+
+ struct OptionalWithBoolSelFc
+ {
+ };
+
+ struct OptionalWithIntSelFc
+ {
+ };
+
+ struct OptionalWithUIntSelFc
+ {
+ };
+
+ struct OptionalWithSIntSelFc
+ {
+ };
+
+ struct VariantFcOpt
+ {
+ };
+
+ struct VariantFc
+ {
+ };
+
+ struct VariantWithUIntSelFc
+ {
+ };
+
+ struct VariantWithSIntSelFc
+ {
+ };
+
+ struct ClkCls
+ {
+ };
+
+ struct EventRecordCls
+ {
+ };
+
+ struct DataStreamCls
+ {
+ };
+
+ struct TraceCls
+ {
+ };
+};
+
+} /* namespace ir */
+} /* namespace ctf */
+
+#endif /* BABELTRACE_PLUGINS_CTF_COMMON_METADATA_CTF_IR_HPP */