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