sessiond: express field references as locations instead of names
[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
0220be14
JG
11#include <memory>
12#include <string>
13#include <type_traits>
14#include <vector>
15
16#include <vendor/optional.hpp>
17
18namespace lttng {
19namespace sessiond {
20namespace trace {
21
22class field_visitor;
23class type_visitor;
24
24ed18f2
JG
25enum class byte_order {
26 BIG_ENDIAN_,
27 LITTLE_ENDIAN_,
28};
29
eda1aa02
JG
30class field_location {
31public:
32 enum class root {
33 PACKET_HEADER,
34 PACKET_CONTEXT,
35 EVENT_RECORD_HEADER,
36 EVENT_RECORD_COMMON_CONTEXT,
37 EVENT_RECORD_SPECIFIC_CONTEXT,
38 EVENT_RECORD_PAYLOAD,
39 };
40
41 using elements = std::vector<std::string>;
42
43 field_location(root lookup_root, elements elements);
44 bool operator==(const field_location& other) const noexcept;
45
46 const root root_;
47 const elements elements_;
48};
49
0220be14
JG
50/*
51 * Field, and the various field types, represents fields as exposed by the
52 * LTTng tracers. These classes do not attempt to describe the complete spectrum of the CTF
53 * specification.
54 */
55
56class type {
57public:
58 using cuptr = std::unique_ptr<const type>;
59
60 static byte_order reverse_byte_order(byte_order byte_order) noexcept;
61
62 bool operator==(const type& other) const noexcept;
63 bool operator!=(const type& other) const noexcept;
64 virtual ~type();
65 virtual void accept(type_visitor& visitor) const = 0;
66
67 const unsigned int alignment;
68
69protected:
70 type(unsigned int alignment);
71
72private:
73 virtual bool _is_equal(const type& rhs) const noexcept = 0;
74};
75
76class field {
77public:
78 using cuptr = std::unique_ptr<const field>;
79
80 field(std::string name, type::cuptr type);
81 void accept(field_visitor& visitor) const;
82 bool operator==(const field& other) const noexcept;
83
84 const std::string name;
85 const type::cuptr _type;
86};
87
88class integer_type : public type {
89public:
90 enum class signedness {
91 SIGNED,
92 UNSIGNED,
93 };
94
95 enum class base {
96 BINARY = 2,
97 OCTAL = 8,
98 DECIMAL = 10,
99 HEXADECIMAL = 16,
100 };
101
e7360180
JG
102 enum class role {
103 DEFAULT_CLOCK_TIMESTAMP,
104 /* Packet header field class specific roles. */
105 DATA_STREAM_CLASS_ID,
106 DATA_STREAM_ID,
107 PACKET_MAGIC_NUMBER,
108 /* Packet context field class specific roles. */
109 DISCARDED_EVENT_RECORD_COUNTER_SNAPSHOT,
110 PACKET_CONTENT_LENGTH,
111 PACKET_END_DEFAULT_CLOCK_TIMESTAMP,
112 PACKET_SEQUENCE_NUMBER,
113 PACKET_TOTAL_LENGTH,
114 /* Event record field class roles. */
115 EVENT_RECORD_CLASS_ID,
116 };
117
118 using roles = std::vector<role>;
119
0220be14
JG
120 integer_type(unsigned int alignment,
121 byte_order byte_order,
122 unsigned int size,
123 signedness signedness,
e7360180
JG
124 base base,
125 roles roles = {});
0220be14
JG
126
127 virtual void accept(type_visitor& visitor) const override;
128
129 const enum byte_order byte_order;
130 const unsigned int size;
65cd3c0c
JG
131 /*
132 * signedness and base are suffixed with '_' to work-around a bug in older
133 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
134 * nested-name-specifiers.
135 */
136 const signedness signedness_;
137 const base base_;
e7360180 138 const roles roles_;
0220be14
JG
139
140protected:
141 virtual bool _is_equal(const type& other) const noexcept override;
142};
143
144class floating_point_type : public type {
145public:
146 floating_point_type(unsigned int alignment,
147 byte_order byte_order,
148 unsigned int exponent_digits,
149 unsigned int mantissa_digits);
150
151 virtual void accept(type_visitor& visitor) const override final;
152
153 const enum byte_order byte_order;
154 const unsigned int exponent_digits;
155 const unsigned int mantissa_digits;
156
157private:
158 virtual bool _is_equal(const type& other) const noexcept override final;
159};
160
161class enumeration_type : public integer_type {
162protected:
163 enumeration_type(unsigned int alignment,
164 enum byte_order byte_order,
165 unsigned int size,
166 enum signedness signedness,
e7360180
JG
167 enum base base,
168 integer_type::roles roles = {});
0220be14
JG
169
170 virtual void accept(type_visitor& visitor) const = 0;
171};
172
173namespace details {
174template <class MappingIntegerType>
175class enumeration_mapping_range {
176public:
177 using range_integer_t = MappingIntegerType;
178
179 enumeration_mapping_range(MappingIntegerType in_begin, MappingIntegerType in_end) :
180 begin{in_begin}, end{in_end}
181 {
182 }
183
184 const range_integer_t begin, end;
185};
186
187template <class MappingIntegerType>
188bool operator==(const enumeration_mapping_range<MappingIntegerType>& lhs,
189 const enumeration_mapping_range<MappingIntegerType>& rhs) noexcept
190{
191 return lhs.begin == rhs.begin && lhs.end == rhs.end;
192}
193
194template <class MappingIntegerType>
195class enumeration_mapping {
196public:
197 using range_t = enumeration_mapping_range<MappingIntegerType>;
198
199 enumeration_mapping(const enumeration_mapping<MappingIntegerType>& other) = delete;
200 enumeration_mapping(const enumeration_mapping<MappingIntegerType>&& other) :
201 name{std::move(other.name)}, range{other.range}
202 {
203 }
204
205 /* Mapping with an implicit value. */
206 enumeration_mapping(std::string in_name) : name{std::move(in_name)}
207 {
208 }
209
210 enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range}
211 {
212 }
213
214 const std::string name;
215 const nonstd::optional<range_t> range;
216};
217
218template <class MappingIntegerType>
219bool operator==(const enumeration_mapping<MappingIntegerType>& lhs,
220 const enumeration_mapping<MappingIntegerType>& rhs) noexcept
221{
222 return lhs.name == rhs.name && lhs.range == rhs.range;
223}
224} /* namespace details */
225
226template <class MappingIntegerType>
227class typed_enumeration_type : public enumeration_type {
228public:
229 using mapping = details::enumeration_mapping<MappingIntegerType>;
230 using mappings = std::vector<mapping>;
231
232 static_assert(std::is_integral<MappingIntegerType>::value &&
233 sizeof(MappingIntegerType) == 8,
234 "MappingIntegerType must be either int64_t or uint64_t");
235
236 typed_enumeration_type(unsigned int in_alignment,
237 enum byte_order in_byte_order,
238 unsigned int in_size,
0220be14 239 enum base in_base,
e7360180
JG
240 const std::shared_ptr<const mappings>& in_mappings,
241 integer_type::roles in_roles = {}) :
0220be14
JG
242 enumeration_type(in_alignment,
243 in_byte_order,
244 in_size,
e7360180
JG
245 std::is_signed<MappingIntegerType>::value ?
246 integer_type::signedness::SIGNED :
247 integer_type::signedness::UNSIGNED,
248 in_base,
249 std::move(in_roles)),
0220be14
JG
250 _mappings{std::move(in_mappings)}
251 {
252 }
253
254 virtual void accept(type_visitor& visitor) const override final;
255
256 const std::shared_ptr<const mappings> _mappings;
257
258private:
259 virtual bool _is_equal(const type& base_other) const noexcept override final
260 {
261 const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
262 base_other);
263
264 return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings;
265 }
266};
267
268/* Aliases for all allowed enumeration mapping types. */
269using signed_enumeration_type = typed_enumeration_type<int64_t>;
270using unsigned_enumeration_type = typed_enumeration_type<uint64_t>;
271
272class array_type : public type {
273public:
274 array_type(unsigned int alignment, type::cuptr element_type);
275
d7bfb9b0 276 const type::cuptr element_type;
0220be14
JG
277
278protected:
279 virtual bool _is_equal(const type& base_other) const noexcept override;
280};
281
282class static_length_array_type : public array_type {
283public:
284 static_length_array_type(unsigned int alignment,
285 type::cuptr element_type,
286 uint64_t in_length);
287
288 virtual void accept(type_visitor& visitor) const override final;
289
290 const uint64_t length;
291
292private:
293 virtual bool _is_equal(const type& base_other) const noexcept override final;
294};
295
296class dynamic_length_array_type : public array_type {
297public:
298 dynamic_length_array_type(unsigned int alignment,
299 type::cuptr element_type,
eda1aa02 300 field_location length_field_location);
0220be14
JG
301
302 virtual void accept(type_visitor& visitor) const override final;
303
eda1aa02 304 const field_location length_field_location;
0220be14
JG
305
306private:
307 virtual bool _is_equal(const type& base_other) const noexcept override final;
308};
309
e7360180
JG
310class static_length_blob_type : public type {
311public:
312 enum class role {
313 /* Packet header field class specific role. */
314 TRACE_CLASS_UUID,
315 };
316
317 using roles = std::vector<role>;
318
319 static_length_blob_type(unsigned int alignment, uint64_t in_length_bytes, roles roles = {});
320
321 virtual void accept(type_visitor& visitor) const override final;
322
323 const uint64_t length_bytes;
324 const roles roles_;
325
326private:
327 virtual bool _is_equal(const type& base_other) const noexcept override final;
328};
329
330class dynamic_length_blob_type : public type {
331public:
eda1aa02 332 dynamic_length_blob_type(unsigned int alignment, field_location length_field_location);
e7360180
JG
333
334 virtual void accept(type_visitor& visitor) const override final;
335
eda1aa02 336 const field_location length_field_location;
e7360180
JG
337
338private:
339 virtual bool _is_equal(const type& base_other) const noexcept override final;
340};
341
0220be14
JG
342class string_type : public type {
343public:
344 enum class encoding {
345 ASCII,
346 UTF8,
347 };
348
349 string_type(unsigned int alignment, enum encoding encoding);
350
65cd3c0c
JG
351 /*
352 * encoding is suffixed with '_' to work-around a bug in older
353 * GCCs (before 6) that do not recognize hidden/shadowed enumeration as valid
354 * nested-name-specifiers.
355 */
356 const encoding encoding_;
0220be14
JG
357
358protected:
359 virtual bool _is_equal(const type& base_other) const noexcept override;
360};
361
362class static_length_string_type : public string_type {
363public:
364 static_length_string_type(
365 unsigned int alignment, enum encoding in_encoding, uint64_t length);
366 virtual void accept(type_visitor& visitor) const override final;
367
368 const uint64_t length;
369
370private:
371 virtual bool _is_equal(const type& base_other) const noexcept override final;
372};
373
374class dynamic_length_string_type : public string_type {
375public:
376 dynamic_length_string_type(unsigned int alignment,
377 enum encoding in_encoding,
eda1aa02 378 field_location length_field_location);
0220be14
JG
379 virtual void accept(type_visitor& visitor) const override final;
380
eda1aa02 381 const field_location length_field_location;
0220be14
JG
382
383private:
384 virtual bool _is_equal(const type& base_other) const noexcept override final;
385};
386
387class null_terminated_string_type : public string_type {
388public:
389 null_terminated_string_type(unsigned int alignment, enum encoding in_encoding);
390 virtual void accept(type_visitor& visitor) const override final;
391};
392
393class structure_type : public type {
394public:
395 using fields = std::vector<field::cuptr>;
396
397 structure_type(unsigned int alignment, fields in_fields);
398
399 virtual void accept(type_visitor& visitor) const override final;
400
401 const fields _fields;
402
403private:
404 virtual bool _is_equal(const type& base_other) const noexcept override final;
405};
406
407class variant_type : public type {
408public:
409 using choices = std::vector<field::cuptr>;
410
eda1aa02
JG
411 variant_type(unsigned int alignment,
412 field_location selector_field_location,
413 choices in_choices);
0220be14
JG
414
415 virtual void accept(type_visitor& visitor) const override final;
416
eda1aa02 417 const field_location selector_field_location;
0220be14 418 const choices _choices;
eda1aa02 419;
0220be14
JG
420
421private:
422 virtual bool _is_equal(const type& base_other) const noexcept override final;
423};
424
425class field_visitor {
426public:
427 virtual ~field_visitor() = default;
428 virtual void visit(const field& field) = 0;
429
430protected:
431 field_visitor() = default;
432};
433
434class type_visitor {
435public:
436 virtual ~type_visitor() = default;
437 virtual void visit(const integer_type& type) = 0;
438 virtual void visit(const floating_point_type& type) = 0;
439 virtual void visit(const signed_enumeration_type& type) = 0;
440 virtual void visit(const unsigned_enumeration_type& type) = 0;
441 virtual void visit(const static_length_array_type& type) = 0;
442 virtual void visit(const dynamic_length_array_type& type) = 0;
e7360180
JG
443 virtual void visit(const static_length_blob_type& type) = 0;
444 virtual void visit(const dynamic_length_blob_type& type) = 0;
0220be14
JG
445 virtual void visit(const null_terminated_string_type& type) = 0;
446 virtual void visit(const static_length_string_type& type) = 0;
447 virtual void visit(const dynamic_length_string_type& type) = 0;
448 virtual void visit(const structure_type& type) = 0;
449 virtual void visit(const variant_type& type) = 0;
450
451protected:
452 type_visitor() = default;
453};
454
455} /* namespace trace */
456} /* namespace sessiond */
457} /* namespace lttng */
458
459#endif /* LTTNG_FIELD_H */
This page took 0.042702 seconds and 4 git commands to generate.