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