2 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 * SPDX-License-Identifier: GPL-2.0-only
11 #include "trace-class.hpp"
15 #include <type_traits>
18 #include <vendor/optional.hpp>
28 * Field, and the various field types, represents fields as exposed by the
29 * LTTng tracers. These classes do not attempt to describe the complete spectrum of the CTF
35 using cuptr = std::unique_ptr<const type>;
37 static byte_order reverse_byte_order(byte_order byte_order) noexcept;
39 bool operator==(const type& other) const noexcept;
40 bool operator!=(const type& other) const noexcept;
42 virtual void accept(type_visitor& visitor) const = 0;
44 const unsigned int alignment;
47 type(unsigned int alignment);
50 virtual bool _is_equal(const type& rhs) const noexcept = 0;
55 using cuptr = std::unique_ptr<const field>;
57 field(std::string name, type::cuptr type);
58 void accept(field_visitor& visitor) const;
59 bool operator==(const field& other) const noexcept;
61 const std::string name;
62 const type::cuptr _type;
65 class integer_type : public type {
67 enum class signedness {
80 DEFAULT_CLOCK_TIMESTAMP,
81 /* Packet header field class specific roles. */
85 /* Packet context field class specific roles. */
86 DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT,
87 PACKET_CONTENT_LENGTH,
88 PACKET_END_DEFAULT_CLOCK_TIMESTAMP,
89 PACKET_SEQUENCE_NUMBER,
91 /* Event record field class roles. */
92 EVENT_RECORD_CLASS_ID,
95 using roles = std::vector<role>;
97 integer_type(unsigned int alignment,
98 byte_order byte_order,
100 signedness signedness,
104 virtual void accept(type_visitor& visitor) const override;
106 const enum byte_order byte_order;
107 const unsigned int size;
109 * signedness and base are suffixed with '_' to work-around a bug in older
110 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
111 * nested-name-specifiers.
113 const signedness signedness_;
118 virtual bool _is_equal(const type& other) const noexcept override;
121 class floating_point_type : public type {
123 floating_point_type(unsigned int alignment,
124 byte_order byte_order,
125 unsigned int exponent_digits,
126 unsigned int mantissa_digits);
128 virtual void accept(type_visitor& visitor) const override final;
130 const enum byte_order byte_order;
131 const unsigned int exponent_digits;
132 const unsigned int mantissa_digits;
135 virtual bool _is_equal(const type& other) const noexcept override final;
138 class enumeration_type : public integer_type {
140 enumeration_type(unsigned int alignment,
141 enum byte_order byte_order,
143 enum signedness signedness,
145 integer_type::roles roles = {});
147 virtual void accept(type_visitor& visitor) const = 0;
151 template <class MappingIntegerType>
152 class enumeration_mapping_range {
154 using range_integer_t = MappingIntegerType;
156 enumeration_mapping_range(MappingIntegerType in_begin, MappingIntegerType in_end) :
157 begin{in_begin}, end{in_end}
161 const range_integer_t begin, end;
164 template <class MappingIntegerType>
165 bool operator==(const enumeration_mapping_range<MappingIntegerType>& lhs,
166 const enumeration_mapping_range<MappingIntegerType>& rhs) noexcept
168 return lhs.begin == rhs.begin && lhs.end == rhs.end;
171 template <class MappingIntegerType>
172 class enumeration_mapping {
174 using range_t = enumeration_mapping_range<MappingIntegerType>;
176 enumeration_mapping(const enumeration_mapping<MappingIntegerType>& other) = delete;
177 enumeration_mapping(const enumeration_mapping<MappingIntegerType>&& other) :
178 name{std::move(other.name)}, range{other.range}
182 /* Mapping with an implicit value. */
183 enumeration_mapping(std::string in_name) : name{std::move(in_name)}
187 enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range}
191 const std::string name;
192 const nonstd::optional<range_t> range;
195 template <class MappingIntegerType>
196 bool operator==(const enumeration_mapping<MappingIntegerType>& lhs,
197 const enumeration_mapping<MappingIntegerType>& rhs) noexcept
199 return lhs.name == rhs.name && lhs.range == rhs.range;
201 } /* namespace details */
203 template <class MappingIntegerType>
204 class typed_enumeration_type : public enumeration_type {
206 using mapping = details::enumeration_mapping<MappingIntegerType>;
207 using mappings = std::vector<mapping>;
209 static_assert(std::is_integral<MappingIntegerType>::value &&
210 sizeof(MappingIntegerType) == 8,
211 "MappingIntegerType must be either int64_t or uint64_t");
213 typed_enumeration_type(unsigned int in_alignment,
214 enum byte_order in_byte_order,
215 unsigned int in_size,
217 const std::shared_ptr<const mappings>& in_mappings,
218 integer_type::roles in_roles = {}) :
219 enumeration_type(in_alignment,
222 std::is_signed<MappingIntegerType>::value ?
223 integer_type::signedness::SIGNED :
224 integer_type::signedness::UNSIGNED,
226 std::move(in_roles)),
227 _mappings{std::move(in_mappings)}
231 virtual void accept(type_visitor& visitor) const override final;
233 const std::shared_ptr<const mappings> _mappings;
236 virtual bool _is_equal(const type& base_other) const noexcept override final
238 const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
241 return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings;
245 /* Aliases for all allowed enumeration mapping types. */
246 using signed_enumeration_type = typed_enumeration_type<int64_t>;
247 using unsigned_enumeration_type = typed_enumeration_type<uint64_t>;
249 class array_type : public type {
251 array_type(unsigned int alignment, type::cuptr element_type);
253 const type::cuptr element_type;
256 virtual bool _is_equal(const type& base_other) const noexcept override;
259 class static_length_array_type : public array_type {
261 static_length_array_type(unsigned int alignment,
262 type::cuptr element_type,
265 virtual void accept(type_visitor& visitor) const override final;
267 const uint64_t length;
270 virtual bool _is_equal(const type& base_other) const noexcept override final;
273 class dynamic_length_array_type : public array_type {
275 dynamic_length_array_type(unsigned int alignment,
276 type::cuptr element_type,
277 std::string length_field_name);
279 virtual void accept(type_visitor& visitor) const override final;
281 const std::string length_field_name;
284 virtual bool _is_equal(const type& base_other) const noexcept override final;
287 class static_length_blob_type : public type {
290 /* Packet header field class specific role. */
294 using roles = std::vector<role>;
296 static_length_blob_type(unsigned int alignment, uint64_t in_length_bytes, roles roles = {});
298 virtual void accept(type_visitor& visitor) const override final;
300 const uint64_t length_bytes;
304 virtual bool _is_equal(const type& base_other) const noexcept override final;
307 class dynamic_length_blob_type : public type {
309 dynamic_length_blob_type(unsigned int alignment, std::string length_field_name);
311 virtual void accept(type_visitor& visitor) const override final;
313 const std::string length_field_name;
316 virtual bool _is_equal(const type& base_other) const noexcept override final;
319 class string_type : public type {
321 enum class encoding {
326 string_type(unsigned int alignment, enum encoding encoding);
329 * encoding is suffixed with '_' to work-around a bug in older
330 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
331 * nested-name-specifiers.
333 const encoding encoding_;
336 virtual bool _is_equal(const type& base_other) const noexcept override;
339 class static_length_string_type : public string_type {
341 static_length_string_type(
342 unsigned int alignment, enum encoding in_encoding, uint64_t length);
343 virtual void accept(type_visitor& visitor) const override final;
345 const uint64_t length;
348 virtual bool _is_equal(const type& base_other) const noexcept override final;
351 class dynamic_length_string_type : public string_type {
353 dynamic_length_string_type(unsigned int alignment,
354 enum encoding in_encoding,
355 std::string length_field_name);
356 virtual void accept(type_visitor& visitor) const override final;
358 const std::string length_field_name;
361 virtual bool _is_equal(const type& base_other) const noexcept override final;
364 class null_terminated_string_type : public string_type {
366 null_terminated_string_type(unsigned int alignment, enum encoding in_encoding);
367 virtual void accept(type_visitor& visitor) const override final;
370 class structure_type : public type {
372 using fields = std::vector<field::cuptr>;
374 structure_type(unsigned int alignment, fields in_fields);
376 virtual void accept(type_visitor& visitor) const override final;
378 const fields _fields;
381 virtual bool _is_equal(const type& base_other) const noexcept override final;
384 class variant_type : public type {
386 using choices = std::vector<field::cuptr>;
388 variant_type(unsigned int alignment, std::string tag_name, choices in_choices);
390 virtual void accept(type_visitor& visitor) const override final;
392 const std::string tag_name;
393 const choices _choices;
396 virtual bool _is_equal(const type& base_other) const noexcept override final;
399 class field_visitor {
401 virtual ~field_visitor() = default;
402 virtual void visit(const field& field) = 0;
405 field_visitor() = default;
410 virtual ~type_visitor() = default;
411 virtual void visit(const integer_type& type) = 0;
412 virtual void visit(const floating_point_type& type) = 0;
413 virtual void visit(const signed_enumeration_type& type) = 0;
414 virtual void visit(const unsigned_enumeration_type& type) = 0;
415 virtual void visit(const static_length_array_type& type) = 0;
416 virtual void visit(const dynamic_length_array_type& type) = 0;
417 virtual void visit(const static_length_blob_type& type) = 0;
418 virtual void visit(const dynamic_length_blob_type& type) = 0;
419 virtual void visit(const null_terminated_string_type& type) = 0;
420 virtual void visit(const static_length_string_type& type) = 0;
421 virtual void visit(const dynamic_length_string_type& type) = 0;
422 virtual void visit(const structure_type& type) = 0;
423 virtual void visit(const variant_type& type) = 0;
426 type_visitor() = default;
429 } /* namespace trace */
430 } /* namespace sessiond */
431 } /* namespace lttng */
433 #endif /* LTTNG_FIELD_H */