Clean-up: coverity warns of uncaught exception during logging
[lttng-tools.git] / src / bin / lttng-sessiond / field.hpp
CommitLineData
0220be14
JG
1/*
2 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8#ifndef LTTNG_FIELD_H
9#define LTTNG_FIELD_H
10
6e01cdc6
JG
11#include <common/format.hpp>
12
13#include <vendor/optional.hpp>
14
45110cdd 15#include <algorithm>
0220be14
JG
16#include <memory>
17#include <string>
18#include <type_traits>
19#include <vector>
20
0220be14
JG
21namespace lttng {
22namespace sessiond {
23namespace trace {
24
25class field_visitor;
26class type_visitor;
27
24ed18f2
JG
28enum class byte_order {
29 BIG_ENDIAN_,
30 LITTLE_ENDIAN_,
31};
32
eda1aa02
JG
33class field_location {
34public:
35 enum class root {
36 PACKET_HEADER,
37 PACKET_CONTEXT,
38 EVENT_RECORD_HEADER,
39 EVENT_RECORD_COMMON_CONTEXT,
40 EVENT_RECORD_SPECIFIC_CONTEXT,
41 EVENT_RECORD_PAYLOAD,
42 };
43
44 using elements = std::vector<std::string>;
45
46 field_location(root lookup_root, elements elements);
47 bool operator==(const field_location& other) const noexcept;
48
49 const root root_;
50 const elements elements_;
51};
52
0220be14
JG
53/*
54 * Field, and the various field types, represents fields as exposed by the
55 * LTTng tracers. These classes do not attempt to describe the complete spectrum of the CTF
56 * specification.
57 */
58
59class type {
60public:
61 using cuptr = std::unique_ptr<const type>;
62
63 static byte_order reverse_byte_order(byte_order byte_order) noexcept;
64
65 bool operator==(const type& other) const noexcept;
66 bool operator!=(const type& other) const noexcept;
67 virtual ~type();
68 virtual void accept(type_visitor& visitor) const = 0;
69
70 const unsigned int alignment;
71
72protected:
73 type(unsigned int alignment);
74
75private:
76 virtual bool _is_equal(const type& rhs) const noexcept = 0;
77};
78
79class field {
80public:
45110cdd 81 using uptr = std::unique_ptr<field>;
0220be14
JG
82 using cuptr = std::unique_ptr<const field>;
83
84 field(std::string name, type::cuptr type);
85 void accept(field_visitor& visitor) const;
86 bool operator==(const field& other) const noexcept;
87
45110cdd
JG
88 const type& get_type() const;
89 type::cuptr move_type() noexcept;
90
0220be14 91 const std::string name;
45110cdd
JG
92
93private:
94 type::cuptr _type;
0220be14
JG
95};
96
97class integer_type : public type {
98public:
99 enum class signedness {
100 SIGNED,
101 UNSIGNED,
102 };
103
104 enum class base {
105 BINARY = 2,
106 OCTAL = 8,
107 DECIMAL = 10,
108 HEXADECIMAL = 16,
109 };
110
e7360180
JG
111 enum class role {
112 DEFAULT_CLOCK_TIMESTAMP,
113 /* Packet header field class specific roles. */
114 DATA_STREAM_CLASS_ID,
115 DATA_STREAM_ID,
116 PACKET_MAGIC_NUMBER,
117 /* Packet context field class specific roles. */
118 DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT,
119 PACKET_CONTENT_LENGTH,
120 PACKET_END_DEFAULT_CLOCK_TIMESTAMP,
121 PACKET_SEQUENCE_NUMBER,
122 PACKET_TOTAL_LENGTH,
123 /* Event record field class roles. */
124 EVENT_RECORD_CLASS_ID,
125 };
126
127 using roles = std::vector<role>;
128
0220be14
JG
129 integer_type(unsigned int alignment,
130 byte_order byte_order,
131 unsigned int size,
132 signedness signedness,
e7360180
JG
133 base base,
134 roles roles = {});
0220be14
JG
135
136 virtual void accept(type_visitor& visitor) const override;
137
138 const enum byte_order byte_order;
139 const unsigned int size;
65cd3c0c
JG
140 /*
141 * signedness and base are suffixed with '_' to work-around a bug in older
142 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
143 * nested-name-specifiers.
144 */
145 const signedness signedness_;
146 const base base_;
e7360180 147 const roles roles_;
0220be14
JG
148
149protected:
150 virtual bool _is_equal(const type& other) const noexcept override;
151};
152
153class floating_point_type : public type {
154public:
155 floating_point_type(unsigned int alignment,
156 byte_order byte_order,
157 unsigned int exponent_digits,
158 unsigned int mantissa_digits);
159
160 virtual void accept(type_visitor& visitor) const override final;
161
162 const enum byte_order byte_order;
163 const unsigned int exponent_digits;
164 const unsigned int mantissa_digits;
165
166private:
167 virtual bool _is_equal(const type& other) const noexcept override final;
168};
169
170class enumeration_type : public integer_type {
171protected:
172 enumeration_type(unsigned int alignment,
173 enum byte_order byte_order,
174 unsigned int size,
175 enum signedness signedness,
e7360180
JG
176 enum base base,
177 integer_type::roles roles = {});
0220be14
JG
178
179 virtual void accept(type_visitor& visitor) const = 0;
180};
181
182namespace details {
183template <class MappingIntegerType>
184class enumeration_mapping_range {
185public:
186 using range_integer_t = MappingIntegerType;
187
188 enumeration_mapping_range(MappingIntegerType in_begin, MappingIntegerType in_end) :
189 begin{in_begin}, end{in_end}
190 {
191 }
192
193 const range_integer_t begin, end;
194};
195
196template <class MappingIntegerType>
197bool operator==(const enumeration_mapping_range<MappingIntegerType>& lhs,
198 const enumeration_mapping_range<MappingIntegerType>& rhs) noexcept
199{
200 return lhs.begin == rhs.begin && lhs.end == rhs.end;
201}
202
203template <class MappingIntegerType>
204class enumeration_mapping {
205public:
206 using range_t = enumeration_mapping_range<MappingIntegerType>;
207
45110cdd 208 enumeration_mapping(const enumeration_mapping<MappingIntegerType>& other) = default;
0220be14
JG
209 enumeration_mapping(const enumeration_mapping<MappingIntegerType>&& other) :
210 name{std::move(other.name)}, range{other.range}
211 {
212 }
213
da9dd521 214 enumeration_mapping(std::string in_name, MappingIntegerType value) : name{std::move(in_name)}, range{value, value}
0220be14
JG
215 {
216 }
217
218 enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range}
219 {
220 }
221
222 const std::string name;
da9dd521
JG
223 /*
224 * Only one range per mapping is supported for the moment as
225 * the tracers (and CTF 1.8) can't express multiple ranges per
226 * mapping, which is allowed by CTF 2.
227 */
228 const range_t range;
0220be14
JG
229};
230
231template <class MappingIntegerType>
232bool operator==(const enumeration_mapping<MappingIntegerType>& lhs,
233 const enumeration_mapping<MappingIntegerType>& rhs) noexcept
234{
235 return lhs.name == rhs.name && lhs.range == rhs.range;
236}
237} /* namespace details */
238
239template <class MappingIntegerType>
240class typed_enumeration_type : public enumeration_type {
241public:
242 using mapping = details::enumeration_mapping<MappingIntegerType>;
243 using mappings = std::vector<mapping>;
244
245 static_assert(std::is_integral<MappingIntegerType>::value &&
246 sizeof(MappingIntegerType) == 8,
247 "MappingIntegerType must be either int64_t or uint64_t");
248
249 typed_enumeration_type(unsigned int in_alignment,
250 enum byte_order in_byte_order,
251 unsigned int in_size,
0220be14 252 enum base in_base,
e7360180
JG
253 const std::shared_ptr<const mappings>& in_mappings,
254 integer_type::roles in_roles = {}) :
0220be14
JG
255 enumeration_type(in_alignment,
256 in_byte_order,
257 in_size,
e7360180
JG
258 std::is_signed<MappingIntegerType>::value ?
259 integer_type::signedness::SIGNED :
260 integer_type::signedness::UNSIGNED,
261 in_base,
262 std::move(in_roles)),
da9dd521 263 mappings_{std::move(in_mappings)}
0220be14
JG
264 {
265 }
266
267 virtual void accept(type_visitor& visitor) const override final;
268
da9dd521 269 const std::shared_ptr<const mappings> mappings_;
0220be14
JG
270
271private:
272 virtual bool _is_equal(const type& base_other) const noexcept override final
273 {
274 const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
275 base_other);
276
da9dd521 277 return integer_type::_is_equal(base_other) && *this->mappings_ == *other.mappings_;
0220be14
JG
278 }
279};
280
281/* Aliases for all allowed enumeration mapping types. */
282using signed_enumeration_type = typed_enumeration_type<int64_t>;
283using unsigned_enumeration_type = typed_enumeration_type<uint64_t>;
284
285class array_type : public type {
286public:
287 array_type(unsigned int alignment, type::cuptr element_type);
288
d7bfb9b0 289 const type::cuptr element_type;
0220be14
JG
290
291protected:
292 virtual bool _is_equal(const type& base_other) const noexcept override;
293};
294
295class static_length_array_type : public array_type {
296public:
297 static_length_array_type(unsigned int alignment,
298 type::cuptr element_type,
299 uint64_t in_length);
300
301 virtual void accept(type_visitor& visitor) const override final;
302
303 const uint64_t length;
304
305private:
306 virtual bool _is_equal(const type& base_other) const noexcept override final;
307};
308
309class dynamic_length_array_type : public array_type {
310public:
311 dynamic_length_array_type(unsigned int alignment,
312 type::cuptr element_type,
eda1aa02 313 field_location length_field_location);
0220be14
JG
314
315 virtual void accept(type_visitor& visitor) const override final;
316
eda1aa02 317 const field_location length_field_location;
0220be14
JG
318
319private:
320 virtual bool _is_equal(const type& base_other) const noexcept override final;
321};
322
e7360180
JG
323class static_length_blob_type : public type {
324public:
325 enum class role {
326 /* Packet header field class specific role. */
da9dd521 327 METADATA_STREAM_UUID,
e7360180
JG
328 };
329
330 using roles = std::vector<role>;
331
332 static_length_blob_type(unsigned int alignment, uint64_t in_length_bytes, roles roles = {});
333
334 virtual void accept(type_visitor& visitor) const override final;
335
336 const uint64_t length_bytes;
337 const roles roles_;
338
339private:
340 virtual bool _is_equal(const type& base_other) const noexcept override final;
341};
342
343class dynamic_length_blob_type : public type {
344public:
eda1aa02 345 dynamic_length_blob_type(unsigned int alignment, field_location length_field_location);
e7360180
JG
346
347 virtual void accept(type_visitor& visitor) const override final;
348
eda1aa02 349 const field_location length_field_location;
e7360180
JG
350
351private:
352 virtual bool _is_equal(const type& base_other) const noexcept override final;
353};
354
0220be14
JG
355class string_type : public type {
356public:
357 enum class encoding {
358 ASCII,
359 UTF8,
360 };
361
362 string_type(unsigned int alignment, enum encoding encoding);
363
65cd3c0c
JG
364 /*
365 * encoding is suffixed with '_' to work-around a bug in older
366 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
367 * nested-name-specifiers.
368 */
369 const encoding encoding_;
0220be14
JG
370
371protected:
372 virtual bool _is_equal(const type& base_other) const noexcept override;
373};
374
375class static_length_string_type : public string_type {
376public:
377 static_length_string_type(
378 unsigned int alignment, enum encoding in_encoding, uint64_t length);
379 virtual void accept(type_visitor& visitor) const override final;
380
381 const uint64_t length;
382
383private:
384 virtual bool _is_equal(const type& base_other) const noexcept override final;
385};
386
387class dynamic_length_string_type : public string_type {
388public:
389 dynamic_length_string_type(unsigned int alignment,
390 enum encoding in_encoding,
eda1aa02 391 field_location length_field_location);
0220be14
JG
392 virtual void accept(type_visitor& visitor) const override final;
393
eda1aa02 394 const field_location length_field_location;
0220be14
JG
395
396private:
397 virtual bool _is_equal(const type& base_other) const noexcept override final;
398};
399
400class null_terminated_string_type : public string_type {
401public:
402 null_terminated_string_type(unsigned int alignment, enum encoding in_encoding);
403 virtual void accept(type_visitor& visitor) const override final;
404};
405
406class structure_type : public type {
407public:
408 using fields = std::vector<field::cuptr>;
409
410 structure_type(unsigned int alignment, fields in_fields);
411
412 virtual void accept(type_visitor& visitor) const override final;
413
da9dd521 414 const fields fields_;
0220be14
JG
415
416private:
417 virtual bool _is_equal(const type& base_other) const noexcept override final;
418};
419
45110cdd 420template <class MappingIntegerType>
0220be14 421class variant_type : public type {
45110cdd
JG
422 static_assert(std::is_same<MappingIntegerType,
423 unsigned_enumeration_type::mapping::range_t::
424 range_integer_t>::value ||
425 std::is_same<MappingIntegerType,
426 signed_enumeration_type::mapping::range_t::
427 range_integer_t>::value,
428 "Variant mapping integer type must be one of those allowed by typed_enumeration_type");
0220be14 429
45110cdd
JG
430public:
431 using choice = std::pair<const details::enumeration_mapping<MappingIntegerType>, type::cuptr>;
432 using choices = std::vector<choice>;
433
434 variant_type(unsigned int in_alignment,
435 field_location in_selector_field_location,
436 choices in_choices) :
437 type(in_alignment),
438 selector_field_location{std::move(in_selector_field_location)},
da9dd521 439 choices_{std::move(in_choices)}
45110cdd
JG
440 {
441 }
0220be14
JG
442
443 virtual void accept(type_visitor& visitor) const override final;
444
eda1aa02 445 const field_location selector_field_location;
da9dd521
JG
446 const choices choices_;
447;
0220be14
JG
448
449private:
45110cdd
JG
450 static bool _choices_are_equal(const choices& a, const choices& b)
451 {
452 if (a.size() != b.size()) {
453 return false;
454 }
455
456 return true;
457
458 return std::equal(a.cbegin(), a.cend(), b.cbegin(),
459 [](const choice& choice_a, const choice& choice_b) {
460 return choice_a.first == choice_b.first &&
461 *choice_a.second == *choice_b.second;
462 });
463 }
464
465 virtual bool _is_equal(const type& base_other) const noexcept override final
466 {
467 const auto& other = static_cast<decltype(*this)&>(base_other);
468
469 return selector_field_location == other.selector_field_location &&
da9dd521 470 _choices_are_equal(choices_, other.choices_);
45110cdd 471 }
0220be14
JG
472};
473
474class field_visitor {
475public:
476 virtual ~field_visitor() = default;
477 virtual void visit(const field& field) = 0;
478
479protected:
480 field_visitor() = default;
481};
482
483class type_visitor {
484public:
485 virtual ~type_visitor() = default;
486 virtual void visit(const integer_type& type) = 0;
487 virtual void visit(const floating_point_type& type) = 0;
488 virtual void visit(const signed_enumeration_type& type) = 0;
489 virtual void visit(const unsigned_enumeration_type& type) = 0;
490 virtual void visit(const static_length_array_type& type) = 0;
491 virtual void visit(const dynamic_length_array_type& type) = 0;
e7360180
JG
492 virtual void visit(const static_length_blob_type& type) = 0;
493 virtual void visit(const dynamic_length_blob_type& type) = 0;
0220be14
JG
494 virtual void visit(const null_terminated_string_type& type) = 0;
495 virtual void visit(const static_length_string_type& type) = 0;
496 virtual void visit(const dynamic_length_string_type& type) = 0;
497 virtual void visit(const structure_type& type) = 0;
45110cdd
JG
498 virtual void visit(const variant_type<signed_enumeration_type::mapping::range_t::range_integer_t>& type) = 0;
499 virtual void visit(const variant_type<unsigned_enumeration_type::mapping::range_t::range_integer_t>& type) = 0;
0220be14
JG
500
501protected:
502 type_visitor() = default;
503};
504
505} /* namespace trace */
506} /* namespace sessiond */
507} /* namespace lttng */
508
6e01cdc6
JG
509/*
510 * Due to a bug in g++ < 7.1, this specialization must be enclosed in the fmt namespace,
511 * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480.
512 */
513namespace fmt {
514template <>
515struct formatter<lttng::sessiond::trace::field_location> : formatter<std::string> {
516 template <typename FormatCtx>
517 typename FormatCtx::iterator format(
518 const lttng::sessiond::trace::field_location& location, FormatCtx& ctx)
519 {
520 std::string location_str{"["};
521
522 switch (location.root_) {
523 case lttng::sessiond::trace::field_location::root::PACKET_HEADER:
524 location_str += "\"packet-header\"";
525 break;
526 case lttng::sessiond::trace::field_location::root::PACKET_CONTEXT:
527 location_str += "\"packet-context\"";
528 break;
529 case lttng::sessiond::trace::field_location::root::EVENT_RECORD_HEADER:
530 location_str += "\"event-record-header\"";
531 break;
532 case lttng::sessiond::trace::field_location::root::EVENT_RECORD_COMMON_CONTEXT:
533 location_str += "\"event-record-common-context\"";
534 break;
535 case lttng::sessiond::trace::field_location::root::EVENT_RECORD_SPECIFIC_CONTEXT:
536 location_str += "\"event-record-specific-context\"";
537 break;
538 case lttng::sessiond::trace::field_location::root::EVENT_RECORD_PAYLOAD:
539 location_str += "\"event-record-payload\"";
540 break;
541 }
542
543 for (const auto &name : location.elements_) {
544 location_str += ", \"" + name + "\"";
545 }
546
547 location_str += "]";
548 return format_to(ctx.out(), location_str);
549 }
550};
551} /* namespace fmt */
552
0220be14 553#endif /* LTTNG_FIELD_H */
This page took 0.05028 seconds and 4 git commands to generate.