docs: Add supported versions and fix-backport policy
[lttng-tools.git] / src / bin / lttng-sessiond / field.cpp
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 #include "field.hpp"
9
10 #include <common/exception.hpp>
11 #include <common/format.hpp>
12
13 #include <set>
14
15 namespace lst = lttng::sessiond::trace;
16
17 namespace {
18 template <class FieldTypeContainerType>
19 bool fields_are_equal(const FieldTypeContainerType& a, const FieldTypeContainerType& b)
20 {
21 if (a.size() != b.size()) {
22 return false;
23 }
24
25 return std::equal(a.cbegin(),
26 a.cend(),
27 b.cbegin(),
28 [](typename FieldTypeContainerType::const_reference field_a,
29 typename FieldTypeContainerType::const_reference field_b) {
30 return *field_a == *field_b;
31 });
32 }
33 } /* namespace */
34
35 lst::field_location::field_location(lst::field_location::root in_lookup_root,
36 lst::field_location::elements in_elements) :
37 root_{ in_lookup_root }, elements_{ std::move(in_elements) }
38 {
39 }
40
41 bool lst::field_location::operator==(const lst::field_location& other) const noexcept
42 {
43 return root_ == other.root_ && elements_ == other.elements_;
44 }
45
46 lst::type::type(unsigned int in_alignment) : alignment{ in_alignment }
47 {
48 }
49
50 lst::type::~type() = default;
51
52 bool lst::type::operator==(const lst::type& other) const noexcept
53 {
54 return typeid(*this) == typeid(other) && alignment == other.alignment &&
55 /* defer to concrete type comparison */
56 this->_is_equal(other);
57 }
58
59 bool lst::type::operator!=(const lst::type& other) const noexcept
60 {
61 return !(*this == other);
62 }
63
64 lst::field::field(std::string in_name, lst::type::cuptr in_type) :
65 name{ std::move(in_name) }, _type{ std::move(in_type) }
66 {
67 if (!_type) {
68 LTTNG_THROW_ERROR(
69 fmt::format("Invalid type used to create field: field name = `{}`", name));
70 }
71 }
72
73 void lst::field::accept(lst::field_visitor& visitor) const
74 {
75 visitor.visit(*this);
76 }
77
78 bool lst::field::operator==(const lst::field& other) const noexcept
79 {
80 return name == other.name && *_type == *other._type;
81 }
82
83 lst::type::cuptr lst::field::move_type() noexcept
84 {
85 return std::move(_type);
86 }
87
88 const lst::type& lst::field::get_type() const
89 {
90 if (_type) {
91 return *_type;
92 } else {
93 LTTNG_THROW_ERROR(fmt::format(
94 "Invalid attempt to access field type after transfer: field name = `{}`",
95 name));
96 }
97 }
98
99 lst::integer_type::integer_type(unsigned int in_alignment,
100 enum lst::byte_order in_byte_order,
101 unsigned int in_size,
102 enum lst::integer_type::signedness in_signedness,
103 enum lst::integer_type::base in_base,
104 roles in_roles) :
105 type(in_alignment),
106 byte_order{ in_byte_order },
107 size{ in_size },
108 signedness_{ in_signedness },
109 base_{ in_base },
110 roles_{ std::move(in_roles) }
111 {
112 }
113
114 lst::type::cuptr lst::integer_type::copy() const
115 {
116 return lttng::make_unique<integer_type>(
117 alignment, byte_order, size, signedness_, base_, roles_);
118 }
119
120 bool lst::integer_type::_is_equal(const type& base_other) const noexcept
121 {
122 const auto& other = static_cast<decltype(*this)&>(base_other);
123
124 return this->byte_order == other.byte_order && this->size == other.size &&
125 this->signedness_ == other.signedness_ && this->base_ == other.base_ &&
126 this->roles_ == other.roles_;
127 }
128
129 void lst::integer_type::accept(type_visitor& visitor) const
130 {
131 visitor.visit(*this);
132 }
133
134 lst::byte_order lst::type::reverse_byte_order(lst::byte_order byte_order) noexcept
135 {
136 if (byte_order == lst::byte_order::BIG_ENDIAN_) {
137 return lst::byte_order::LITTLE_ENDIAN_;
138 } else {
139 return lst::byte_order::BIG_ENDIAN_;
140 }
141 }
142
143 lst::floating_point_type::floating_point_type(unsigned int in_alignment,
144 lst::byte_order in_byte_order,
145 unsigned int in_exponent_digits,
146 unsigned int in_mantissa_digits) :
147 type(in_alignment),
148 byte_order(in_byte_order),
149 exponent_digits{ in_exponent_digits },
150 mantissa_digits(in_mantissa_digits)
151 {
152 /* Allowed (exponent, mantissa) pairs. */
153 static const std::set<std::pair<unsigned int, unsigned int>> allowed_pairs{
154 { 5, 11 }, /* binary16 */
155 { 8, 24 }, /* binary32 */
156 { 11, 53 }, /* binary64 */
157 { 15, 113 }, /* binary128 */
158 };
159
160 if (allowed_pairs.find({ exponent_digits, mantissa_digits }) != allowed_pairs.end()) {
161 /* mantissa and exponent digits is a valid pair. */
162 return;
163 }
164
165 LTTNG_THROW_INVALID_ARGUMENT_ERROR(fmt::format(
166 "Invalid exponent/mantissa values provided while creating {}", typeid(*this)));
167 }
168
169 lst::type::cuptr lst::floating_point_type::copy() const
170 {
171 return lttng::make_unique<floating_point_type>(
172 alignment, byte_order, exponent_digits, mantissa_digits);
173 }
174
175 void lst::floating_point_type::accept(type_visitor& visitor) const
176 {
177 visitor.visit(*this);
178 }
179
180 bool lst::floating_point_type::_is_equal(const type& base_other) const noexcept
181 {
182 const auto& other = static_cast<decltype(*this)&>(base_other);
183
184 return this->byte_order == other.byte_order &&
185 this->exponent_digits == other.exponent_digits &&
186 this->mantissa_digits == other.mantissa_digits;
187 }
188
189 lst::enumeration_type::enumeration_type(unsigned int in_alignment,
190 enum lst::byte_order in_byte_order,
191 unsigned int in_size,
192 enum signedness in_signedness,
193 enum base in_base,
194 lst::integer_type::roles in_roles) :
195 integer_type(
196 in_alignment, in_byte_order, in_size, in_signedness, in_base, std::move(in_roles))
197 {
198 }
199
200 /*
201 * Due to a bug in g++ < 7.1, these specializations must be enclosed in the namespaces
202 * rather than using the usual `namespace::namespace::function` notation:
203 * see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480.
204 */
205 namespace lttng {
206 namespace sessiond {
207 namespace trace {
208 template <>
209 void signed_enumeration_type::accept(type_visitor& visitor) const
210 {
211 visitor.visit(*this);
212 }
213
214 template <>
215 void unsigned_enumeration_type::accept(type_visitor& visitor) const
216 {
217 visitor.visit(*this);
218 }
219
220 template <>
221 void variant_type<lst::signed_enumeration_type::mapping::range_t::range_integer_t>::accept(
222 lst::type_visitor& visitor) const
223 {
224 visitor.visit(*this);
225 }
226
227 template <>
228 void variant_type<lst::unsigned_enumeration_type::mapping::range_t::range_integer_t>::accept(
229 lst::type_visitor& visitor) const
230 {
231 visitor.visit(*this);
232 }
233 } /* namespace trace */
234 } /* namespace sessiond */
235 } /* namespace lttng */
236
237 lst::array_type::array_type(unsigned int in_alignment, type::cuptr in_element_type) :
238 type(in_alignment), element_type{ std::move(in_element_type) }
239 {
240 }
241
242 bool lst::array_type::_is_equal(const type& base_other) const noexcept
243 {
244 const auto& other = static_cast<decltype(*this)&>(base_other);
245
246 return *this->element_type == *other.element_type;
247 }
248
249 lst::static_length_array_type::static_length_array_type(unsigned int in_alignment,
250 type::cuptr in_element_type,
251 uint64_t in_length) :
252 array_type(in_alignment, std::move(in_element_type)), length{ in_length }
253 {
254 }
255
256 bool lst::static_length_array_type::_is_equal(const type& base_other) const noexcept
257 {
258 const auto& other = static_cast<decltype(*this)&>(base_other);
259
260 return array_type::_is_equal(base_other) && this->length == other.length;
261 }
262
263 lst::type::cuptr lst::static_length_array_type::copy() const
264 {
265 return lttng::make_unique<static_length_array_type>(
266 alignment, element_type->copy(), length);
267 }
268
269 void lst::static_length_array_type::accept(type_visitor& visitor) const
270 {
271 visitor.visit(*this);
272 }
273
274 lst::dynamic_length_array_type::dynamic_length_array_type(
275 unsigned int in_alignment,
276 type::cuptr in_element_type,
277 lst::field_location in_length_field_location) :
278 array_type(in_alignment, std::move(in_element_type)),
279 length_field_location{ std::move(in_length_field_location) }
280 {
281 }
282
283 bool lst::dynamic_length_array_type::_is_equal(const type& base_other) const noexcept
284 {
285 const auto& other = static_cast<decltype(*this)&>(base_other);
286
287 return array_type::_is_equal(base_other) &&
288 this->length_field_location == other.length_field_location;
289 }
290
291 lst::type::cuptr lst::dynamic_length_array_type::copy() const
292 {
293 return lttng::make_unique<dynamic_length_array_type>(
294 alignment, element_type->copy(), length_field_location);
295 }
296
297 void lst::dynamic_length_array_type::accept(type_visitor& visitor) const
298 {
299 visitor.visit(*this);
300 }
301
302 lst::static_length_blob_type::static_length_blob_type(unsigned int in_alignment,
303 uint64_t in_length_bytes,
304 roles in_roles) :
305 type(in_alignment), length_bytes{ in_length_bytes }, roles_{ std::move(in_roles) }
306 {
307 }
308
309 bool lst::static_length_blob_type::_is_equal(const type& base_other) const noexcept
310 {
311 const auto& other = static_cast<decltype(*this)&>(base_other);
312
313 return length_bytes == other.length_bytes && roles_ == other.roles_;
314 }
315
316 lst::type::cuptr lst::static_length_blob_type::copy() const
317 {
318 return lttng::make_unique<static_length_blob_type>(alignment, length_bytes, roles_);
319 }
320
321 void lst::static_length_blob_type::accept(type_visitor& visitor) const
322 {
323 visitor.visit(*this);
324 }
325
326 lst::dynamic_length_blob_type::dynamic_length_blob_type(
327 unsigned int in_alignment, lst::field_location in_length_field_location) :
328 type(in_alignment), length_field_location{ std::move(in_length_field_location) }
329 {
330 }
331
332 bool lst::dynamic_length_blob_type::_is_equal(const type& base_other) const noexcept
333 {
334 const auto& other = dynamic_cast<decltype(*this)&>(base_other);
335
336 return length_field_location == other.length_field_location;
337 }
338
339 lst::type::cuptr lst::dynamic_length_blob_type::copy() const
340 {
341 return lttng::make_unique<dynamic_length_blob_type>(alignment, length_field_location);
342 }
343
344 void lst::dynamic_length_blob_type::accept(type_visitor& visitor) const
345 {
346 visitor.visit(*this);
347 }
348
349 lst::string_type::string_type(unsigned int in_alignment, enum encoding in_encoding) :
350 type(in_alignment), encoding_{ in_encoding }
351 {
352 }
353
354 bool lst::string_type::_is_equal(const type& base_other) const noexcept
355 {
356 const auto& other = static_cast<decltype(*this)&>(base_other);
357
358 return this->encoding_ == other.encoding_;
359 }
360
361 lst::static_length_string_type::static_length_string_type(unsigned int in_alignment,
362 enum encoding in_encoding,
363 uint64_t in_length) :
364 string_type(in_alignment, in_encoding), length{ in_length }
365 {
366 }
367
368 bool lst::static_length_string_type::_is_equal(const type& base_other) const noexcept
369 {
370 const auto& other = static_cast<decltype(*this)&>(base_other);
371
372 return string_type::_is_equal(base_other) && this->length == other.length;
373 }
374
375 lst::type::cuptr lst::static_length_string_type::copy() const
376 {
377 return lttng::make_unique<static_length_string_type>(alignment, encoding_, length);
378 }
379
380 void lst::static_length_string_type::accept(type_visitor& visitor) const
381 {
382 visitor.visit(*this);
383 }
384
385 lst::dynamic_length_string_type::dynamic_length_string_type(
386 unsigned int in_alignment,
387 enum encoding in_encoding,
388 field_location in_length_field_location) :
389 string_type(in_alignment, in_encoding),
390 length_field_location{ std::move(in_length_field_location) }
391 {
392 }
393
394 bool lst::dynamic_length_string_type::_is_equal(const type& base_other) const noexcept
395 {
396 const auto& other = static_cast<decltype(*this)&>(base_other);
397
398 return string_type::_is_equal(base_other) &&
399 this->length_field_location == other.length_field_location;
400 }
401
402 lst::type::cuptr lst::dynamic_length_string_type::copy() const
403 {
404 return lttng::make_unique<dynamic_length_string_type>(
405 alignment, encoding_, length_field_location);
406 }
407
408 void lst::dynamic_length_string_type::accept(type_visitor& visitor) const
409 {
410 visitor.visit(*this);
411 }
412
413 lst::null_terminated_string_type::null_terminated_string_type(unsigned int in_alignment,
414 enum encoding in_encoding) :
415 string_type(in_alignment, in_encoding)
416 {
417 }
418
419 lst::type::cuptr lst::null_terminated_string_type::copy() const
420 {
421 return lttng::make_unique<null_terminated_string_type>(alignment, encoding_);
422 }
423
424 void lst::null_terminated_string_type::accept(type_visitor& visitor) const
425 {
426 visitor.visit(*this);
427 }
428
429 lst::structure_type::structure_type(unsigned int in_alignment, fields in_fields) :
430 type(in_alignment), fields_{ std::move(in_fields) }
431 {
432 }
433
434 bool lst::structure_type::_is_equal(const type& base_other) const noexcept
435 {
436 const auto& other = static_cast<decltype(*this)&>(base_other);
437
438 return fields_are_equal(this->fields_, other.fields_);
439 }
440
441 lst::type::cuptr lst::structure_type::copy() const
442 {
443 structure_type::fields copy_of_fields;
444
445 copy_of_fields.reserve(fields_.size());
446 for (const auto& field : fields_) {
447 copy_of_fields.emplace_back(
448 lttng::make_unique<lst::field>(field->name, field->get_type().copy()));
449 }
450
451 return lttng::make_unique<structure_type>(alignment, std::move(copy_of_fields));
452 }
453
454 void lst::structure_type::accept(type_visitor& visitor) const
455 {
456 visitor.visit(*this);
457 }
This page took 0.038427 seconds and 4 git commands to generate.