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