Commit | Line | Data |
---|---|---|
273b65be | 1 | /* |
2e33ac5a | 2 | * field-types.c |
273b65be | 3 | * |
d2dc44b6 | 4 | * Babeltrace CTF IR - Event Types |
273b65be | 5 | * |
de9dd397 | 6 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
273b65be JG |
7 | * |
8 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
9 | * | |
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
11 | * of this software and associated documentation files (the "Software"), to deal | |
12 | * in the Software without restriction, including without limitation the rights | |
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
14 | * copies of the Software, and to permit persons to whom the Software is | |
15 | * furnished to do so, subject to the following conditions: | |
16 | * | |
17 | * The above copyright notice and this permission notice shall be included in | |
18 | * all copies or substantial portions of the Software. | |
19 | * | |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
26 | * SOFTWARE. | |
27 | */ | |
28 | ||
4e8304f7 PP |
29 | #define BT_LOG_TAG "FIELD-TYPES" |
30 | #include <babeltrace/lib-logging-internal.h> | |
31 | ||
2e33ac5a | 32 | #include <babeltrace/ctf-ir/field-types-internal.h> |
b011f6b0 | 33 | #include <babeltrace/ctf-ir/field-path-internal.h> |
654c1444 | 34 | #include <babeltrace/ctf-ir/utils.h> |
83509119 | 35 | #include <babeltrace/ref.h> |
ac0c6bdd PP |
36 | #include <babeltrace/ctf-ir/clock-class.h> |
37 | #include <babeltrace/ctf-ir/clock-class-internal.h> | |
273b65be | 38 | #include <babeltrace/ctf-writer/writer-internal.h> |
83509119 JG |
39 | #include <babeltrace/object-internal.h> |
40 | #include <babeltrace/ref.h> | |
3d9990ac PP |
41 | #include <babeltrace/compiler-internal.h> |
42 | #include <babeltrace/endian-internal.h> | |
f6ccaed9 | 43 | #include <babeltrace/assert-internal.h> |
d975f66c | 44 | #include <babeltrace/assert-pre-internal.h> |
273b65be JG |
45 | #include <float.h> |
46 | #include <inttypes.h> | |
a39fa057 | 47 | #include <stdlib.h> |
273b65be | 48 | |
d975f66c PP |
49 | #define BT_ASSERT_PRE_FT_HAS_ID(_ft, _type_id, _name) \ |
50 | BT_ASSERT_PRE((_ft)->id == (_type_id), \ | |
51 | _name " has the wrong type ID: expected-type-id=%s, " \ | |
52 | "%![ft-]+F", bt_field_type_id_string(_type_id), (_ft)) | |
53 | ||
54 | #define BT_ASSERT_PRE_FT_HOT(_ft, _name) \ | |
55 | BT_ASSERT_PRE_HOT((_ft), (_name), ": +%!+F", (_ft)) | |
56 | ||
273b65be | 57 | struct range_overlap_query { |
b92ddaaa JG |
58 | union { |
59 | uint64_t _unsigned; | |
60 | int64_t _signed; | |
61 | } range_start; | |
62 | ||
63 | union { | |
64 | uint64_t _unsigned; | |
65 | int64_t _signed; | |
66 | } range_end; | |
273b65be JG |
67 | int overlaps; |
68 | GQuark mapping_name; | |
69 | }; | |
70 | ||
2f2d8e05 | 71 | static |
50842bdc | 72 | void bt_field_type_destroy(struct bt_object *); |
273b65be | 73 | static |
50842bdc | 74 | void bt_field_type_integer_destroy(struct bt_field_type *); |
273b65be | 75 | static |
50842bdc | 76 | void bt_field_type_enumeration_destroy(struct bt_field_type *); |
273b65be | 77 | static |
50842bdc | 78 | void bt_field_type_floating_point_destroy(struct bt_field_type *); |
273b65be | 79 | static |
50842bdc | 80 | void bt_field_type_structure_destroy(struct bt_field_type *); |
273b65be | 81 | static |
50842bdc | 82 | void bt_field_type_variant_destroy(struct bt_field_type *); |
273b65be | 83 | static |
50842bdc | 84 | void bt_field_type_array_destroy(struct bt_field_type *); |
273b65be | 85 | static |
50842bdc | 86 | void bt_field_type_sequence_destroy(struct bt_field_type *); |
273b65be | 87 | static |
50842bdc | 88 | void bt_field_type_string_destroy(struct bt_field_type *); |
273b65be JG |
89 | |
90 | static | |
50842bdc PP |
91 | void (* const type_destroy_funcs[])(struct bt_field_type *) = { |
92 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_destroy, | |
93 | [BT_FIELD_TYPE_ID_ENUM] = | |
94 | bt_field_type_enumeration_destroy, | |
95 | [BT_FIELD_TYPE_ID_FLOAT] = | |
96 | bt_field_type_floating_point_destroy, | |
97 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_destroy, | |
98 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_destroy, | |
99 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_destroy, | |
100 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_destroy, | |
101 | [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_destroy, | |
273b65be JG |
102 | }; |
103 | ||
104 | static | |
50842bdc | 105 | void generic_field_type_freeze(struct bt_field_type *); |
273b65be | 106 | static |
50842bdc | 107 | void bt_field_type_integer_freeze(struct bt_field_type *); |
586411e5 | 108 | static |
50842bdc | 109 | void bt_field_type_enumeration_freeze(struct bt_field_type *); |
273b65be | 110 | static |
50842bdc | 111 | void bt_field_type_structure_freeze(struct bt_field_type *); |
273b65be | 112 | static |
50842bdc | 113 | void bt_field_type_variant_freeze(struct bt_field_type *); |
273b65be | 114 | static |
50842bdc | 115 | void bt_field_type_array_freeze(struct bt_field_type *); |
273b65be | 116 | static |
50842bdc | 117 | void bt_field_type_sequence_freeze(struct bt_field_type *); |
273b65be JG |
118 | |
119 | static | |
120 | type_freeze_func const type_freeze_funcs[] = { | |
50842bdc PP |
121 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_freeze, |
122 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_freeze, | |
123 | [BT_FIELD_TYPE_ID_FLOAT] = generic_field_type_freeze, | |
124 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_freeze, | |
125 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_freeze, | |
126 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_freeze, | |
127 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_freeze, | |
128 | [BT_FIELD_TYPE_ID_STRING] = generic_field_type_freeze, | |
273b65be JG |
129 | }; |
130 | ||
131 | static | |
50842bdc | 132 | int bt_field_type_integer_serialize(struct bt_field_type *, |
273b65be JG |
133 | struct metadata_context *); |
134 | static | |
50842bdc | 135 | int bt_field_type_enumeration_serialize(struct bt_field_type *, |
273b65be JG |
136 | struct metadata_context *); |
137 | static | |
50842bdc PP |
138 | int bt_field_type_floating_point_serialize( |
139 | struct bt_field_type *, struct metadata_context *); | |
273b65be | 140 | static |
50842bdc | 141 | int bt_field_type_structure_serialize(struct bt_field_type *, |
273b65be JG |
142 | struct metadata_context *); |
143 | static | |
50842bdc | 144 | int bt_field_type_variant_serialize(struct bt_field_type *, |
273b65be JG |
145 | struct metadata_context *); |
146 | static | |
50842bdc | 147 | int bt_field_type_array_serialize(struct bt_field_type *, |
273b65be JG |
148 | struct metadata_context *); |
149 | static | |
50842bdc | 150 | int bt_field_type_sequence_serialize(struct bt_field_type *, |
273b65be JG |
151 | struct metadata_context *); |
152 | static | |
50842bdc | 153 | int bt_field_type_string_serialize(struct bt_field_type *, |
273b65be JG |
154 | struct metadata_context *); |
155 | ||
156 | static | |
157 | type_serialize_func const type_serialize_funcs[] = { | |
50842bdc PP |
158 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_serialize, |
159 | [BT_FIELD_TYPE_ID_ENUM] = | |
160 | bt_field_type_enumeration_serialize, | |
161 | [BT_FIELD_TYPE_ID_FLOAT] = | |
162 | bt_field_type_floating_point_serialize, | |
163 | [BT_FIELD_TYPE_ID_STRUCT] = | |
164 | bt_field_type_structure_serialize, | |
165 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_serialize, | |
166 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_serialize, | |
167 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_serialize, | |
168 | [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_serialize, | |
273b65be JG |
169 | }; |
170 | ||
171 | static | |
50842bdc PP |
172 | void bt_field_type_integer_set_byte_order(struct bt_field_type *, |
173 | enum bt_byte_order byte_order); | |
c35a1669 | 174 | static |
50842bdc PP |
175 | void bt_field_type_enumeration_set_byte_order(struct bt_field_type *, |
176 | enum bt_byte_order byte_order); | |
273b65be | 177 | static |
50842bdc PP |
178 | void bt_field_type_floating_point_set_byte_order( |
179 | struct bt_field_type *, enum bt_byte_order byte_order); | |
c35a1669 | 180 | static |
50842bdc PP |
181 | void bt_field_type_structure_set_byte_order(struct bt_field_type *, |
182 | enum bt_byte_order byte_order); | |
c35a1669 | 183 | static |
50842bdc PP |
184 | void bt_field_type_variant_set_byte_order(struct bt_field_type *, |
185 | enum bt_byte_order byte_order); | |
c35a1669 | 186 | static |
50842bdc PP |
187 | void bt_field_type_array_set_byte_order(struct bt_field_type *, |
188 | enum bt_byte_order byte_order); | |
c35a1669 | 189 | static |
50842bdc PP |
190 | void bt_field_type_sequence_set_byte_order(struct bt_field_type *, |
191 | enum bt_byte_order byte_order); | |
273b65be JG |
192 | |
193 | static | |
50842bdc PP |
194 | void (* const set_byte_order_funcs[])(struct bt_field_type *, |
195 | enum bt_byte_order) = { | |
196 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_set_byte_order, | |
197 | [BT_FIELD_TYPE_ID_ENUM] = | |
198 | bt_field_type_enumeration_set_byte_order, | |
199 | [BT_FIELD_TYPE_ID_FLOAT] = | |
200 | bt_field_type_floating_point_set_byte_order, | |
201 | [BT_FIELD_TYPE_ID_STRUCT] = | |
202 | bt_field_type_structure_set_byte_order, | |
203 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_set_byte_order, | |
204 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_set_byte_order, | |
205 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_set_byte_order, | |
206 | [BT_FIELD_TYPE_ID_STRING] = NULL, | |
273b65be JG |
207 | }; |
208 | ||
24724933 | 209 | static |
50842bdc PP |
210 | struct bt_field_type *bt_field_type_integer_copy( |
211 | struct bt_field_type *); | |
24724933 | 212 | static |
50842bdc PP |
213 | struct bt_field_type *bt_field_type_enumeration_copy( |
214 | struct bt_field_type *); | |
24724933 | 215 | static |
50842bdc PP |
216 | struct bt_field_type *bt_field_type_floating_point_copy( |
217 | struct bt_field_type *); | |
24724933 | 218 | static |
50842bdc PP |
219 | struct bt_field_type *bt_field_type_structure_copy( |
220 | struct bt_field_type *); | |
24724933 | 221 | static |
50842bdc PP |
222 | struct bt_field_type *bt_field_type_variant_copy( |
223 | struct bt_field_type *); | |
24724933 | 224 | static |
50842bdc PP |
225 | struct bt_field_type *bt_field_type_array_copy( |
226 | struct bt_field_type *); | |
24724933 | 227 | static |
50842bdc PP |
228 | struct bt_field_type *bt_field_type_sequence_copy( |
229 | struct bt_field_type *); | |
24724933 | 230 | static |
50842bdc PP |
231 | struct bt_field_type *bt_field_type_string_copy( |
232 | struct bt_field_type *); | |
24724933 JG |
233 | |
234 | static | |
50842bdc PP |
235 | struct bt_field_type *(* const type_copy_funcs[])( |
236 | struct bt_field_type *) = { | |
237 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_copy, | |
238 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_copy, | |
239 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_type_floating_point_copy, | |
240 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_copy, | |
241 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_copy, | |
242 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_copy, | |
243 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_copy, | |
244 | [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_copy, | |
24724933 JG |
245 | }; |
246 | ||
265e809c | 247 | static |
50842bdc PP |
248 | int bt_field_type_integer_compare(struct bt_field_type *, |
249 | struct bt_field_type *); | |
265e809c | 250 | static |
50842bdc PP |
251 | int bt_field_type_floating_point_compare(struct bt_field_type *, |
252 | struct bt_field_type *); | |
265e809c | 253 | static |
50842bdc PP |
254 | int bt_field_type_enumeration_compare(struct bt_field_type *, |
255 | struct bt_field_type *); | |
265e809c | 256 | static |
50842bdc PP |
257 | int bt_field_type_string_compare(struct bt_field_type *, |
258 | struct bt_field_type *); | |
265e809c | 259 | static |
50842bdc PP |
260 | int bt_field_type_structure_compare(struct bt_field_type *, |
261 | struct bt_field_type *); | |
265e809c | 262 | static |
50842bdc PP |
263 | int bt_field_type_variant_compare(struct bt_field_type *, |
264 | struct bt_field_type *); | |
265e809c | 265 | static |
50842bdc PP |
266 | int bt_field_type_array_compare(struct bt_field_type *, |
267 | struct bt_field_type *); | |
265e809c | 268 | static |
50842bdc PP |
269 | int bt_field_type_sequence_compare(struct bt_field_type *, |
270 | struct bt_field_type *); | |
265e809c PP |
271 | |
272 | static | |
50842bdc PP |
273 | int (* const type_compare_funcs[])(struct bt_field_type *, |
274 | struct bt_field_type *) = { | |
275 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_compare, | |
276 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_compare, | |
277 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_type_floating_point_compare, | |
278 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_compare, | |
279 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_compare, | |
280 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_compare, | |
281 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_compare, | |
282 | [BT_FIELD_TYPE_ID_STRING] = bt_field_type_string_compare, | |
265e809c PP |
283 | }; |
284 | ||
b3dbeb52 | 285 | static |
50842bdc | 286 | int bt_field_type_integer_validate(struct bt_field_type *); |
81e36fac | 287 | static |
50842bdc | 288 | int bt_field_type_enumeration_validate(struct bt_field_type *); |
81e36fac | 289 | static |
50842bdc | 290 | int bt_field_type_structure_validate(struct bt_field_type *); |
81e36fac | 291 | static |
50842bdc | 292 | int bt_field_type_variant_validate(struct bt_field_type *); |
81e36fac | 293 | static |
50842bdc | 294 | int bt_field_type_array_validate(struct bt_field_type *); |
81e36fac | 295 | static |
50842bdc | 296 | int bt_field_type_sequence_validate(struct bt_field_type *); |
81e36fac PP |
297 | |
298 | static | |
50842bdc PP |
299 | int (* const type_validate_funcs[])(struct bt_field_type *) = { |
300 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_type_integer_validate, | |
301 | [BT_FIELD_TYPE_ID_FLOAT] = NULL, | |
302 | [BT_FIELD_TYPE_ID_STRING] = NULL, | |
303 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_type_enumeration_validate, | |
304 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_type_structure_validate, | |
305 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_type_variant_validate, | |
306 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_type_array_validate, | |
307 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_type_sequence_validate, | |
81e36fac PP |
308 | }; |
309 | ||
273b65be JG |
310 | static |
311 | void destroy_enumeration_mapping(struct enumeration_mapping *mapping) | |
312 | { | |
313 | g_free(mapping); | |
314 | } | |
315 | ||
316 | static | |
317 | void destroy_structure_field(struct structure_field *field) | |
318 | { | |
34462b62 PP |
319 | if (!field) { |
320 | return; | |
321 | } | |
322 | ||
323 | BT_LOGD("Destroying structure/variant field type's field object: " | |
324 | "addr=%p, field-ft-addr=%p, field-name=\"%s\"", | |
325 | field, field->type, g_quark_to_string(field->name)); | |
ec159b1e | 326 | BT_LOGD_STR("Putting field type."); |
83509119 | 327 | bt_put(field->type); |
273b65be JG |
328 | g_free(field); |
329 | } | |
330 | ||
331 | static | |
332 | void check_ranges_overlap(gpointer element, gpointer query) | |
333 | { | |
334 | struct enumeration_mapping *mapping = element; | |
335 | struct range_overlap_query *overlap_query = query; | |
336 | ||
b92ddaaa | 337 | if (mapping->range_start._signed <= overlap_query->range_end._signed |
4e8304f7 PP |
338 | && overlap_query->range_start._signed <= |
339 | mapping->range_end._signed) { | |
b92ddaaa JG |
340 | overlap_query->overlaps = 1; |
341 | overlap_query->mapping_name = mapping->string; | |
342 | } | |
343 | ||
344 | overlap_query->overlaps |= | |
345 | mapping->string == overlap_query->mapping_name; | |
4e8304f7 PP |
346 | |
347 | if (overlap_query->overlaps) { | |
348 | BT_LOGV("Overlapping enumeration field type mappings: " | |
349 | "mapping-name=\"%s\", " | |
350 | "mapping-a-range-start=%" PRId64 ", " | |
351 | "mapping-a-range-end=%" PRId64 ", " | |
352 | "mapping-b-range-start=%" PRId64 ", " | |
353 | "mapping-b-range-end=%" PRId64, | |
354 | g_quark_to_string(mapping->string), | |
355 | mapping->range_start._signed, | |
356 | mapping->range_end._signed, | |
357 | overlap_query->range_start._signed, | |
358 | overlap_query->range_end._signed); | |
359 | } | |
b92ddaaa JG |
360 | } |
361 | ||
362 | static | |
363 | void check_ranges_overlap_unsigned(gpointer element, gpointer query) | |
364 | { | |
365 | struct enumeration_mapping *mapping = element; | |
366 | struct range_overlap_query *overlap_query = query; | |
367 | ||
368 | if (mapping->range_start._unsigned <= overlap_query->range_end._unsigned | |
4e8304f7 PP |
369 | && overlap_query->range_start._unsigned <= |
370 | mapping->range_end._unsigned) { | |
273b65be JG |
371 | overlap_query->overlaps = 1; |
372 | overlap_query->mapping_name = mapping->string; | |
373 | } | |
374 | ||
375 | overlap_query->overlaps |= | |
376 | mapping->string == overlap_query->mapping_name; | |
4e8304f7 PP |
377 | |
378 | if (overlap_query->overlaps) { | |
379 | BT_LOGW("Overlapping enumeration field type mappings: " | |
380 | "mapping-name=\"%s\", " | |
381 | "mapping-a-range-start=%" PRIu64 ", " | |
382 | "mapping-a-range-end=%" PRIu64 ", " | |
383 | "mapping-b-range-start=%" PRIu64 ", " | |
384 | "mapping-b-range-end=%" PRIu64, | |
385 | g_quark_to_string(mapping->string), | |
386 | mapping->range_start._unsigned, | |
387 | mapping->range_end._unsigned, | |
388 | overlap_query->range_start._unsigned, | |
389 | overlap_query->range_end._unsigned); | |
390 | } | |
273b65be JG |
391 | } |
392 | ||
b92ddaaa JG |
393 | static |
394 | gint compare_enumeration_mappings_signed(struct enumeration_mapping **a, | |
395 | struct enumeration_mapping **b) | |
396 | { | |
397 | return ((*a)->range_start._signed < (*b)->range_start._signed) ? -1 : 1; | |
398 | } | |
399 | ||
400 | static | |
401 | gint compare_enumeration_mappings_unsigned(struct enumeration_mapping **a, | |
402 | struct enumeration_mapping **b) | |
403 | { | |
404 | return ((*a)->range_start._unsigned < (*b)->range_start._unsigned) ? -1 : 1; | |
405 | } | |
406 | ||
273b65be | 407 | static |
50842bdc | 408 | void bt_field_type_init(struct bt_field_type *type, bt_bool init_bo) |
273b65be | 409 | { |
f6ccaed9 | 410 | BT_ASSERT(type && (type->id > BT_FIELD_TYPE_ID_UNKNOWN) && |
50842bdc | 411 | (type->id < BT_FIELD_TYPE_ID_NR)); |
273b65be | 412 | |
50842bdc | 413 | bt_object_init(type, bt_field_type_destroy); |
dc3fffef PP |
414 | type->freeze = type_freeze_funcs[type->id]; |
415 | type->serialize = type_serialize_funcs[type->id]; | |
59acd4f5 PP |
416 | |
417 | if (init_bo) { | |
ec159b1e | 418 | int ret; |
50842bdc | 419 | const enum bt_byte_order bo = BT_BYTE_ORDER_NATIVE; |
ec159b1e PP |
420 | |
421 | BT_LOGD("Setting initial field type's byte order: bo=%s", | |
50842bdc PP |
422 | bt_byte_order_string(bo)); |
423 | ret = bt_field_type_set_byte_order(type, bo); | |
f6ccaed9 | 424 | BT_ASSERT(ret == 0); |
59acd4f5 PP |
425 | } |
426 | ||
dc3fffef | 427 | type->alignment = 1; |
273b65be JG |
428 | } |
429 | ||
430 | static | |
431 | int add_structure_field(GPtrArray *fields, | |
432 | GHashTable *field_name_to_index, | |
50842bdc | 433 | struct bt_field_type *field_type, |
273b65be JG |
434 | const char *field_name) |
435 | { | |
436 | int ret = 0; | |
437 | GQuark name_quark = g_quark_from_string(field_name); | |
438 | struct structure_field *field; | |
439 | ||
440 | /* Make sure structure does not contain a field of the same name */ | |
fe0fe95c | 441 | if (g_hash_table_lookup_extended(field_name_to_index, |
4e8304f7 PP |
442 | GUINT_TO_POINTER(name_quark), NULL, NULL)) { |
443 | BT_LOGW("Structure or variant field type already contains a field type with this name: " | |
444 | "field-name=\"%s\"", field_name); | |
273b65be JG |
445 | ret = -1; |
446 | goto end; | |
447 | } | |
448 | ||
449 | field = g_new0(struct structure_field, 1); | |
450 | if (!field) { | |
4e8304f7 | 451 | BT_LOGE_STR("Failed to allocate one structure/variant field type field."); |
273b65be JG |
452 | ret = -1; |
453 | goto end; | |
454 | } | |
455 | ||
83509119 | 456 | bt_get(field_type); |
273b65be JG |
457 | field->name = name_quark; |
458 | field->type = field_type; | |
459 | g_hash_table_insert(field_name_to_index, | |
5b44aff2 MJ |
460 | GUINT_TO_POINTER(name_quark), |
461 | GUINT_TO_POINTER(fields->len)); | |
273b65be | 462 | g_ptr_array_add(fields, field); |
dfc1504d PP |
463 | BT_LOGV("Added structure/variant field type field: field-ft-addr=%p, " |
464 | "field-name=\"%s\"", field_type, field_name); | |
273b65be JG |
465 | end: |
466 | return ret; | |
467 | } | |
468 | ||
2f2d8e05 | 469 | static |
50842bdc | 470 | void bt_field_type_destroy(struct bt_object *obj) |
2f2d8e05 | 471 | { |
50842bdc PP |
472 | struct bt_field_type *type; |
473 | enum bt_field_type_id type_id; | |
2f2d8e05 | 474 | |
50842bdc | 475 | type = container_of(obj, struct bt_field_type, base); |
dc3fffef | 476 | type_id = type->id; |
f6ccaed9 | 477 | BT_ASSERT(type_id > BT_FIELD_TYPE_ID_UNKNOWN && |
50842bdc | 478 | type_id < BT_FIELD_TYPE_ID_NR); |
de3dd40e | 479 | type_destroy_funcs[type_id](type); |
2f2d8e05 JG |
480 | } |
481 | ||
b3dbeb52 | 482 | static |
50842bdc | 483 | int bt_field_type_integer_validate(struct bt_field_type *type) |
b3dbeb52 PP |
484 | { |
485 | int ret = 0; | |
486 | ||
50842bdc PP |
487 | struct bt_field_type_integer *integer = |
488 | container_of(type, struct bt_field_type_integer, | |
b3dbeb52 PP |
489 | parent); |
490 | ||
dc3fffef | 491 | if (integer->mapped_clock && integer->is_signed) { |
4e8304f7 PP |
492 | BT_LOGW("Invalid integer field type: cannot be signed and have a mapped clock class: " |
493 | "ft-addr=%p, clock-class-addr=%p, clock-class-name=\"%s\"", | |
494 | type, integer->mapped_clock, | |
50842bdc | 495 | bt_clock_class_get_name(integer->mapped_clock)); |
b3dbeb52 PP |
496 | ret = -1; |
497 | goto end; | |
498 | } | |
499 | ||
500 | end: | |
501 | return ret; | |
502 | } | |
503 | ||
d49e1284 JG |
504 | static |
505 | struct enumeration_mapping *get_enumeration_mapping( | |
50842bdc | 506 | struct bt_field_type *type, uint64_t index) |
d49e1284 JG |
507 | { |
508 | struct enumeration_mapping *mapping = NULL; | |
50842bdc | 509 | struct bt_field_type_enumeration *enumeration; |
d49e1284 | 510 | |
50842bdc | 511 | enumeration = container_of(type, struct bt_field_type_enumeration, |
d49e1284 JG |
512 | parent); |
513 | if (index >= enumeration->entries->len) { | |
4e8304f7 PP |
514 | BT_LOGW("Invalid parameter: index is out of bounds: " |
515 | "addr=%p, index=%" PRIu64 ", count=%u", | |
516 | type, index, enumeration->entries->len); | |
d49e1284 JG |
517 | goto end; |
518 | } | |
519 | ||
520 | mapping = g_ptr_array_index(enumeration->entries, index); | |
521 | end: | |
522 | return mapping; | |
523 | } | |
524 | ||
525 | /* | |
526 | * Note: This algorithm is O(n^2) vs number of enumeration mappings. | |
527 | * Only used when freezing an enumeration. | |
528 | */ | |
529 | static | |
530 | void set_enumeration_range_overlap( | |
50842bdc | 531 | struct bt_field_type *type) |
d49e1284 | 532 | { |
4e8304f7 | 533 | int64_t i, j, len; |
50842bdc PP |
534 | struct bt_field_type *container_type; |
535 | struct bt_field_type_enumeration *enumeration_type; | |
d49e1284 JG |
536 | int is_signed; |
537 | ||
4e8304f7 PP |
538 | BT_LOGV("Setting enumeration field type's overlap flag: addr=%p", |
539 | type); | |
d49e1284 | 540 | enumeration_type = container_of(type, |
50842bdc | 541 | struct bt_field_type_enumeration, parent); |
d49e1284 JG |
542 | |
543 | len = enumeration_type->entries->len; | |
544 | container_type = enumeration_type->container; | |
50842bdc | 545 | is_signed = bt_field_type_integer_is_signed(container_type); |
d49e1284 JG |
546 | |
547 | for (i = 0; i < len; i++) { | |
548 | for (j = i + 1; j < len; j++) { | |
549 | struct enumeration_mapping *mapping[2]; | |
550 | ||
551 | mapping[0] = get_enumeration_mapping(type, i); | |
552 | mapping[1] = get_enumeration_mapping(type, j); | |
553 | if (is_signed) { | |
554 | if (mapping[0]->range_start._signed | |
555 | <= mapping[1]->range_end._signed | |
556 | && mapping[0]->range_end._signed | |
557 | >= mapping[1]->range_start._signed) { | |
c55a9f58 | 558 | enumeration_type->has_overlapping_ranges = BT_TRUE; |
dfc1504d | 559 | goto end; |
d49e1284 JG |
560 | } |
561 | } else { | |
562 | if (mapping[0]->range_start._unsigned | |
563 | <= mapping[1]->range_end._unsigned | |
564 | && mapping[0]->range_end._unsigned | |
565 | >= mapping[1]->range_start._unsigned) { | |
c55a9f58 | 566 | enumeration_type->has_overlapping_ranges = BT_TRUE; |
dfc1504d | 567 | goto end; |
d49e1284 JG |
568 | } |
569 | } | |
570 | } | |
571 | } | |
dfc1504d PP |
572 | |
573 | end: | |
574 | if (enumeration_type->has_overlapping_ranges) { | |
575 | BT_LOGV_STR("Enumeration field type has overlapping ranges."); | |
576 | } else { | |
577 | BT_LOGV_STR("Enumeration field type has no overlapping ranges."); | |
578 | } | |
d49e1284 JG |
579 | } |
580 | ||
81e36fac | 581 | static |
50842bdc | 582 | int bt_field_type_enumeration_validate(struct bt_field_type *type) |
9ce21c30 JG |
583 | { |
584 | int ret = 0; | |
585 | ||
50842bdc PP |
586 | struct bt_field_type_enumeration *enumeration = |
587 | container_of(type, struct bt_field_type_enumeration, | |
81e36fac | 588 | parent); |
50842bdc PP |
589 | struct bt_field_type *container_type = |
590 | bt_field_type_enumeration_get_container_type(type); | |
81e36fac | 591 | |
f6ccaed9 | 592 | BT_ASSERT(container_type); |
50842bdc | 593 | ret = bt_field_type_validate(container_type); |
81e36fac | 594 | if (ret) { |
4e8304f7 PP |
595 | BT_LOGW("Invalid enumeration field type: container type is invalid: " |
596 | "enum-ft-addr=%p, int-ft-addr=%p", | |
597 | type, container_type); | |
81e36fac PP |
598 | goto end; |
599 | } | |
9ce21c30 | 600 | |
81e36fac | 601 | /* Ensure enum has entries */ |
4e8304f7 PP |
602 | if (enumeration->entries->len == 0) { |
603 | BT_LOGW("Invalid enumeration field type: no entries: " | |
604 | "addr=%p", type); | |
605 | ret = -1; | |
606 | goto end; | |
607 | } | |
81e36fac PP |
608 | |
609 | end: | |
610 | BT_PUT(container_type); | |
611 | return ret; | |
612 | } | |
613 | ||
614 | static | |
50842bdc | 615 | int bt_field_type_sequence_validate(struct bt_field_type *type) |
81e36fac PP |
616 | { |
617 | int ret = 0; | |
50842bdc PP |
618 | struct bt_field_type *element_type = NULL; |
619 | struct bt_field_type_sequence *sequence = | |
620 | container_of(type, struct bt_field_type_sequence, | |
81e36fac PP |
621 | parent); |
622 | ||
623 | /* Length field name should be set at this point */ | |
624 | if (sequence->length_field_name->len == 0) { | |
4e8304f7 PP |
625 | BT_LOGW("Invalid sequence field type: no length field name: " |
626 | "addr=%p", type); | |
81e36fac PP |
627 | ret = -1; |
628 | goto end; | |
5d161ecc | 629 | } |
81e36fac | 630 | |
50842bdc | 631 | element_type = bt_field_type_sequence_get_element_type(type); |
f6ccaed9 | 632 | BT_ASSERT(element_type); |
50842bdc | 633 | ret = bt_field_type_validate(element_type); |
4e8304f7 PP |
634 | if (ret) { |
635 | BT_LOGW("Invalid sequence field type: invalid element field type: " | |
636 | "seq-ft-addr=%p, element-ft-add=%p", | |
637 | type, element_type); | |
638 | } | |
81e36fac PP |
639 | |
640 | end: | |
641 | BT_PUT(element_type); | |
642 | ||
643 | return ret; | |
644 | } | |
645 | ||
646 | static | |
50842bdc | 647 | int bt_field_type_array_validate(struct bt_field_type *type) |
81e36fac PP |
648 | { |
649 | int ret = 0; | |
50842bdc | 650 | struct bt_field_type *element_type = NULL; |
81e36fac | 651 | |
50842bdc | 652 | element_type = bt_field_type_array_get_element_type(type); |
f6ccaed9 | 653 | BT_ASSERT(element_type); |
50842bdc | 654 | ret = bt_field_type_validate(element_type); |
4e8304f7 PP |
655 | if (ret) { |
656 | BT_LOGW("Invalid array field type: invalid element field type: " | |
657 | "array-ft-addr=%p, element-ft-add=%p", | |
658 | type, element_type); | |
659 | } | |
81e36fac | 660 | |
81e36fac | 661 | BT_PUT(element_type); |
81e36fac PP |
662 | return ret; |
663 | } | |
664 | ||
665 | static | |
50842bdc | 666 | int bt_field_type_structure_validate(struct bt_field_type *type) |
81e36fac PP |
667 | { |
668 | int ret = 0; | |
50842bdc PP |
669 | struct bt_field_type *child_type = NULL; |
670 | int64_t field_count = bt_field_type_structure_get_field_count(type); | |
544d0515 | 671 | int64_t i; |
81e36fac | 672 | |
f6ccaed9 | 673 | BT_ASSERT(field_count >= 0); |
81e36fac PP |
674 | |
675 | for (i = 0; i < field_count; ++i) { | |
4e8304f7 | 676 | const char *field_name; |
81e36fac | 677 | |
50842bdc | 678 | ret = bt_field_type_structure_get_field_by_index(type, |
4e8304f7 | 679 | &field_name, &child_type, i); |
f6ccaed9 | 680 | BT_ASSERT(ret == 0); |
50842bdc | 681 | ret = bt_field_type_validate(child_type); |
81e36fac | 682 | if (ret) { |
4e8304f7 PP |
683 | BT_LOGW("Invalid structure field type: " |
684 | "a contained field type is invalid: " | |
685 | "struct-ft-addr=%p, field-ft-addr=%p, " | |
686 | "field-name=\"%s\", field-index=%" PRId64, | |
687 | type, child_type, field_name, i); | |
81e36fac PP |
688 | goto end; |
689 | } | |
690 | ||
691 | BT_PUT(child_type); | |
692 | } | |
693 | ||
694 | end: | |
695 | BT_PUT(child_type); | |
696 | ||
697 | return ret; | |
698 | } | |
699 | ||
96e8f959 | 700 | static |
50842bdc PP |
701 | bt_bool bt_field_type_enumeration_has_overlapping_ranges( |
702 | struct bt_field_type_enumeration *enumeration_type) | |
96e8f959 | 703 | { |
d49e1284 JG |
704 | if (!enumeration_type->parent.frozen) { |
705 | set_enumeration_range_overlap(&enumeration_type->parent); | |
706 | } | |
96e8f959 MD |
707 | return enumeration_type->has_overlapping_ranges; |
708 | } | |
709 | ||
81e36fac | 710 | static |
50842bdc | 711 | int bt_field_type_variant_validate(struct bt_field_type *type) |
81e36fac PP |
712 | { |
713 | int ret = 0; | |
544d0515 | 714 | int64_t field_count; |
50842bdc PP |
715 | struct bt_field_type *child_type = NULL; |
716 | struct bt_field_type_variant *variant = | |
717 | container_of(type, struct bt_field_type_variant, | |
c6c0ca42 | 718 | parent); |
544d0515 | 719 | int64_t i; |
c6c0ca42 | 720 | |
4e8304f7 PP |
721 | if (variant->tag_name->len == 0) { |
722 | BT_LOGW("Invalid variant field type: no tag field name: " | |
723 | "addr=%p", type); | |
724 | ret = -1; | |
725 | goto end; | |
726 | } | |
727 | ||
728 | if (!variant->tag) { | |
729 | BT_LOGW("Invalid variant field type: no tag field type: " | |
730 | "addr=%p, tag-field-name=\"%s\"", type, | |
731 | variant->tag_name->str); | |
81e36fac PP |
732 | ret = -1; |
733 | goto end; | |
734 | } | |
735 | ||
50842bdc | 736 | if (bt_field_type_enumeration_has_overlapping_ranges( |
96e8f959 | 737 | variant->tag)) { |
4e8304f7 PP |
738 | BT_LOGW("Invalid variant field type: enumeration tag field type has overlapping ranges: " |
739 | "variant-ft-addr=%p, tag-field-name=\"%s\", " | |
740 | "enum-ft-addr=%p", type, variant->tag_name->str, | |
741 | variant->tag); | |
96e8f959 MD |
742 | ret = -1; |
743 | goto end; | |
744 | } | |
745 | ||
e9eb537e | 746 | /* |
2d4b0539 MD |
747 | * It is valid to have a variant field type which does not have |
748 | * the fields corresponding to each label in the associated | |
749 | * enumeration. | |
e9eb537e | 750 | * |
2d4b0539 MD |
751 | * It is also valid to have variant field type fields which |
752 | * cannot be selected because the variant field type tag has no | |
753 | * mapping named as such. This scenario, while not ideal, cannot | |
754 | * cause any error. | |
755 | * | |
756 | * If a non-existing field happens to be selected by an | |
757 | * enumeration while reading a variant field, an error will be | |
758 | * generated at that point (while reading the stream). | |
e9eb537e | 759 | */ |
50842bdc | 760 | field_count = bt_field_type_variant_get_field_count(type); |
81e36fac | 761 | if (field_count < 0) { |
4e8304f7 PP |
762 | BT_LOGW("Invalid variant field type: no fields: " |
763 | "addr=%p, tag-field-name=\"%s\"", | |
764 | type, variant->tag_name->str); | |
81e36fac PP |
765 | ret = -1; |
766 | goto end; | |
767 | } | |
768 | ||
769 | for (i = 0; i < field_count; ++i) { | |
4e8304f7 | 770 | const char *field_name; |
81e36fac | 771 | |
50842bdc | 772 | ret = bt_field_type_variant_get_field_by_index(type, |
4e8304f7 | 773 | &field_name, &child_type, i); |
f6ccaed9 | 774 | BT_ASSERT(ret == 0); |
50842bdc | 775 | ret = bt_field_type_validate(child_type); |
81e36fac | 776 | if (ret) { |
4e8304f7 PP |
777 | BT_LOGW("Invalid variant field type: " |
778 | "a contained field type is invalid: " | |
779 | "variant-ft-addr=%p, tag-field-name=\"%s\", " | |
780 | "field-ft-addr=%p, field-name=\"%s\", " | |
781 | "field-index=%" PRId64, | |
782 | type, variant->tag_name->str, child_type, | |
783 | field_name, i); | |
81e36fac PP |
784 | goto end; |
785 | } | |
786 | ||
787 | BT_PUT(child_type); | |
788 | } | |
789 | ||
790 | end: | |
791 | BT_PUT(child_type); | |
792 | ||
793 | return ret; | |
794 | } | |
795 | ||
796 | /* | |
797 | * This function validates a given field type without considering | |
798 | * where this field type is located. It only validates the properties | |
799 | * of the given field type and the properties of its children if | |
800 | * applicable. | |
801 | */ | |
802 | BT_HIDDEN | |
50842bdc | 803 | int bt_field_type_validate(struct bt_field_type *type) |
81e36fac PP |
804 | { |
805 | int ret = 0; | |
50842bdc | 806 | enum bt_field_type_id id = bt_field_type_get_type_id(type); |
81e36fac | 807 | |
f6ccaed9 | 808 | BT_ASSERT(type); |
81e36fac PP |
809 | |
810 | if (type->valid) { | |
811 | /* Already marked as valid */ | |
812 | goto end; | |
813 | } | |
814 | ||
815 | if (type_validate_funcs[id]) { | |
816 | ret = type_validate_funcs[id](type); | |
817 | } | |
818 | ||
819 | if (!ret && type->frozen) { | |
820 | /* Field type is valid */ | |
ec159b1e | 821 | BT_LOGV("Marking field type as valid: addr=%p", type); |
81e36fac PP |
822 | type->valid = 1; |
823 | } | |
824 | ||
9ce21c30 JG |
825 | end: |
826 | return ret; | |
827 | } | |
828 | ||
50842bdc | 829 | struct bt_field_type *bt_field_type_integer_create(unsigned int size) |
273b65be | 830 | { |
50842bdc PP |
831 | struct bt_field_type_integer *integer = |
832 | g_new0(struct bt_field_type_integer, 1); | |
273b65be | 833 | |
4e8304f7 PP |
834 | BT_LOGD("Creating integer field type object: size=%u", size); |
835 | ||
836 | if (!integer) { | |
837 | BT_LOGE_STR("Failed to allocate one integer field type."); | |
838 | return NULL; | |
839 | } | |
840 | ||
841 | if (size == 0 || size > 64) { | |
842 | BT_LOGW("Invalid parameter: size must be between 1 and 64: " | |
843 | "size=%u", size); | |
273b65be JG |
844 | return NULL; |
845 | } | |
846 | ||
50842bdc | 847 | integer->parent.id = BT_FIELD_TYPE_ID_INTEGER; |
dc3fffef | 848 | integer->size = size; |
50842bdc PP |
849 | integer->base = BT_INTEGER_BASE_DECIMAL; |
850 | integer->encoding = BT_STRING_ENCODING_NONE; | |
851 | bt_field_type_init(&integer->parent, TRUE); | |
4e8304f7 PP |
852 | BT_LOGD("Created integer field type object: addr=%p, size=%u", |
853 | &integer->parent, size); | |
273b65be JG |
854 | return &integer->parent; |
855 | } | |
856 | ||
50842bdc | 857 | int bt_field_type_integer_get_size(struct bt_field_type *type) |
b92ddaaa | 858 | { |
50842bdc | 859 | struct bt_field_type_integer *integer; |
b92ddaaa | 860 | |
d975f66c PP |
861 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
862 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type"); | |
50842bdc | 863 | integer = container_of(type, struct bt_field_type_integer, parent); |
d975f66c | 864 | return (int) integer->size; |
b92ddaaa JG |
865 | } |
866 | ||
50842bdc | 867 | int bt_ctf_field_type_integer_get_signed(struct bt_field_type *type) |
b92ddaaa | 868 | { |
50842bdc | 869 | struct bt_field_type_integer *integer; |
b92ddaaa | 870 | |
d975f66c PP |
871 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
872 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type"); | |
50842bdc | 873 | integer = container_of(type, struct bt_field_type_integer, parent); |
d975f66c | 874 | return integer->is_signed; |
b92ddaaa JG |
875 | } |
876 | ||
50842bdc PP |
877 | bt_bool bt_field_type_integer_is_signed( |
878 | struct bt_field_type *int_field_type) | |
c14d64fa PP |
879 | { |
880 | return bt_ctf_field_type_integer_get_signed(int_field_type) ? | |
881 | BT_TRUE : BT_FALSE; | |
882 | } | |
883 | ||
50842bdc | 884 | int bt_field_type_integer_set_is_signed(struct bt_field_type *type, |
c14d64fa | 885 | bt_bool is_signed) |
273b65be JG |
886 | { |
887 | int ret = 0; | |
50842bdc | 888 | struct bt_field_type_integer *integer; |
273b65be | 889 | |
4e8304f7 PP |
890 | if (!type) { |
891 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
892 | ret = -1; | |
893 | goto end; | |
894 | } | |
895 | ||
896 | if (type->frozen) { | |
897 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
898 | type); | |
899 | ret = -1; | |
900 | goto end; | |
901 | } | |
902 | ||
50842bdc | 903 | if (type->id != BT_FIELD_TYPE_ID_INTEGER) { |
4e8304f7 PP |
904 | BT_LOGW("Invalid parameter: field type is not an integer field type: " |
905 | "addr=%p, ft-id=%s", type, | |
50842bdc | 906 | bt_field_type_id_string(type->id)); |
273b65be JG |
907 | ret = -1; |
908 | goto end; | |
909 | } | |
910 | ||
50842bdc | 911 | integer = container_of(type, struct bt_field_type_integer, parent); |
dc3fffef | 912 | integer->is_signed = !!is_signed; |
dfc1504d PP |
913 | BT_LOGV("Set integer field type's signedness: addr=%p, is-signed=%d", |
914 | type, is_signed); | |
273b65be JG |
915 | end: |
916 | return ret; | |
917 | } | |
918 | ||
50842bdc | 919 | int bt_field_type_integer_set_size(struct bt_field_type *type, |
3bc8ebda | 920 | unsigned int size) |
c3c35de4 JD |
921 | { |
922 | int ret = 0; | |
50842bdc | 923 | struct bt_field_type_integer *integer; |
c3c35de4 | 924 | |
4e8304f7 PP |
925 | if (!type) { |
926 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
927 | ret = -1; | |
928 | goto end; | |
929 | } | |
930 | ||
931 | if (type->frozen) { | |
932 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
933 | type); | |
934 | ret = -1; | |
935 | goto end; | |
936 | } | |
937 | ||
50842bdc | 938 | if (type->id != BT_FIELD_TYPE_ID_INTEGER) { |
4e8304f7 PP |
939 | BT_LOGW("Invalid parameter: field type is not an integer field type: " |
940 | "addr=%p, ft-id=%s", type, | |
50842bdc | 941 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
942 | ret = -1; |
943 | goto end; | |
944 | } | |
945 | ||
946 | if (size == 0 || size > 64) { | |
947 | BT_LOGW("Invalid parameter: size must be between 1 and 64: " | |
3bc8ebda | 948 | "addr=%p, size=%u", type, size); |
c3c35de4 JD |
949 | ret = -1; |
950 | goto end; | |
951 | } | |
952 | ||
50842bdc | 953 | integer = container_of(type, struct bt_field_type_integer, parent); |
c3c35de4 | 954 | integer->size = size; |
3bc8ebda | 955 | BT_LOGV("Set integer field type's size: addr=%p, size=%u", |
dfc1504d | 956 | type, size); |
c3c35de4 JD |
957 | end: |
958 | return ret; | |
959 | } | |
960 | ||
50842bdc PP |
961 | enum bt_integer_base bt_field_type_integer_get_base( |
962 | struct bt_field_type *type) | |
b92ddaaa | 963 | { |
50842bdc | 964 | struct bt_field_type_integer *integer; |
b92ddaaa | 965 | |
d975f66c PP |
966 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
967 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type"); | |
50842bdc | 968 | integer = container_of(type, struct bt_field_type_integer, parent); |
d975f66c | 969 | return integer->base; |
b92ddaaa JG |
970 | } |
971 | ||
50842bdc PP |
972 | int bt_field_type_integer_set_base(struct bt_field_type *type, |
973 | enum bt_integer_base base) | |
273b65be JG |
974 | { |
975 | int ret = 0; | |
976 | ||
4e8304f7 PP |
977 | if (!type) { |
978 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
979 | ret = -1; | |
980 | goto end; | |
981 | } | |
982 | ||
983 | if (type->frozen) { | |
984 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
985 | type); | |
986 | ret = -1; | |
987 | goto end; | |
988 | } | |
989 | ||
50842bdc | 990 | if (type->id != BT_FIELD_TYPE_ID_INTEGER) { |
4e8304f7 PP |
991 | BT_LOGW("Invalid parameter: field type is not an integer field type: " |
992 | "addr=%p, ft-id=%s", type, | |
50842bdc | 993 | bt_field_type_id_string(type->id)); |
273b65be JG |
994 | ret = -1; |
995 | goto end; | |
996 | } | |
997 | ||
998 | switch (base) { | |
50842bdc PP |
999 | case BT_INTEGER_BASE_UNSPECIFIED: |
1000 | case BT_INTEGER_BASE_BINARY: | |
1001 | case BT_INTEGER_BASE_OCTAL: | |
1002 | case BT_INTEGER_BASE_DECIMAL: | |
1003 | case BT_INTEGER_BASE_HEXADECIMAL: | |
273b65be | 1004 | { |
50842bdc PP |
1005 | struct bt_field_type_integer *integer = container_of(type, |
1006 | struct bt_field_type_integer, parent); | |
dc3fffef | 1007 | integer->base = base; |
273b65be JG |
1008 | break; |
1009 | } | |
1010 | default: | |
4e8304f7 PP |
1011 | BT_LOGW("Invalid parameter: unknown integer field type base: " |
1012 | "addr=%p, base=%d", type, base); | |
273b65be JG |
1013 | ret = -1; |
1014 | } | |
dfc1504d PP |
1015 | |
1016 | BT_LOGV("Set integer field type's base: addr=%p, base=%s", | |
50842bdc | 1017 | type, bt_integer_base_string(base)); |
dfc1504d | 1018 | |
273b65be JG |
1019 | end: |
1020 | return ret; | |
1021 | } | |
1022 | ||
50842bdc PP |
1023 | enum bt_string_encoding bt_field_type_integer_get_encoding( |
1024 | struct bt_field_type *type) | |
b92ddaaa | 1025 | { |
50842bdc | 1026 | struct bt_field_type_integer *integer; |
b92ddaaa | 1027 | |
d975f66c PP |
1028 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1029 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type"); | |
50842bdc | 1030 | integer = container_of(type, struct bt_field_type_integer, parent); |
d975f66c | 1031 | return integer->encoding; |
b92ddaaa JG |
1032 | } |
1033 | ||
50842bdc PP |
1034 | int bt_field_type_integer_set_encoding(struct bt_field_type *type, |
1035 | enum bt_string_encoding encoding) | |
273b65be JG |
1036 | { |
1037 | int ret = 0; | |
50842bdc | 1038 | struct bt_field_type_integer *integer; |
273b65be | 1039 | |
4e8304f7 PP |
1040 | if (!type) { |
1041 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1042 | ret = -1; | |
1043 | goto end; | |
1044 | } | |
1045 | ||
1046 | if (type->frozen) { | |
1047 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1048 | type); | |
1049 | ret = -1; | |
1050 | goto end; | |
1051 | } | |
1052 | ||
50842bdc | 1053 | if (type->id != BT_FIELD_TYPE_ID_INTEGER) { |
4e8304f7 PP |
1054 | BT_LOGW("Invalid parameter: field type is not an integer field type: " |
1055 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1056 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
1057 | ret = -1; |
1058 | goto end; | |
1059 | } | |
1060 | ||
50842bdc PP |
1061 | if (encoding != BT_STRING_ENCODING_UTF8 && |
1062 | encoding != BT_STRING_ENCODING_ASCII && | |
1063 | encoding != BT_STRING_ENCODING_NONE) { | |
4e8304f7 PP |
1064 | BT_LOGW("Invalid parameter: unknown string encoding: " |
1065 | "addr=%p, encoding=%d", type, encoding); | |
273b65be JG |
1066 | ret = -1; |
1067 | goto end; | |
1068 | } | |
1069 | ||
50842bdc | 1070 | integer = container_of(type, struct bt_field_type_integer, parent); |
dc3fffef | 1071 | integer->encoding = encoding; |
dfc1504d | 1072 | BT_LOGV("Set integer field type's encoding: addr=%p, encoding=%s", |
50842bdc | 1073 | type, bt_string_encoding_string(encoding)); |
273b65be JG |
1074 | end: |
1075 | return ret; | |
1076 | } | |
1077 | ||
50842bdc PP |
1078 | struct bt_clock_class *bt_field_type_integer_get_mapped_clock_class( |
1079 | struct bt_field_type *type) | |
6cfb906f | 1080 | { |
50842bdc | 1081 | struct bt_field_type_integer *integer; |
6cfb906f | 1082 | |
d975f66c PP |
1083 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1084 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_INTEGER, "Field type"); | |
50842bdc | 1085 | integer = container_of(type, struct bt_field_type_integer, parent); |
d975f66c | 1086 | return bt_get(integer->mapped_clock); |
6cfb906f JG |
1087 | } |
1088 | ||
e011d2c1 | 1089 | BT_HIDDEN |
50842bdc PP |
1090 | int bt_field_type_integer_set_mapped_clock_class_no_check( |
1091 | struct bt_field_type *type, | |
1092 | struct bt_clock_class *clock_class) | |
6cfb906f | 1093 | { |
50842bdc | 1094 | struct bt_field_type_integer *integer; |
6cfb906f JG |
1095 | int ret = 0; |
1096 | ||
4e8304f7 PP |
1097 | if (!type) { |
1098 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1099 | ret = -1; | |
1100 | goto end; | |
1101 | } | |
1102 | ||
1103 | if (!clock_class) { | |
1104 | BT_LOGW_STR("Invalid parameter: clock class is NULL."); | |
1105 | ret = -1; | |
1106 | goto end; | |
1107 | } | |
1108 | ||
50842bdc | 1109 | if (type->id != BT_FIELD_TYPE_ID_INTEGER) { |
e011d2c1 PP |
1110 | BT_LOGW("Invalid parameter: field type is not an integer field type: " |
1111 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1112 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
1113 | goto end; |
1114 | } | |
1115 | ||
50842bdc | 1116 | if (!bt_clock_class_is_valid(clock_class)) { |
4e8304f7 PP |
1117 | BT_LOGW("Invalid parameter: clock class is invalid: ft-addr=%p" |
1118 | "clock-class-addr=%p, clock-class-name=\"%s\"", | |
1119 | type, clock_class, | |
50842bdc | 1120 | bt_clock_class_get_name(clock_class)); |
6cfb906f JG |
1121 | ret = -1; |
1122 | goto end; | |
1123 | } | |
1124 | ||
50842bdc | 1125 | integer = container_of(type, struct bt_field_type_integer, parent); |
83509119 | 1126 | bt_put(integer->mapped_clock); |
ac0c6bdd | 1127 | integer->mapped_clock = bt_get(clock_class); |
dfc1504d PP |
1128 | BT_LOGV("Set integer field type's mapped clock class: ft-addr=%p, " |
1129 | "clock-class-addr=%p, clock-class-name=\"%s\"", | |
50842bdc | 1130 | type, clock_class, bt_clock_class_get_name(clock_class)); |
6cfb906f JG |
1131 | end: |
1132 | return ret; | |
1133 | } | |
1134 | ||
50842bdc PP |
1135 | int bt_field_type_integer_set_mapped_clock_class( |
1136 | struct bt_field_type *type, | |
1137 | struct bt_clock_class *clock_class) | |
e011d2c1 PP |
1138 | { |
1139 | int ret = 0; | |
1140 | ||
1141 | if (!type) { | |
1142 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1143 | ret = -1; | |
1144 | goto end; | |
1145 | } | |
1146 | ||
1147 | if (type->frozen) { | |
1148 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1149 | type); | |
1150 | ret = -1; | |
1151 | goto end; | |
1152 | } | |
1153 | ||
50842bdc | 1154 | ret = bt_field_type_integer_set_mapped_clock_class_no_check( |
e011d2c1 PP |
1155 | type, clock_class); |
1156 | ||
1157 | end: | |
1158 | return ret; | |
1159 | } | |
1160 | ||
96e8f959 | 1161 | static |
50842bdc | 1162 | void bt_field_type_enum_iter_destroy(struct bt_object *obj) |
96e8f959 | 1163 | { |
50842bdc | 1164 | struct bt_field_type_enumeration_mapping_iterator *iter = |
d49e1284 | 1165 | container_of(obj, |
50842bdc | 1166 | struct bt_field_type_enumeration_mapping_iterator, |
d49e1284 | 1167 | base); |
96e8f959 | 1168 | |
ec159b1e PP |
1169 | BT_LOGD("Destroying enumeration field type mapping iterator: addr=%p", |
1170 | obj); | |
1171 | BT_LOGD_STR("Putting parent enumeration field type."); | |
d49e1284 JG |
1172 | bt_put(&iter->enumeration_type->parent); |
1173 | g_free(iter); | |
1174 | } | |
1175 | ||
1176 | static | |
50842bdc PP |
1177 | struct bt_field_type_enumeration_mapping_iterator * |
1178 | bt_field_type_enumeration_find_mappings_type( | |
1179 | struct bt_field_type *type, | |
1180 | enum bt_field_type_enumeration_mapping_iterator_type iterator_type) | |
d49e1284 | 1181 | { |
50842bdc PP |
1182 | struct bt_field_type_enumeration *enumeration_type; |
1183 | struct bt_field_type_enumeration_mapping_iterator *iter = NULL; | |
d49e1284 | 1184 | |
d975f66c PP |
1185 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1186 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type"); | |
d49e1284 | 1187 | enumeration_type = container_of(type, |
50842bdc PP |
1188 | struct bt_field_type_enumeration, parent); |
1189 | iter = g_new0(struct bt_field_type_enumeration_mapping_iterator, 1); | |
d49e1284 | 1190 | if (!iter) { |
4e8304f7 | 1191 | BT_LOGE_STR("Failed to allocate one enumeration field type mapping."); |
d49e1284 JG |
1192 | goto end; |
1193 | } | |
1194 | ||
50842bdc | 1195 | bt_object_init(&iter->base, bt_field_type_enum_iter_destroy); |
d49e1284 JG |
1196 | bt_get(type); |
1197 | iter->enumeration_type = enumeration_type; | |
1198 | iter->index = -1; | |
1199 | iter->type = iterator_type; | |
96e8f959 | 1200 | end: |
d49e1284 | 1201 | return iter; |
96e8f959 MD |
1202 | } |
1203 | ||
50842bdc PP |
1204 | struct bt_field_type_enumeration_mapping_iterator * |
1205 | bt_field_type_enumeration_find_mappings_by_name( | |
1206 | struct bt_field_type *type, const char *name) | |
96e8f959 | 1207 | { |
50842bdc | 1208 | struct bt_field_type_enumeration_mapping_iterator *iter; |
96e8f959 | 1209 | |
50842bdc | 1210 | iter = bt_field_type_enumeration_find_mappings_type( |
d49e1284 JG |
1211 | type, ITERATOR_BY_NAME); |
1212 | if (!iter) { | |
631234da | 1213 | BT_LOGW("Cannot create enumeration field type mapping iterator: " |
4e8304f7 | 1214 | "ft-addr=%p, mapping-name=\"%s\"", type, name); |
d49e1284 JG |
1215 | goto error; |
1216 | } | |
1217 | ||
1218 | iter->u.name_quark = g_quark_try_string(name); | |
1219 | if (!iter->u.name_quark) { | |
74fb0452 JG |
1220 | /* |
1221 | * No results are possible, set the iterator's position at the | |
1222 | * end. | |
1223 | */ | |
1224 | iter->index = iter->enumeration_type->entries->len; | |
d49e1284 | 1225 | } |
d49e1284 JG |
1226 | return iter; |
1227 | error: | |
1228 | bt_put(iter); | |
1229 | return NULL; | |
96e8f959 MD |
1230 | } |
1231 | ||
50842bdc PP |
1232 | int bt_field_type_enumeration_mapping_iterator_next( |
1233 | struct bt_field_type_enumeration_mapping_iterator *iter) | |
96e8f959 | 1234 | { |
50842bdc PP |
1235 | struct bt_field_type_enumeration *enumeration; |
1236 | struct bt_field_type *type; | |
96e8f959 MD |
1237 | int i, ret = 0, len; |
1238 | ||
d975f66c | 1239 | BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator"); |
96e8f959 MD |
1240 | enumeration = iter->enumeration_type; |
1241 | type = &enumeration->parent; | |
1242 | len = enumeration->entries->len; | |
1243 | for (i = iter->index + 1; i < len; i++) { | |
1244 | struct enumeration_mapping *mapping = | |
1245 | get_enumeration_mapping(type, i); | |
1246 | ||
d49e1284 | 1247 | switch (iter->type) { |
96e8f959 MD |
1248 | case ITERATOR_BY_NAME: |
1249 | if (mapping->string == iter->u.name_quark) { | |
1250 | iter->index = i; | |
1251 | goto end; | |
1252 | } | |
1253 | break; | |
1254 | case ITERATOR_BY_SIGNED_VALUE: | |
1255 | { | |
1256 | int64_t value = iter->u.signed_value; | |
1257 | ||
1258 | if (value >= mapping->range_start._signed && | |
1259 | value <= mapping->range_end._signed) { | |
1260 | iter->index = i; | |
1261 | goto end; | |
1262 | } | |
1263 | break; | |
1264 | } | |
1265 | case ITERATOR_BY_UNSIGNED_VALUE: | |
1266 | { | |
1267 | uint64_t value = iter->u.unsigned_value; | |
1268 | ||
1269 | if (value >= mapping->range_start._unsigned && | |
1270 | value <= mapping->range_end._unsigned) { | |
1271 | iter->index = i; | |
1272 | goto end; | |
1273 | } | |
1274 | break; | |
1275 | } | |
1276 | default: | |
ec159b1e PP |
1277 | BT_LOGF("Invalid enumeration field type mapping iterator type: " |
1278 | "type=%d", iter->type); | |
96e8f959 MD |
1279 | abort(); |
1280 | } | |
1281 | } | |
1282 | ||
1283 | ret = -1; | |
1284 | end: | |
1285 | return ret; | |
1286 | } | |
1287 | ||
50842bdc PP |
1288 | struct bt_field_type_enumeration_mapping_iterator * |
1289 | bt_field_type_enumeration_find_mappings_by_signed_value( | |
1290 | struct bt_field_type *type, int64_t value) | |
96e8f959 | 1291 | { |
50842bdc | 1292 | struct bt_field_type_enumeration_mapping_iterator *iter; |
96e8f959 | 1293 | |
50842bdc | 1294 | iter = bt_field_type_enumeration_find_mappings_type( |
96e8f959 MD |
1295 | type, ITERATOR_BY_SIGNED_VALUE); |
1296 | if (!iter) { | |
631234da | 1297 | BT_LOGW("Cannot create enumeration field type mapping iterator: " |
4e8304f7 | 1298 | "ft-addr=%p, value=%" PRId64, type, value); |
96e8f959 MD |
1299 | goto error; |
1300 | } | |
d49e1284 | 1301 | |
96e8f959 MD |
1302 | if (bt_ctf_field_type_integer_get_signed( |
1303 | iter->enumeration_type->container) != 1) { | |
4e8304f7 PP |
1304 | BT_LOGW("Invalid parameter: enumeration field type is unsigned: " |
1305 | "enum-ft-addr=%p, int-ft-addr=%p", | |
1306 | type, iter->enumeration_type->container); | |
96e8f959 MD |
1307 | goto error; |
1308 | } | |
4e8304f7 | 1309 | |
96e8f959 | 1310 | iter->u.signed_value = value; |
d49e1284 | 1311 | return iter; |
96e8f959 MD |
1312 | error: |
1313 | bt_put(iter); | |
1314 | return NULL; | |
1315 | } | |
1316 | ||
50842bdc PP |
1317 | struct bt_field_type_enumeration_mapping_iterator * |
1318 | bt_field_type_enumeration_find_mappings_by_unsigned_value( | |
1319 | struct bt_field_type *type, uint64_t value) | |
96e8f959 | 1320 | { |
50842bdc | 1321 | struct bt_field_type_enumeration_mapping_iterator *iter; |
96e8f959 | 1322 | |
50842bdc | 1323 | iter = bt_field_type_enumeration_find_mappings_type( |
96e8f959 MD |
1324 | type, ITERATOR_BY_UNSIGNED_VALUE); |
1325 | if (!iter) { | |
631234da | 1326 | BT_LOGW("Cannot create enumeration field type mapping iterator: " |
4e8304f7 | 1327 | "ft-addr=%p, value=%" PRIu64, type, value); |
96e8f959 MD |
1328 | goto error; |
1329 | } | |
d49e1284 | 1330 | |
96e8f959 MD |
1331 | if (bt_ctf_field_type_integer_get_signed( |
1332 | iter->enumeration_type->container) != 0) { | |
4e8304f7 PP |
1333 | BT_LOGW("Invalid parameter: enumeration field type is signed: " |
1334 | "enum-ft-addr=%p, int-ft-addr=%p", | |
1335 | type, iter->enumeration_type->container); | |
96e8f959 MD |
1336 | goto error; |
1337 | } | |
1338 | iter->u.unsigned_value = value; | |
d49e1284 | 1339 | return iter; |
96e8f959 MD |
1340 | error: |
1341 | bt_put(iter); | |
1342 | return NULL; | |
1343 | } | |
1344 | ||
50842bdc PP |
1345 | int bt_field_type_enumeration_mapping_iterator_get_signed( |
1346 | struct bt_field_type_enumeration_mapping_iterator *iter, | |
d49e1284 JG |
1347 | const char **mapping_name, int64_t *range_begin, |
1348 | int64_t *range_end) | |
1349 | { | |
d975f66c PP |
1350 | BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator"); |
1351 | BT_ASSERT_PRE(iter->index != -1, | |
1352 | "Invalid enumeration field type mapping iterator access: " | |
1353 | "addr=%p, position=-1", iter); | |
1354 | return bt_field_type_enumeration_get_mapping_signed( | |
d49e1284 JG |
1355 | &iter->enumeration_type->parent, iter->index, |
1356 | mapping_name, range_begin, range_end); | |
d49e1284 JG |
1357 | } |
1358 | ||
50842bdc PP |
1359 | int bt_field_type_enumeration_mapping_iterator_get_unsigned( |
1360 | struct bt_field_type_enumeration_mapping_iterator *iter, | |
d49e1284 JG |
1361 | const char **mapping_name, uint64_t *range_begin, |
1362 | uint64_t *range_end) | |
1363 | { | |
d975f66c PP |
1364 | BT_ASSERT_PRE_NON_NULL(iter, "Enumeration field type mapping iterator"); |
1365 | BT_ASSERT_PRE(iter->index != -1, | |
1366 | "Invalid enumeration field type mapping iterator access: " | |
1367 | "addr=%p, position=-1", iter); | |
1368 | return bt_field_type_enumeration_get_mapping_unsigned( | |
d49e1284 JG |
1369 | &iter->enumeration_type->parent, iter->index, |
1370 | mapping_name, range_begin, range_end); | |
96e8f959 MD |
1371 | } |
1372 | ||
50842bdc PP |
1373 | int bt_field_type_enumeration_get_mapping_signed( |
1374 | struct bt_field_type *enum_field_type, | |
9ac68eb1 | 1375 | uint64_t index, const char **mapping_name, int64_t *range_begin, |
96e8f959 MD |
1376 | int64_t *range_end) |
1377 | { | |
d49e1284 | 1378 | int ret = 0; |
96e8f959 MD |
1379 | struct enumeration_mapping *mapping; |
1380 | ||
d975f66c PP |
1381 | BT_ASSERT_PRE_NON_NULL(enum_field_type, "Field type"); |
1382 | BT_ASSERT_PRE_FT_HAS_ID(enum_field_type, | |
1383 | BT_FIELD_TYPE_ID_ENUM, "Field type"); | |
96e8f959 MD |
1384 | mapping = get_enumeration_mapping(enum_field_type, index); |
1385 | if (!mapping) { | |
4e8304f7 | 1386 | /* get_enumeration_mapping() reports any error */ |
d49e1284 JG |
1387 | ret = -1; |
1388 | goto end; | |
96e8f959 | 1389 | } |
d49e1284 | 1390 | |
96e8f959 MD |
1391 | if (mapping_name) { |
1392 | *mapping_name = g_quark_to_string(mapping->string); | |
f6ccaed9 | 1393 | BT_ASSERT(*mapping_name); |
96e8f959 | 1394 | } |
d49e1284 | 1395 | |
96e8f959 MD |
1396 | if (range_begin) { |
1397 | *range_begin = mapping->range_start._signed; | |
1398 | } | |
d49e1284 | 1399 | |
96e8f959 MD |
1400 | if (range_end) { |
1401 | *range_end = mapping->range_end._signed; | |
1402 | } | |
d975f66c | 1403 | |
d49e1284 JG |
1404 | end: |
1405 | return ret; | |
96e8f959 MD |
1406 | } |
1407 | ||
50842bdc PP |
1408 | int bt_field_type_enumeration_get_mapping_unsigned( |
1409 | struct bt_field_type *enum_field_type, | |
9ac68eb1 | 1410 | uint64_t index, |
96e8f959 MD |
1411 | const char **mapping_name, uint64_t *range_begin, |
1412 | uint64_t *range_end) | |
1413 | { | |
d49e1284 | 1414 | int ret = 0; |
96e8f959 MD |
1415 | struct enumeration_mapping *mapping; |
1416 | ||
d975f66c PP |
1417 | BT_ASSERT_PRE_NON_NULL(enum_field_type, "Field type"); |
1418 | BT_ASSERT_PRE_FT_HAS_ID(enum_field_type, | |
1419 | BT_FIELD_TYPE_ID_ENUM, "Field type"); | |
96e8f959 MD |
1420 | mapping = get_enumeration_mapping(enum_field_type, index); |
1421 | if (!mapping) { | |
4e8304f7 | 1422 | /* get_enumeration_mapping() reports any error */ |
d49e1284 JG |
1423 | ret = -1; |
1424 | goto end; | |
96e8f959 | 1425 | } |
d49e1284 | 1426 | |
96e8f959 MD |
1427 | if (mapping_name) { |
1428 | *mapping_name = g_quark_to_string(mapping->string); | |
f6ccaed9 | 1429 | BT_ASSERT(*mapping_name); |
96e8f959 | 1430 | } |
d49e1284 | 1431 | |
96e8f959 MD |
1432 | if (range_begin) { |
1433 | *range_begin = mapping->range_start._unsigned; | |
1434 | } | |
d49e1284 | 1435 | |
96e8f959 MD |
1436 | if (range_end) { |
1437 | *range_end = mapping->range_end._unsigned; | |
1438 | } | |
d975f66c | 1439 | |
d49e1284 JG |
1440 | end: |
1441 | return ret; | |
96e8f959 MD |
1442 | } |
1443 | ||
50842bdc PP |
1444 | struct bt_field_type *bt_field_type_enumeration_create( |
1445 | struct bt_field_type *integer_container_type) | |
273b65be | 1446 | { |
50842bdc | 1447 | struct bt_field_type_enumeration *enumeration = NULL; |
273b65be | 1448 | |
4e8304f7 PP |
1449 | BT_LOGD("Creating enumeration field type object: int-ft-addr=%p", |
1450 | integer_container_type); | |
1451 | ||
273b65be | 1452 | if (!integer_container_type) { |
4e8304f7 | 1453 | BT_LOGW_STR("Invalid parameter: field type is NULL."); |
273b65be JG |
1454 | goto error; |
1455 | } | |
1456 | ||
50842bdc | 1457 | if (integer_container_type->id != BT_FIELD_TYPE_ID_INTEGER) { |
4e8304f7 PP |
1458 | BT_LOGW("Invalid parameter: container field type is not an integer field type: " |
1459 | "container-ft-addr=%p, container-ft-id=%s", | |
1460 | integer_container_type, | |
50842bdc | 1461 | bt_field_type_id_string(integer_container_type->id)); |
2a610bb7 JG |
1462 | goto error; |
1463 | } | |
1464 | ||
50842bdc | 1465 | enumeration = g_new0(struct bt_field_type_enumeration, 1); |
273b65be | 1466 | if (!enumeration) { |
4e8304f7 | 1467 | BT_LOGE_STR("Failed to allocate one enumeration field type."); |
273b65be JG |
1468 | goto error; |
1469 | } | |
1470 | ||
50842bdc | 1471 | enumeration->parent.id = BT_FIELD_TYPE_ID_ENUM; |
83509119 | 1472 | bt_get(integer_container_type); |
273b65be JG |
1473 | enumeration->container = integer_container_type; |
1474 | enumeration->entries = g_ptr_array_new_with_free_func( | |
1475 | (GDestroyNotify)destroy_enumeration_mapping); | |
50842bdc | 1476 | bt_field_type_init(&enumeration->parent, FALSE); |
4e8304f7 PP |
1477 | BT_LOGD("Created enumeration field type object: addr=%p, " |
1478 | "int-ft-addr=%p, int-ft-size=%u", | |
1479 | &enumeration->parent, integer_container_type, | |
50842bdc | 1480 | bt_field_type_integer_get_size(integer_container_type)); |
273b65be JG |
1481 | return &enumeration->parent; |
1482 | error: | |
1483 | g_free(enumeration); | |
1484 | return NULL; | |
1485 | } | |
1486 | ||
50842bdc PP |
1487 | struct bt_field_type *bt_field_type_enumeration_get_container_type( |
1488 | struct bt_field_type *type) | |
b92ddaaa | 1489 | { |
50842bdc | 1490 | struct bt_field_type_enumeration *enumeration_type; |
b92ddaaa | 1491 | |
d975f66c PP |
1492 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1493 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type"); | |
b92ddaaa | 1494 | enumeration_type = container_of(type, |
50842bdc | 1495 | struct bt_field_type_enumeration, parent); |
d975f66c | 1496 | return bt_get(enumeration_type->container); |
b92ddaaa JG |
1497 | } |
1498 | ||
50842bdc PP |
1499 | int bt_field_type_enumeration_add_mapping_signed( |
1500 | struct bt_field_type *type, const char *string, | |
273b65be JG |
1501 | int64_t range_start, int64_t range_end) |
1502 | { | |
1503 | int ret = 0; | |
1504 | GQuark mapping_name; | |
1505 | struct enumeration_mapping *mapping; | |
50842bdc | 1506 | struct bt_field_type_enumeration *enumeration; |
a39fa057 | 1507 | char *escaped_string; |
273b65be | 1508 | |
4e8304f7 PP |
1509 | if (!type) { |
1510 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1511 | ret = -1; | |
1512 | goto end; | |
1513 | } | |
1514 | ||
1515 | if (!string) { | |
1516 | BT_LOGW_STR("Invalid parameter: string is NULL."); | |
1517 | ret = -1; | |
1518 | goto end; | |
1519 | } | |
1520 | ||
1521 | if (type->frozen) { | |
1522 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1523 | type); | |
1524 | ret = -1; | |
1525 | goto end; | |
1526 | } | |
1527 | ||
50842bdc | 1528 | if (type->id != BT_FIELD_TYPE_ID_ENUM) { |
4e8304f7 PP |
1529 | BT_LOGW("Invalid parameter: field type is not an enumeration field type: " |
1530 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1531 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
1532 | ret = -1; |
1533 | goto end; | |
1534 | } | |
1535 | ||
1536 | if (range_end < range_start) { | |
1537 | BT_LOGW("Invalid parameter: range's end is lesser than range's start: " | |
1538 | "addr=%p, range-start=%" PRId64 ", range-end=%" PRId64, | |
1539 | type, range_start, range_end); | |
273b65be JG |
1540 | ret = -1; |
1541 | goto end; | |
1542 | } | |
1543 | ||
4e8304f7 PP |
1544 | if (strlen(string) == 0) { |
1545 | BT_LOGW("Invalid parameter: mapping name is an empty string: " | |
1546 | "enum-ft-addr=%p, mapping-name-addr=%p", type, | |
1547 | string); | |
273b65be JG |
1548 | ret = -1; |
1549 | goto end; | |
1550 | } | |
1551 | ||
a39fa057 JG |
1552 | escaped_string = g_strescape(string, NULL); |
1553 | if (!escaped_string) { | |
4e8304f7 PP |
1554 | BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, " |
1555 | "mapping-name-addr=%p, mapping-name=\"%s\"", | |
1556 | type, string, string); | |
a39fa057 JG |
1557 | ret = -1; |
1558 | goto end; | |
1559 | } | |
1560 | ||
273b65be JG |
1561 | mapping = g_new(struct enumeration_mapping, 1); |
1562 | if (!mapping) { | |
4e8304f7 | 1563 | BT_LOGE_STR("Failed to allocate one enumeration mapping."); |
273b65be | 1564 | ret = -1; |
a39fa057 | 1565 | goto error_free; |
273b65be | 1566 | } |
96e8f959 | 1567 | mapping_name = g_quark_from_string(escaped_string); |
b92ddaaa JG |
1568 | *mapping = (struct enumeration_mapping) { |
1569 | .range_start._signed = range_start, | |
96e8f959 MD |
1570 | .range_end._signed = range_end, |
1571 | .string = mapping_name, | |
1572 | }; | |
50842bdc | 1573 | enumeration = container_of(type, struct bt_field_type_enumeration, |
96e8f959 | 1574 | parent); |
273b65be | 1575 | g_ptr_array_add(enumeration->entries, mapping); |
b92ddaaa JG |
1576 | g_ptr_array_sort(enumeration->entries, |
1577 | (GCompareFunc)compare_enumeration_mappings_signed); | |
dfc1504d PP |
1578 | BT_LOGV("Added mapping to signed enumeration field type: addr=%p, " |
1579 | "name=\"%s\", range-start=%" PRId64 ", " | |
1580 | "range-end=%" PRId64, | |
1581 | type, string, range_start, range_end); | |
b92ddaaa JG |
1582 | error_free: |
1583 | free(escaped_string); | |
1584 | end: | |
1585 | return ret; | |
1586 | } | |
1587 | ||
50842bdc PP |
1588 | int bt_field_type_enumeration_add_mapping_unsigned( |
1589 | struct bt_field_type *type, const char *string, | |
b92ddaaa JG |
1590 | uint64_t range_start, uint64_t range_end) |
1591 | { | |
1592 | int ret = 0; | |
1593 | GQuark mapping_name; | |
1594 | struct enumeration_mapping *mapping; | |
50842bdc | 1595 | struct bt_field_type_enumeration *enumeration; |
b92ddaaa JG |
1596 | char *escaped_string; |
1597 | ||
4e8304f7 PP |
1598 | if (!type) { |
1599 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1600 | ret = -1; | |
1601 | goto end; | |
1602 | } | |
1603 | ||
1604 | if (!string) { | |
1605 | BT_LOGW_STR("Invalid parameter: string is NULL."); | |
1606 | ret = -1; | |
1607 | goto end; | |
1608 | } | |
1609 | ||
1610 | if (type->frozen) { | |
1611 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1612 | type); | |
1613 | ret = -1; | |
1614 | goto end; | |
1615 | } | |
1616 | ||
50842bdc | 1617 | if (type->id != BT_FIELD_TYPE_ID_ENUM) { |
4e8304f7 PP |
1618 | BT_LOGW("Invalid parameter: field type is not an enumeration field type: " |
1619 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1620 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
1621 | ret = -1; |
1622 | goto end; | |
1623 | } | |
1624 | ||
1625 | if (range_end < range_start) { | |
1626 | BT_LOGW("Invalid parameter: range's end is lesser than range's start: " | |
1627 | "addr=%p, range-start=%" PRIu64 ", range-end=%" PRIu64, | |
1628 | type, range_start, range_end); | |
b92ddaaa JG |
1629 | ret = -1; |
1630 | goto end; | |
1631 | } | |
1632 | ||
4e8304f7 PP |
1633 | if (strlen(string) == 0) { |
1634 | BT_LOGW("Invalid parameter: mapping name is an empty string: " | |
1635 | "enum-ft-addr=%p, mapping-name-addr=%p", type, | |
1636 | string); | |
b92ddaaa JG |
1637 | ret = -1; |
1638 | goto end; | |
1639 | } | |
1640 | ||
1641 | escaped_string = g_strescape(string, NULL); | |
1642 | if (!escaped_string) { | |
4e8304f7 PP |
1643 | BT_LOGE("Cannot escape mapping name: enum-ft-addr=%p, " |
1644 | "mapping-name-addr=%p, mapping-name=\"%s\"", | |
1645 | type, string, string); | |
b92ddaaa JG |
1646 | ret = -1; |
1647 | goto end; | |
1648 | } | |
1649 | ||
b92ddaaa JG |
1650 | mapping = g_new(struct enumeration_mapping, 1); |
1651 | if (!mapping) { | |
4e8304f7 | 1652 | BT_LOGE_STR("Failed to allocate one enumeration mapping."); |
b92ddaaa JG |
1653 | ret = -1; |
1654 | goto error_free; | |
1655 | } | |
96e8f959 | 1656 | mapping_name = g_quark_from_string(escaped_string); |
b92ddaaa JG |
1657 | *mapping = (struct enumeration_mapping) { |
1658 | .range_start._unsigned = range_start, | |
96e8f959 MD |
1659 | .range_end._unsigned = range_end, |
1660 | .string = mapping_name, | |
1661 | }; | |
50842bdc | 1662 | enumeration = container_of(type, struct bt_field_type_enumeration, |
96e8f959 | 1663 | parent); |
b92ddaaa JG |
1664 | g_ptr_array_add(enumeration->entries, mapping); |
1665 | g_ptr_array_sort(enumeration->entries, | |
1666 | (GCompareFunc)compare_enumeration_mappings_unsigned); | |
dfc1504d PP |
1667 | BT_LOGV("Added mapping to unsigned enumeration field type: addr=%p, " |
1668 | "name=\"%s\", range-start=%" PRIu64 ", " | |
1669 | "range-end=%" PRIu64, | |
1670 | type, string, range_start, range_end); | |
a39fa057 JG |
1671 | error_free: |
1672 | free(escaped_string); | |
273b65be JG |
1673 | end: |
1674 | return ret; | |
1675 | } | |
1676 | ||
50842bdc PP |
1677 | int64_t bt_field_type_enumeration_get_mapping_count( |
1678 | struct bt_field_type *type) | |
b92ddaaa | 1679 | { |
50842bdc | 1680 | struct bt_field_type_enumeration *enumeration; |
b92ddaaa | 1681 | |
d975f66c PP |
1682 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1683 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ENUM, "Field type"); | |
50842bdc | 1684 | enumeration = container_of(type, struct bt_field_type_enumeration, |
b92ddaaa | 1685 | parent); |
d975f66c | 1686 | return (int64_t) enumeration->entries->len; |
b92ddaaa JG |
1687 | } |
1688 | ||
50842bdc | 1689 | struct bt_field_type *bt_field_type_floating_point_create(void) |
273b65be | 1690 | { |
50842bdc PP |
1691 | struct bt_field_type_floating_point *floating_point = |
1692 | g_new0(struct bt_field_type_floating_point, 1); | |
273b65be | 1693 | |
4e8304f7 PP |
1694 | BT_LOGD_STR("Creating floating point number field type object."); |
1695 | ||
273b65be | 1696 | if (!floating_point) { |
4e8304f7 | 1697 | BT_LOGE_STR("Failed to allocate one floating point number field type."); |
273b65be JG |
1698 | goto end; |
1699 | } | |
1700 | ||
50842bdc | 1701 | floating_point->parent.id = BT_FIELD_TYPE_ID_FLOAT; |
dc3fffef PP |
1702 | floating_point->exp_dig = sizeof(float) * CHAR_BIT - FLT_MANT_DIG; |
1703 | floating_point->mant_dig = FLT_MANT_DIG; | |
50842bdc | 1704 | bt_field_type_init(&floating_point->parent, TRUE); |
4e8304f7 PP |
1705 | BT_LOGD("Created floating point number field type object: addr=%p, " |
1706 | "exp-size=%u, mant-size=%u", &floating_point->parent, | |
1707 | floating_point->exp_dig, floating_point->mant_dig); | |
273b65be JG |
1708 | end: |
1709 | return floating_point ? &floating_point->parent : NULL; | |
1710 | } | |
1711 | ||
50842bdc PP |
1712 | int bt_field_type_floating_point_get_exponent_digits( |
1713 | struct bt_field_type *type) | |
b92ddaaa | 1714 | { |
50842bdc | 1715 | struct bt_field_type_floating_point *floating_point; |
b92ddaaa | 1716 | |
d975f66c PP |
1717 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1718 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_FLOAT, "Field type"); | |
b92ddaaa | 1719 | floating_point = container_of(type, |
50842bdc | 1720 | struct bt_field_type_floating_point, parent); |
d975f66c | 1721 | return (int) floating_point->exp_dig; |
b92ddaaa JG |
1722 | } |
1723 | ||
50842bdc | 1724 | int bt_field_type_floating_point_set_exponent_digits( |
d975f66c | 1725 | struct bt_field_type *type, unsigned int exponent_digits) |
273b65be JG |
1726 | { |
1727 | int ret = 0; | |
50842bdc | 1728 | struct bt_field_type_floating_point *floating_point; |
273b65be | 1729 | |
4e8304f7 PP |
1730 | if (!type) { |
1731 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1732 | ret = -1; | |
1733 | goto end; | |
1734 | } | |
1735 | ||
1736 | if (type->frozen) { | |
1737 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1738 | type); | |
1739 | ret = -1; | |
1740 | goto end; | |
1741 | } | |
1742 | ||
50842bdc | 1743 | if (type->id != BT_FIELD_TYPE_ID_FLOAT) { |
4e8304f7 PP |
1744 | BT_LOGW("Invalid parameter: field type is not a floating point number field type: " |
1745 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1746 | bt_field_type_id_string(type->id)); |
273b65be JG |
1747 | ret = -1; |
1748 | goto end; | |
1749 | } | |
1750 | ||
1751 | floating_point = container_of(type, | |
50842bdc | 1752 | struct bt_field_type_floating_point, parent); |
273b65be JG |
1753 | if ((exponent_digits != sizeof(float) * CHAR_BIT - FLT_MANT_DIG) && |
1754 | (exponent_digits != sizeof(double) * CHAR_BIT - DBL_MANT_DIG) && | |
1755 | (exponent_digits != | |
1756 | sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG)) { | |
4e8304f7 PP |
1757 | BT_LOGW("Invalid parameter: invalid exponent size: " |
1758 | "addr=%p, exp-size=%u", type, exponent_digits); | |
273b65be JG |
1759 | ret = -1; |
1760 | goto end; | |
1761 | } | |
1762 | ||
dc3fffef | 1763 | floating_point->exp_dig = exponent_digits; |
dfc1504d PP |
1764 | BT_LOGV("Set floating point number field type's exponent size: addr=%p, " |
1765 | "exp-size=%u", type, exponent_digits); | |
273b65be JG |
1766 | end: |
1767 | return ret; | |
1768 | } | |
1769 | ||
50842bdc PP |
1770 | int bt_field_type_floating_point_get_mantissa_digits( |
1771 | struct bt_field_type *type) | |
b92ddaaa | 1772 | { |
50842bdc | 1773 | struct bt_field_type_floating_point *floating_point; |
b92ddaaa | 1774 | |
d975f66c PP |
1775 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1776 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_FLOAT, "Field type"); | |
b92ddaaa | 1777 | floating_point = container_of(type, |
50842bdc | 1778 | struct bt_field_type_floating_point, parent); |
d975f66c | 1779 | return (int) floating_point->mant_dig; |
b92ddaaa JG |
1780 | } |
1781 | ||
50842bdc | 1782 | int bt_field_type_floating_point_set_mantissa_digits( |
d975f66c | 1783 | struct bt_field_type *type, unsigned int mantissa_digits) |
273b65be JG |
1784 | { |
1785 | int ret = 0; | |
50842bdc | 1786 | struct bt_field_type_floating_point *floating_point; |
273b65be | 1787 | |
4e8304f7 PP |
1788 | if (!type) { |
1789 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1790 | ret = -1; | |
1791 | goto end; | |
1792 | } | |
1793 | ||
1794 | if (type->frozen) { | |
1795 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1796 | type); | |
1797 | ret = -1; | |
1798 | goto end; | |
1799 | } | |
1800 | ||
50842bdc | 1801 | if (type->id != BT_FIELD_TYPE_ID_FLOAT) { |
4e8304f7 PP |
1802 | BT_LOGW("Invalid parameter: field type is not a floating point number field type: " |
1803 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1804 | bt_field_type_id_string(type->id)); |
273b65be JG |
1805 | ret = -1; |
1806 | goto end; | |
1807 | } | |
1808 | ||
1809 | floating_point = container_of(type, | |
50842bdc | 1810 | struct bt_field_type_floating_point, parent); |
273b65be JG |
1811 | |
1812 | if ((mantissa_digits != FLT_MANT_DIG) && | |
1813 | (mantissa_digits != DBL_MANT_DIG) && | |
1814 | (mantissa_digits != LDBL_MANT_DIG)) { | |
4e8304f7 PP |
1815 | BT_LOGW("Invalid parameter: invalid mantissa size: " |
1816 | "addr=%p, mant-size=%u", type, mantissa_digits); | |
273b65be JG |
1817 | ret = -1; |
1818 | goto end; | |
1819 | } | |
1820 | ||
dc3fffef | 1821 | floating_point->mant_dig = mantissa_digits; |
dfc1504d PP |
1822 | BT_LOGV("Set floating point number field type's mantissa size: addr=%p, " |
1823 | "mant-size=%u", type, mantissa_digits); | |
273b65be JG |
1824 | end: |
1825 | return ret; | |
1826 | } | |
1827 | ||
50842bdc | 1828 | struct bt_field_type *bt_field_type_structure_create(void) |
273b65be | 1829 | { |
50842bdc PP |
1830 | struct bt_field_type_structure *structure = |
1831 | g_new0(struct bt_field_type_structure, 1); | |
273b65be | 1832 | |
4e8304f7 PP |
1833 | BT_LOGD_STR("Creating structure field type object."); |
1834 | ||
273b65be | 1835 | if (!structure) { |
4e8304f7 | 1836 | BT_LOGE_STR("Failed to allocate one structure field type."); |
273b65be JG |
1837 | goto error; |
1838 | } | |
1839 | ||
50842bdc | 1840 | structure->parent.id = BT_FIELD_TYPE_ID_STRUCT; |
273b65be JG |
1841 | structure->fields = g_ptr_array_new_with_free_func( |
1842 | (GDestroyNotify)destroy_structure_field); | |
1843 | structure->field_name_to_index = g_hash_table_new(NULL, NULL); | |
50842bdc | 1844 | bt_field_type_init(&structure->parent, TRUE); |
4e8304f7 PP |
1845 | BT_LOGD("Created structure field type object: addr=%p", |
1846 | &structure->parent); | |
273b65be JG |
1847 | return &structure->parent; |
1848 | error: | |
1849 | return NULL; | |
1850 | } | |
1851 | ||
79422a2b PP |
1852 | BT_HIDDEN |
1853 | int bt_field_type_structure_replace_field(struct bt_field_type *type, | |
1854 | const char *field_name, struct bt_field_type *field_type) | |
1855 | { | |
1856 | int ret = 0; | |
1857 | struct bt_field_type_structure *structure; | |
1858 | GQuark name_quark; | |
1859 | uint64_t i; | |
1860 | ||
f6ccaed9 PP |
1861 | BT_ASSERT(type); |
1862 | BT_ASSERT(field_name); | |
1863 | BT_ASSERT(field_type); | |
1864 | BT_ASSERT(type->id == BT_FIELD_TYPE_ID_STRUCT); | |
79422a2b PP |
1865 | structure = container_of(type, struct bt_field_type_structure, parent); |
1866 | name_quark = g_quark_from_string(field_name); | |
1867 | ||
1868 | for (i = 0; i < structure->fields->len; i++) { | |
1869 | struct structure_field *field = g_ptr_array_index( | |
1870 | structure->fields, i); | |
1871 | ||
1872 | if (field->name == name_quark) { | |
1873 | bt_put(field->type); | |
1874 | field->type = bt_get(field_type); | |
1875 | } | |
1876 | } | |
1877 | ||
1878 | return ret; | |
1879 | } | |
1880 | ||
50842bdc PP |
1881 | int bt_field_type_structure_add_field(struct bt_field_type *type, |
1882 | struct bt_field_type *field_type, | |
273b65be JG |
1883 | const char *field_name) |
1884 | { | |
1885 | int ret = 0; | |
50842bdc | 1886 | struct bt_field_type_structure *structure; |
273b65be | 1887 | |
73892edc PP |
1888 | /* |
1889 | * TODO: check that `field_type` does not contain `type`, | |
1890 | * recursively. | |
1891 | */ | |
4e8304f7 PP |
1892 | if (!type) { |
1893 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
1894 | ret = -1; | |
1895 | goto end; | |
1896 | } | |
1897 | ||
1898 | if (!field_name) { | |
1899 | BT_LOGW_STR("Invalid parameter: field name is NULL."); | |
1900 | ret = -1; | |
1901 | goto end; | |
1902 | } | |
1903 | ||
1904 | if (type->frozen) { | |
1905 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
1906 | type); | |
1907 | ret = -1; | |
1908 | goto end; | |
1909 | } | |
1910 | ||
50842bdc | 1911 | if (type->id != BT_FIELD_TYPE_ID_STRUCT) { |
4e8304f7 PP |
1912 | BT_LOGW("Invalid parameter: field type is not a structure field type: " |
1913 | "addr=%p, ft-id=%s", type, | |
50842bdc | 1914 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
1915 | ret = -1; |
1916 | goto end; | |
1917 | } | |
1918 | ||
1919 | if (type == field_type) { | |
1920 | BT_LOGW("Invalid parameter: structure field type and field type to add are the same: " | |
1921 | "addr=%p", type); | |
e6235f1f | 1922 | ret = -1; |
273b65be JG |
1923 | goto end; |
1924 | } | |
1925 | ||
1926 | structure = container_of(type, | |
50842bdc | 1927 | struct bt_field_type_structure, parent); |
273b65be | 1928 | if (add_structure_field(structure->fields, |
4e8304f7 PP |
1929 | structure->field_name_to_index, field_type, field_name)) { |
1930 | BT_LOGW("Cannot add field to structure field type: " | |
1931 | "struct-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"", | |
1932 | type, field_type, field_name); | |
273b65be JG |
1933 | ret = -1; |
1934 | goto end; | |
1935 | } | |
dfc1504d PP |
1936 | |
1937 | BT_LOGV("Added structure field type field: struct-ft-addr=%p, " | |
1938 | "field-ft-addr=%p, field-name=\"%s\"", type, | |
1939 | field_type, field_name); | |
b92ddaaa JG |
1940 | end: |
1941 | return ret; | |
1942 | } | |
1943 | ||
50842bdc PP |
1944 | int64_t bt_field_type_structure_get_field_count( |
1945 | struct bt_field_type *type) | |
b92ddaaa | 1946 | { |
50842bdc | 1947 | struct bt_field_type_structure *structure; |
b92ddaaa | 1948 | |
d975f66c PP |
1949 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1950 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type"); | |
50842bdc | 1951 | structure = container_of(type, struct bt_field_type_structure, |
b92ddaaa | 1952 | parent); |
d975f66c | 1953 | return (int64_t) structure->fields->len; |
b92ddaaa JG |
1954 | } |
1955 | ||
50842bdc PP |
1956 | int bt_field_type_structure_get_field_by_index( |
1957 | struct bt_field_type *type, | |
1958 | const char **field_name, struct bt_field_type **field_type, | |
9ac68eb1 | 1959 | uint64_t index) |
b92ddaaa | 1960 | { |
50842bdc | 1961 | struct bt_field_type_structure *structure; |
b92ddaaa | 1962 | struct structure_field *field; |
b92ddaaa | 1963 | |
d975f66c PP |
1964 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1965 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type"); | |
50842bdc | 1966 | structure = container_of(type, struct bt_field_type_structure, |
b92ddaaa | 1967 | parent); |
d975f66c PP |
1968 | BT_ASSERT_PRE(index < structure->fields->len, |
1969 | "Index is out of bounds: index=%" PRIu64 ", " | |
1970 | "count=%u, %![ft-]+F", | |
1971 | index, structure->fields->len, type); | |
b92ddaaa | 1972 | field = g_ptr_array_index(structure->fields, index); |
d975f66c | 1973 | |
f9b799fc JG |
1974 | if (field_type) { |
1975 | *field_type = field->type; | |
83509119 | 1976 | bt_get(field->type); |
f9b799fc | 1977 | } |
d975f66c | 1978 | |
f9b799fc JG |
1979 | if (field_name) { |
1980 | *field_name = g_quark_to_string(field->name); | |
f6ccaed9 | 1981 | BT_ASSERT(*field_name); |
f9b799fc | 1982 | } |
d975f66c PP |
1983 | |
1984 | return 0; | |
b92ddaaa JG |
1985 | } |
1986 | ||
50842bdc | 1987 | struct bt_field_type *bt_field_type_structure_get_field_type_by_name( |
d975f66c | 1988 | struct bt_field_type *type, const char *name) |
b92ddaaa JG |
1989 | { |
1990 | size_t index; | |
1991 | GQuark name_quark; | |
1992 | struct structure_field *field; | |
50842bdc PP |
1993 | struct bt_field_type_structure *structure; |
1994 | struct bt_field_type *field_type = NULL; | |
b92ddaaa | 1995 | |
d975f66c PP |
1996 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
1997 | BT_ASSERT_PRE_NON_NULL(name, "Name"); | |
1998 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type"); | |
b92ddaaa JG |
1999 | name_quark = g_quark_try_string(name); |
2000 | if (!name_quark) { | |
6fa8d37b PP |
2001 | BT_LOGV("No such structure field type field name: " |
2002 | "ft-addr=%p, field-name=\"%s\"", | |
2003 | type, name); | |
b92ddaaa JG |
2004 | goto end; |
2005 | } | |
2006 | ||
50842bdc | 2007 | structure = container_of(type, struct bt_field_type_structure, |
b92ddaaa JG |
2008 | parent); |
2009 | if (!g_hash_table_lookup_extended(structure->field_name_to_index, | |
6fa8d37b PP |
2010 | GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) { |
2011 | BT_LOGV("No such structure field type field name: " | |
2012 | "ft-addr=%p, field-name=\"%s\"", | |
2013 | type, name); | |
b92ddaaa | 2014 | goto end; |
273b65be | 2015 | } |
b92ddaaa JG |
2016 | |
2017 | field = structure->fields->pdata[index]; | |
2018 | field_type = field->type; | |
83509119 | 2019 | bt_get(field_type); |
d975f66c | 2020 | |
273b65be | 2021 | end: |
b92ddaaa | 2022 | return field_type; |
273b65be JG |
2023 | } |
2024 | ||
50842bdc PP |
2025 | struct bt_field_type *bt_field_type_variant_create( |
2026 | struct bt_field_type *enum_tag, const char *tag_name) | |
273b65be | 2027 | { |
50842bdc | 2028 | struct bt_field_type_variant *variant = NULL; |
273b65be | 2029 | |
4e8304f7 PP |
2030 | BT_LOGD("Creating variant field type object: " |
2031 | "tag-ft-addr=%p, tag-field-name=\"%s\"", | |
2032 | enum_tag, tag_name); | |
2033 | ||
f4cc9a21 | 2034 | if (tag_name && !bt_identifier_is_valid(tag_name)) { |
4e8304f7 PP |
2035 | BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: " |
2036 | "tag-ft-addr=%p, tag-field-name=\"%s\"", | |
2037 | enum_tag, tag_name); | |
273b65be JG |
2038 | goto error; |
2039 | } | |
2040 | ||
50842bdc | 2041 | variant = g_new0(struct bt_field_type_variant, 1); |
273b65be | 2042 | if (!variant) { |
4e8304f7 | 2043 | BT_LOGE_STR("Failed to allocate one variant field type."); |
273b65be JG |
2044 | goto error; |
2045 | } | |
2046 | ||
50842bdc | 2047 | variant->parent.id = BT_FIELD_TYPE_ID_VARIANT; |
273b65be | 2048 | variant->tag_name = g_string_new(tag_name); |
273b65be JG |
2049 | variant->field_name_to_index = g_hash_table_new(NULL, NULL); |
2050 | variant->fields = g_ptr_array_new_with_free_func( | |
83509119 | 2051 | (GDestroyNotify) destroy_structure_field); |
6964b7fd | 2052 | if (enum_tag) { |
83509119 | 2053 | bt_get(enum_tag); |
6964b7fd | 2054 | variant->tag = container_of(enum_tag, |
50842bdc | 2055 | struct bt_field_type_enumeration, parent); |
6964b7fd JG |
2056 | } |
2057 | ||
50842bdc | 2058 | bt_field_type_init(&variant->parent, TRUE); |
46caf2cb | 2059 | /* A variant's alignment is undefined */ |
dc3fffef | 2060 | variant->parent.alignment = 0; |
4e8304f7 PP |
2061 | BT_LOGD("Created variant field type object: addr=%p, " |
2062 | "tag-ft-addr=%p, tag-field-name=\"%s\"", | |
2063 | &variant->parent, enum_tag, tag_name); | |
273b65be JG |
2064 | return &variant->parent; |
2065 | error: | |
2066 | return NULL; | |
2067 | } | |
2068 | ||
50842bdc PP |
2069 | struct bt_field_type *bt_field_type_variant_get_tag_type( |
2070 | struct bt_field_type *type) | |
b92ddaaa | 2071 | { |
50842bdc PP |
2072 | struct bt_field_type_variant *variant; |
2073 | struct bt_field_type *tag_type = NULL; | |
b92ddaaa | 2074 | |
d975f66c PP |
2075 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2076 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc | 2077 | variant = container_of(type, struct bt_field_type_variant, parent); |
6964b7fd | 2078 | if (!variant->tag) { |
4e8304f7 PP |
2079 | BT_LOGV("Variant field type has no tag field type: " |
2080 | "addr=%p", type); | |
6964b7fd JG |
2081 | goto end; |
2082 | } | |
2083 | ||
b92ddaaa | 2084 | tag_type = &variant->tag->parent; |
83509119 | 2085 | bt_get(tag_type); |
d975f66c | 2086 | |
b92ddaaa JG |
2087 | end: |
2088 | return tag_type; | |
2089 | } | |
2090 | ||
d975f66c | 2091 | const char *bt_field_type_variant_get_tag_name(struct bt_field_type *type) |
b92ddaaa | 2092 | { |
50842bdc | 2093 | struct bt_field_type_variant *variant; |
b92ddaaa JG |
2094 | const char *tag_name = NULL; |
2095 | ||
d975f66c PP |
2096 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2097 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc | 2098 | variant = container_of(type, struct bt_field_type_variant, parent); |
6964b7fd | 2099 | if (variant->tag_name->len == 0) { |
4e8304f7 PP |
2100 | BT_LOGV("Variant field type has no tag field name: " |
2101 | "addr=%p", type); | |
6964b7fd JG |
2102 | goto end; |
2103 | } | |
2104 | ||
b92ddaaa JG |
2105 | tag_name = variant->tag_name->str; |
2106 | end: | |
2107 | return tag_name; | |
2108 | } | |
2109 | ||
50842bdc PP |
2110 | int bt_field_type_variant_set_tag_name( |
2111 | struct bt_field_type *type, const char *name) | |
d9b1ab6d JG |
2112 | { |
2113 | int ret = 0; | |
50842bdc | 2114 | struct bt_field_type_variant *variant; |
d9b1ab6d | 2115 | |
4e8304f7 PP |
2116 | if (!type) { |
2117 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
2118 | ret = -1; | |
2119 | goto end; | |
2120 | } | |
2121 | ||
2122 | if (type->frozen) { | |
2123 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
2124 | type); | |
2125 | ret = -1; | |
2126 | goto end; | |
2127 | } | |
2128 | ||
50842bdc | 2129 | if (type->id != BT_FIELD_TYPE_ID_VARIANT) { |
4e8304f7 PP |
2130 | BT_LOGW("Invalid parameter: field type is not a variant field type: " |
2131 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2132 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
2133 | ret = -1; |
2134 | goto end; | |
2135 | } | |
2136 | ||
f4cc9a21 | 2137 | if (!bt_identifier_is_valid(name)) { |
4e8304f7 PP |
2138 | BT_LOGW("Invalid parameter: tag field name is not a valid CTF identifier: " |
2139 | "variant-ft-addr=%p, tag-field-name=\"%s\"", | |
2140 | type, name); | |
d9b1ab6d JG |
2141 | ret = -1; |
2142 | goto end; | |
2143 | } | |
2144 | ||
50842bdc | 2145 | variant = container_of(type, struct bt_field_type_variant, parent); |
d9b1ab6d | 2146 | g_string_assign(variant->tag_name, name); |
dfc1504d PP |
2147 | BT_LOGV("Set variant field type's tag field name: addr=%p, " |
2148 | "tag-field-name=\"%s\"", type, name); | |
d9b1ab6d JG |
2149 | end: |
2150 | return ret; | |
2151 | } | |
2152 | ||
50842bdc PP |
2153 | int bt_field_type_variant_add_field(struct bt_field_type *type, |
2154 | struct bt_field_type *field_type, | |
4e8304f7 PP |
2155 | const char *field_name) |
2156 | { | |
2157 | size_t i; | |
2158 | int ret = 0; | |
50842bdc | 2159 | struct bt_field_type_variant *variant; |
4e8304f7 PP |
2160 | GQuark field_name_quark = g_quark_from_string(field_name); |
2161 | ||
2162 | /* | |
2163 | * TODO: check that `field_type` does not contain `type`, | |
2164 | * recursively. | |
2165 | */ | |
2166 | if (!type) { | |
2167 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
2168 | ret = -1; | |
2169 | goto end; | |
2170 | } | |
2171 | ||
2172 | if (type->frozen) { | |
2173 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
2174 | type); | |
2175 | ret = -1; | |
2176 | goto end; | |
2177 | } | |
2178 | ||
50842bdc | 2179 | if (type->id != BT_FIELD_TYPE_ID_VARIANT) { |
4e8304f7 PP |
2180 | BT_LOGW("Invalid parameter: field type is not a variant field type: " |
2181 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2182 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
2183 | ret = -1; |
2184 | goto end; | |
2185 | } | |
273b65be | 2186 | |
4e8304f7 PP |
2187 | if (type == field_type) { |
2188 | BT_LOGW("Invalid parameter: variant field type and field type to add are the same: " | |
2189 | "addr=%p", type); | |
273b65be JG |
2190 | ret = -1; |
2191 | goto end; | |
2192 | } | |
2193 | ||
50842bdc | 2194 | variant = container_of(type, struct bt_field_type_variant, parent); |
273b65be | 2195 | |
6964b7fd JG |
2196 | /* The user has explicitly provided a tag; validate against it. */ |
2197 | if (variant->tag) { | |
2198 | int name_found = 0; | |
2199 | ||
2200 | /* Make sure this name is present in the enum tag */ | |
2201 | for (i = 0; i < variant->tag->entries->len; i++) { | |
2202 | struct enumeration_mapping *mapping = | |
2203 | g_ptr_array_index(variant->tag->entries, i); | |
2204 | ||
2205 | if (mapping->string == field_name_quark) { | |
2206 | name_found = 1; | |
2207 | break; | |
2208 | } | |
2209 | } | |
2210 | ||
2211 | if (!name_found) { | |
2212 | /* Validation failed */ | |
4e8304f7 PP |
2213 | BT_LOGW("Invalid parameter: field name does not name a tag field type's mapping: " |
2214 | "variant-ft-addr=%p, tag-ft-addr=%p, " | |
2215 | "tag-field-name=\"%s\"" | |
2216 | "field-ft-addr=%p, field-name=\"%s\"", | |
2217 | type, variant->tag, variant->tag_name->str, | |
2218 | field_type, field_name); | |
6964b7fd JG |
2219 | ret = -1; |
2220 | goto end; | |
273b65be JG |
2221 | } |
2222 | } | |
2223 | ||
6964b7fd | 2224 | if (add_structure_field(variant->fields, variant->field_name_to_index, |
4e8304f7 PP |
2225 | field_type, field_name)) { |
2226 | BT_LOGW("Cannot add field to variant field type: " | |
2227 | "variant-ft-addr=%p, field-ft-addr=%p, field-name=\"%s\"", | |
2228 | type, field_type, field_name); | |
273b65be JG |
2229 | ret = -1; |
2230 | goto end; | |
2231 | } | |
dfc1504d PP |
2232 | |
2233 | BT_LOGV("Added variant field type field: variant-ft-addr=%p, " | |
2234 | "field-ft-addr=%p, field-name=\"%s\"", type, | |
2235 | field_type, field_name); | |
2236 | ||
273b65be JG |
2237 | end: |
2238 | return ret; | |
2239 | } | |
2240 | ||
50842bdc PP |
2241 | struct bt_field_type *bt_field_type_variant_get_field_type_by_name( |
2242 | struct bt_field_type *type, | |
b92ddaaa JG |
2243 | const char *field_name) |
2244 | { | |
2245 | size_t index; | |
2246 | GQuark name_quark; | |
2247 | struct structure_field *field; | |
50842bdc PP |
2248 | struct bt_field_type_variant *variant; |
2249 | struct bt_field_type *field_type = NULL; | |
b92ddaaa | 2250 | |
d975f66c PP |
2251 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2252 | BT_ASSERT_PRE_NON_NULL(field_name, "Name"); | |
2253 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
b92ddaaa JG |
2254 | name_quark = g_quark_try_string(field_name); |
2255 | if (!name_quark) { | |
6fa8d37b PP |
2256 | BT_LOGV("No such variant field type field name: " |
2257 | "ft-addr=%p, field-name=\"%s\"", | |
2258 | type, field_name); | |
b92ddaaa JG |
2259 | goto end; |
2260 | } | |
2261 | ||
50842bdc | 2262 | variant = container_of(type, struct bt_field_type_variant, parent); |
b92ddaaa | 2263 | if (!g_hash_table_lookup_extended(variant->field_name_to_index, |
6fa8d37b PP |
2264 | GUINT_TO_POINTER(name_quark), NULL, (gpointer *)&index)) { |
2265 | BT_LOGV("No such variant field type field name: " | |
2266 | "ft-addr=%p, field-name=\"%s\"", | |
2267 | type, field_name); | |
b92ddaaa JG |
2268 | goto end; |
2269 | } | |
2270 | ||
2271 | field = g_ptr_array_index(variant->fields, index); | |
2272 | field_type = field->type; | |
83509119 | 2273 | bt_get(field_type); |
d975f66c | 2274 | |
b92ddaaa JG |
2275 | end: |
2276 | return field_type; | |
2277 | } | |
2278 | ||
50842bdc PP |
2279 | struct bt_field_type *bt_field_type_variant_get_field_type_from_tag( |
2280 | struct bt_field_type *type, | |
2281 | struct bt_field *tag) | |
b92ddaaa | 2282 | { |
e0f15669 | 2283 | int ret; |
b92ddaaa | 2284 | const char *enum_value; |
50842bdc PP |
2285 | struct bt_field_type *field_type = NULL; |
2286 | struct bt_field_type_enumeration_mapping_iterator *iter = NULL; | |
b92ddaaa | 2287 | |
d975f66c PP |
2288 | BT_ASSERT_PRE_NON_NULL(type, "Variant field type"); |
2289 | BT_ASSERT_PRE_NON_NULL(tag, "Tag field type"); | |
2290 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc PP |
2291 | iter = bt_field_enumeration_get_mappings(tag); |
2292 | ret = bt_field_type_enumeration_mapping_iterator_next(iter); | |
74fb0452 | 2293 | if (!iter || ret) { |
631234da | 2294 | BT_LOGW("Cannot get enumeration field type mapping iterator from enumeration field: " |
4e8304f7 | 2295 | "enum-field-addr=%p", tag); |
e0f15669 JG |
2296 | goto end; |
2297 | } | |
2298 | ||
50842bdc | 2299 | ret = bt_field_type_enumeration_mapping_iterator_get_signed(iter, |
5c3f3b7e | 2300 | &enum_value, NULL, NULL); |
e0f15669 | 2301 | if (ret) { |
4e8304f7 PP |
2302 | BT_LOGW("Cannot get enumeration field type mapping iterator's current mapping: " |
2303 | "iter-addr=%p", iter); | |
b92ddaaa JG |
2304 | goto end; |
2305 | } | |
2306 | ||
50842bdc | 2307 | field_type = bt_field_type_variant_get_field_type_by_name( |
b92ddaaa JG |
2308 | type, enum_value); |
2309 | end: | |
e0f15669 | 2310 | bt_put(iter); |
b92ddaaa JG |
2311 | return field_type; |
2312 | } | |
2313 | ||
50842bdc | 2314 | int64_t bt_field_type_variant_get_field_count(struct bt_field_type *type) |
b92ddaaa | 2315 | { |
50842bdc | 2316 | struct bt_field_type_variant *variant; |
b92ddaaa | 2317 | |
d975f66c PP |
2318 | BT_ASSERT_PRE_NON_NULL(type, "Variant field type"); |
2319 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc | 2320 | variant = container_of(type, struct bt_field_type_variant, |
b92ddaaa | 2321 | parent); |
d975f66c | 2322 | return (int64_t) variant->fields->len; |
b92ddaaa JG |
2323 | } |
2324 | ||
50842bdc PP |
2325 | int bt_field_type_variant_get_field_by_index(struct bt_field_type *type, |
2326 | const char **field_name, struct bt_field_type **field_type, | |
9ac68eb1 | 2327 | uint64_t index) |
b92ddaaa | 2328 | { |
50842bdc | 2329 | struct bt_field_type_variant *variant; |
b92ddaaa | 2330 | struct structure_field *field; |
b92ddaaa | 2331 | |
d975f66c PP |
2332 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2333 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc | 2334 | variant = container_of(type, struct bt_field_type_variant, |
b92ddaaa | 2335 | parent); |
d975f66c PP |
2336 | BT_ASSERT_PRE(index < variant->fields->len, |
2337 | "Index is out of bounds: index=%" PRIu64 ", " | |
2338 | "count=%u, %![ft-]+F", | |
2339 | index, variant->fields->len, type); | |
b92ddaaa | 2340 | field = g_ptr_array_index(variant->fields, index); |
d975f66c | 2341 | |
647f3b93 JG |
2342 | if (field_type) { |
2343 | *field_type = field->type; | |
83509119 | 2344 | bt_get(field->type); |
647f3b93 | 2345 | } |
d975f66c | 2346 | |
647f3b93 JG |
2347 | if (field_name) { |
2348 | *field_name = g_quark_to_string(field->name); | |
f6ccaed9 | 2349 | BT_ASSERT(*field_name); |
647f3b93 | 2350 | } |
d975f66c PP |
2351 | |
2352 | return 0; | |
b92ddaaa JG |
2353 | } |
2354 | ||
50842bdc PP |
2355 | struct bt_field_type *bt_field_type_array_create( |
2356 | struct bt_field_type *element_type, | |
273b65be JG |
2357 | unsigned int length) |
2358 | { | |
50842bdc | 2359 | struct bt_field_type_array *array = NULL; |
273b65be | 2360 | |
4e8304f7 PP |
2361 | BT_LOGD("Creating array field type object: element-ft-addr=%p, " |
2362 | "length=%u", element_type, length); | |
2363 | ||
2364 | if (!element_type) { | |
2365 | BT_LOGW_STR("Invalid parameter: element field type is NULL."); | |
2366 | goto error; | |
2367 | } | |
2368 | ||
2369 | if (length == 0) { | |
2370 | BT_LOGW_STR("Invalid parameter: length is zero."); | |
273b65be JG |
2371 | goto error; |
2372 | } | |
2373 | ||
50842bdc | 2374 | array = g_new0(struct bt_field_type_array, 1); |
273b65be | 2375 | if (!array) { |
4e8304f7 | 2376 | BT_LOGE_STR("Failed to allocate one array field type."); |
273b65be JG |
2377 | goto error; |
2378 | } | |
2379 | ||
50842bdc | 2380 | array->parent.id = BT_FIELD_TYPE_ID_ARRAY; |
83509119 | 2381 | bt_get(element_type); |
273b65be JG |
2382 | array->element_type = element_type; |
2383 | array->length = length; | |
50842bdc | 2384 | bt_field_type_init(&array->parent, FALSE); |
4e8304f7 PP |
2385 | BT_LOGD("Created array field type object: addr=%p, " |
2386 | "element-ft-addr=%p, length=%u", | |
2387 | &array->parent, element_type, length); | |
273b65be JG |
2388 | return &array->parent; |
2389 | error: | |
2390 | return NULL; | |
2391 | } | |
2392 | ||
50842bdc PP |
2393 | struct bt_field_type *bt_field_type_array_get_element_type( |
2394 | struct bt_field_type *type) | |
b92ddaaa | 2395 | { |
50842bdc | 2396 | struct bt_field_type_array *array; |
b92ddaaa | 2397 | |
d975f66c PP |
2398 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2399 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ARRAY, "Field type"); | |
50842bdc | 2400 | array = container_of(type, struct bt_field_type_array, parent); |
d975f66c | 2401 | return bt_get(array->element_type); |
b92ddaaa JG |
2402 | } |
2403 | ||
626e93aa | 2404 | BT_HIDDEN |
50842bdc PP |
2405 | int bt_field_type_array_set_element_type(struct bt_field_type *type, |
2406 | struct bt_field_type *element_type) | |
626e93aa PP |
2407 | { |
2408 | int ret = 0; | |
50842bdc | 2409 | struct bt_field_type_array *array; |
626e93aa | 2410 | |
4e8304f7 PP |
2411 | if (!type) { |
2412 | BT_LOGW_STR("Invalid parameter: array field type is NULL."); | |
2413 | ret = -1; | |
2414 | goto end; | |
2415 | } | |
2416 | ||
2417 | if (!element_type) { | |
2418 | BT_LOGW_STR("Invalid parameter: element field type is NULL."); | |
2419 | ret = -1; | |
2420 | goto end; | |
2421 | } | |
2422 | ||
50842bdc | 2423 | if (type->id != BT_FIELD_TYPE_ID_ARRAY) { |
4e8304f7 PP |
2424 | BT_LOGW("Invalid parameter: field type is not an array field type: " |
2425 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2426 | bt_field_type_id_string(type->id)); |
626e93aa PP |
2427 | ret = -1; |
2428 | goto end; | |
2429 | } | |
2430 | ||
50842bdc | 2431 | array = container_of(type, struct bt_field_type_array, parent); |
626e93aa PP |
2432 | |
2433 | if (array->element_type) { | |
2434 | BT_PUT(array->element_type); | |
2435 | } | |
2436 | ||
2437 | array->element_type = element_type; | |
2438 | bt_get(array->element_type); | |
dfc1504d PP |
2439 | BT_LOGV("Set array field type's element field type: array-ft-addr=%p, " |
2440 | "element-ft-addr=%p", type, element_type); | |
626e93aa PP |
2441 | |
2442 | end: | |
2443 | return ret; | |
2444 | } | |
2445 | ||
50842bdc | 2446 | int64_t bt_field_type_array_get_length(struct bt_field_type *type) |
b92ddaaa | 2447 | { |
50842bdc | 2448 | struct bt_field_type_array *array; |
b92ddaaa | 2449 | |
d975f66c PP |
2450 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2451 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_ARRAY, "Field type"); | |
50842bdc | 2452 | array = container_of(type, struct bt_field_type_array, parent); |
d975f66c | 2453 | return (int64_t) array->length; |
b92ddaaa JG |
2454 | } |
2455 | ||
50842bdc PP |
2456 | struct bt_field_type *bt_field_type_sequence_create( |
2457 | struct bt_field_type *element_type, | |
273b65be JG |
2458 | const char *length_field_name) |
2459 | { | |
50842bdc | 2460 | struct bt_field_type_sequence *sequence = NULL; |
273b65be | 2461 | |
4e8304f7 PP |
2462 | BT_LOGD("Creating sequence field type object: element-ft-addr=%p, " |
2463 | "length-field-name=\"%s\"", element_type, length_field_name); | |
2464 | ||
2465 | if (!element_type) { | |
2466 | BT_LOGW_STR("Invalid parameter: element field type is NULL."); | |
2467 | goto error; | |
2468 | } | |
2469 | ||
f4cc9a21 | 2470 | if (!bt_identifier_is_valid(length_field_name)) { |
4e8304f7 PP |
2471 | BT_LOGW("Invalid parameter: length field name is not a valid CTF identifier: " |
2472 | "length-field-name=\"%s\"", length_field_name); | |
273b65be JG |
2473 | goto error; |
2474 | } | |
2475 | ||
50842bdc | 2476 | sequence = g_new0(struct bt_field_type_sequence, 1); |
273b65be | 2477 | if (!sequence) { |
4e8304f7 | 2478 | BT_LOGE_STR("Failed to allocate one sequence field type."); |
273b65be JG |
2479 | goto error; |
2480 | } | |
2481 | ||
50842bdc | 2482 | sequence->parent.id = BT_FIELD_TYPE_ID_SEQUENCE; |
83509119 | 2483 | bt_get(element_type); |
273b65be JG |
2484 | sequence->element_type = element_type; |
2485 | sequence->length_field_name = g_string_new(length_field_name); | |
50842bdc | 2486 | bt_field_type_init(&sequence->parent, FALSE); |
4e8304f7 PP |
2487 | BT_LOGD("Created sequence field type object: addr=%p, " |
2488 | "element-ft-addr=%p, length-field-name=\"%s\"", | |
2489 | &sequence->parent, element_type, length_field_name); | |
273b65be JG |
2490 | return &sequence->parent; |
2491 | error: | |
2492 | return NULL; | |
2493 | } | |
2494 | ||
50842bdc PP |
2495 | struct bt_field_type *bt_field_type_sequence_get_element_type( |
2496 | struct bt_field_type *type) | |
b92ddaaa | 2497 | { |
50842bdc | 2498 | struct bt_field_type_sequence *sequence; |
b92ddaaa | 2499 | |
d975f66c PP |
2500 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2501 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type"); | |
50842bdc | 2502 | sequence = container_of(type, struct bt_field_type_sequence, |
b92ddaaa | 2503 | parent); |
d975f66c | 2504 | return bt_get(sequence->element_type); |
b92ddaaa JG |
2505 | } |
2506 | ||
626e93aa | 2507 | BT_HIDDEN |
50842bdc PP |
2508 | int bt_field_type_sequence_set_element_type(struct bt_field_type *type, |
2509 | struct bt_field_type *element_type) | |
626e93aa PP |
2510 | { |
2511 | int ret = 0; | |
50842bdc | 2512 | struct bt_field_type_sequence *sequence; |
626e93aa | 2513 | |
4e8304f7 PP |
2514 | if (!type) { |
2515 | BT_LOGW_STR("Invalid parameter: sequence field type is NULL."); | |
626e93aa PP |
2516 | ret = -1; |
2517 | goto end; | |
2518 | } | |
2519 | ||
4e8304f7 PP |
2520 | if (!element_type) { |
2521 | BT_LOGW_STR("Invalid parameter: element field type is NULL."); | |
2522 | ret = -1; | |
2523 | goto end; | |
2524 | } | |
2525 | ||
50842bdc | 2526 | if (type->id != BT_FIELD_TYPE_ID_SEQUENCE) { |
4e8304f7 PP |
2527 | BT_LOGW("Invalid parameter: field type is not a sequence field type: " |
2528 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2529 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
2530 | ret = -1; |
2531 | goto end; | |
2532 | } | |
626e93aa | 2533 | |
50842bdc | 2534 | sequence = container_of(type, struct bt_field_type_sequence, parent); |
626e93aa PP |
2535 | if (sequence->element_type) { |
2536 | BT_PUT(sequence->element_type); | |
2537 | } | |
2538 | ||
2539 | sequence->element_type = element_type; | |
2540 | bt_get(sequence->element_type); | |
dfc1504d PP |
2541 | BT_LOGV("Set sequence field type's element field type: sequence-ft-addr=%p, " |
2542 | "element-ft-addr=%p", type, element_type); | |
626e93aa PP |
2543 | |
2544 | end: | |
2545 | return ret; | |
2546 | } | |
2547 | ||
50842bdc PP |
2548 | const char *bt_field_type_sequence_get_length_field_name( |
2549 | struct bt_field_type *type) | |
b92ddaaa | 2550 | { |
50842bdc | 2551 | struct bt_field_type_sequence *sequence; |
b92ddaaa | 2552 | |
d975f66c PP |
2553 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2554 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type"); | |
50842bdc | 2555 | sequence = container_of(type, struct bt_field_type_sequence, |
b92ddaaa | 2556 | parent); |
d975f66c PP |
2557 | return sequence->length_field_name ? |
2558 | sequence->length_field_name->str : NULL; | |
b92ddaaa JG |
2559 | } |
2560 | ||
50842bdc | 2561 | struct bt_field_type *bt_field_type_string_create(void) |
273b65be | 2562 | { |
50842bdc PP |
2563 | struct bt_field_type_string *string = |
2564 | g_new0(struct bt_field_type_string, 1); | |
273b65be | 2565 | |
4e8304f7 PP |
2566 | BT_LOGD_STR("Creating string field type object."); |
2567 | ||
273b65be | 2568 | if (!string) { |
4e8304f7 | 2569 | BT_LOGE_STR("Failed to allocate one string field type."); |
273b65be JG |
2570 | return NULL; |
2571 | } | |
2572 | ||
50842bdc PP |
2573 | string->parent.id = BT_FIELD_TYPE_ID_STRING; |
2574 | bt_field_type_init(&string->parent, TRUE); | |
2575 | string->encoding = BT_STRING_ENCODING_UTF8; | |
dc3fffef | 2576 | string->parent.alignment = CHAR_BIT; |
4e8304f7 | 2577 | BT_LOGD("Created string field type object: addr=%p", &string->parent); |
273b65be JG |
2578 | return &string->parent; |
2579 | } | |
2580 | ||
50842bdc PP |
2581 | enum bt_string_encoding bt_field_type_string_get_encoding( |
2582 | struct bt_field_type *type) | |
b92ddaaa | 2583 | { |
50842bdc | 2584 | struct bt_field_type_string *string; |
b92ddaaa | 2585 | |
d975f66c PP |
2586 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
2587 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRING, "Field type"); | |
50842bdc | 2588 | string = container_of(type, struct bt_field_type_string, |
b92ddaaa | 2589 | parent); |
d975f66c | 2590 | return string->encoding; |
b92ddaaa JG |
2591 | } |
2592 | ||
50842bdc PP |
2593 | int bt_field_type_string_set_encoding(struct bt_field_type *type, |
2594 | enum bt_string_encoding encoding) | |
273b65be JG |
2595 | { |
2596 | int ret = 0; | |
50842bdc | 2597 | struct bt_field_type_string *string; |
273b65be | 2598 | |
4e8304f7 PP |
2599 | if (!type) { |
2600 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
2601 | ret = -1; | |
2602 | goto end; | |
2603 | } | |
2604 | ||
50842bdc | 2605 | if (type->id != BT_FIELD_TYPE_ID_STRING) { |
4e8304f7 PP |
2606 | BT_LOGW("Invalid parameter: field type is not a string field type: " |
2607 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2608 | bt_field_type_id_string(type->id)); |
4e8304f7 PP |
2609 | ret = -1; |
2610 | goto end; | |
2611 | } | |
2612 | ||
50842bdc PP |
2613 | if (encoding != BT_STRING_ENCODING_UTF8 && |
2614 | encoding != BT_STRING_ENCODING_ASCII) { | |
4e8304f7 PP |
2615 | BT_LOGW("Invalid parameter: unknown string encoding: " |
2616 | "addr=%p, encoding=%d", type, encoding); | |
273b65be JG |
2617 | ret = -1; |
2618 | goto end; | |
2619 | } | |
2620 | ||
50842bdc | 2621 | string = container_of(type, struct bt_field_type_string, parent); |
dc3fffef | 2622 | string->encoding = encoding; |
dfc1504d | 2623 | BT_LOGV("Set string field type's encoding: addr=%p, encoding=%s", |
50842bdc | 2624 | type, bt_string_encoding_string(encoding)); |
273b65be JG |
2625 | end: |
2626 | return ret; | |
2627 | } | |
2628 | ||
50842bdc | 2629 | int bt_field_type_get_alignment(struct bt_field_type *type) |
b92ddaaa JG |
2630 | { |
2631 | int ret; | |
50842bdc | 2632 | enum bt_field_type_id type_id; |
b92ddaaa | 2633 | |
d975f66c | 2634 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
b92ddaaa | 2635 | |
3ffba961 | 2636 | if (type->frozen) { |
dc3fffef | 2637 | ret = (int) type->alignment; |
3ffba961 JG |
2638 | goto end; |
2639 | } | |
2640 | ||
50842bdc | 2641 | type_id = bt_field_type_get_type_id(type); |
3ffba961 | 2642 | switch (type_id) { |
50842bdc | 2643 | case BT_FIELD_TYPE_ID_SEQUENCE: |
3ffba961 | 2644 | { |
50842bdc PP |
2645 | struct bt_field_type *element = |
2646 | bt_field_type_sequence_get_element_type(type); | |
3ffba961 | 2647 | |
f6ccaed9 | 2648 | BT_ASSERT(element); |
50842bdc | 2649 | ret = bt_field_type_get_alignment(element); |
83509119 | 2650 | bt_put(element); |
3ffba961 JG |
2651 | break; |
2652 | } | |
50842bdc | 2653 | case BT_FIELD_TYPE_ID_ARRAY: |
3ffba961 | 2654 | { |
50842bdc PP |
2655 | struct bt_field_type *element = |
2656 | bt_field_type_array_get_element_type(type); | |
3ffba961 | 2657 | |
f6ccaed9 | 2658 | BT_ASSERT(element); |
50842bdc | 2659 | ret = bt_field_type_get_alignment(element); |
83509119 | 2660 | bt_put(element); |
3ffba961 JG |
2661 | break; |
2662 | } | |
50842bdc | 2663 | case BT_FIELD_TYPE_ID_STRUCT: |
3ffba961 | 2664 | { |
544d0515 | 2665 | int64_t i, element_count; |
3ffba961 | 2666 | |
50842bdc | 2667 | element_count = bt_field_type_structure_get_field_count( |
3ffba961 | 2668 | type); |
f6ccaed9 | 2669 | BT_ASSERT(element_count >= 0); |
3ffba961 JG |
2670 | |
2671 | for (i = 0; i < element_count; i++) { | |
bc85036f | 2672 | struct bt_field_type *field = NULL; |
3ffba961 JG |
2673 | int field_alignment; |
2674 | ||
50842bdc | 2675 | ret = bt_field_type_structure_get_field_by_index( |
9ac68eb1 | 2676 | type, NULL, &field, i); |
f6ccaed9 PP |
2677 | BT_ASSERT(ret == 0); |
2678 | BT_ASSERT(field); | |
50842bdc | 2679 | field_alignment = bt_field_type_get_alignment( |
3ffba961 | 2680 | field); |
83509119 | 2681 | bt_put(field); |
3ffba961 JG |
2682 | if (field_alignment < 0) { |
2683 | ret = field_alignment; | |
2684 | goto end; | |
2685 | } | |
2686 | ||
dc3fffef | 2687 | type->alignment = MAX(field_alignment, type->alignment); |
3ffba961 | 2688 | } |
dc3fffef | 2689 | ret = (int) type->alignment; |
3ffba961 JG |
2690 | break; |
2691 | } | |
89e9af01 JG |
2692 | case BT_FIELD_TYPE_ID_ENUM: |
2693 | { | |
2694 | struct bt_field_type *container = | |
2695 | bt_field_type_enumeration_get_container_type(type); | |
2696 | ||
2697 | ret = bt_field_type_get_alignment(container); | |
2698 | bt_put(container); | |
2699 | break; | |
2700 | } | |
50842bdc | 2701 | case BT_FIELD_TYPE_ID_UNKNOWN: |
4e8304f7 PP |
2702 | BT_LOGW("Invalid parameter: unknown field type ID: " |
2703 | "addr=%p, ft-id=%d", type, type_id); | |
3ffba961 JG |
2704 | ret = -1; |
2705 | break; | |
2706 | default: | |
dc3fffef | 2707 | ret = (int) type->alignment; |
3ffba961 JG |
2708 | break; |
2709 | } | |
b92ddaaa JG |
2710 | end: |
2711 | return ret; | |
2712 | } | |
2713 | ||
9ad2f879 PP |
2714 | static inline |
2715 | int is_power_of_two(unsigned int value) | |
2716 | { | |
2717 | return ((value & (value - 1)) == 0) && value > 0; | |
2718 | } | |
2719 | ||
50842bdc | 2720 | int bt_field_type_set_alignment(struct bt_field_type *type, |
273b65be JG |
2721 | unsigned int alignment) |
2722 | { | |
2723 | int ret = 0; | |
50842bdc | 2724 | enum bt_field_type_id type_id; |
273b65be | 2725 | |
9ad2f879 | 2726 | /* Alignment must be a power of two */ |
4e8304f7 PP |
2727 | if (!type) { |
2728 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
2729 | ret = -1; | |
2730 | goto end; | |
2731 | } | |
2732 | ||
2733 | if (type->frozen) { | |
2734 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
2735 | type); | |
2736 | ret = -1; | |
2737 | goto end; | |
2738 | } | |
2739 | ||
2740 | if (!is_power_of_two(alignment)) { | |
2741 | BT_LOGW("Invalid parameter: alignment is not a power of two: " | |
2742 | "addr=%p, align=%u", type, alignment); | |
273b65be JG |
2743 | ret = -1; |
2744 | goto end; | |
2745 | } | |
2746 | ||
50842bdc PP |
2747 | type_id = bt_field_type_get_type_id(type); |
2748 | if (type_id == BT_FIELD_TYPE_ID_UNKNOWN) { | |
4e8304f7 PP |
2749 | BT_LOGW("Invalid parameter: unknown field type ID: " |
2750 | "addr=%p, ft-id=%d", type, type_id); | |
6a43d732 JG |
2751 | ret = -1; |
2752 | goto end; | |
2753 | } | |
2754 | ||
50842bdc | 2755 | if (type->id == BT_FIELD_TYPE_ID_STRING && |
4e8304f7 PP |
2756 | alignment != CHAR_BIT) { |
2757 | BT_LOGW("Invalid parameter: alignment must be %u for a string field type: " | |
2758 | "addr=%p, align=%u", CHAR_BIT, type, alignment); | |
273b65be JG |
2759 | ret = -1; |
2760 | goto end; | |
2761 | } | |
2762 | ||
50842bdc PP |
2763 | if (type_id == BT_FIELD_TYPE_ID_VARIANT || |
2764 | type_id == BT_FIELD_TYPE_ID_SEQUENCE || | |
2765 | type_id == BT_FIELD_TYPE_ID_ARRAY) { | |
6a43d732 | 2766 | /* Setting an alignment on these types makes no sense */ |
4e8304f7 PP |
2767 | BT_LOGW("Invalid parameter: cannot set the alignment of this field type: " |
2768 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2769 | bt_field_type_id_string(type->id)); |
6a43d732 JG |
2770 | ret = -1; |
2771 | goto end; | |
2772 | } | |
2773 | ||
dc3fffef | 2774 | type->alignment = alignment; |
273b65be | 2775 | ret = 0; |
dfc1504d PP |
2776 | BT_LOGV("Set field type's alignment: addr=%p, align=%u", |
2777 | type, alignment); | |
273b65be JG |
2778 | end: |
2779 | return ret; | |
2780 | } | |
2781 | ||
50842bdc PP |
2782 | enum bt_byte_order bt_field_type_get_byte_order( |
2783 | struct bt_field_type *type) | |
b92ddaaa | 2784 | { |
50842bdc | 2785 | enum bt_byte_order ret = BT_BYTE_ORDER_UNKNOWN; |
b92ddaaa | 2786 | |
d975f66c | 2787 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
b92ddaaa | 2788 | |
dc3fffef | 2789 | switch (type->id) { |
50842bdc | 2790 | case BT_FIELD_TYPE_ID_INTEGER: |
b92ddaaa | 2791 | { |
50842bdc PP |
2792 | struct bt_field_type_integer *integer = container_of( |
2793 | type, struct bt_field_type_integer, parent); | |
445c3471 | 2794 | ret = integer->user_byte_order; |
b92ddaaa JG |
2795 | break; |
2796 | } | |
50842bdc | 2797 | case BT_FIELD_TYPE_ID_ENUM: |
4b2da5f0 | 2798 | { |
50842bdc PP |
2799 | struct bt_field_type_enumeration *enum_ft = container_of( |
2800 | type, struct bt_field_type_enumeration, parent); | |
2801 | ret = bt_field_type_get_byte_order(enum_ft->container); | |
4b2da5f0 PP |
2802 | break; |
2803 | } | |
50842bdc | 2804 | case BT_FIELD_TYPE_ID_FLOAT: |
b92ddaaa | 2805 | { |
50842bdc | 2806 | struct bt_field_type_floating_point *floating_point = |
b92ddaaa | 2807 | container_of(type, |
50842bdc | 2808 | struct bt_field_type_floating_point, |
b92ddaaa | 2809 | parent); |
445c3471 | 2810 | ret = floating_point->user_byte_order; |
b92ddaaa JG |
2811 | break; |
2812 | } | |
2813 | default: | |
4e8304f7 PP |
2814 | BT_LOGW("Invalid parameter: cannot get the byte order of this field type: " |
2815 | "addr=%p, ft-id=%s", type, | |
50842bdc | 2816 | bt_field_type_id_string(type->id)); |
c35a1669 JG |
2817 | goto end; |
2818 | } | |
2819 | ||
f6ccaed9 | 2820 | BT_ASSERT(ret == BT_BYTE_ORDER_NATIVE || |
50842bdc PP |
2821 | ret == BT_BYTE_ORDER_LITTLE_ENDIAN || |
2822 | ret == BT_BYTE_ORDER_BIG_ENDIAN || | |
2823 | ret == BT_BYTE_ORDER_NETWORK); | |
445c3471 | 2824 | |
b92ddaaa JG |
2825 | end: |
2826 | return ret; | |
2827 | } | |
2828 | ||
50842bdc PP |
2829 | int bt_field_type_set_byte_order(struct bt_field_type *type, |
2830 | enum bt_byte_order byte_order) | |
273b65be JG |
2831 | { |
2832 | int ret = 0; | |
273b65be | 2833 | |
4e8304f7 PP |
2834 | if (!type) { |
2835 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
2836 | ret = -1; | |
2837 | goto end; | |
2838 | } | |
2839 | ||
2840 | if (type->frozen) { | |
2841 | BT_LOGW("Invalid parameter: field type is frozen: addr=%p", | |
2842 | type); | |
273b65be JG |
2843 | ret = -1; |
2844 | goto end; | |
2845 | } | |
2846 | ||
50842bdc PP |
2847 | if (byte_order != BT_BYTE_ORDER_NATIVE && |
2848 | byte_order != BT_BYTE_ORDER_LITTLE_ENDIAN && | |
2849 | byte_order != BT_BYTE_ORDER_BIG_ENDIAN && | |
2850 | byte_order != BT_BYTE_ORDER_NETWORK) { | |
d41cff38 | 2851 | BT_LOGW("Invalid parameter: invalid byte order: " |
4e8304f7 | 2852 | "addr=%p, bo=%s", type, |
50842bdc | 2853 | bt_byte_order_string(byte_order)); |
273b65be JG |
2854 | ret = -1; |
2855 | goto end; | |
2856 | } | |
2857 | ||
dc3fffef PP |
2858 | if (set_byte_order_funcs[type->id]) { |
2859 | set_byte_order_funcs[type->id](type, byte_order); | |
273b65be | 2860 | } |
dfc1504d PP |
2861 | |
2862 | BT_LOGV("Set field type's byte order: addr=%p, bo=%s", | |
50842bdc | 2863 | type, bt_byte_order_string(byte_order)); |
dfc1504d | 2864 | |
273b65be JG |
2865 | end: |
2866 | return ret; | |
2867 | } | |
2868 | ||
50842bdc PP |
2869 | enum bt_field_type_id bt_field_type_get_type_id( |
2870 | struct bt_field_type *type) | |
b92ddaaa | 2871 | { |
d975f66c | 2872 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
dc3fffef | 2873 | return type->id; |
b92ddaaa | 2874 | } |
2f2d8e05 | 2875 | |
50842bdc | 2876 | int bt_field_type_is_integer(struct bt_field_type *type) |
56db8d7a | 2877 | { |
50842bdc | 2878 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_INTEGER; |
56db8d7a PP |
2879 | } |
2880 | ||
50842bdc | 2881 | int bt_field_type_is_floating_point(struct bt_field_type *type) |
56db8d7a | 2882 | { |
50842bdc | 2883 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_FLOAT; |
56db8d7a PP |
2884 | } |
2885 | ||
50842bdc | 2886 | int bt_field_type_is_enumeration(struct bt_field_type *type) |
56db8d7a | 2887 | { |
50842bdc | 2888 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ENUM; |
56db8d7a PP |
2889 | } |
2890 | ||
50842bdc | 2891 | int bt_field_type_is_string(struct bt_field_type *type) |
56db8d7a | 2892 | { |
50842bdc | 2893 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRING; |
56db8d7a PP |
2894 | } |
2895 | ||
50842bdc | 2896 | int bt_field_type_is_structure(struct bt_field_type *type) |
56db8d7a | 2897 | { |
50842bdc | 2898 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_STRUCT; |
56db8d7a PP |
2899 | } |
2900 | ||
50842bdc | 2901 | int bt_field_type_is_array(struct bt_field_type *type) |
56db8d7a | 2902 | { |
50842bdc | 2903 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_ARRAY; |
56db8d7a PP |
2904 | } |
2905 | ||
50842bdc | 2906 | int bt_field_type_is_sequence(struct bt_field_type *type) |
56db8d7a | 2907 | { |
50842bdc | 2908 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_SEQUENCE; |
56db8d7a PP |
2909 | } |
2910 | ||
50842bdc | 2911 | int bt_field_type_is_variant(struct bt_field_type *type) |
56db8d7a | 2912 | { |
50842bdc | 2913 | return bt_field_type_get_type_id(type) == BT_FIELD_TYPE_ID_VARIANT; |
56db8d7a PP |
2914 | } |
2915 | ||
4e8304f7 | 2916 | /* Pre-2.0 CTF writer backward compatibility */ |
50842bdc | 2917 | void bt_ctf_field_type_get(struct bt_field_type *type) |
273b65be | 2918 | { |
83509119 | 2919 | bt_get(type); |
273b65be JG |
2920 | } |
2921 | ||
4e8304f7 | 2922 | /* Pre-2.0 CTF writer backward compatibility */ |
50842bdc | 2923 | void bt_ctf_field_type_put(struct bt_field_type *type) |
273b65be | 2924 | { |
83509119 | 2925 | bt_put(type); |
273b65be JG |
2926 | } |
2927 | ||
2928 | BT_HIDDEN | |
f6ccaed9 | 2929 | void _bt_field_type_freeze(struct bt_field_type *type) |
273b65be | 2930 | { |
4e8304f7 | 2931 | if (!type || type->frozen) { |
273b65be JG |
2932 | return; |
2933 | } | |
2934 | ||
2935 | type->freeze(type); | |
2936 | } | |
2937 | ||
2938 | BT_HIDDEN | |
50842bdc PP |
2939 | struct bt_field_type *bt_field_type_variant_get_field_type_signed( |
2940 | struct bt_field_type_variant *variant, | |
b92ddaaa | 2941 | int64_t tag_value) |
273b65be | 2942 | { |
50842bdc | 2943 | struct bt_field_type *type = NULL; |
b92ddaaa JG |
2944 | GQuark field_name_quark; |
2945 | gpointer index; | |
2946 | struct structure_field *field_entry; | |
2947 | struct range_overlap_query query = { | |
2948 | .range_start._signed = tag_value, | |
2949 | .range_end._signed = tag_value, | |
96e8f959 MD |
2950 | .mapping_name = 0, |
2951 | .overlaps = 0, | |
2952 | }; | |
273b65be | 2953 | |
b92ddaaa JG |
2954 | g_ptr_array_foreach(variant->tag->entries, check_ranges_overlap, |
2955 | &query); | |
2956 | if (!query.overlaps) { | |
273b65be JG |
2957 | goto end; |
2958 | } | |
2959 | ||
b92ddaaa JG |
2960 | field_name_quark = query.mapping_name; |
2961 | if (!g_hash_table_lookup_extended(variant->field_name_to_index, | |
ec159b1e | 2962 | GUINT_TO_POINTER(field_name_quark), NULL, &index)) { |
273b65be JG |
2963 | goto end; |
2964 | } | |
2965 | ||
e54fab7e | 2966 | field_entry = g_ptr_array_index(variant->fields, (size_t) index); |
b92ddaaa | 2967 | type = field_entry->type; |
273b65be JG |
2968 | end: |
2969 | return type; | |
2970 | } | |
2971 | ||
2972 | BT_HIDDEN | |
50842bdc PP |
2973 | struct bt_field_type *bt_field_type_variant_get_field_type_unsigned( |
2974 | struct bt_field_type_variant *variant, | |
b92ddaaa | 2975 | uint64_t tag_value) |
273b65be | 2976 | { |
50842bdc | 2977 | struct bt_field_type *type = NULL; |
273b65be JG |
2978 | GQuark field_name_quark; |
2979 | gpointer index; | |
2980 | struct structure_field *field_entry; | |
b92ddaaa JG |
2981 | struct range_overlap_query query = { |
2982 | .range_start._unsigned = tag_value, | |
2983 | .range_end._unsigned = tag_value, | |
96e8f959 MD |
2984 | .mapping_name = 0, |
2985 | .overlaps = 0, | |
2986 | }; | |
273b65be | 2987 | |
b92ddaaa JG |
2988 | g_ptr_array_foreach(variant->tag->entries, |
2989 | check_ranges_overlap_unsigned, | |
273b65be JG |
2990 | &query); |
2991 | if (!query.overlaps) { | |
2992 | goto end; | |
2993 | } | |
2994 | ||
2995 | field_name_quark = query.mapping_name; | |
2996 | if (!g_hash_table_lookup_extended(variant->field_name_to_index, | |
2997 | GUINT_TO_POINTER(field_name_quark), NULL, &index)) { | |
2998 | goto end; | |
2999 | } | |
3000 | ||
3001 | field_entry = g_ptr_array_index(variant->fields, (size_t)index); | |
3002 | type = field_entry->type; | |
3003 | end: | |
3004 | return type; | |
3005 | } | |
3006 | ||
3007 | BT_HIDDEN | |
50842bdc | 3008 | int bt_field_type_serialize(struct bt_field_type *type, |
273b65be JG |
3009 | struct metadata_context *context) |
3010 | { | |
3011 | int ret; | |
3012 | ||
f6ccaed9 PP |
3013 | BT_ASSERT(type); |
3014 | BT_ASSERT(context); | |
4e8304f7 | 3015 | |
81e36fac | 3016 | /* Make sure field type is valid before serializing it */ |
50842bdc | 3017 | ret = bt_field_type_validate(type); |
81e36fac | 3018 | if (ret) { |
f45cd48c PP |
3019 | BT_LOGW("Cannot serialize field type's metadata: field type is invalid: " |
3020 | "addr=%p", type); | |
81e36fac PP |
3021 | goto end; |
3022 | } | |
3023 | ||
273b65be JG |
3024 | ret = type->serialize(type, context); |
3025 | end: | |
3026 | return ret; | |
3027 | } | |
3028 | ||
50842bdc | 3029 | struct bt_field_type *bt_field_type_copy(struct bt_field_type *type) |
24724933 | 3030 | { |
50842bdc | 3031 | struct bt_field_type *copy = NULL; |
24724933 | 3032 | |
d975f66c | 3033 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
dc3fffef | 3034 | copy = type_copy_funcs[type->id](type); |
4e8304f7 PP |
3035 | if (!copy) { |
3036 | BT_LOGE_STR("Cannot copy field type."); | |
3037 | goto end; | |
3038 | } | |
3039 | ||
dc3fffef | 3040 | copy->alignment = type->alignment; |
d975f66c | 3041 | |
24724933 JG |
3042 | end: |
3043 | return copy; | |
3044 | } | |
3045 | ||
39a5e0db | 3046 | BT_HIDDEN |
50842bdc PP |
3047 | int bt_field_type_structure_get_field_name_index( |
3048 | struct bt_field_type *type, const char *name) | |
39a5e0db JG |
3049 | { |
3050 | int ret; | |
3051 | size_t index; | |
3052 | GQuark name_quark; | |
50842bdc | 3053 | struct bt_field_type_structure *structure; |
39a5e0db | 3054 | |
d975f66c PP |
3055 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
3056 | BT_ASSERT_PRE_NON_NULL(name, "Name"); | |
3057 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_STRUCT, "Field type"); | |
39a5e0db JG |
3058 | |
3059 | name_quark = g_quark_try_string(name); | |
3060 | if (!name_quark) { | |
6fa8d37b PP |
3061 | BT_LOGV("No such structure field type field name: " |
3062 | "ft-addr=%p, field-name=\"%s\"", | |
3063 | type, name); | |
39a5e0db JG |
3064 | ret = -1; |
3065 | goto end; | |
3066 | } | |
3067 | ||
50842bdc | 3068 | structure = container_of(type, struct bt_field_type_structure, |
39a5e0db JG |
3069 | parent); |
3070 | if (!g_hash_table_lookup_extended(structure->field_name_to_index, | |
ec159b1e PP |
3071 | GUINT_TO_POINTER(name_quark), |
3072 | NULL, (gpointer *)&index)) { | |
6fa8d37b PP |
3073 | BT_LOGV("No such structure field type field name: " |
3074 | "ft-addr=%p, field-name=\"%s\"", | |
3075 | type, name); | |
39a5e0db JG |
3076 | ret = -1; |
3077 | goto end; | |
3078 | } | |
3079 | ret = (int) index; | |
3080 | end: | |
3081 | return ret; | |
3082 | } | |
736133f1 JG |
3083 | |
3084 | BT_HIDDEN | |
50842bdc PP |
3085 | int bt_field_type_variant_get_field_name_index( |
3086 | struct bt_field_type *type, const char *name) | |
736133f1 JG |
3087 | { |
3088 | int ret; | |
3089 | size_t index; | |
3090 | GQuark name_quark; | |
50842bdc | 3091 | struct bt_field_type_variant *variant; |
736133f1 | 3092 | |
d975f66c PP |
3093 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
3094 | BT_ASSERT_PRE_NON_NULL(name, "Name"); | |
3095 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
736133f1 JG |
3096 | name_quark = g_quark_try_string(name); |
3097 | if (!name_quark) { | |
6fa8d37b PP |
3098 | BT_LOGV("No such variant field type field name: " |
3099 | "ft-addr=%p, field-name=\"%s\"", | |
3100 | type, name); | |
736133f1 JG |
3101 | ret = -1; |
3102 | goto end; | |
3103 | } | |
3104 | ||
50842bdc | 3105 | variant = container_of(type, struct bt_field_type_variant, |
736133f1 JG |
3106 | parent); |
3107 | if (!g_hash_table_lookup_extended(variant->field_name_to_index, | |
ec159b1e PP |
3108 | GUINT_TO_POINTER(name_quark), |
3109 | NULL, (gpointer *)&index)) { | |
6fa8d37b PP |
3110 | BT_LOGV("No such variant field type field name: " |
3111 | "ft-addr=%p, field-name=\"%s\"", | |
3112 | type, name); | |
736133f1 JG |
3113 | ret = -1; |
3114 | goto end; | |
3115 | } | |
3116 | ret = (int) index; | |
3117 | end: | |
3118 | return ret; | |
3119 | } | |
aa4e271c JG |
3120 | |
3121 | BT_HIDDEN | |
50842bdc | 3122 | int bt_field_type_sequence_set_length_field_path( |
d975f66c | 3123 | struct bt_field_type *type, struct bt_field_path *path) |
aa4e271c JG |
3124 | { |
3125 | int ret = 0; | |
50842bdc | 3126 | struct bt_field_type_sequence *sequence; |
aa4e271c | 3127 | |
4e8304f7 PP |
3128 | if (!type) { |
3129 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
3130 | ret = -1; | |
3131 | goto end; | |
3132 | } | |
3133 | ||
50842bdc | 3134 | if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_SEQUENCE) { |
4e8304f7 PP |
3135 | BT_LOGW("Invalid parameter: field type is not a sequence field type: " |
3136 | "addr=%p, ft-id=%s", type, | |
50842bdc | 3137 | bt_field_type_id_string(type->id)); |
aa4e271c JG |
3138 | ret = -1; |
3139 | goto end; | |
3140 | } | |
3141 | ||
50842bdc | 3142 | sequence = container_of(type, struct bt_field_type_sequence, |
aa4e271c | 3143 | parent); |
b011f6b0 PP |
3144 | bt_get(path); |
3145 | BT_MOVE(sequence->length_field_path, path); | |
dfc1504d PP |
3146 | BT_LOGV("Set sequence field type's length field path: ft-addr=%p, " |
3147 | "field-path-addr=%p", type, path); | |
aa4e271c JG |
3148 | end: |
3149 | return ret; | |
3150 | } | |
4a1e8671 JG |
3151 | |
3152 | BT_HIDDEN | |
50842bdc PP |
3153 | int bt_field_type_variant_set_tag_field_path(struct bt_field_type *type, |
3154 | struct bt_field_path *path) | |
4a1e8671 JG |
3155 | { |
3156 | int ret = 0; | |
50842bdc | 3157 | struct bt_field_type_variant *variant; |
4a1e8671 | 3158 | |
4e8304f7 PP |
3159 | if (!type) { |
3160 | BT_LOGW_STR("Invalid parameter: field type is NULL."); | |
3161 | ret = -1; | |
3162 | goto end; | |
3163 | } | |
3164 | ||
50842bdc | 3165 | if (bt_field_type_get_type_id(type) != BT_FIELD_TYPE_ID_VARIANT) { |
4e8304f7 PP |
3166 | BT_LOGW("Invalid parameter: field type is not a variant field type: " |
3167 | "addr=%p, ft-id=%s", type, | |
50842bdc | 3168 | bt_field_type_id_string(type->id)); |
4a1e8671 JG |
3169 | ret = -1; |
3170 | goto end; | |
3171 | } | |
3172 | ||
50842bdc | 3173 | variant = container_of(type, struct bt_field_type_variant, |
4a1e8671 | 3174 | parent); |
b011f6b0 PP |
3175 | bt_get(path); |
3176 | BT_MOVE(variant->tag_field_path, path); | |
dfc1504d PP |
3177 | BT_LOGV("Set variant field type's tag field path: ft-addr=%p, " |
3178 | "field-path-addr=%p", type, path); | |
4a1e8671 JG |
3179 | end: |
3180 | return ret; | |
3181 | } | |
3f39933a JG |
3182 | |
3183 | BT_HIDDEN | |
50842bdc PP |
3184 | int bt_field_type_variant_set_tag_field_type(struct bt_field_type *type, |
3185 | struct bt_field_type *tag) | |
3f39933a JG |
3186 | { |
3187 | int ret = 0; | |
50842bdc | 3188 | struct bt_field_type_variant *variant; |
3f39933a | 3189 | |
4e8304f7 PP |
3190 | if (!type) { |
3191 | BT_LOGW_STR("Invalid parameter: variant field type is NULL."); | |
3f39933a JG |
3192 | ret = -1; |
3193 | goto end; | |
3194 | } | |
3195 | ||
4e8304f7 PP |
3196 | if (!tag) { |
3197 | BT_LOGW_STR("Invalid parameter: tag field type is NULL."); | |
3198 | ret = -1; | |
3199 | goto end; | |
3f39933a | 3200 | } |
5cec03e4 | 3201 | |
50842bdc | 3202 | if (bt_field_type_get_type_id(tag) != BT_FIELD_TYPE_ID_ENUM) { |
4e8304f7 PP |
3203 | BT_LOGW("Invalid parameter: field type is not an enumeration field type: " |
3204 | "addr=%p, ft-id=%s", type, | |
50842bdc | 3205 | bt_field_type_id_string(type->id)); |
5cec03e4 JG |
3206 | ret = -1; |
3207 | goto end; | |
3208 | } | |
3209 | ||
50842bdc | 3210 | variant = container_of(type, struct bt_field_type_variant, |
5cec03e4 | 3211 | parent); |
4e8304f7 PP |
3212 | bt_get(tag); |
3213 | if (variant->tag) { | |
3214 | bt_put(&variant->tag->parent); | |
5cec03e4 | 3215 | } |
50842bdc | 3216 | variant->tag = container_of(tag, struct bt_field_type_enumeration, |
4e8304f7 | 3217 | parent); |
dfc1504d PP |
3218 | BT_LOGV("Set variant field type's tag field type: variant-ft-addr=%p, " |
3219 | "tag-ft-addr=%p", type, tag); | |
5cec03e4 JG |
3220 | end: |
3221 | return ret; | |
3222 | } | |
3223 | ||
273b65be | 3224 | static |
50842bdc | 3225 | void bt_field_type_integer_destroy(struct bt_field_type *type) |
273b65be | 3226 | { |
50842bdc PP |
3227 | struct bt_field_type_integer *integer = |
3228 | (struct bt_field_type_integer *) type; | |
273b65be | 3229 | |
de3dd40e | 3230 | if (!type) { |
273b65be JG |
3231 | return; |
3232 | } | |
3233 | ||
4e8304f7 | 3234 | BT_LOGD("Destroying integer field type object: addr=%p", type); |
ec159b1e | 3235 | BT_LOGD_STR("Putting mapped clock class."); |
83509119 | 3236 | bt_put(integer->mapped_clock); |
273b65be JG |
3237 | g_free(integer); |
3238 | } | |
3239 | ||
3240 | static | |
50842bdc | 3241 | void bt_field_type_enumeration_destroy(struct bt_field_type *type) |
273b65be | 3242 | { |
50842bdc PP |
3243 | struct bt_field_type_enumeration *enumeration = |
3244 | (struct bt_field_type_enumeration *) type; | |
273b65be | 3245 | |
de3dd40e | 3246 | if (!type) { |
273b65be JG |
3247 | return; |
3248 | } | |
3249 | ||
4e8304f7 | 3250 | BT_LOGD("Destroying enumeration field type object: addr=%p", type); |
273b65be | 3251 | g_ptr_array_free(enumeration->entries, TRUE); |
ec159b1e | 3252 | BT_LOGD_STR("Putting container field type."); |
83509119 | 3253 | bt_put(enumeration->container); |
273b65be JG |
3254 | g_free(enumeration); |
3255 | } | |
3256 | ||
3257 | static | |
50842bdc | 3258 | void bt_field_type_floating_point_destroy(struct bt_field_type *type) |
273b65be | 3259 | { |
50842bdc PP |
3260 | struct bt_field_type_floating_point *floating_point = |
3261 | (struct bt_field_type_floating_point *) type; | |
273b65be | 3262 | |
de3dd40e | 3263 | if (!type) { |
273b65be JG |
3264 | return; |
3265 | } | |
3266 | ||
4e8304f7 | 3267 | BT_LOGD("Destroying floating point number field type object: addr=%p", type); |
273b65be JG |
3268 | g_free(floating_point); |
3269 | } | |
3270 | ||
3271 | static | |
50842bdc | 3272 | void bt_field_type_structure_destroy(struct bt_field_type *type) |
273b65be | 3273 | { |
50842bdc PP |
3274 | struct bt_field_type_structure *structure = |
3275 | (struct bt_field_type_structure *) type; | |
273b65be | 3276 | |
de3dd40e | 3277 | if (!type) { |
273b65be JG |
3278 | return; |
3279 | } | |
3280 | ||
4e8304f7 | 3281 | BT_LOGD("Destroying structure field type object: addr=%p", type); |
273b65be JG |
3282 | g_ptr_array_free(structure->fields, TRUE); |
3283 | g_hash_table_destroy(structure->field_name_to_index); | |
3284 | g_free(structure); | |
3285 | } | |
3286 | ||
3287 | static | |
50842bdc | 3288 | void bt_field_type_variant_destroy(struct bt_field_type *type) |
273b65be | 3289 | { |
50842bdc PP |
3290 | struct bt_field_type_variant *variant = |
3291 | (struct bt_field_type_variant *) type; | |
273b65be | 3292 | |
de3dd40e | 3293 | if (!type) { |
273b65be JG |
3294 | return; |
3295 | } | |
3296 | ||
4e8304f7 | 3297 | BT_LOGD("Destroying variant field type object: addr=%p", type); |
273b65be JG |
3298 | g_ptr_array_free(variant->fields, TRUE); |
3299 | g_hash_table_destroy(variant->field_name_to_index); | |
3300 | g_string_free(variant->tag_name, TRUE); | |
ec159b1e | 3301 | BT_LOGD_STR("Putting tag field type."); |
83509119 | 3302 | bt_put(&variant->tag->parent); |
b011f6b0 | 3303 | BT_PUT(variant->tag_field_path); |
273b65be JG |
3304 | g_free(variant); |
3305 | } | |
3306 | ||
3307 | static | |
50842bdc | 3308 | void bt_field_type_array_destroy(struct bt_field_type *type) |
273b65be | 3309 | { |
50842bdc PP |
3310 | struct bt_field_type_array *array = |
3311 | (struct bt_field_type_array *) type; | |
273b65be | 3312 | |
de3dd40e | 3313 | if (!type) { |
273b65be JG |
3314 | return; |
3315 | } | |
3316 | ||
4e8304f7 | 3317 | BT_LOGD("Destroying array field type object: addr=%p", type); |
ec159b1e | 3318 | BT_LOGD_STR("Putting element field type."); |
83509119 | 3319 | bt_put(array->element_type); |
273b65be JG |
3320 | g_free(array); |
3321 | } | |
3322 | ||
3323 | static | |
50842bdc | 3324 | void bt_field_type_sequence_destroy(struct bt_field_type *type) |
273b65be | 3325 | { |
50842bdc PP |
3326 | struct bt_field_type_sequence *sequence = |
3327 | (struct bt_field_type_sequence *) type; | |
273b65be | 3328 | |
de3dd40e | 3329 | if (!type) { |
273b65be JG |
3330 | return; |
3331 | } | |
3332 | ||
4e8304f7 | 3333 | BT_LOGD("Destroying sequence field type object: addr=%p", type); |
ec159b1e | 3334 | BT_LOGD_STR("Putting element field type."); |
83509119 | 3335 | bt_put(sequence->element_type); |
273b65be | 3336 | g_string_free(sequence->length_field_name, TRUE); |
ec159b1e | 3337 | BT_LOGD_STR("Putting length field path."); |
b011f6b0 | 3338 | BT_PUT(sequence->length_field_path); |
273b65be JG |
3339 | g_free(sequence); |
3340 | } | |
3341 | ||
3342 | static | |
50842bdc | 3343 | void bt_field_type_string_destroy(struct bt_field_type *type) |
273b65be | 3344 | { |
50842bdc PP |
3345 | struct bt_field_type_string *string = |
3346 | (struct bt_field_type_string *) type; | |
273b65be | 3347 | |
de3dd40e | 3348 | if (!type) { |
273b65be JG |
3349 | return; |
3350 | } | |
3351 | ||
4e8304f7 | 3352 | BT_LOGD("Destroying string field type object: addr=%p", type); |
273b65be JG |
3353 | g_free(string); |
3354 | } | |
3355 | ||
3356 | static | |
50842bdc | 3357 | void generic_field_type_freeze(struct bt_field_type *type) |
273b65be JG |
3358 | { |
3359 | type->frozen = 1; | |
3360 | } | |
3361 | ||
586411e5 | 3362 | static |
50842bdc | 3363 | void bt_field_type_integer_freeze(struct bt_field_type *type) |
586411e5 | 3364 | { |
50842bdc PP |
3365 | struct bt_field_type_integer *integer_type = container_of( |
3366 | type, struct bt_field_type_integer, parent); | |
586411e5 | 3367 | |
4e8304f7 PP |
3368 | BT_LOGD("Freezing integer field type object: addr=%p", type); |
3369 | ||
586411e5 | 3370 | if (integer_type->mapped_clock) { |
ec159b1e | 3371 | BT_LOGD_STR("Freezing integer field type's mapped clock class."); |
50842bdc | 3372 | bt_clock_class_freeze(integer_type->mapped_clock); |
586411e5 PP |
3373 | } |
3374 | ||
3375 | generic_field_type_freeze(type); | |
3376 | } | |
3377 | ||
273b65be | 3378 | static |
50842bdc | 3379 | void bt_field_type_enumeration_freeze(struct bt_field_type *type) |
273b65be | 3380 | { |
50842bdc PP |
3381 | struct bt_field_type_enumeration *enumeration_type = container_of( |
3382 | type, struct bt_field_type_enumeration, parent); | |
273b65be | 3383 | |
4e8304f7 | 3384 | BT_LOGD("Freezing enumeration field type object: addr=%p", type); |
89e9af01 | 3385 | type->alignment = bt_field_type_get_alignment(type); |
d49e1284 | 3386 | set_enumeration_range_overlap(type); |
273b65be | 3387 | generic_field_type_freeze(type); |
225f3384 PP |
3388 | BT_LOGD("Freezing enumeration field type object's container field type: int-ft-addr=%p", |
3389 | enumeration_type->container); | |
50842bdc | 3390 | bt_field_type_freeze(enumeration_type->container); |
273b65be JG |
3391 | } |
3392 | ||
3393 | static | |
3394 | void freeze_structure_field(struct structure_field *field) | |
3395 | { | |
225f3384 PP |
3396 | BT_LOGD("Freezing structure/variant field type field: field-addr=%p, " |
3397 | "field-ft-addr=%p, field-name=\"%s\"", field, | |
3398 | field->type, g_quark_to_string(field->name)); | |
50842bdc | 3399 | bt_field_type_freeze(field->type); |
273b65be JG |
3400 | } |
3401 | ||
3402 | static | |
50842bdc | 3403 | void bt_field_type_structure_freeze(struct bt_field_type *type) |
273b65be | 3404 | { |
50842bdc PP |
3405 | struct bt_field_type_structure *structure_type = container_of( |
3406 | type, struct bt_field_type_structure, parent); | |
273b65be | 3407 | |
3ffba961 | 3408 | /* Cache the alignment */ |
4e8304f7 | 3409 | BT_LOGD("Freezing structure field type object: addr=%p", type); |
50842bdc | 3410 | type->alignment = bt_field_type_get_alignment(type); |
273b65be | 3411 | generic_field_type_freeze(type); |
3ffba961 JG |
3412 | g_ptr_array_foreach(structure_type->fields, |
3413 | (GFunc) freeze_structure_field, NULL); | |
273b65be JG |
3414 | } |
3415 | ||
3416 | static | |
50842bdc | 3417 | void bt_field_type_variant_freeze(struct bt_field_type *type) |
273b65be | 3418 | { |
50842bdc PP |
3419 | struct bt_field_type_variant *variant_type = container_of( |
3420 | type, struct bt_field_type_variant, parent); | |
273b65be | 3421 | |
4e8304f7 | 3422 | BT_LOGD("Freezing variant field type object: addr=%p", type); |
273b65be | 3423 | generic_field_type_freeze(type); |
3ffba961 JG |
3424 | g_ptr_array_foreach(variant_type->fields, |
3425 | (GFunc) freeze_structure_field, NULL); | |
273b65be JG |
3426 | } |
3427 | ||
3428 | static | |
50842bdc | 3429 | void bt_field_type_array_freeze(struct bt_field_type *type) |
273b65be | 3430 | { |
50842bdc PP |
3431 | struct bt_field_type_array *array_type = container_of( |
3432 | type, struct bt_field_type_array, parent); | |
273b65be | 3433 | |
3ffba961 | 3434 | /* Cache the alignment */ |
4e8304f7 | 3435 | BT_LOGD("Freezing array field type object: addr=%p", type); |
50842bdc | 3436 | type->alignment = bt_field_type_get_alignment(type); |
273b65be | 3437 | generic_field_type_freeze(type); |
225f3384 PP |
3438 | BT_LOGD("Freezing array field type object's element field type: element-ft-addr=%p", |
3439 | array_type->element_type); | |
50842bdc | 3440 | bt_field_type_freeze(array_type->element_type); |
273b65be JG |
3441 | } |
3442 | ||
3443 | static | |
50842bdc | 3444 | void bt_field_type_sequence_freeze(struct bt_field_type *type) |
273b65be | 3445 | { |
50842bdc PP |
3446 | struct bt_field_type_sequence *sequence_type = container_of( |
3447 | type, struct bt_field_type_sequence, parent); | |
273b65be | 3448 | |
3ffba961 | 3449 | /* Cache the alignment */ |
4e8304f7 | 3450 | BT_LOGD("Freezing sequence field type object: addr=%p", type); |
50842bdc | 3451 | type->alignment = bt_field_type_get_alignment(type); |
273b65be | 3452 | generic_field_type_freeze(type); |
225f3384 PP |
3453 | BT_LOGD("Freezing sequence field type object's element field type: element-ft-addr=%p", |
3454 | sequence_type->element_type); | |
50842bdc | 3455 | bt_field_type_freeze(sequence_type->element_type); |
273b65be JG |
3456 | } |
3457 | ||
3458 | static | |
50842bdc | 3459 | const char *get_encoding_string(enum bt_string_encoding encoding) |
273b65be JG |
3460 | { |
3461 | const char *encoding_string; | |
3462 | ||
3463 | switch (encoding) { | |
50842bdc | 3464 | case BT_STRING_ENCODING_NONE: |
273b65be JG |
3465 | encoding_string = "none"; |
3466 | break; | |
50842bdc | 3467 | case BT_STRING_ENCODING_ASCII: |
273b65be JG |
3468 | encoding_string = "ASCII"; |
3469 | break; | |
50842bdc | 3470 | case BT_STRING_ENCODING_UTF8: |
273b65be JG |
3471 | encoding_string = "UTF8"; |
3472 | break; | |
3473 | default: | |
3474 | encoding_string = "unknown"; | |
3475 | break; | |
3476 | } | |
3477 | ||
3478 | return encoding_string; | |
3479 | } | |
3480 | ||
3481 | static | |
50842bdc | 3482 | const char *get_integer_base_string(enum bt_integer_base base) |
273b65be JG |
3483 | { |
3484 | const char *base_string; | |
3485 | ||
3486 | switch (base) { | |
50842bdc PP |
3487 | case BT_INTEGER_BASE_DECIMAL: |
3488 | case BT_INTEGER_BASE_UNSPECIFIED: | |
273b65be JG |
3489 | base_string = "decimal"; |
3490 | break; | |
50842bdc | 3491 | case BT_INTEGER_BASE_HEXADECIMAL: |
273b65be JG |
3492 | base_string = "hexadecimal"; |
3493 | break; | |
50842bdc | 3494 | case BT_INTEGER_BASE_OCTAL: |
273b65be JG |
3495 | base_string = "octal"; |
3496 | break; | |
50842bdc | 3497 | case BT_INTEGER_BASE_BINARY: |
273b65be JG |
3498 | base_string = "binary"; |
3499 | break; | |
3500 | default: | |
3501 | base_string = "unknown"; | |
3502 | break; | |
3503 | } | |
3504 | ||
3505 | return base_string; | |
3506 | } | |
3507 | ||
6acddae3 | 3508 | static |
27e326eb | 3509 | void append_field_name(struct metadata_context *context, |
6acddae3 PP |
3510 | const char *name) |
3511 | { | |
3512 | g_string_append_c(context->string, ' '); | |
3513 | ||
f4cc9a21 | 3514 | if (!bt_identifier_is_valid(name) || *name == '_') { |
6acddae3 PP |
3515 | g_string_append_c(context->string, '_'); |
3516 | } | |
3517 | ||
3518 | g_string_append(context->string, name); | |
3519 | } | |
3520 | ||
273b65be | 3521 | static |
50842bdc | 3522 | int bt_field_type_integer_serialize(struct bt_field_type *type, |
273b65be JG |
3523 | struct metadata_context *context) |
3524 | { | |
50842bdc PP |
3525 | struct bt_field_type_integer *integer = container_of(type, |
3526 | struct bt_field_type_integer, parent); | |
6cfb906f | 3527 | int ret = 0; |
273b65be | 3528 | |
4e8304f7 PP |
3529 | BT_LOGD("Serializing integer field type's metadata: " |
3530 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
273b65be | 3531 | g_string_append_printf(context->string, |
dc3fffef PP |
3532 | "integer { size = %u; align = %u; signed = %s; encoding = %s; base = %s; byte_order = %s", |
3533 | integer->size, type->alignment, | |
3534 | (integer->is_signed ? "true" : "false"), | |
3535 | get_encoding_string(integer->encoding), | |
3536 | get_integer_base_string(integer->base), | |
3537 | get_byte_order_string(integer->user_byte_order)); | |
6cfb906f | 3538 | if (integer->mapped_clock) { |
50842bdc | 3539 | const char *clock_name = bt_clock_class_get_name( |
6cfb906f JG |
3540 | integer->mapped_clock); |
3541 | ||
f6ccaed9 | 3542 | BT_ASSERT(clock_name); |
6cfb906f | 3543 | g_string_append_printf(context->string, |
4ebdec03 | 3544 | "; map = clock.%s.value", clock_name); |
6cfb906f JG |
3545 | } |
3546 | ||
3547 | g_string_append(context->string, "; }"); | |
6cfb906f | 3548 | return ret; |
273b65be JG |
3549 | } |
3550 | ||
3551 | static | |
50842bdc | 3552 | int bt_field_type_enumeration_serialize(struct bt_field_type *type, |
273b65be JG |
3553 | struct metadata_context *context) |
3554 | { | |
3555 | size_t entry; | |
9ce21c30 | 3556 | int ret; |
50842bdc PP |
3557 | struct bt_field_type_enumeration *enumeration = container_of(type, |
3558 | struct bt_field_type_enumeration, parent); | |
3559 | struct bt_field_type *container_type; | |
b92ddaaa | 3560 | int container_signed; |
273b65be | 3561 | |
4e8304f7 PP |
3562 | BT_LOGD("Serializing enumeration field type's metadata: " |
3563 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
50842bdc | 3564 | container_type = bt_field_type_enumeration_get_container_type(type); |
f6ccaed9 | 3565 | BT_ASSERT(container_type); |
b92ddaaa | 3566 | container_signed = bt_ctf_field_type_integer_get_signed(container_type); |
f6ccaed9 | 3567 | BT_ASSERT(container_signed >= 0); |
273b65be | 3568 | g_string_append(context->string, "enum : "); |
ec159b1e | 3569 | BT_LOGD_STR("Serializing enumeration field type's container field type's metadata."); |
50842bdc | 3570 | ret = bt_field_type_serialize(enumeration->container, context); |
273b65be | 3571 | if (ret) { |
4e8304f7 PP |
3572 | BT_LOGW("Cannot serialize enumeration field type's container field type's metadata: " |
3573 | "container-ft-addr=%p", enumeration->container); | |
3574 | goto end; | |
273b65be JG |
3575 | } |
3576 | ||
3577 | g_string_append(context->string, " { "); | |
3578 | for (entry = 0; entry < enumeration->entries->len; entry++) { | |
3579 | struct enumeration_mapping *mapping = | |
3580 | enumeration->entries->pdata[entry]; | |
f4cc9a21 PP |
3581 | const char *label = g_quark_to_string(mapping->string); |
3582 | ||
3583 | g_string_append(context->string, "\""); | |
3584 | ||
3585 | if (!bt_identifier_is_valid(label) || label[0] == '_') { | |
3586 | g_string_append(context->string, "_"); | |
3587 | } | |
3588 | ||
3589 | g_string_append_printf(context->string, "%s\" = ", label); | |
273b65be | 3590 | |
b92ddaaa JG |
3591 | if (container_signed) { |
3592 | if (mapping->range_start._signed == | |
3593 | mapping->range_end._signed) { | |
3594 | g_string_append_printf(context->string, | |
f4cc9a21 | 3595 | "%" PRId64, |
b92ddaaa JG |
3596 | mapping->range_start._signed); |
3597 | } else { | |
3598 | g_string_append_printf(context->string, | |
f4cc9a21 | 3599 | "%" PRId64 " ... %" PRId64, |
b92ddaaa JG |
3600 | mapping->range_start._signed, |
3601 | mapping->range_end._signed); | |
3602 | } | |
273b65be | 3603 | } else { |
b92ddaaa JG |
3604 | if (mapping->range_start._unsigned == |
3605 | mapping->range_end._unsigned) { | |
3606 | g_string_append_printf(context->string, | |
f4cc9a21 | 3607 | "%" PRIu64, |
b92ddaaa JG |
3608 | mapping->range_start._unsigned); |
3609 | } else { | |
3610 | g_string_append_printf(context->string, | |
f4cc9a21 | 3611 | "%" PRIu64 " ... %" PRIu64, |
b92ddaaa JG |
3612 | mapping->range_start._unsigned, |
3613 | mapping->range_end._unsigned); | |
3614 | } | |
273b65be JG |
3615 | } |
3616 | ||
3617 | g_string_append(context->string, | |
3618 | ((entry != (enumeration->entries->len - 1)) ? | |
3619 | ", " : " }")); | |
3620 | } | |
3621 | ||
3622 | if (context->field_name->len) { | |
27e326eb | 3623 | append_field_name(context, |
273b65be JG |
3624 | context->field_name->str); |
3625 | g_string_assign(context->field_name, ""); | |
3626 | } | |
3627 | end: | |
4e8304f7 | 3628 | bt_put(container_type); |
273b65be JG |
3629 | return ret; |
3630 | } | |
3631 | ||
3632 | static | |
50842bdc | 3633 | int bt_field_type_floating_point_serialize(struct bt_field_type *type, |
273b65be JG |
3634 | struct metadata_context *context) |
3635 | { | |
50842bdc PP |
3636 | struct bt_field_type_floating_point *floating_point = container_of( |
3637 | type, struct bt_field_type_floating_point, parent); | |
273b65be | 3638 | |
4e8304f7 PP |
3639 | BT_LOGD("Serializing floating point number field type's metadata: " |
3640 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
273b65be | 3641 | g_string_append_printf(context->string, |
dc3fffef PP |
3642 | "floating_point { exp_dig = %u; mant_dig = %u; byte_order = %s; align = %u; }", |
3643 | floating_point->exp_dig, | |
3644 | floating_point->mant_dig, | |
3645 | get_byte_order_string(floating_point->user_byte_order), | |
3646 | type->alignment); | |
273b65be JG |
3647 | return 0; |
3648 | } | |
3649 | ||
3650 | static | |
50842bdc | 3651 | int bt_field_type_structure_serialize(struct bt_field_type *type, |
273b65be JG |
3652 | struct metadata_context *context) |
3653 | { | |
3654 | size_t i; | |
3655 | unsigned int indent; | |
5286528d | 3656 | int ret = 0; |
50842bdc PP |
3657 | struct bt_field_type_structure *structure = container_of(type, |
3658 | struct bt_field_type_structure, parent); | |
273b65be JG |
3659 | GString *structure_field_name = context->field_name; |
3660 | ||
4e8304f7 PP |
3661 | BT_LOGD("Serializing structure field type's metadata: " |
3662 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
273b65be JG |
3663 | context->field_name = g_string_new(""); |
3664 | ||
3665 | context->current_indentation_level++; | |
3666 | g_string_append(context->string, "struct {\n"); | |
3667 | ||
3668 | for (i = 0; i < structure->fields->len; i++) { | |
dfc1504d PP |
3669 | struct structure_field *field = structure->fields->pdata[i]; |
3670 | ||
ec159b1e | 3671 | BT_LOGD("Serializing structure field type's field metadata: " |
1974687e | 3672 | "index=%zu, " |
dfc1504d PP |
3673 | "field-ft-addr=%p, field-name=\"%s\"", |
3674 | i, field, g_quark_to_string(field->name)); | |
273b65be JG |
3675 | |
3676 | for (indent = 0; indent < context->current_indentation_level; | |
3677 | indent++) { | |
3678 | g_string_append_c(context->string, '\t'); | |
3679 | } | |
3680 | ||
273b65be JG |
3681 | g_string_assign(context->field_name, |
3682 | g_quark_to_string(field->name)); | |
50842bdc | 3683 | ret = bt_field_type_serialize(field->type, context); |
273b65be | 3684 | if (ret) { |
4e8304f7 | 3685 | BT_LOGW("Cannot serialize structure field type's field's metadata: " |
1974687e | 3686 | "index=%zu, " |
4e8304f7 PP |
3687 | "field-ft-addr=%p, field-name=\"%s\"", |
3688 | i, field->type, | |
3689 | g_quark_to_string(field->name)); | |
273b65be JG |
3690 | goto end; |
3691 | } | |
3692 | ||
3693 | if (context->field_name->len) { | |
27e326eb | 3694 | append_field_name(context, |
273b65be JG |
3695 | context->field_name->str); |
3696 | } | |
3697 | g_string_append(context->string, ";\n"); | |
3698 | } | |
3699 | ||
3700 | context->current_indentation_level--; | |
3701 | for (indent = 0; indent < context->current_indentation_level; | |
3702 | indent++) { | |
3703 | g_string_append_c(context->string, '\t'); | |
3704 | } | |
3705 | ||
dc3fffef PP |
3706 | g_string_append_printf(context->string, "} align(%u)", |
3707 | type->alignment); | |
273b65be JG |
3708 | end: |
3709 | g_string_free(context->field_name, TRUE); | |
3710 | context->field_name = structure_field_name; | |
3711 | return ret; | |
3712 | } | |
3713 | ||
3714 | static | |
50842bdc | 3715 | int bt_field_type_variant_serialize(struct bt_field_type *type, |
273b65be JG |
3716 | struct metadata_context *context) |
3717 | { | |
3718 | size_t i; | |
3719 | unsigned int indent; | |
3720 | int ret = 0; | |
50842bdc PP |
3721 | struct bt_field_type_variant *variant = container_of( |
3722 | type, struct bt_field_type_variant, parent); | |
273b65be JG |
3723 | GString *variant_field_name = context->field_name; |
3724 | ||
4e8304f7 PP |
3725 | BT_LOGD("Serializing variant field type's metadata: " |
3726 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
273b65be | 3727 | context->field_name = g_string_new(""); |
6964b7fd | 3728 | if (variant->tag_name->len > 0) { |
27e326eb JG |
3729 | g_string_append(context->string, "variant <"); |
3730 | append_field_name(context, variant->tag_name->str); | |
3731 | g_string_append(context->string, "> {\n"); | |
6964b7fd JG |
3732 | } else { |
3733 | g_string_append(context->string, "variant {\n"); | |
3734 | } | |
3735 | ||
273b65be JG |
3736 | context->current_indentation_level++; |
3737 | for (i = 0; i < variant->fields->len; i++) { | |
3738 | struct structure_field *field = variant->fields->pdata[i]; | |
3739 | ||
ec159b1e | 3740 | BT_LOGD("Serializing variant field type's field metadata: " |
1974687e | 3741 | "index=%zu, " |
dfc1504d PP |
3742 | "field-ft-addr=%p, field-name=\"%s\"", |
3743 | i, field, g_quark_to_string(field->name)); | |
3744 | ||
273b65be JG |
3745 | g_string_assign(context->field_name, |
3746 | g_quark_to_string(field->name)); | |
3747 | for (indent = 0; indent < context->current_indentation_level; | |
3748 | indent++) { | |
3749 | g_string_append_c(context->string, '\t'); | |
3750 | } | |
3751 | ||
3752 | g_string_assign(context->field_name, | |
3753 | g_quark_to_string(field->name)); | |
50842bdc | 3754 | ret = bt_field_type_serialize(field->type, context); |
273b65be | 3755 | if (ret) { |
4e8304f7 | 3756 | BT_LOGW("Cannot serialize variant field type's field's metadata: " |
1974687e | 3757 | "index=%zu, " |
4e8304f7 PP |
3758 | "field-ft-addr=%p, field-name=\"%s\"", |
3759 | i, field->type, | |
3760 | g_quark_to_string(field->name)); | |
273b65be JG |
3761 | goto end; |
3762 | } | |
3763 | ||
3764 | if (context->field_name->len) { | |
27e326eb | 3765 | append_field_name(context, |
273b65be | 3766 | context->field_name->str); |
6acddae3 | 3767 | g_string_append_c(context->string, ';'); |
273b65be JG |
3768 | } |
3769 | ||
3770 | g_string_append_c(context->string, '\n'); | |
3771 | } | |
3772 | ||
3773 | context->current_indentation_level--; | |
3774 | for (indent = 0; indent < context->current_indentation_level; | |
3775 | indent++) { | |
3776 | g_string_append_c(context->string, '\t'); | |
3777 | } | |
3778 | ||
3779 | g_string_append(context->string, "}"); | |
3780 | end: | |
3781 | g_string_free(context->field_name, TRUE); | |
3782 | context->field_name = variant_field_name; | |
3783 | return ret; | |
3784 | } | |
3785 | ||
3786 | static | |
50842bdc | 3787 | int bt_field_type_array_serialize(struct bt_field_type *type, |
273b65be JG |
3788 | struct metadata_context *context) |
3789 | { | |
3790 | int ret = 0; | |
50842bdc PP |
3791 | struct bt_field_type_array *array = container_of(type, |
3792 | struct bt_field_type_array, parent); | |
273b65be | 3793 | |
4e8304f7 PP |
3794 | BT_LOGD("Serializing array field type's metadata: " |
3795 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
ec159b1e | 3796 | BT_LOGD_STR("Serializing array field type's element field type's metadata."); |
50842bdc | 3797 | ret = bt_field_type_serialize(array->element_type, context); |
273b65be | 3798 | if (ret) { |
4e8304f7 PP |
3799 | BT_LOGW("Cannot serialize array field type's element field type's metadata: " |
3800 | "element-ft-addr=%p", array->element_type); | |
273b65be JG |
3801 | goto end; |
3802 | } | |
3803 | ||
3804 | if (context->field_name->len) { | |
27e326eb | 3805 | append_field_name(context, |
6acddae3 PP |
3806 | context->field_name->str); |
3807 | ||
3808 | g_string_append_printf(context->string, "[%u]", array->length); | |
273b65be JG |
3809 | g_string_assign(context->field_name, ""); |
3810 | } else { | |
3811 | g_string_append_printf(context->string, "[%u]", array->length); | |
3812 | } | |
3813 | end: | |
3814 | return ret; | |
3815 | } | |
3816 | ||
3817 | static | |
50842bdc | 3818 | int bt_field_type_sequence_serialize(struct bt_field_type *type, |
273b65be JG |
3819 | struct metadata_context *context) |
3820 | { | |
3821 | int ret = 0; | |
50842bdc PP |
3822 | struct bt_field_type_sequence *sequence = container_of( |
3823 | type, struct bt_field_type_sequence, parent); | |
273b65be | 3824 | |
4e8304f7 PP |
3825 | BT_LOGD("Serializing sequence field type's metadata: " |
3826 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
ec159b1e | 3827 | BT_LOGD_STR("Serializing sequence field type's element field type's metadata."); |
50842bdc | 3828 | ret = bt_field_type_serialize(sequence->element_type, context); |
273b65be | 3829 | if (ret) { |
4e8304f7 PP |
3830 | BT_LOGW("Cannot serialize sequence field type's element field type's metadata: " |
3831 | "element-ft-addr=%p", sequence->element_type); | |
273b65be JG |
3832 | goto end; |
3833 | } | |
3834 | ||
3835 | if (context->field_name->len) { | |
27e326eb | 3836 | append_field_name(context, context->field_name->str); |
273b65be | 3837 | g_string_assign(context->field_name, ""); |
273b65be | 3838 | } |
27e326eb JG |
3839 | g_string_append(context->string, "["); |
3840 | append_field_name(context, sequence->length_field_name->str); | |
3841 | g_string_append(context->string, "]"); | |
273b65be JG |
3842 | end: |
3843 | return ret; | |
3844 | } | |
3845 | ||
3846 | static | |
50842bdc | 3847 | int bt_field_type_string_serialize(struct bt_field_type *type, |
273b65be JG |
3848 | struct metadata_context *context) |
3849 | { | |
50842bdc PP |
3850 | struct bt_field_type_string *string = container_of( |
3851 | type, struct bt_field_type_string, parent); | |
273b65be | 3852 | |
4e8304f7 PP |
3853 | BT_LOGD("Serializing string field type's metadata: " |
3854 | "ft-addr=%p, metadata-context-addr=%p", type, context); | |
273b65be JG |
3855 | g_string_append_printf(context->string, |
3856 | "string { encoding = %s; }", | |
dc3fffef | 3857 | get_encoding_string(string->encoding)); |
273b65be JG |
3858 | return 0; |
3859 | } | |
3860 | ||
3861 | static | |
50842bdc PP |
3862 | void bt_field_type_integer_set_byte_order(struct bt_field_type *type, |
3863 | enum bt_byte_order byte_order) | |
273b65be | 3864 | { |
50842bdc PP |
3865 | struct bt_field_type_integer *integer_type = container_of(type, |
3866 | struct bt_field_type_integer, parent); | |
273b65be | 3867 | |
dc3fffef | 3868 | integer_type->user_byte_order = byte_order; |
c35a1669 JG |
3869 | } |
3870 | ||
3871 | static | |
50842bdc PP |
3872 | void bt_field_type_enumeration_set_byte_order( |
3873 | struct bt_field_type *type, enum bt_byte_order byte_order) | |
c35a1669 | 3874 | { |
50842bdc PP |
3875 | struct bt_field_type_enumeration *enum_type = container_of(type, |
3876 | struct bt_field_type_enumeration, parent); | |
c35a1669 JG |
3877 | |
3878 | /* Safe to assume that container is an integer */ | |
50842bdc | 3879 | bt_field_type_integer_set_byte_order(enum_type->container, |
dc3fffef | 3880 | byte_order); |
273b65be JG |
3881 | } |
3882 | ||
3883 | static | |
50842bdc PP |
3884 | void bt_field_type_floating_point_set_byte_order( |
3885 | struct bt_field_type *type, enum bt_byte_order byte_order) | |
273b65be | 3886 | { |
50842bdc PP |
3887 | struct bt_field_type_floating_point *floating_point_type = |
3888 | container_of(type, struct bt_field_type_floating_point, | |
273b65be JG |
3889 | parent); |
3890 | ||
dc3fffef | 3891 | floating_point_type->user_byte_order = byte_order; |
c35a1669 JG |
3892 | } |
3893 | ||
3894 | static | |
50842bdc PP |
3895 | void bt_field_type_structure_set_byte_order(struct bt_field_type *type, |
3896 | enum bt_byte_order byte_order) | |
c35a1669 JG |
3897 | { |
3898 | int i; | |
50842bdc PP |
3899 | struct bt_field_type_structure *structure_type = |
3900 | container_of(type, struct bt_field_type_structure, | |
c35a1669 JG |
3901 | parent); |
3902 | ||
3903 | for (i = 0; i < structure_type->fields->len; i++) { | |
3904 | struct structure_field *field = g_ptr_array_index( | |
3905 | structure_type->fields, i); | |
50842bdc | 3906 | struct bt_field_type *field_type = field->type; |
c35a1669 | 3907 | |
dc3fffef PP |
3908 | if (set_byte_order_funcs[field_type->id]) { |
3909 | set_byte_order_funcs[field_type->id]( | |
3910 | field_type, byte_order); | |
c35a1669 JG |
3911 | } |
3912 | } | |
3913 | } | |
3914 | ||
3915 | static | |
50842bdc PP |
3916 | void bt_field_type_variant_set_byte_order(struct bt_field_type *type, |
3917 | enum bt_byte_order byte_order) | |
c35a1669 JG |
3918 | { |
3919 | int i; | |
50842bdc PP |
3920 | struct bt_field_type_variant *variant_type = |
3921 | container_of(type, struct bt_field_type_variant, | |
c35a1669 JG |
3922 | parent); |
3923 | ||
3924 | for (i = 0; i < variant_type->fields->len; i++) { | |
3925 | struct structure_field *field = g_ptr_array_index( | |
3926 | variant_type->fields, i); | |
50842bdc | 3927 | struct bt_field_type *field_type = field->type; |
c35a1669 | 3928 | |
dc3fffef PP |
3929 | if (set_byte_order_funcs[field_type->id]) { |
3930 | set_byte_order_funcs[field_type->id]( | |
3931 | field_type, byte_order); | |
c35a1669 JG |
3932 | } |
3933 | } | |
3934 | } | |
3935 | ||
3936 | static | |
50842bdc PP |
3937 | void bt_field_type_array_set_byte_order(struct bt_field_type *type, |
3938 | enum bt_byte_order byte_order) | |
c35a1669 | 3939 | { |
50842bdc PP |
3940 | struct bt_field_type_array *array_type = |
3941 | container_of(type, struct bt_field_type_array, | |
c35a1669 JG |
3942 | parent); |
3943 | ||
dc3fffef PP |
3944 | if (set_byte_order_funcs[array_type->element_type->id]) { |
3945 | set_byte_order_funcs[array_type->element_type->id]( | |
3946 | array_type->element_type, byte_order); | |
c35a1669 JG |
3947 | } |
3948 | } | |
3949 | ||
3950 | static | |
50842bdc PP |
3951 | void bt_field_type_sequence_set_byte_order(struct bt_field_type *type, |
3952 | enum bt_byte_order byte_order) | |
c35a1669 | 3953 | { |
50842bdc PP |
3954 | struct bt_field_type_sequence *sequence_type = |
3955 | container_of(type, struct bt_field_type_sequence, | |
c35a1669 JG |
3956 | parent); |
3957 | ||
3958 | if (set_byte_order_funcs[ | |
dc3fffef | 3959 | sequence_type->element_type->id]) { |
c35a1669 | 3960 | set_byte_order_funcs[ |
dc3fffef PP |
3961 | sequence_type->element_type->id]( |
3962 | sequence_type->element_type, byte_order); | |
c35a1669 | 3963 | } |
273b65be | 3964 | } |
24724933 JG |
3965 | |
3966 | static | |
50842bdc PP |
3967 | struct bt_field_type *bt_field_type_integer_copy( |
3968 | struct bt_field_type *type) | |
24724933 | 3969 | { |
50842bdc PP |
3970 | struct bt_field_type *copy; |
3971 | struct bt_field_type_integer *integer, *copy_integer; | |
24724933 | 3972 | |
4e8304f7 | 3973 | BT_LOGD("Copying integer field type's: addr=%p", type); |
50842bdc PP |
3974 | integer = container_of(type, struct bt_field_type_integer, parent); |
3975 | copy = bt_field_type_integer_create(integer->size); | |
24724933 | 3976 | if (!copy) { |
4e8304f7 | 3977 | BT_LOGE_STR("Cannot create integer field type."); |
24724933 JG |
3978 | goto end; |
3979 | } | |
3980 | ||
50842bdc | 3981 | copy_integer = container_of(copy, struct bt_field_type_integer, |
24724933 | 3982 | parent); |
dc3fffef | 3983 | copy_integer->mapped_clock = bt_get(integer->mapped_clock); |
445c3471 | 3984 | copy_integer->user_byte_order = integer->user_byte_order; |
dc3fffef PP |
3985 | copy_integer->is_signed = integer->is_signed; |
3986 | copy_integer->size = integer->size; | |
3987 | copy_integer->base = integer->base; | |
3988 | copy_integer->encoding = integer->encoding; | |
4e8304f7 PP |
3989 | BT_LOGD("Copied integer field type: original-ft-addr=%p, copy-ft-addr=%p", |
3990 | type, copy); | |
445c3471 | 3991 | |
24724933 JG |
3992 | end: |
3993 | return copy; | |
3994 | } | |
3995 | ||
3996 | static | |
50842bdc PP |
3997 | struct bt_field_type *bt_field_type_enumeration_copy( |
3998 | struct bt_field_type *type) | |
24724933 JG |
3999 | { |
4000 | size_t i; | |
50842bdc PP |
4001 | struct bt_field_type *copy = NULL, *copy_container; |
4002 | struct bt_field_type_enumeration *enumeration, *copy_enumeration; | |
24724933 | 4003 | |
4e8304f7 | 4004 | BT_LOGD("Copying enumeration field type's: addr=%p", type); |
50842bdc | 4005 | enumeration = container_of(type, struct bt_field_type_enumeration, |
24724933 JG |
4006 | parent); |
4007 | ||
4008 | /* Copy the source enumeration's container */ | |
ec159b1e | 4009 | BT_LOGD_STR("Copying enumeration field type's container field type."); |
50842bdc | 4010 | copy_container = bt_field_type_copy(enumeration->container); |
24724933 | 4011 | if (!copy_container) { |
4e8304f7 | 4012 | BT_LOGE_STR("Cannot copy enumeration field type's container field type."); |
24724933 JG |
4013 | goto end; |
4014 | } | |
4015 | ||
50842bdc | 4016 | copy = bt_field_type_enumeration_create(copy_container); |
24724933 | 4017 | if (!copy) { |
4e8304f7 | 4018 | BT_LOGE_STR("Cannot create enumeration field type."); |
24724933 JG |
4019 | goto end; |
4020 | } | |
4021 | copy_enumeration = container_of(copy, | |
50842bdc | 4022 | struct bt_field_type_enumeration, parent); |
24724933 JG |
4023 | |
4024 | /* Copy all enumaration entries */ | |
4025 | for (i = 0; i < enumeration->entries->len; i++) { | |
4026 | struct enumeration_mapping *mapping = g_ptr_array_index( | |
4027 | enumeration->entries, i); | |
96e8f959 | 4028 | struct enumeration_mapping *copy_mapping = g_new0( |
24724933 JG |
4029 | struct enumeration_mapping, 1); |
4030 | ||
4031 | if (!copy_mapping) { | |
4e8304f7 | 4032 | BT_LOGE_STR("Failed to allocate one enumeration mapping."); |
24724933 JG |
4033 | goto error; |
4034 | } | |
4035 | ||
4036 | *copy_mapping = *mapping; | |
4037 | g_ptr_array_add(copy_enumeration->entries, copy_mapping); | |
4038 | } | |
4039 | ||
4e8304f7 PP |
4040 | BT_LOGD("Copied enumeration field type: original-ft-addr=%p, copy-ft-addr=%p", |
4041 | type, copy); | |
4042 | ||
24724933 | 4043 | end: |
83509119 | 4044 | bt_put(copy_container); |
24724933 JG |
4045 | return copy; |
4046 | error: | |
83509119 JG |
4047 | bt_put(copy_container); |
4048 | BT_PUT(copy); | |
4049 | return copy; | |
24724933 JG |
4050 | } |
4051 | ||
4052 | static | |
50842bdc PP |
4053 | struct bt_field_type *bt_field_type_floating_point_copy( |
4054 | struct bt_field_type *type) | |
24724933 | 4055 | { |
50842bdc PP |
4056 | struct bt_field_type *copy; |
4057 | struct bt_field_type_floating_point *floating_point, *copy_float; | |
24724933 | 4058 | |
4e8304f7 | 4059 | BT_LOGD("Copying floating point number field type's: addr=%p", type); |
24724933 | 4060 | floating_point = container_of(type, |
50842bdc PP |
4061 | struct bt_field_type_floating_point, parent); |
4062 | copy = bt_field_type_floating_point_create(); | |
24724933 | 4063 | if (!copy) { |
4e8304f7 | 4064 | BT_LOGE_STR("Cannot create floating point number field type."); |
24724933 JG |
4065 | goto end; |
4066 | } | |
4067 | ||
4068 | copy_float = container_of(copy, | |
50842bdc | 4069 | struct bt_field_type_floating_point, parent); |
445c3471 | 4070 | copy_float->user_byte_order = floating_point->user_byte_order; |
dc3fffef PP |
4071 | copy_float->exp_dig = floating_point->exp_dig; |
4072 | copy_float->mant_dig = floating_point->mant_dig; | |
4e8304f7 PP |
4073 | BT_LOGD("Copied floating point number field type: original-ft-addr=%p, copy-ft-addr=%p", |
4074 | type, copy); | |
24724933 JG |
4075 | end: |
4076 | return copy; | |
4077 | } | |
4078 | ||
4079 | static | |
50842bdc PP |
4080 | struct bt_field_type *bt_field_type_structure_copy( |
4081 | struct bt_field_type *type) | |
24724933 | 4082 | { |
4e8304f7 | 4083 | int64_t i; |
24724933 JG |
4084 | GHashTableIter iter; |
4085 | gpointer key, value; | |
50842bdc PP |
4086 | struct bt_field_type *copy; |
4087 | struct bt_field_type_structure *structure, *copy_structure; | |
24724933 | 4088 | |
4e8304f7 | 4089 | BT_LOGD("Copying structure field type's: addr=%p", type); |
50842bdc | 4090 | structure = container_of(type, struct bt_field_type_structure, |
24724933 | 4091 | parent); |
50842bdc | 4092 | copy = bt_field_type_structure_create(); |
24724933 | 4093 | if (!copy) { |
4e8304f7 | 4094 | BT_LOGE_STR("Cannot create structure field type."); |
24724933 JG |
4095 | goto end; |
4096 | } | |
4097 | ||
4098 | copy_structure = container_of(copy, | |
50842bdc | 4099 | struct bt_field_type_structure, parent); |
24724933 JG |
4100 | |
4101 | /* Copy field_name_to_index */ | |
4102 | g_hash_table_iter_init(&iter, structure->field_name_to_index); | |
4103 | while (g_hash_table_iter_next (&iter, &key, &value)) { | |
4104 | g_hash_table_insert(copy_structure->field_name_to_index, | |
4105 | key, value); | |
4106 | } | |
4107 | ||
4108 | for (i = 0; i < structure->fields->len; i++) { | |
4109 | struct structure_field *entry, *copy_entry; | |
50842bdc | 4110 | struct bt_field_type *copy_field; |
24724933 | 4111 | |
dfc1504d | 4112 | entry = g_ptr_array_index(structure->fields, i); |
ec159b1e | 4113 | BT_LOGD("Copying structure field type's field: " |
dfc1504d PP |
4114 | "index=%" PRId64 ", " |
4115 | "field-ft-addr=%p, field-name=\"%s\"", | |
4116 | i, entry, g_quark_to_string(entry->name)); | |
24724933 JG |
4117 | copy_entry = g_new0(struct structure_field, 1); |
4118 | if (!copy_entry) { | |
4e8304f7 | 4119 | BT_LOGE_STR("Failed to allocate one structure field type field."); |
24724933 JG |
4120 | goto error; |
4121 | } | |
4122 | ||
50842bdc | 4123 | copy_field = bt_field_type_copy(entry->type); |
24724933 | 4124 | if (!copy_field) { |
4e8304f7 PP |
4125 | BT_LOGE("Cannot copy structure field type's field: " |
4126 | "index=%" PRId64 ", " | |
4127 | "field-ft-addr=%p, field-name=\"%s\"", | |
4128 | i, entry, g_quark_to_string(entry->name)); | |
24724933 JG |
4129 | g_free(copy_entry); |
4130 | goto error; | |
4131 | } | |
4132 | ||
4133 | copy_entry->name = entry->name; | |
4134 | copy_entry->type = copy_field; | |
4135 | g_ptr_array_add(copy_structure->fields, copy_entry); | |
4136 | } | |
4137 | ||
4e8304f7 PP |
4138 | BT_LOGD("Copied structure field type: original-ft-addr=%p, copy-ft-addr=%p", |
4139 | type, copy); | |
4140 | ||
24724933 JG |
4141 | end: |
4142 | return copy; | |
4143 | error: | |
83509119 JG |
4144 | BT_PUT(copy); |
4145 | return copy; | |
24724933 JG |
4146 | } |
4147 | ||
4148 | static | |
50842bdc PP |
4149 | struct bt_field_type *bt_field_type_variant_copy( |
4150 | struct bt_field_type *type) | |
24724933 | 4151 | { |
4e8304f7 | 4152 | int64_t i; |
24724933 JG |
4153 | GHashTableIter iter; |
4154 | gpointer key, value; | |
50842bdc PP |
4155 | struct bt_field_type *copy = NULL, *copy_tag = NULL; |
4156 | struct bt_field_type_variant *variant, *copy_variant; | |
24724933 | 4157 | |
4e8304f7 | 4158 | BT_LOGD("Copying variant field type's: addr=%p", type); |
50842bdc | 4159 | variant = container_of(type, struct bt_field_type_variant, |
24724933 JG |
4160 | parent); |
4161 | if (variant->tag) { | |
ec159b1e | 4162 | BT_LOGD_STR("Copying variant field type's tag field type."); |
50842bdc | 4163 | copy_tag = bt_field_type_copy(&variant->tag->parent); |
24724933 | 4164 | if (!copy_tag) { |
4e8304f7 | 4165 | BT_LOGE_STR("Cannot copy variant field type's tag field type."); |
24724933 JG |
4166 | goto end; |
4167 | } | |
4168 | } | |
4169 | ||
50842bdc | 4170 | copy = bt_field_type_variant_create(copy_tag, |
24724933 JG |
4171 | variant->tag_name->len ? variant->tag_name->str : NULL); |
4172 | if (!copy) { | |
4e8304f7 | 4173 | BT_LOGE_STR("Cannot create variant field type."); |
24724933 JG |
4174 | goto end; |
4175 | } | |
4176 | ||
50842bdc | 4177 | copy_variant = container_of(copy, struct bt_field_type_variant, |
24724933 JG |
4178 | parent); |
4179 | ||
4180 | /* Copy field_name_to_index */ | |
4181 | g_hash_table_iter_init(&iter, variant->field_name_to_index); | |
4182 | while (g_hash_table_iter_next (&iter, &key, &value)) { | |
4183 | g_hash_table_insert(copy_variant->field_name_to_index, | |
4184 | key, value); | |
4185 | } | |
4186 | ||
4187 | for (i = 0; i < variant->fields->len; i++) { | |
4188 | struct structure_field *entry, *copy_entry; | |
50842bdc | 4189 | struct bt_field_type *copy_field; |
24724933 | 4190 | |
dfc1504d | 4191 | entry = g_ptr_array_index(variant->fields, i); |
ec159b1e | 4192 | BT_LOGD("Copying variant field type's field: " |
dfc1504d PP |
4193 | "index=%" PRId64 ", " |
4194 | "field-ft-addr=%p, field-name=\"%s\"", | |
4195 | i, entry, g_quark_to_string(entry->name)); | |
24724933 JG |
4196 | copy_entry = g_new0(struct structure_field, 1); |
4197 | if (!copy_entry) { | |
4e8304f7 | 4198 | BT_LOGE_STR("Failed to allocate one variant field type field."); |
24724933 JG |
4199 | goto error; |
4200 | } | |
4201 | ||
50842bdc | 4202 | copy_field = bt_field_type_copy(entry->type); |
24724933 | 4203 | if (!copy_field) { |
4e8304f7 PP |
4204 | BT_LOGE("Cannot copy variant field type's field: " |
4205 | "index=%" PRId64 ", " | |
4206 | "field-ft-addr=%p, field-name=\"%s\"", | |
4207 | i, entry, g_quark_to_string(entry->name)); | |
24724933 JG |
4208 | g_free(copy_entry); |
4209 | goto error; | |
4210 | } | |
4211 | ||
4212 | copy_entry->name = entry->name; | |
4213 | copy_entry->type = copy_field; | |
4214 | g_ptr_array_add(copy_variant->fields, copy_entry); | |
4215 | } | |
4216 | ||
b011f6b0 | 4217 | if (variant->tag_field_path) { |
ec159b1e | 4218 | BT_LOGD_STR("Copying variant field type's tag field path."); |
50842bdc | 4219 | copy_variant->tag_field_path = bt_field_path_copy( |
b011f6b0 PP |
4220 | variant->tag_field_path); |
4221 | if (!copy_variant->tag_field_path) { | |
4e8304f7 | 4222 | BT_LOGE_STR("Cannot copy variant field type's tag field path."); |
4a1e8671 JG |
4223 | goto error; |
4224 | } | |
4225 | } | |
4e8304f7 PP |
4226 | |
4227 | BT_LOGD("Copied variant field type: original-ft-addr=%p, copy-ft-addr=%p", | |
4228 | type, copy); | |
4229 | ||
24724933 | 4230 | end: |
83509119 | 4231 | bt_put(copy_tag); |
24724933 JG |
4232 | return copy; |
4233 | error: | |
83509119 JG |
4234 | bt_put(copy_tag); |
4235 | BT_PUT(copy); | |
4236 | return copy; | |
24724933 JG |
4237 | } |
4238 | ||
4239 | static | |
50842bdc PP |
4240 | struct bt_field_type *bt_field_type_array_copy( |
4241 | struct bt_field_type *type) | |
24724933 | 4242 | { |
50842bdc PP |
4243 | struct bt_field_type *copy = NULL, *copy_element; |
4244 | struct bt_field_type_array *array; | |
24724933 | 4245 | |
4e8304f7 | 4246 | BT_LOGD("Copying array field type's: addr=%p", type); |
50842bdc | 4247 | array = container_of(type, struct bt_field_type_array, |
24724933 | 4248 | parent); |
ec159b1e | 4249 | BT_LOGD_STR("Copying array field type's element field type."); |
50842bdc | 4250 | copy_element = bt_field_type_copy(array->element_type); |
24724933 | 4251 | if (!copy_element) { |
4e8304f7 | 4252 | BT_LOGE_STR("Cannot copy array field type's element field type."); |
24724933 JG |
4253 | goto end; |
4254 | } | |
4255 | ||
50842bdc | 4256 | copy = bt_field_type_array_create(copy_element, array->length); |
24724933 | 4257 | if (!copy) { |
4e8304f7 | 4258 | BT_LOGE_STR("Cannot create array field type."); |
24724933 JG |
4259 | goto end; |
4260 | } | |
4e8304f7 PP |
4261 | |
4262 | BT_LOGD("Copied array field type: original-ft-addr=%p, copy-ft-addr=%p", | |
4263 | type, copy); | |
4264 | ||
24724933 | 4265 | end: |
83509119 | 4266 | bt_put(copy_element); |
24724933 JG |
4267 | return copy; |
4268 | } | |
4269 | ||
4270 | static | |
50842bdc PP |
4271 | struct bt_field_type *bt_field_type_sequence_copy( |
4272 | struct bt_field_type *type) | |
24724933 | 4273 | { |
50842bdc PP |
4274 | struct bt_field_type *copy = NULL, *copy_element; |
4275 | struct bt_field_type_sequence *sequence, *copy_sequence; | |
24724933 | 4276 | |
4e8304f7 | 4277 | BT_LOGD("Copying sequence field type's: addr=%p", type); |
50842bdc | 4278 | sequence = container_of(type, struct bt_field_type_sequence, |
24724933 | 4279 | parent); |
ec159b1e | 4280 | BT_LOGD_STR("Copying sequence field type's element field type."); |
50842bdc | 4281 | copy_element = bt_field_type_copy(sequence->element_type); |
24724933 | 4282 | if (!copy_element) { |
4e8304f7 | 4283 | BT_LOGE_STR("Cannot copy sequence field type's element field type."); |
24724933 JG |
4284 | goto end; |
4285 | } | |
4286 | ||
50842bdc | 4287 | copy = bt_field_type_sequence_create(copy_element, |
24724933 JG |
4288 | sequence->length_field_name->len ? |
4289 | sequence->length_field_name->str : NULL); | |
4290 | if (!copy) { | |
4e8304f7 | 4291 | BT_LOGE_STR("Cannot create sequence field type."); |
24724933 JG |
4292 | goto end; |
4293 | } | |
4294 | ||
50842bdc | 4295 | copy_sequence = container_of(copy, struct bt_field_type_sequence, |
24724933 | 4296 | parent); |
aa4e271c | 4297 | if (sequence->length_field_path) { |
ec159b1e | 4298 | BT_LOGD_STR("Copying sequence field type's length field path."); |
50842bdc | 4299 | copy_sequence->length_field_path = bt_field_path_copy( |
aa4e271c JG |
4300 | sequence->length_field_path); |
4301 | if (!copy_sequence->length_field_path) { | |
4e8304f7 | 4302 | BT_LOGE_STR("Cannot copy sequence field type's length field path."); |
aa4e271c JG |
4303 | goto error; |
4304 | } | |
4305 | } | |
4e8304f7 PP |
4306 | |
4307 | BT_LOGD("Copied sequence field type: original-ft-addr=%p, copy-ft-addr=%p", | |
4308 | type, copy); | |
4309 | ||
24724933 | 4310 | end: |
83509119 | 4311 | bt_put(copy_element); |
24724933 | 4312 | return copy; |
aa4e271c | 4313 | error: |
83509119 | 4314 | BT_PUT(copy); |
aa4e271c | 4315 | goto end; |
24724933 JG |
4316 | } |
4317 | ||
4318 | static | |
50842bdc PP |
4319 | struct bt_field_type *bt_field_type_string_copy( |
4320 | struct bt_field_type *type) | |
24724933 | 4321 | { |
50842bdc | 4322 | struct bt_field_type *copy; |
24724933 | 4323 | |
4e8304f7 | 4324 | BT_LOGD("Copying string field type's: addr=%p", type); |
50842bdc | 4325 | copy = bt_field_type_string_create(); |
24724933 | 4326 | if (!copy) { |
4e8304f7 | 4327 | BT_LOGE_STR("Cannot create string field type."); |
24724933 JG |
4328 | goto end; |
4329 | } | |
4330 | ||
4e8304f7 PP |
4331 | BT_LOGD("Copied string field type: original-ft-addr=%p, copy-ft-addr=%p", |
4332 | type, copy); | |
24724933 JG |
4333 | end: |
4334 | return copy; | |
4335 | } | |
265e809c PP |
4336 | |
4337 | static | |
50842bdc PP |
4338 | int bt_field_type_integer_compare(struct bt_field_type *type_a, |
4339 | struct bt_field_type *type_b) | |
265e809c PP |
4340 | { |
4341 | int ret = 1; | |
50842bdc PP |
4342 | struct bt_field_type_integer *int_type_a; |
4343 | struct bt_field_type_integer *int_type_b; | |
265e809c | 4344 | |
50842bdc | 4345 | int_type_a = container_of(type_a, struct bt_field_type_integer, |
265e809c | 4346 | parent); |
50842bdc | 4347 | int_type_b = container_of(type_b, struct bt_field_type_integer, |
265e809c | 4348 | parent); |
265e809c PP |
4349 | |
4350 | /* Length */ | |
dc3fffef | 4351 | if (int_type_a->size != int_type_b->size) { |
4e8304f7 PP |
4352 | BT_LOGV("Integer field types differ: different sizes: " |
4353 | "ft-a-size=%u, ft-b-size=%u", | |
4354 | int_type_a->size, int_type_b->size); | |
265e809c PP |
4355 | goto end; |
4356 | } | |
4357 | ||
dc3fffef PP |
4358 | /* Byte order */ |
4359 | if (int_type_a->user_byte_order != int_type_b->user_byte_order) { | |
4e8304f7 PP |
4360 | BT_LOGV("Integer field types differ: different byte orders: " |
4361 | "ft-a-bo=%s, ft-b-bo=%s", | |
50842bdc PP |
4362 | bt_byte_order_string(int_type_a->user_byte_order), |
4363 | bt_byte_order_string(int_type_b->user_byte_order)); | |
265e809c PP |
4364 | goto end; |
4365 | } | |
4366 | ||
4367 | /* Signedness */ | |
dc3fffef | 4368 | if (int_type_a->is_signed != int_type_b->is_signed) { |
4e8304f7 PP |
4369 | BT_LOGV("Integer field types differ: different signedness: " |
4370 | "ft-a-is-signed=%d, ft-b-is-signed=%d", | |
4371 | int_type_a->is_signed, | |
4372 | int_type_b->is_signed); | |
265e809c PP |
4373 | goto end; |
4374 | } | |
4375 | ||
4376 | /* Base */ | |
dc3fffef | 4377 | if (int_type_a->base != int_type_b->base) { |
4e8304f7 PP |
4378 | BT_LOGV("Integer field types differ: different bases: " |
4379 | "ft-a-base=%s, ft-b-base=%s", | |
50842bdc PP |
4380 | bt_integer_base_string(int_type_a->base), |
4381 | bt_integer_base_string(int_type_b->base)); | |
265e809c PP |
4382 | goto end; |
4383 | } | |
4384 | ||
4385 | /* Encoding */ | |
dc3fffef | 4386 | if (int_type_a->encoding != int_type_b->encoding) { |
4e8304f7 PP |
4387 | BT_LOGV("Integer field types differ: different encodings: " |
4388 | "ft-a-encoding=%s, ft-b-encoding=%s", | |
50842bdc PP |
4389 | bt_string_encoding_string(int_type_a->encoding), |
4390 | bt_string_encoding_string(int_type_b->encoding)); | |
265e809c PP |
4391 | goto end; |
4392 | } | |
4393 | ||
93dda901 PP |
4394 | /* Mapped clock class */ |
4395 | if (int_type_a->mapped_clock) { | |
4396 | if (!int_type_b->mapped_clock) { | |
4397 | BT_LOGV_STR("Integer field types differ: field type A " | |
4398 | "has a mapped clock class, but field type B " | |
4399 | "does not."); | |
4400 | goto end; | |
4401 | } | |
4402 | ||
4403 | if (bt_clock_class_compare(int_type_a->mapped_clock, | |
4404 | int_type_b->mapped_clock) != 0) { | |
4405 | BT_LOGV_STR("Integer field types differ: different " | |
4406 | "mapped clock classes."); | |
4407 | } | |
4408 | } else { | |
4409 | if (int_type_b->mapped_clock) { | |
4410 | BT_LOGV_STR("Integer field types differ: field type A " | |
4411 | "has no description, but field type B has one."); | |
4412 | goto end; | |
4413 | } | |
265e809c PP |
4414 | } |
4415 | ||
4416 | /* Equal */ | |
4417 | ret = 0; | |
4418 | ||
4419 | end: | |
4420 | return ret; | |
4421 | } | |
4422 | ||
4423 | static | |
50842bdc PP |
4424 | int bt_field_type_floating_point_compare(struct bt_field_type *type_a, |
4425 | struct bt_field_type *type_b) | |
265e809c PP |
4426 | { |
4427 | int ret = 1; | |
50842bdc PP |
4428 | struct bt_field_type_floating_point *float_a; |
4429 | struct bt_field_type_floating_point *float_b; | |
265e809c PP |
4430 | |
4431 | float_a = container_of(type_a, | |
50842bdc | 4432 | struct bt_field_type_floating_point, parent); |
265e809c | 4433 | float_b = container_of(type_b, |
50842bdc | 4434 | struct bt_field_type_floating_point, parent); |
265e809c | 4435 | |
dc3fffef PP |
4436 | /* Byte order */ |
4437 | if (float_a->user_byte_order != float_b->user_byte_order) { | |
4e8304f7 PP |
4438 | BT_LOGV("Floating point number field types differ: different byte orders: " |
4439 | "ft-a-bo=%s, ft-b-bo=%s", | |
50842bdc PP |
4440 | bt_byte_order_string(float_a->user_byte_order), |
4441 | bt_byte_order_string(float_b->user_byte_order)); | |
265e809c PP |
4442 | goto end; |
4443 | } | |
4444 | ||
4445 | /* Exponent length */ | |
dc3fffef | 4446 | if (float_a->exp_dig != float_b->exp_dig) { |
4e8304f7 | 4447 | BT_LOGV("Floating point number field types differ: different exponent sizes: " |
32e87ceb | 4448 | "ft-a-exp-size=%u, ft-b-exp-size=%u", |
4e8304f7 | 4449 | float_a->exp_dig, float_b->exp_dig); |
265e809c PP |
4450 | goto end; |
4451 | } | |
4452 | ||
4453 | /* Mantissa length */ | |
dc3fffef | 4454 | if (float_a->mant_dig != float_b->mant_dig) { |
4e8304f7 | 4455 | BT_LOGV("Floating point number field types differ: different mantissa sizes: " |
32e87ceb | 4456 | "ft-a-mant-size=%u, ft-b-mant-size=%u", |
4e8304f7 | 4457 | float_a->mant_dig, float_b->mant_dig); |
265e809c PP |
4458 | goto end; |
4459 | } | |
4460 | ||
4461 | /* Equal */ | |
4462 | ret = 0; | |
4463 | ||
4464 | end: | |
4465 | return ret; | |
4466 | } | |
4467 | ||
4468 | static | |
4469 | int compare_enumeration_mappings(struct enumeration_mapping *mapping_a, | |
4470 | struct enumeration_mapping *mapping_b) | |
4471 | { | |
4472 | int ret = 1; | |
4473 | ||
4474 | /* Label */ | |
4475 | if (mapping_a->string != mapping_b->string) { | |
4e8304f7 PP |
4476 | BT_LOGV("Enumeration field type mappings differ: different names: " |
4477 | "mapping-a-name=\"%s\", mapping-b-name=\"%s\"", | |
4478 | g_quark_to_string(mapping_a->string), | |
4479 | g_quark_to_string(mapping_b->string)); | |
265e809c PP |
4480 | goto end; |
4481 | } | |
4482 | ||
4483 | /* Range start */ | |
4484 | if (mapping_a->range_start._unsigned != | |
4485 | mapping_b->range_start._unsigned) { | |
4e8304f7 PP |
4486 | BT_LOGV("Enumeration field type mappings differ: different starts of range: " |
4487 | "mapping-a-range-start-unsigned=%" PRIu64 ", " | |
4488 | "mapping-b-range-start-unsigned=%" PRIu64, | |
4489 | mapping_a->range_start._unsigned, | |
4490 | mapping_b->range_start._unsigned); | |
265e809c PP |
4491 | goto end; |
4492 | } | |
4493 | ||
4494 | /* Range end */ | |
4495 | if (mapping_a->range_end._unsigned != | |
4496 | mapping_b->range_end._unsigned) { | |
4e8304f7 PP |
4497 | BT_LOGV("Enumeration field type mappings differ: different ends of range: " |
4498 | "mapping-a-range-end-unsigned=%" PRIu64 ", " | |
4499 | "mapping-b-range-end-unsigned=%" PRIu64, | |
4500 | mapping_a->range_end._unsigned, | |
4501 | mapping_b->range_end._unsigned); | |
265e809c PP |
4502 | goto end; |
4503 | } | |
4504 | ||
4505 | /* Equal */ | |
4506 | ret = 0; | |
4507 | ||
4508 | end: | |
4509 | return ret; | |
4510 | } | |
4511 | ||
4512 | static | |
50842bdc PP |
4513 | int bt_field_type_enumeration_compare(struct bt_field_type *type_a, |
4514 | struct bt_field_type *type_b) | |
265e809c PP |
4515 | { |
4516 | int ret = 1; | |
4517 | int i; | |
50842bdc PP |
4518 | struct bt_field_type_enumeration *enum_a; |
4519 | struct bt_field_type_enumeration *enum_b; | |
265e809c PP |
4520 | |
4521 | enum_a = container_of(type_a, | |
50842bdc | 4522 | struct bt_field_type_enumeration, parent); |
265e809c | 4523 | enum_b = container_of(type_b, |
50842bdc | 4524 | struct bt_field_type_enumeration, parent); |
265e809c PP |
4525 | |
4526 | /* Container field type */ | |
50842bdc | 4527 | ret = bt_field_type_compare(enum_a->container, enum_b->container); |
265e809c | 4528 | if (ret) { |
4e8304f7 PP |
4529 | BT_LOGV("Enumeration field types differ: different container field types: " |
4530 | "ft-a-container-ft-addr=%p, ft-b-container-ft-addr=%p", | |
4531 | enum_a->container, enum_b->container); | |
265e809c PP |
4532 | goto end; |
4533 | } | |
4534 | ||
4535 | ret = 1; | |
4536 | ||
4537 | /* Entries */ | |
4538 | if (enum_a->entries->len != enum_b->entries->len) { | |
4539 | goto end; | |
4540 | } | |
4541 | ||
4542 | for (i = 0; i < enum_a->entries->len; ++i) { | |
4543 | struct enumeration_mapping *mapping_a = | |
4544 | g_ptr_array_index(enum_a->entries, i); | |
4545 | struct enumeration_mapping *mapping_b = | |
4546 | g_ptr_array_index(enum_b->entries, i); | |
4547 | ||
4548 | if (compare_enumeration_mappings(mapping_a, mapping_b)) { | |
4e8304f7 PP |
4549 | BT_LOGV("Enumeration field types differ: different mappings: " |
4550 | "ft-a-mapping-addr=%p, ft-b-mapping-addr=%p, " | |
4551 | "ft-a-mapping-name=\"%s\", ft-b-mapping-name=\"%s\"", | |
4552 | mapping_a, mapping_b, | |
4553 | g_quark_to_string(mapping_a->string), | |
4554 | g_quark_to_string(mapping_b->string)); | |
265e809c PP |
4555 | goto end; |
4556 | } | |
4557 | } | |
4558 | ||
4559 | /* Equal */ | |
4560 | ret = 0; | |
4561 | ||
4562 | end: | |
4563 | return ret; | |
4564 | } | |
4565 | ||
4566 | static | |
50842bdc PP |
4567 | int bt_field_type_string_compare(struct bt_field_type *type_a, |
4568 | struct bt_field_type *type_b) | |
265e809c PP |
4569 | { |
4570 | int ret = 1; | |
50842bdc PP |
4571 | struct bt_field_type_string *string_a; |
4572 | struct bt_field_type_string *string_b; | |
265e809c PP |
4573 | |
4574 | string_a = container_of(type_a, | |
50842bdc | 4575 | struct bt_field_type_string, parent); |
265e809c | 4576 | string_b = container_of(type_b, |
50842bdc | 4577 | struct bt_field_type_string, parent); |
265e809c PP |
4578 | |
4579 | /* Encoding */ | |
dc3fffef | 4580 | if (string_a->encoding != string_b->encoding) { |
4e8304f7 PP |
4581 | BT_LOGV("String field types differ: different encodings: " |
4582 | "ft-a-encoding=%s, ft-b-encoding=%s", | |
50842bdc PP |
4583 | bt_string_encoding_string(string_a->encoding), |
4584 | bt_string_encoding_string(string_b->encoding)); | |
265e809c PP |
4585 | goto end; |
4586 | } | |
4587 | ||
4588 | /* Equal */ | |
4589 | ret = 0; | |
4590 | ||
4591 | end: | |
4592 | return ret; | |
4593 | } | |
4594 | ||
4595 | static | |
4596 | int compare_structure_fields(struct structure_field *field_a, | |
4597 | struct structure_field *field_b) | |
4598 | { | |
4599 | int ret = 1; | |
4600 | ||
4601 | /* Label */ | |
4602 | if (field_a->name != field_b->name) { | |
4e8304f7 PP |
4603 | BT_LOGV("Structure/variant field type fields differ: different names: " |
4604 | "field-a-name=%s, field-b-name=%s", | |
4605 | g_quark_to_string(field_a->name), | |
4606 | g_quark_to_string(field_b->name)); | |
265e809c PP |
4607 | goto end; |
4608 | } | |
4609 | ||
4610 | /* Type */ | |
50842bdc | 4611 | ret = bt_field_type_compare(field_a->type, field_b->type); |
4e8304f7 PP |
4612 | if (ret == 1) { |
4613 | BT_LOGV("Structure/variant field type fields differ: different field types: " | |
32e87ceb | 4614 | "field-name=\"%s\", field-a-ft-addr=%p, field-b-ft-addr=%p", |
4e8304f7 PP |
4615 | g_quark_to_string(field_a->name), |
4616 | field_a->type, field_b->type); | |
4617 | } | |
265e809c PP |
4618 | |
4619 | end: | |
4620 | return ret; | |
4621 | } | |
4622 | ||
4623 | static | |
50842bdc PP |
4624 | int bt_field_type_structure_compare(struct bt_field_type *type_a, |
4625 | struct bt_field_type *type_b) | |
265e809c PP |
4626 | { |
4627 | int ret = 1; | |
4628 | int i; | |
50842bdc PP |
4629 | struct bt_field_type_structure *struct_a; |
4630 | struct bt_field_type_structure *struct_b; | |
265e809c PP |
4631 | |
4632 | struct_a = container_of(type_a, | |
50842bdc | 4633 | struct bt_field_type_structure, parent); |
265e809c | 4634 | struct_b = container_of(type_b, |
50842bdc | 4635 | struct bt_field_type_structure, parent); |
265e809c PP |
4636 | |
4637 | /* Alignment */ | |
50842bdc PP |
4638 | if (bt_field_type_get_alignment(type_a) != |
4639 | bt_field_type_get_alignment(type_b)) { | |
4e8304f7 PP |
4640 | BT_LOGV("Structure field types differ: different alignments: " |
4641 | "ft-a-align=%u, ft-b-align=%u", | |
50842bdc PP |
4642 | bt_field_type_get_alignment(type_a), |
4643 | bt_field_type_get_alignment(type_b)); | |
265e809c PP |
4644 | goto end; |
4645 | } | |
4646 | ||
4647 | /* Fields */ | |
4648 | if (struct_a->fields->len != struct_b->fields->len) { | |
4e8304f7 PP |
4649 | BT_LOGV("Structure field types differ: different field counts: " |
4650 | "ft-a-field-count=%u, ft-b-field-count=%u", | |
4651 | struct_a->fields->len, struct_b->fields->len); | |
265e809c PP |
4652 | goto end; |
4653 | } | |
4654 | ||
4655 | for (i = 0; i < struct_a->fields->len; ++i) { | |
4656 | struct structure_field *field_a = | |
4657 | g_ptr_array_index(struct_a->fields, i); | |
4658 | struct structure_field *field_b = | |
4659 | g_ptr_array_index(struct_b->fields, i); | |
4660 | ||
4661 | ret = compare_structure_fields(field_a, field_b); | |
4662 | if (ret) { | |
4e8304f7 PP |
4663 | /* compare_structure_fields() logs what differs */ |
4664 | BT_LOGV_STR("Structure field types differ: different fields."); | |
265e809c PP |
4665 | goto end; |
4666 | } | |
265e809c PP |
4667 | } |
4668 | ||
4669 | /* Equal */ | |
4670 | ret = 0; | |
4671 | ||
4672 | end: | |
4673 | return ret; | |
4674 | } | |
4675 | ||
4676 | static | |
50842bdc PP |
4677 | int bt_field_type_variant_compare(struct bt_field_type *type_a, |
4678 | struct bt_field_type *type_b) | |
265e809c PP |
4679 | { |
4680 | int ret = 1; | |
4681 | int i; | |
50842bdc PP |
4682 | struct bt_field_type_variant *variant_a; |
4683 | struct bt_field_type_variant *variant_b; | |
265e809c PP |
4684 | |
4685 | variant_a = container_of(type_a, | |
50842bdc | 4686 | struct bt_field_type_variant, parent); |
265e809c | 4687 | variant_b = container_of(type_b, |
50842bdc | 4688 | struct bt_field_type_variant, parent); |
265e809c PP |
4689 | |
4690 | /* Tag name */ | |
4691 | if (strcmp(variant_a->tag_name->str, variant_b->tag_name->str)) { | |
4e8304f7 | 4692 | BT_LOGV("Variant field types differ: different tag field names: " |
32e87ceb | 4693 | "ft-a-tag-field-name=\"%s\", ft-b-tag-field-name=\"%s\"", |
4e8304f7 | 4694 | variant_a->tag_name->str, variant_b->tag_name->str); |
265e809c PP |
4695 | goto end; |
4696 | } | |
4697 | ||
4698 | /* Tag type */ | |
50842bdc PP |
4699 | ret = bt_field_type_compare( |
4700 | (struct bt_field_type *) variant_a->tag, | |
4701 | (struct bt_field_type *) variant_b->tag); | |
265e809c | 4702 | if (ret) { |
4e8304f7 PP |
4703 | BT_LOGV("Variant field types differ: different tag field types: " |
4704 | "ft-a-tag-ft-addr=%p, ft-b-tag-ft-addr=%p", | |
4705 | variant_a->tag, variant_b->tag); | |
265e809c PP |
4706 | goto end; |
4707 | } | |
4708 | ||
4709 | ret = 1; | |
4710 | ||
4711 | /* Fields */ | |
4712 | if (variant_a->fields->len != variant_b->fields->len) { | |
4e8304f7 PP |
4713 | BT_LOGV("Structure field types differ: different field counts: " |
4714 | "ft-a-field-count=%u, ft-b-field-count=%u", | |
4715 | variant_a->fields->len, variant_b->fields->len); | |
265e809c PP |
4716 | goto end; |
4717 | } | |
4718 | ||
4719 | for (i = 0; i < variant_a->fields->len; ++i) { | |
4720 | struct structure_field *field_a = | |
4721 | g_ptr_array_index(variant_a->fields, i); | |
4722 | struct structure_field *field_b = | |
4723 | g_ptr_array_index(variant_b->fields, i); | |
4724 | ||
4725 | ret = compare_structure_fields(field_a, field_b); | |
4726 | if (ret) { | |
4e8304f7 PP |
4727 | /* compare_structure_fields() logs what differs */ |
4728 | BT_LOGV_STR("Variant field types differ: different fields."); | |
265e809c PP |
4729 | goto end; |
4730 | } | |
265e809c PP |
4731 | } |
4732 | ||
4733 | /* Equal */ | |
4734 | ret = 0; | |
4735 | ||
4736 | end: | |
4737 | return ret; | |
4738 | } | |
4739 | ||
4740 | static | |
50842bdc PP |
4741 | int bt_field_type_array_compare(struct bt_field_type *type_a, |
4742 | struct bt_field_type *type_b) | |
265e809c PP |
4743 | { |
4744 | int ret = 1; | |
50842bdc PP |
4745 | struct bt_field_type_array *array_a; |
4746 | struct bt_field_type_array *array_b; | |
265e809c PP |
4747 | |
4748 | array_a = container_of(type_a, | |
50842bdc | 4749 | struct bt_field_type_array, parent); |
265e809c | 4750 | array_b = container_of(type_b, |
50842bdc | 4751 | struct bt_field_type_array, parent); |
265e809c PP |
4752 | |
4753 | /* Length */ | |
4754 | if (array_a->length != array_b->length) { | |
4e8304f7 PP |
4755 | BT_LOGV("Structure field types differ: different lengths: " |
4756 | "ft-a-length=%u, ft-b-length=%u", | |
4757 | array_a->length, array_b->length); | |
265e809c PP |
4758 | goto end; |
4759 | } | |
4760 | ||
4761 | /* Element type */ | |
50842bdc | 4762 | ret = bt_field_type_compare(array_a->element_type, |
265e809c | 4763 | array_b->element_type); |
4e8304f7 PP |
4764 | if (ret == 1) { |
4765 | BT_LOGV("Array field types differ: different element field types: " | |
4766 | "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p", | |
4767 | array_a->element_type, array_b->element_type); | |
4768 | } | |
265e809c PP |
4769 | |
4770 | end: | |
4771 | return ret; | |
4772 | } | |
4773 | ||
4774 | static | |
50842bdc PP |
4775 | int bt_field_type_sequence_compare(struct bt_field_type *type_a, |
4776 | struct bt_field_type *type_b) | |
265e809c PP |
4777 | { |
4778 | int ret = -1; | |
50842bdc PP |
4779 | struct bt_field_type_sequence *sequence_a; |
4780 | struct bt_field_type_sequence *sequence_b; | |
265e809c PP |
4781 | |
4782 | sequence_a = container_of(type_a, | |
50842bdc | 4783 | struct bt_field_type_sequence, parent); |
265e809c | 4784 | sequence_b = container_of(type_b, |
50842bdc | 4785 | struct bt_field_type_sequence, parent); |
265e809c PP |
4786 | |
4787 | /* Length name */ | |
4788 | if (strcmp(sequence_a->length_field_name->str, | |
4789 | sequence_b->length_field_name->str)) { | |
4e8304f7 | 4790 | BT_LOGV("Sequence field types differ: different length field names: " |
32e87ceb PP |
4791 | "ft-a-length-field-name=\"%s\", " |
4792 | "ft-b-length-field-name=\"%s\"", | |
4e8304f7 PP |
4793 | sequence_a->length_field_name->str, |
4794 | sequence_b->length_field_name->str); | |
265e809c PP |
4795 | goto end; |
4796 | } | |
4797 | ||
4798 | /* Element type */ | |
50842bdc | 4799 | ret = bt_field_type_compare(sequence_a->element_type, |
265e809c | 4800 | sequence_b->element_type); |
4e8304f7 PP |
4801 | if (ret == 1) { |
4802 | BT_LOGV("Sequence field types differ: different element field types: " | |
4803 | "ft-a-element-ft-addr=%p, ft-b-element-ft-addr=%p", | |
4804 | sequence_a->element_type, sequence_b->element_type); | |
4805 | } | |
265e809c PP |
4806 | |
4807 | end: | |
4808 | return ret; | |
4809 | } | |
4810 | ||
50842bdc PP |
4811 | int bt_field_type_compare(struct bt_field_type *type_a, |
4812 | struct bt_field_type *type_b) | |
265e809c PP |
4813 | { |
4814 | int ret = 1; | |
4815 | ||
d975f66c PP |
4816 | BT_ASSERT_PRE_NON_NULL(type_a, "Field type A"); |
4817 | BT_ASSERT_PRE_NON_NULL(type_b, "Field type B"); | |
4818 | ||
265e809c PP |
4819 | if (type_a == type_b) { |
4820 | /* Same reference: equal (even if both are NULL) */ | |
4821 | ret = 0; | |
4822 | goto end; | |
4823 | } | |
4824 | ||
4e8304f7 PP |
4825 | if (!type_a) { |
4826 | BT_LOGW_STR("Invalid parameter: field type A is NULL."); | |
4827 | ret = -1; | |
4828 | goto end; | |
4829 | } | |
4830 | ||
4831 | if (!type_b) { | |
4832 | BT_LOGW_STR("Invalid parameter: field type B is NULL."); | |
265e809c PP |
4833 | ret = -1; |
4834 | goto end; | |
4835 | } | |
4836 | ||
dc3fffef | 4837 | if (type_a->id != type_b->id) { |
265e809c | 4838 | /* Different type IDs */ |
4e8304f7 PP |
4839 | BT_LOGV("Field types differ: different IDs: " |
4840 | "ft-a-addr=%p, ft-b-addr=%p, " | |
4841 | "ft-a-id=%s, ft-b-id=%s", | |
4842 | type_a, type_b, | |
50842bdc PP |
4843 | bt_field_type_id_string(type_a->id), |
4844 | bt_field_type_id_string(type_b->id)); | |
265e809c PP |
4845 | goto end; |
4846 | } | |
4847 | ||
50842bdc | 4848 | if (type_a->id == BT_FIELD_TYPE_ID_UNKNOWN) { |
265e809c | 4849 | /* Both have unknown type IDs */ |
4e8304f7 | 4850 | BT_LOGW_STR("Invalid parameter: field type IDs are unknown."); |
265e809c PP |
4851 | goto end; |
4852 | } | |
4853 | ||
dc3fffef | 4854 | ret = type_compare_funcs[type_a->id](type_a, type_b); |
4e8304f7 PP |
4855 | if (ret == 1) { |
4856 | BT_LOGV("Field types differ: ft-a-addr=%p, ft-b-addr=%p", | |
4857 | type_a, type_b); | |
4858 | } | |
265e809c PP |
4859 | |
4860 | end: | |
4861 | return ret; | |
4862 | } | |
09840de5 PP |
4863 | |
4864 | BT_HIDDEN | |
50842bdc | 4865 | int64_t bt_field_type_get_field_count(struct bt_field_type *field_type) |
09840de5 | 4866 | { |
544d0515 | 4867 | int64_t field_count = -1; |
50842bdc | 4868 | enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type); |
09840de5 PP |
4869 | |
4870 | switch (type_id) { | |
4871 | case CTF_TYPE_STRUCT: | |
4872 | field_count = | |
50842bdc | 4873 | bt_field_type_structure_get_field_count(field_type); |
09840de5 PP |
4874 | break; |
4875 | case CTF_TYPE_VARIANT: | |
4876 | field_count = | |
50842bdc | 4877 | bt_field_type_variant_get_field_count(field_type); |
09840de5 PP |
4878 | break; |
4879 | case CTF_TYPE_ARRAY: | |
4880 | case CTF_TYPE_SEQUENCE: | |
4881 | /* | |
4882 | * Array and sequence types always contain a single member | |
4883 | * (the element type). | |
4884 | */ | |
4885 | field_count = 1; | |
4886 | break; | |
4887 | default: | |
4888 | break; | |
4889 | } | |
4890 | ||
4891 | return field_count; | |
4892 | } | |
4893 | ||
4894 | BT_HIDDEN | |
50842bdc PP |
4895 | struct bt_field_type *bt_field_type_get_field_at_index( |
4896 | struct bt_field_type *field_type, int index) | |
09840de5 | 4897 | { |
50842bdc PP |
4898 | struct bt_field_type *field = NULL; |
4899 | enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type); | |
09840de5 PP |
4900 | |
4901 | switch (type_id) { | |
4902 | case CTF_TYPE_STRUCT: | |
aa15981c | 4903 | { |
50842bdc | 4904 | int ret = bt_field_type_structure_get_field_by_index( |
aa15981c MD |
4905 | field_type, NULL, &field, index); |
4906 | if (ret) { | |
4907 | field = NULL; | |
4908 | goto end; | |
4909 | } | |
09840de5 | 4910 | break; |
aa15981c | 4911 | } |
09840de5 | 4912 | case CTF_TYPE_VARIANT: |
8f3a93d9 | 4913 | { |
50842bdc | 4914 | int ret = bt_field_type_variant_get_field_by_index( |
9ac68eb1 | 4915 | field_type, NULL, &field, index); |
8f3a93d9 JG |
4916 | if (ret) { |
4917 | field = NULL; | |
4918 | goto end; | |
4919 | } | |
09840de5 | 4920 | break; |
8f3a93d9 | 4921 | } |
09840de5 | 4922 | case CTF_TYPE_ARRAY: |
50842bdc | 4923 | field = bt_field_type_array_get_element_type(field_type); |
09840de5 PP |
4924 | break; |
4925 | case CTF_TYPE_SEQUENCE: | |
50842bdc | 4926 | field = bt_field_type_sequence_get_element_type(field_type); |
09840de5 PP |
4927 | break; |
4928 | default: | |
4929 | break; | |
4930 | } | |
8f3a93d9 | 4931 | end: |
09840de5 PP |
4932 | return field; |
4933 | } | |
4934 | ||
4935 | BT_HIDDEN | |
50842bdc | 4936 | int bt_field_type_get_field_index(struct bt_field_type *field_type, |
09840de5 PP |
4937 | const char *name) |
4938 | { | |
4939 | int field_index = -1; | |
50842bdc | 4940 | enum bt_field_type_id type_id = bt_field_type_get_type_id(field_type); |
09840de5 PP |
4941 | |
4942 | switch (type_id) { | |
4943 | case CTF_TYPE_STRUCT: | |
50842bdc | 4944 | field_index = bt_field_type_structure_get_field_name_index( |
09840de5 PP |
4945 | field_type, name); |
4946 | break; | |
4947 | case CTF_TYPE_VARIANT: | |
50842bdc | 4948 | field_index = bt_field_type_variant_get_field_name_index( |
09840de5 PP |
4949 | field_type, name); |
4950 | break; | |
4951 | default: | |
4952 | break; | |
4953 | } | |
4954 | ||
4955 | return field_index; | |
4956 | } | |
b011f6b0 | 4957 | |
50842bdc PP |
4958 | struct bt_field_path *bt_field_type_variant_get_tag_field_path( |
4959 | struct bt_field_type *type) | |
b011f6b0 | 4960 | { |
50842bdc | 4961 | struct bt_field_type_variant *variant; |
b011f6b0 | 4962 | |
d975f66c PP |
4963 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
4964 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_VARIANT, "Field type"); | |
50842bdc | 4965 | variant = container_of(type, struct bt_field_type_variant, |
b011f6b0 | 4966 | parent); |
d975f66c | 4967 | return bt_get(variant->tag_field_path); |
b011f6b0 PP |
4968 | } |
4969 | ||
50842bdc PP |
4970 | struct bt_field_path *bt_field_type_sequence_get_length_field_path( |
4971 | struct bt_field_type *type) | |
b011f6b0 | 4972 | { |
50842bdc | 4973 | struct bt_field_type_sequence *sequence; |
b011f6b0 | 4974 | |
d975f66c PP |
4975 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
4976 | BT_ASSERT_PRE_FT_HAS_ID(type, BT_FIELD_TYPE_ID_SEQUENCE, "Field type"); | |
50842bdc | 4977 | sequence = container_of(type, struct bt_field_type_sequence, |
b011f6b0 | 4978 | parent); |
d975f66c | 4979 | return bt_get(sequence->length_field_path); |
b011f6b0 | 4980 | } |