sessiond: field: add field roles and blob types
[lttng-tools.git] / src / bin / lttng-sessiond / field.hpp
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
11 #include "trace-class.hpp"
12
13 #include <memory>
14 #include <string>
15 #include <type_traits>
16 #include <vector>
17
18 #include <vendor/optional.hpp>
19
20 namespace lttng {
21 namespace sessiond {
22 namespace trace {
23
24 class field_visitor;
25 class type_visitor;
26
27 /*
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
30 * specification.
31 */
32
33 class type {
34 public:
35 using cuptr = std::unique_ptr<const type>;
36
37 static byte_order reverse_byte_order(byte_order byte_order) noexcept;
38
39 bool operator==(const type& other) const noexcept;
40 bool operator!=(const type& other) const noexcept;
41 virtual ~type();
42 virtual void accept(type_visitor& visitor) const = 0;
43
44 const unsigned int alignment;
45
46 protected:
47 type(unsigned int alignment);
48
49 private:
50 virtual bool _is_equal(const type& rhs) const noexcept = 0;
51 };
52
53 class field {
54 public:
55 using cuptr = std::unique_ptr<const field>;
56
57 field(std::string name, type::cuptr type);
58 void accept(field_visitor& visitor) const;
59 bool operator==(const field& other) const noexcept;
60
61 const std::string name;
62 const type::cuptr _type;
63 };
64
65 class integer_type : public type {
66 public:
67 enum class signedness {
68 SIGNED,
69 UNSIGNED,
70 };
71
72 enum class base {
73 BINARY = 2,
74 OCTAL = 8,
75 DECIMAL = 10,
76 HEXADECIMAL = 16,
77 };
78
79 enum class role {
80 DEFAULT_CLOCK_TIMESTAMP,
81 /* Packet header field class specific roles. */
82 DATA_STREAM_CLASS_ID,
83 DATA_STREAM_ID,
84 PACKET_MAGIC_NUMBER,
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,
90 PACKET_TOTAL_LENGTH,
91 /* Event record field class roles. */
92 EVENT_RECORD_CLASS_ID,
93 };
94
95 using roles = std::vector<role>;
96
97 integer_type(unsigned int alignment,
98 byte_order byte_order,
99 unsigned int size,
100 signedness signedness,
101 base base,
102 roles roles = {});
103
104 virtual void accept(type_visitor& visitor) const override;
105
106 const enum byte_order byte_order;
107 const unsigned int size;
108 /*
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.
112 */
113 const signedness signedness_;
114 const base base_;
115 const roles roles_;
116
117 protected:
118 virtual bool _is_equal(const type& other) const noexcept override;
119 };
120
121 class floating_point_type : public type {
122 public:
123 floating_point_type(unsigned int alignment,
124 byte_order byte_order,
125 unsigned int exponent_digits,
126 unsigned int mantissa_digits);
127
128 virtual void accept(type_visitor& visitor) const override final;
129
130 const enum byte_order byte_order;
131 const unsigned int exponent_digits;
132 const unsigned int mantissa_digits;
133
134 private:
135 virtual bool _is_equal(const type& other) const noexcept override final;
136 };
137
138 class enumeration_type : public integer_type {
139 protected:
140 enumeration_type(unsigned int alignment,
141 enum byte_order byte_order,
142 unsigned int size,
143 enum signedness signedness,
144 enum base base,
145 integer_type::roles roles = {});
146
147 virtual void accept(type_visitor& visitor) const = 0;
148 };
149
150 namespace details {
151 template <class MappingIntegerType>
152 class enumeration_mapping_range {
153 public:
154 using range_integer_t = MappingIntegerType;
155
156 enumeration_mapping_range(MappingIntegerType in_begin, MappingIntegerType in_end) :
157 begin{in_begin}, end{in_end}
158 {
159 }
160
161 const range_integer_t begin, end;
162 };
163
164 template <class MappingIntegerType>
165 bool operator==(const enumeration_mapping_range<MappingIntegerType>& lhs,
166 const enumeration_mapping_range<MappingIntegerType>& rhs) noexcept
167 {
168 return lhs.begin == rhs.begin && lhs.end == rhs.end;
169 }
170
171 template <class MappingIntegerType>
172 class enumeration_mapping {
173 public:
174 using range_t = enumeration_mapping_range<MappingIntegerType>;
175
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}
179 {
180 }
181
182 /* Mapping with an implicit value. */
183 enumeration_mapping(std::string in_name) : name{std::move(in_name)}
184 {
185 }
186
187 enumeration_mapping(std::string in_name, range_t in_range) : name{std::move(in_name)}, range{in_range}
188 {
189 }
190
191 const std::string name;
192 const nonstd::optional<range_t> range;
193 };
194
195 template <class MappingIntegerType>
196 bool operator==(const enumeration_mapping<MappingIntegerType>& lhs,
197 const enumeration_mapping<MappingIntegerType>& rhs) noexcept
198 {
199 return lhs.name == rhs.name && lhs.range == rhs.range;
200 }
201 } /* namespace details */
202
203 template <class MappingIntegerType>
204 class typed_enumeration_type : public enumeration_type {
205 public:
206 using mapping = details::enumeration_mapping<MappingIntegerType>;
207 using mappings = std::vector<mapping>;
208
209 static_assert(std::is_integral<MappingIntegerType>::value &&
210 sizeof(MappingIntegerType) == 8,
211 "MappingIntegerType must be either int64_t or uint64_t");
212
213 typed_enumeration_type(unsigned int in_alignment,
214 enum byte_order in_byte_order,
215 unsigned int in_size,
216 enum base in_base,
217 const std::shared_ptr<const mappings>& in_mappings,
218 integer_type::roles in_roles = {}) :
219 enumeration_type(in_alignment,
220 in_byte_order,
221 in_size,
222 std::is_signed<MappingIntegerType>::value ?
223 integer_type::signedness::SIGNED :
224 integer_type::signedness::UNSIGNED,
225 in_base,
226 std::move(in_roles)),
227 _mappings{std::move(in_mappings)}
228 {
229 }
230
231 virtual void accept(type_visitor& visitor) const override final;
232
233 const std::shared_ptr<const mappings> _mappings;
234
235 private:
236 virtual bool _is_equal(const type& base_other) const noexcept override final
237 {
238 const auto& other = static_cast<const typed_enumeration_type<MappingIntegerType>&>(
239 base_other);
240
241 return integer_type::_is_equal(base_other) && *this->_mappings == *other._mappings;
242 }
243 };
244
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>;
248
249 class array_type : public type {
250 public:
251 array_type(unsigned int alignment, type::cuptr element_type);
252
253 const type::cuptr element_type;
254
255 protected:
256 virtual bool _is_equal(const type& base_other) const noexcept override;
257 };
258
259 class static_length_array_type : public array_type {
260 public:
261 static_length_array_type(unsigned int alignment,
262 type::cuptr element_type,
263 uint64_t in_length);
264
265 virtual void accept(type_visitor& visitor) const override final;
266
267 const uint64_t length;
268
269 private:
270 virtual bool _is_equal(const type& base_other) const noexcept override final;
271 };
272
273 class dynamic_length_array_type : public array_type {
274 public:
275 dynamic_length_array_type(unsigned int alignment,
276 type::cuptr element_type,
277 std::string length_field_name);
278
279 virtual void accept(type_visitor& visitor) const override final;
280
281 const std::string length_field_name;
282
283 private:
284 virtual bool _is_equal(const type& base_other) const noexcept override final;
285 };
286
287 class static_length_blob_type : public type {
288 public:
289 enum class role {
290 /* Packet header field class specific role. */
291 TRACE_CLASS_UUID,
292 };
293
294 using roles = std::vector<role>;
295
296 static_length_blob_type(unsigned int alignment, uint64_t in_length_bytes, roles roles = {});
297
298 virtual void accept(type_visitor& visitor) const override final;
299
300 const uint64_t length_bytes;
301 const roles roles_;
302
303 private:
304 virtual bool _is_equal(const type& base_other) const noexcept override final;
305 };
306
307 class dynamic_length_blob_type : public type {
308 public:
309 dynamic_length_blob_type(unsigned int alignment, std::string length_field_name);
310
311 virtual void accept(type_visitor& visitor) const override final;
312
313 const std::string length_field_name;
314
315 private:
316 virtual bool _is_equal(const type& base_other) const noexcept override final;
317 };
318
319 class string_type : public type {
320 public:
321 enum class encoding {
322 ASCII,
323 UTF8,
324 };
325
326 string_type(unsigned int alignment, enum encoding encoding);
327
328 /*
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.
332 */
333 const encoding encoding_;
334
335 protected:
336 virtual bool _is_equal(const type& base_other) const noexcept override;
337 };
338
339 class static_length_string_type : public string_type {
340 public:
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;
344
345 const uint64_t length;
346
347 private:
348 virtual bool _is_equal(const type& base_other) const noexcept override final;
349 };
350
351 class dynamic_length_string_type : public string_type {
352 public:
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;
357
358 const std::string length_field_name;
359
360 private:
361 virtual bool _is_equal(const type& base_other) const noexcept override final;
362 };
363
364 class null_terminated_string_type : public string_type {
365 public:
366 null_terminated_string_type(unsigned int alignment, enum encoding in_encoding);
367 virtual void accept(type_visitor& visitor) const override final;
368 };
369
370 class structure_type : public type {
371 public:
372 using fields = std::vector<field::cuptr>;
373
374 structure_type(unsigned int alignment, fields in_fields);
375
376 virtual void accept(type_visitor& visitor) const override final;
377
378 const fields _fields;
379
380 private:
381 virtual bool _is_equal(const type& base_other) const noexcept override final;
382 };
383
384 class variant_type : public type {
385 public:
386 using choices = std::vector<field::cuptr>;
387
388 variant_type(unsigned int alignment, std::string tag_name, choices in_choices);
389
390 virtual void accept(type_visitor& visitor) const override final;
391
392 const std::string tag_name;
393 const choices _choices;
394
395 private:
396 virtual bool _is_equal(const type& base_other) const noexcept override final;
397 };
398
399 class field_visitor {
400 public:
401 virtual ~field_visitor() = default;
402 virtual void visit(const field& field) = 0;
403
404 protected:
405 field_visitor() = default;
406 };
407
408 class type_visitor {
409 public:
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;
424
425 protected:
426 type_visitor() = default;
427 };
428
429 } /* namespace trace */
430 } /* namespace sessiond */
431 } /* namespace lttng */
432
433 #endif /* LTTNG_FIELD_H */
This page took 0.038372 seconds and 5 git commands to generate.