Commit | Line | Data |
---|---|---|
273b65be | 1 | /* |
2e33ac5a | 2 | * fields.c |
273b65be | 3 | * |
d2dc44b6 | 4 | * Babeltrace CTF IR - Event Fields |
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 | ||
fc25abce PP |
29 | #define BT_LOG_TAG "FIELDS" |
30 | #include <babeltrace/lib-logging-internal.h> | |
31 | ||
8deee039 | 32 | #include <babeltrace/assert-pre-internal.h> |
18acc6f8 | 33 | #include <babeltrace/ctf-ir/fields.h> |
2e33ac5a PP |
34 | #include <babeltrace/ctf-ir/fields-internal.h> |
35 | #include <babeltrace/ctf-ir/field-types-internal.h> | |
83509119 JG |
36 | #include <babeltrace/object-internal.h> |
37 | #include <babeltrace/ref.h> | |
3d9990ac PP |
38 | #include <babeltrace/compiler-internal.h> |
39 | #include <babeltrace/compat/fcntl-internal.h> | |
40 | #include <babeltrace/align-internal.h> | |
8b45963b | 41 | #include <babeltrace/assert-internal.h> |
fc25abce | 42 | #include <inttypes.h> |
273b65be | 43 | |
a6918753 PP |
44 | #define BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(_field, _name) \ |
45 | BT_ASSERT_PRE((_field)->type->id == BT_FIELD_TYPE_ID_INTEGER || \ | |
46 | (_field)->type->id == BT_FIELD_TYPE_ID_ENUM, \ | |
47 | _name " is not an integer or an enumeration field: " \ | |
48 | "%!+f", (_field)) | |
76f869ab | 49 | |
18acc6f8 PP |
50 | static |
51 | int bt_field_generic_validate(struct bt_field *field); | |
52 | ||
53 | static | |
54 | int bt_field_structure_validate_recursive(struct bt_field *field); | |
55 | ||
56 | static | |
57 | int bt_field_variant_validate_recursive(struct bt_field *field); | |
58 | ||
59 | static | |
60 | int bt_field_array_validate_recursive(struct bt_field *field); | |
61 | ||
62 | static | |
63 | int bt_field_sequence_validate_recursive(struct bt_field *field); | |
64 | ||
65 | static | |
66 | void bt_field_generic_reset(struct bt_field *field); | |
67 | ||
68 | static | |
69 | void bt_field_structure_reset_recursive(struct bt_field *field); | |
70 | ||
71 | static | |
72 | void bt_field_variant_reset_recursive(struct bt_field *field); | |
73 | ||
74 | static | |
75 | void bt_field_array_reset_recursive(struct bt_field *field); | |
76 | ||
77 | static | |
78 | void bt_field_sequence_reset_recursive(struct bt_field *field); | |
79 | ||
80 | static | |
81 | void bt_field_generic_set_is_frozen(struct bt_field *field, | |
82 | bool is_frozen); | |
83 | ||
84 | static | |
85 | void bt_field_structure_set_is_frozen_recursive( | |
86 | struct bt_field *field, bool is_frozen); | |
87 | ||
88 | static | |
89 | void bt_field_variant_set_is_frozen_recursive( | |
90 | struct bt_field *field, bool is_frozen); | |
91 | ||
92 | static | |
93 | void bt_field_array_set_is_frozen_recursive( | |
94 | struct bt_field *field, bool is_frozen); | |
95 | ||
96 | static | |
97 | void bt_field_sequence_set_is_frozen_recursive( | |
98 | struct bt_field *field, bool is_frozen); | |
99 | ||
100 | static | |
101 | bt_bool bt_field_generic_is_set(struct bt_field *field); | |
102 | ||
103 | static | |
104 | bt_bool bt_field_structure_is_set_recursive( | |
105 | struct bt_field *field); | |
106 | ||
107 | static | |
108 | bt_bool bt_field_variant_is_set_recursive(struct bt_field *field); | |
109 | ||
110 | static | |
111 | bt_bool bt_field_array_is_set_recursive(struct bt_field *field); | |
112 | ||
113 | static | |
114 | bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field); | |
115 | ||
116 | static struct bt_field_methods bt_field_integer_methods = { | |
117 | .set_is_frozen = bt_field_generic_set_is_frozen, | |
118 | .validate = bt_field_generic_validate, | |
119 | .is_set = bt_field_generic_is_set, | |
120 | .reset = bt_field_generic_reset, | |
8deee039 | 121 | }; |
273b65be | 122 | |
18acc6f8 PP |
123 | static struct bt_field_methods bt_field_floating_point_methods = { |
124 | .set_is_frozen = bt_field_generic_set_is_frozen, | |
125 | .validate = bt_field_generic_validate, | |
126 | .is_set = bt_field_generic_is_set, | |
127 | .reset = bt_field_generic_reset, | |
273b65be JG |
128 | }; |
129 | ||
18acc6f8 PP |
130 | static struct bt_field_methods bt_field_enumeration_methods = { |
131 | .set_is_frozen = bt_field_generic_set_is_frozen, | |
132 | .validate = bt_field_generic_validate, | |
133 | .is_set = bt_field_generic_is_set, | |
134 | .reset = bt_field_generic_reset, | |
273b65be JG |
135 | }; |
136 | ||
18acc6f8 PP |
137 | static struct bt_field_methods bt_field_string_methods = { |
138 | .set_is_frozen = bt_field_generic_set_is_frozen, | |
139 | .validate = bt_field_generic_validate, | |
140 | .is_set = bt_field_generic_is_set, | |
141 | .reset = bt_field_generic_reset, | |
273b65be JG |
142 | }; |
143 | ||
18acc6f8 PP |
144 | static struct bt_field_methods bt_field_structure_methods = { |
145 | .set_is_frozen = bt_field_structure_set_is_frozen_recursive, | |
146 | .validate = bt_field_structure_validate_recursive, | |
147 | .is_set = bt_field_structure_is_set_recursive, | |
148 | .reset = bt_field_structure_reset_recursive, | |
12c8a1a3 JG |
149 | }; |
150 | ||
18acc6f8 PP |
151 | static struct bt_field_methods bt_field_sequence_methods = { |
152 | .set_is_frozen = bt_field_sequence_set_is_frozen_recursive, | |
153 | .validate = bt_field_sequence_validate_recursive, | |
154 | .is_set = bt_field_sequence_is_set_recursive, | |
155 | .reset = bt_field_sequence_reset_recursive, | |
273b65be JG |
156 | }; |
157 | ||
18acc6f8 PP |
158 | static struct bt_field_methods bt_field_array_methods = { |
159 | .set_is_frozen = bt_field_array_set_is_frozen_recursive, | |
160 | .validate = bt_field_array_validate_recursive, | |
161 | .is_set = bt_field_array_is_set_recursive, | |
162 | .reset = bt_field_array_reset_recursive, | |
87d43dc1 JG |
163 | }; |
164 | ||
18acc6f8 PP |
165 | static struct bt_field_methods bt_field_variant_methods = { |
166 | .set_is_frozen = bt_field_variant_set_is_frozen_recursive, | |
167 | .validate = bt_field_variant_validate_recursive, | |
168 | .is_set = bt_field_variant_is_set_recursive, | |
169 | .reset = bt_field_variant_reset_recursive, | |
918be005 PP |
170 | }; |
171 | ||
76f869ab | 172 | static |
8deee039 | 173 | struct bt_field *bt_field_integer_create(struct bt_field_type *); |
76f869ab | 174 | |
8deee039 PP |
175 | static |
176 | struct bt_field *bt_field_enumeration_create(struct bt_field_type *); | |
177 | ||
178 | static | |
179 | struct bt_field *bt_field_floating_point_create(struct bt_field_type *); | |
180 | ||
181 | static | |
182 | struct bt_field *bt_field_structure_create(struct bt_field_type *); | |
183 | ||
184 | static | |
185 | struct bt_field *bt_field_variant_create(struct bt_field_type *); | |
186 | ||
187 | static | |
188 | struct bt_field *bt_field_array_create(struct bt_field_type *); | |
8b45963b | 189 | |
8deee039 PP |
190 | static |
191 | struct bt_field *bt_field_sequence_create(struct bt_field_type *); | |
8b45963b | 192 | |
8deee039 PP |
193 | static |
194 | struct bt_field *bt_field_string_create(struct bt_field_type *); | |
8b45963b | 195 | |
8deee039 PP |
196 | static |
197 | struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = { | |
198 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create, | |
199 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create, | |
200 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create, | |
201 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create, | |
202 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create, | |
203 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create, | |
204 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create, | |
205 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create, | |
206 | }; | |
8b45963b | 207 | |
a6918753 PP |
208 | static |
209 | void bt_field_integer_destroy(struct bt_field *field); | |
210 | ||
211 | static | |
212 | void bt_field_enumeration_destroy(struct bt_field *field); | |
213 | ||
214 | static | |
215 | void bt_field_floating_point_destroy(struct bt_field *field); | |
216 | ||
217 | static | |
218 | void bt_field_structure_destroy_recursive(struct bt_field *field); | |
219 | ||
220 | static | |
221 | void bt_field_variant_destroy_recursive(struct bt_field *field); | |
222 | ||
223 | static | |
224 | void bt_field_array_destroy_recursive(struct bt_field *field); | |
225 | ||
226 | static | |
227 | void bt_field_sequence_destroy_recursive(struct bt_field *field); | |
228 | ||
229 | static | |
230 | void bt_field_string_destroy(struct bt_field *field); | |
231 | ||
232 | static | |
233 | void (* const field_destroy_funcs[])(struct bt_field *) = { | |
234 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy, | |
235 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy, | |
236 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy, | |
237 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive, | |
238 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive, | |
239 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive, | |
240 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive, | |
241 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy, | |
242 | }; | |
243 | ||
18acc6f8 PP |
244 | BT_ASSERT_PRE_FUNC |
245 | static inline bool value_is_in_range_signed(unsigned int size, int64_t value) | |
246 | { | |
247 | bool ret = true; | |
248 | int64_t min_value, max_value; | |
249 | ||
250 | min_value = -(1ULL << (size - 1)); | |
251 | max_value = (1ULL << (size - 1)) - 1; | |
252 | if (value < min_value || value > max_value) { | |
253 | BT_LOGF("Value is out of bounds: value=%" PRId64 ", " | |
254 | "min-value=%" PRId64 ", max-value=%" PRId64, | |
255 | value, min_value, max_value); | |
256 | ret = false; | |
257 | } | |
258 | ||
259 | return ret; | |
260 | } | |
261 | ||
262 | BT_ASSERT_PRE_FUNC | |
263 | static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value) | |
264 | { | |
265 | bool ret = true; | |
266 | int64_t max_value; | |
267 | ||
268 | max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; | |
269 | if (value > max_value) { | |
270 | BT_LOGF("Value is out of bounds: value=%" PRIu64 ", " | |
271 | "max-value=%" PRIu64, | |
272 | value, max_value); | |
273 | ret = false; | |
274 | } | |
275 | ||
276 | return ret; | |
277 | } | |
278 | ||
a6918753 PP |
279 | BT_HIDDEN |
280 | struct bt_field *bt_field_create_recursive(struct bt_field_type *type) | |
273b65be | 281 | { |
839d52a5 PP |
282 | struct bt_field *field = NULL; |
283 | enum bt_field_type_id type_id; | |
273b65be | 284 | |
8b45963b | 285 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
18acc6f8 PP |
286 | BT_ASSERT(bt_field_type_has_known_id((void *) type)); |
287 | BT_ASSERT_PRE(bt_field_type_validate((void *) type) == 0, | |
8b45963b | 288 | "Field type is invalid: %!+F", type); |
839d52a5 | 289 | type_id = bt_field_type_get_type_id(type); |
273b65be JG |
290 | field = field_create_funcs[type_id](type); |
291 | if (!field) { | |
8deee039 | 292 | goto end; |
273b65be JG |
293 | } |
294 | ||
839d52a5 | 295 | bt_field_type_freeze(type); |
273b65be | 296 | |
8deee039 PP |
297 | end: |
298 | return field; | |
273b65be JG |
299 | } |
300 | ||
5fe68922 | 301 | struct bt_field_type *bt_field_borrow_type(struct bt_field *field) |
cd95e351 | 302 | { |
18acc6f8 PP |
303 | struct bt_field_type *ret = NULL; |
304 | ||
305 | BT_ASSERT_PRE_NON_NULL(field, "Field"); | |
306 | ret = field->type; | |
307 | return ret; | |
cd95e351 JG |
308 | } |
309 | ||
839d52a5 | 310 | enum bt_field_type_id bt_field_get_type_id(struct bt_field *field) |
4ebcc695 | 311 | { |
8b45963b | 312 | BT_ASSERT_PRE_NON_NULL(field, "Field"); |
18acc6f8 | 313 | return field->type->id; |
4ebcc695 PP |
314 | } |
315 | ||
a6918753 | 316 | int64_t bt_field_sequence_get_length(struct bt_field *field) |
fea75608 | 317 | { |
18acc6f8 PP |
318 | struct bt_field_sequence *sequence = (void *) field; |
319 | ||
320 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
321 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
322 | "Field"); | |
323 | return (int64_t) sequence->length; | |
fea75608 PP |
324 | } |
325 | ||
a6918753 | 326 | int bt_field_sequence_set_length(struct bt_field *field, uint64_t length) |
273b65be | 327 | { |
18acc6f8 PP |
328 | int ret = 0; |
329 | struct bt_field_sequence *sequence = (void *) field; | |
330 | ||
331 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
332 | BT_ASSERT_PRE(((int64_t) length) >= 0, | |
333 | "Invalid sequence length (too large): length=%" PRId64, | |
334 | length); | |
335 | BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field"); | |
336 | ||
337 | if (unlikely(length > sequence->elements->len)) { | |
338 | /* Make more room */ | |
339 | struct bt_field_type_sequence *sequence_ft; | |
340 | uint64_t cur_len = sequence->elements->len; | |
341 | uint64_t i; | |
342 | ||
343 | g_ptr_array_set_size(sequence->elements, length); | |
344 | sequence_ft = (void *) sequence->common.type; | |
345 | ||
346 | for (i = cur_len; i < sequence->elements->len; i++) { | |
347 | struct bt_field *elem_field = | |
348 | bt_field_create_recursive( | |
349 | sequence_ft->element_ft); | |
350 | ||
351 | if (!elem_field) { | |
352 | ret = -1; | |
353 | goto end; | |
354 | } | |
355 | ||
356 | BT_ASSERT(!sequence->elements->pdata[i]); | |
357 | sequence->elements->pdata[i] = elem_field; | |
358 | } | |
359 | } | |
360 | ||
361 | sequence->length = length; | |
362 | ||
363 | end: | |
364 | return ret; | |
273b65be JG |
365 | } |
366 | ||
5fe68922 | 367 | struct bt_field *bt_field_structure_borrow_field_by_index( |
839d52a5 | 368 | struct bt_field *field, uint64_t index) |
cd95e351 | 369 | { |
18acc6f8 PP |
370 | struct bt_field_structure *structure = (void *) field; |
371 | ||
372 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); | |
373 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
374 | BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
375 | BT_ASSERT_PRE(index < structure->fields->len, | |
376 | "Index is out of bound: %![struct-field-]+f, " | |
377 | "index=%" PRIu64 ", count=%u", field, index, | |
378 | structure->fields->len); | |
379 | return structure->fields->pdata[index]; | |
8b45963b | 380 | } |
fc25abce | 381 | |
5fe68922 | 382 | struct bt_field *bt_field_structure_borrow_field_by_name( |
8deee039 | 383 | struct bt_field *field, const char *name) |
8b45963b | 384 | { |
18acc6f8 PP |
385 | struct bt_field *ret = NULL; |
386 | GQuark field_quark; | |
387 | struct bt_field_type_structure *structure_ft; | |
388 | struct bt_field_structure *structure = (void *) field; | |
389 | size_t index; | |
390 | GHashTable *field_name_to_index; | |
391 | ||
392 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); | |
393 | BT_ASSERT_PRE_NON_NULL(name, "Field name"); | |
394 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
395 | BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
396 | structure_ft = (void *) field->type; | |
397 | field_name_to_index = structure_ft->field_name_to_index; | |
398 | field_quark = g_quark_from_string(name); | |
399 | if (!g_hash_table_lookup_extended(field_name_to_index, | |
400 | GUINT_TO_POINTER(field_quark), | |
401 | NULL, (gpointer *) &index)) { | |
402 | BT_LOGV("Invalid parameter: no such field in structure field's type: " | |
403 | "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"", | |
404 | field, field->type, name); | |
405 | goto error; | |
406 | } | |
407 | ||
408 | ret = structure->fields->pdata[index]; | |
409 | BT_ASSERT(ret); | |
410 | ||
411 | error: | |
412 | return ret; | |
cd95e351 JG |
413 | } |
414 | ||
5fe68922 | 415 | struct bt_field *bt_field_array_borrow_field( |
8deee039 | 416 | struct bt_field *field, uint64_t index) |
273b65be | 417 | { |
18acc6f8 PP |
418 | struct bt_field_array *array = (void *) field; |
419 | ||
420 | BT_ASSERT_PRE_NON_NULL(field, "Array field"); | |
421 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, | |
422 | "Field"); | |
423 | BT_ASSERT_PRE(index < array->elements->len, | |
424 | "Index is out of bound: %![array-field-]+f, " | |
425 | "index=%" PRIu64 ", count=%u", field, | |
426 | index, array->elements->len); | |
427 | return array->elements->pdata[(size_t) index]; | |
8deee039 | 428 | } |
8b45963b | 429 | |
5fe68922 | 430 | struct bt_field *bt_field_sequence_borrow_field( |
8deee039 PP |
431 | struct bt_field *field, uint64_t index) |
432 | { | |
18acc6f8 PP |
433 | struct bt_field_sequence *sequence = (void *) field; |
434 | ||
435 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
436 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
437 | "Field"); | |
438 | BT_ASSERT_PRE(index < sequence->length, | |
439 | "Index is out of bound: %![seq-field-]+f, " | |
440 | "index=%" PRIu64 ", count=%u", field, index, | |
441 | sequence->elements->len); | |
442 | return sequence->elements->pdata[(size_t) index]; | |
273b65be JG |
443 | } |
444 | ||
5fe68922 | 445 | struct bt_field *bt_field_variant_borrow_current_field( |
18acc6f8 | 446 | struct bt_field *field) |
3f4a108d | 447 | { |
18acc6f8 PP |
448 | struct bt_field_variant *variant = (void *) field; |
449 | ||
450 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); | |
451 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
452 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
453 | BT_ASSERT_PRE(variant->current_field, | |
454 | "Variant field has no current field: %!+f", field); | |
455 | return variant->current_field; | |
456 | } | |
457 | ||
458 | static inline | |
459 | int bt_field_variant_set_tag(struct bt_field *field, | |
460 | uint64_t tag_uval, bool is_signed) | |
461 | { | |
462 | int ret = 0; | |
463 | int64_t choice_index; | |
464 | struct bt_field_variant *variant = (void *) field; | |
465 | ||
466 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); | |
467 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
468 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
469 | ||
470 | /* Find matching index in variant field's type */ | |
471 | choice_index = bt_field_type_variant_find_choice_index( | |
472 | field->type, tag_uval, is_signed); | |
473 | if (choice_index < 0) { | |
474 | ret = -1; | |
475 | goto end; | |
476 | } | |
477 | ||
478 | /* Select corresponding field */ | |
479 | BT_ASSERT(choice_index < variant->fields->len); | |
480 | variant->current_field = variant->fields->pdata[choice_index]; | |
481 | variant->tag_value.u = tag_uval; | |
482 | ||
483 | end: | |
484 | return ret; | |
3f4a108d PP |
485 | } |
486 | ||
a6918753 PP |
487 | int bt_field_variant_set_tag_signed(struct bt_field *variant_field, |
488 | int64_t tag) | |
f78d67fb | 489 | { |
18acc6f8 | 490 | return bt_field_variant_set_tag((void *) variant_field, |
a6918753 PP |
491 | (uint64_t) tag, true); |
492 | } | |
493 | ||
494 | int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field, | |
495 | uint64_t tag) | |
496 | { | |
18acc6f8 | 497 | return bt_field_variant_set_tag((void *) variant_field, |
a6918753 | 498 | (uint64_t) tag, false); |
f78d67fb JG |
499 | } |
500 | ||
18acc6f8 | 501 | int bt_field_variant_get_tag_signed(struct bt_field *field, |
a6918753 | 502 | int64_t *tag) |
273b65be | 503 | { |
18acc6f8 PP |
504 | struct bt_field_variant *variant = (void *) field; |
505 | ||
506 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); | |
507 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
508 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
509 | BT_ASSERT_PRE(variant->current_field, | |
510 | "Variant field has no current field: %!+f", field); | |
511 | *tag = variant->tag_value.i; | |
512 | return 0; | |
a6918753 PP |
513 | } |
514 | ||
18acc6f8 | 515 | int bt_field_variant_get_tag_unsigned(struct bt_field *field, |
a6918753 PP |
516 | uint64_t *tag) |
517 | { | |
18acc6f8 PP |
518 | struct bt_field_variant *variant = (void *) field; |
519 | ||
520 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); | |
521 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
522 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
523 | BT_ASSERT_PRE(variant->current_field, | |
524 | "Variant field has no current field: %!+f", field); | |
525 | *tag = variant->tag_value.u; | |
526 | return 0; | |
273b65be JG |
527 | } |
528 | ||
839d52a5 PP |
529 | struct bt_field_type_enumeration_mapping_iterator * |
530 | bt_field_enumeration_get_mappings(struct bt_field *field) | |
cd95e351 | 531 | { |
a6918753 | 532 | struct bt_field_enumeration *enum_field = (void *) field; |
18acc6f8 PP |
533 | struct bt_field_type_enumeration *enum_type = NULL; |
534 | struct bt_field_type_integer *integer_type = NULL; | |
535 | struct bt_field_type_enumeration_mapping_iterator *iter = NULL; | |
a6918753 | 536 | |
18acc6f8 PP |
537 | BT_ASSERT(field); |
538 | BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_ENUM); | |
539 | BT_ASSERT(field->payload_set); | |
a6918753 | 540 | BT_ASSERT_PRE_NON_NULL(field, "Enumeration field"); |
18acc6f8 | 541 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID((struct bt_field *) field, |
a6918753 | 542 | BT_FIELD_TYPE_ID_ENUM, "Field"); |
18acc6f8 | 543 | BT_ASSERT_PRE_FIELD_IS_SET((struct bt_field *) field, |
a6918753 | 544 | "Enumeration field"); |
18acc6f8 PP |
545 | enum_type = (void *) field->type; |
546 | integer_type = enum_type->container_ft; | |
547 | ||
548 | if (!integer_type->is_signed) { | |
549 | iter = bt_field_type_enumeration_unsigned_find_mappings_by_value( | |
550 | field->type, | |
551 | enum_field->common.payload.unsignd); | |
552 | } else { | |
553 | iter = bt_field_type_enumeration_signed_find_mappings_by_value( | |
554 | field->type, | |
555 | enum_field->common.payload.signd); | |
556 | } | |
557 | ||
558 | return iter; | |
a6918753 PP |
559 | } |
560 | ||
561 | BT_ASSERT_PRE_FUNC | |
562 | static inline | |
18acc6f8 | 563 | struct bt_field_type_integer *get_int_enum_int_ft( |
a6918753 PP |
564 | struct bt_field *field) |
565 | { | |
18acc6f8 PP |
566 | struct bt_field_integer *int_field = (void *) field; |
567 | struct bt_field_type_integer *int_ft = NULL; | |
a6918753 PP |
568 | |
569 | if (int_field->common.type->id == BT_FIELD_TYPE_ID_INTEGER) { | |
18acc6f8 | 570 | int_ft = (void *) int_field->common.type; |
a6918753 | 571 | } else if (int_field->common.type->id == BT_FIELD_TYPE_ID_ENUM) { |
18acc6f8 PP |
572 | struct bt_field_type_enumeration *enum_ft = |
573 | (void *) int_field->common.type; | |
a6918753 | 574 | int_ft = enum_ft->container_ft; |
18acc6f8 PP |
575 | } else { |
576 | abort(); | |
a6918753 PP |
577 | } |
578 | ||
579 | BT_ASSERT(int_ft); | |
580 | return int_ft; | |
cd95e351 JG |
581 | } |
582 | ||
8deee039 | 583 | int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value) |
cd95e351 | 584 | { |
18acc6f8 | 585 | struct bt_field_integer *integer = (void *) field; |
a6918753 PP |
586 | |
587 | BT_ASSERT_PRE_NON_NULL(field, "Integer/enumeration field"); | |
588 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
18acc6f8 | 589 | BT_ASSERT_PRE_FIELD_IS_SET(field, |
a6918753 | 590 | "Integer/enumeration field"); |
18acc6f8 PP |
591 | BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field"); |
592 | BT_ASSERT_PRE(bt_field_type_integer_is_signed( | |
593 | (void *) get_int_enum_int_ft(field)), | |
a6918753 PP |
594 | "Field's type is unsigned: %!+f", field); |
595 | *value = integer->payload.signd; | |
596 | return 0; | |
cd95e351 JG |
597 | } |
598 | ||
a6918753 | 599 | int bt_field_integer_signed_set_value(struct bt_field *field, int64_t value) |
273b65be | 600 | { |
a6918753 | 601 | int ret = 0; |
18acc6f8 | 602 | struct bt_field_integer *integer = (void *) field; |
a6918753 PP |
603 | |
604 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
18acc6f8 PP |
605 | BT_ASSERT_PRE_FIELD_HOT(field, "Integer field"); |
606 | BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field"); | |
607 | BT_ASSERT_PRE(bt_field_type_integer_is_signed( | |
608 | (void *) get_int_enum_int_ft(field)), | |
a6918753 PP |
609 | "Field's type is unsigned: %!+f", field); |
610 | BT_ASSERT_PRE(value_is_in_range_signed( | |
611 | get_int_enum_int_ft(field)->size, value), | |
612 | "Value is out of bounds: value=%" PRId64 ", %![field-]+f", | |
613 | value, field); | |
614 | integer->payload.signd = value; | |
615 | bt_field_set(field, true); | |
616 | return ret; | |
273b65be JG |
617 | } |
618 | ||
a6918753 | 619 | int bt_field_integer_unsigned_get_value(struct bt_field *field, uint64_t *value) |
cd95e351 | 620 | { |
18acc6f8 | 621 | struct bt_field_integer *integer = (void *) field; |
a6918753 PP |
622 | |
623 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
624 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
18acc6f8 PP |
625 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field"); |
626 | BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field"); | |
627 | BT_ASSERT_PRE(!bt_field_type_integer_is_signed( | |
628 | (void *) get_int_enum_int_ft(field)), | |
a6918753 PP |
629 | "Field's type is signed: %!+f", field); |
630 | *value = integer->payload.unsignd; | |
631 | return 0; | |
cd95e351 JG |
632 | } |
633 | ||
a6918753 PP |
634 | int bt_field_integer_unsigned_set_value(struct bt_field *field, |
635 | uint64_t value) | |
273b65be | 636 | { |
18acc6f8 | 637 | struct bt_field_integer *integer = (void *) field; |
a6918753 PP |
638 | |
639 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
18acc6f8 PP |
640 | BT_ASSERT_PRE_FIELD_HOT(field, "Integer field"); |
641 | BT_ASSERT_PRE_FIELD_IS_INT_OR_ENUM(field, "Field"); | |
642 | BT_ASSERT_PRE(!bt_field_type_integer_is_signed( | |
643 | (void *) get_int_enum_int_ft(field)), | |
a6918753 PP |
644 | "Field's type is signed: %!+f", field); |
645 | BT_ASSERT_PRE(value_is_in_range_unsigned( | |
646 | get_int_enum_int_ft(field)->size, value), | |
647 | "Value is out of bounds: value=%" PRIu64 ", %![field-]+f", | |
648 | value, field); | |
649 | integer->payload.unsignd = value; | |
650 | bt_field_set(field, true); | |
651 | return 0; | |
8b45963b PP |
652 | } |
653 | ||
8deee039 PP |
654 | int bt_field_floating_point_get_value(struct bt_field *field, |
655 | double *value) | |
8b45963b | 656 | { |
18acc6f8 PP |
657 | struct bt_field_floating_point *floating_point = (void *) field; |
658 | ||
659 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); | |
660 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
661 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field"); | |
662 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
663 | BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
664 | *value = floating_point->payload; | |
665 | return 0; | |
273b65be JG |
666 | } |
667 | ||
8deee039 PP |
668 | int bt_field_floating_point_set_value(struct bt_field *field, |
669 | double value) | |
cd95e351 | 670 | { |
18acc6f8 PP |
671 | struct bt_field_floating_point *floating_point = (void *) field; |
672 | ||
673 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); | |
674 | BT_ASSERT_PRE_FIELD_HOT(field, "Floating point number field"); | |
675 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
676 | BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
677 | floating_point->payload = value; | |
678 | bt_field_set(field, true); | |
679 | return 0; | |
8b45963b | 680 | } |
fc25abce | 681 | |
8deee039 | 682 | const char *bt_field_string_get_value(struct bt_field *field) |
8b45963b | 683 | { |
18acc6f8 PP |
684 | struct bt_field_string *string = (void *) field; |
685 | ||
686 | BT_ASSERT_PRE_NON_NULL(field, "String field"); | |
687 | BT_ASSERT_PRE_FIELD_IS_SET(field, "String field"); | |
688 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
689 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
690 | return (const char *) string->buf->data; | |
cd95e351 JG |
691 | } |
692 | ||
8deee039 | 693 | int bt_field_string_set_value(struct bt_field *field, const char *value) |
273b65be | 694 | { |
18acc6f8 PP |
695 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
696 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
697 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
698 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
699 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
700 | bt_field_string_clear(field); | |
701 | return bt_field_string_append_len(field, | |
702 | value, strlen(value)); | |
273b65be JG |
703 | } |
704 | ||
8deee039 | 705 | int bt_field_string_append(struct bt_field *field, const char *value) |
cd95e351 | 706 | { |
18acc6f8 PP |
707 | BT_ASSERT_PRE_NON_NULL(value, "Value"); |
708 | return bt_field_string_append_len(field, value, | |
709 | strlen(value)); | |
cd95e351 JG |
710 | } |
711 | ||
8deee039 PP |
712 | int bt_field_string_append_len(struct bt_field *field, |
713 | const char *value, unsigned int length) | |
273b65be | 714 | { |
18acc6f8 PP |
715 | struct bt_field_string *string_field = (void *) field; |
716 | char *data; | |
717 | size_t new_size; | |
273b65be | 718 | |
18acc6f8 PP |
719 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
720 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
721 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
722 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
723 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
a6918753 | 724 | |
18acc6f8 PP |
725 | /* Make sure no null bytes are appended */ |
726 | BT_ASSERT_PRE(memchr(value, '\0', length) == NULL, | |
727 | "String value to append contains a null character: " | |
728 | "partial-value=\"%.32s\", length=%u", value, length); | |
c6f9c5a3 | 729 | |
18acc6f8 PP |
730 | new_size = string_field->size + length; |
731 | ||
732 | if (unlikely(new_size + 1 > string_field->buf->len)) { | |
733 | g_array_set_size(string_field->buf, new_size + 1); | |
c6f9c5a3 PP |
734 | } |
735 | ||
18acc6f8 PP |
736 | data = string_field->buf->data; |
737 | memcpy(data + string_field->size, value, length); | |
738 | ((char *) string_field->buf->data)[new_size] = '\0'; | |
739 | string_field->size = new_size; | |
740 | bt_field_set(field, true); | |
741 | return 0; | |
742 | } | |
8deee039 | 743 | |
18acc6f8 PP |
744 | int bt_field_string_clear(struct bt_field *field) |
745 | { | |
746 | struct bt_field_string *string_field = (void *) field; | |
747 | ||
748 | BT_ASSERT_PRE_NON_NULL(field, "String field"); | |
749 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
750 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, | |
751 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
752 | string_field->size = 0; | |
753 | bt_field_set(field, true); | |
754 | return 0; | |
755 | } | |
756 | ||
757 | static inline | |
758 | void bt_field_finalize(struct bt_field *field) | |
759 | { | |
760 | BT_ASSERT(field); | |
761 | BT_LOGD_STR("Putting field's type."); | |
762 | bt_put(field->type); | |
c6f9c5a3 PP |
763 | } |
764 | ||
a6918753 PP |
765 | static |
766 | void bt_field_integer_destroy(struct bt_field *field) | |
8deee039 | 767 | { |
18acc6f8 | 768 | BT_ASSERT(field); |
a6918753 | 769 | BT_LOGD("Destroying integer field object: addr=%p", field); |
18acc6f8 | 770 | bt_field_finalize(field); |
a6918753 | 771 | g_free(field); |
8deee039 | 772 | } |
f98c6554 | 773 | |
a6918753 PP |
774 | static |
775 | void bt_field_floating_point_destroy(struct bt_field *field) | |
8deee039 | 776 | { |
18acc6f8 | 777 | BT_ASSERT(field); |
a6918753 | 778 | BT_LOGD("Destroying floating point field object: addr=%p", field); |
18acc6f8 | 779 | bt_field_finalize(field); |
a6918753 | 780 | g_free(field); |
f98c6554 PP |
781 | } |
782 | ||
a6918753 PP |
783 | static |
784 | void bt_field_enumeration_destroy(struct bt_field *field) | |
273b65be | 785 | { |
a6918753 | 786 | BT_LOGD("Destroying enumeration field object: addr=%p", field); |
18acc6f8 | 787 | bt_field_finalize((void *) field); |
a6918753 | 788 | g_free(field); |
8deee039 | 789 | } |
273b65be | 790 | |
a6918753 PP |
791 | static |
792 | void bt_field_structure_destroy_recursive(struct bt_field *field) | |
8deee039 | 793 | { |
18acc6f8 PP |
794 | struct bt_field_structure *structure = (void *) field; |
795 | ||
796 | BT_ASSERT(field); | |
a6918753 | 797 | BT_LOGD("Destroying structure field object: addr=%p", field); |
18acc6f8 PP |
798 | bt_field_finalize(field); |
799 | ||
800 | if (structure->fields) { | |
801 | g_ptr_array_free(structure->fields, TRUE); | |
802 | } | |
803 | ||
a6918753 | 804 | g_free(field); |
273b65be JG |
805 | } |
806 | ||
a6918753 PP |
807 | static |
808 | void bt_field_variant_destroy_recursive(struct bt_field *field) | |
8deee039 | 809 | { |
18acc6f8 PP |
810 | struct bt_field_variant *variant = (void *) field; |
811 | ||
812 | BT_ASSERT(field); | |
a6918753 | 813 | BT_LOGD("Destroying variant field object: addr=%p", field); |
18acc6f8 PP |
814 | bt_field_finalize(field); |
815 | ||
816 | if (variant->fields) { | |
817 | g_ptr_array_free(variant->fields, TRUE); | |
818 | } | |
819 | ||
a6918753 | 820 | g_free(field); |
8b45963b | 821 | } |
12c8a1a3 | 822 | |
a6918753 PP |
823 | static |
824 | void bt_field_array_destroy_recursive(struct bt_field *field) | |
8b45963b | 825 | { |
18acc6f8 PP |
826 | struct bt_field_array *array = (void *) field; |
827 | ||
828 | BT_ASSERT(field); | |
a6918753 | 829 | BT_LOGD("Destroying array field object: addr=%p", field); |
18acc6f8 PP |
830 | bt_field_finalize(field); |
831 | ||
832 | if (array->elements) { | |
833 | g_ptr_array_free(array->elements, TRUE); | |
834 | } | |
835 | ||
a6918753 | 836 | g_free(field); |
12c8a1a3 JG |
837 | } |
838 | ||
a6918753 PP |
839 | static |
840 | void bt_field_sequence_destroy_recursive(struct bt_field *field) | |
273b65be | 841 | { |
18acc6f8 PP |
842 | struct bt_field_sequence *sequence = (void *) field; |
843 | ||
844 | BT_ASSERT(field); | |
a6918753 | 845 | BT_LOGD("Destroying sequence field object: addr=%p", field); |
18acc6f8 PP |
846 | bt_field_finalize(field); |
847 | ||
848 | if (sequence->elements) { | |
849 | g_ptr_array_free(sequence->elements, TRUE); | |
850 | } | |
a6918753 | 851 | g_free(field); |
273b65be JG |
852 | } |
853 | ||
a6918753 PP |
854 | static |
855 | void bt_field_string_destroy(struct bt_field *field) | |
76f869ab | 856 | { |
18acc6f8 PP |
857 | struct bt_field_string *string = (void *) field; |
858 | ||
a6918753 | 859 | BT_LOGD("Destroying string field object: addr=%p", field); |
18acc6f8 PP |
860 | BT_ASSERT(field); |
861 | bt_field_finalize(field); | |
862 | ||
863 | if (string->buf) { | |
864 | g_array_free(string->buf, TRUE); | |
865 | } | |
866 | ||
a6918753 | 867 | g_free(field); |
76f869ab JG |
868 | } |
869 | ||
8deee039 | 870 | BT_HIDDEN |
a6918753 | 871 | void bt_field_destroy_recursive(struct bt_field *field) |
87d43dc1 | 872 | { |
a6918753 PP |
873 | if (!field) { |
874 | return; | |
87d43dc1 | 875 | } |
8b45963b | 876 | |
18acc6f8 PP |
877 | BT_ASSERT(bt_field_type_has_known_id((void *) field->type)); |
878 | field_destroy_funcs[field->type->id](field); | |
879 | } | |
880 | ||
881 | static inline | |
882 | void bt_field_initialize(struct bt_field *field, | |
883 | struct bt_field_type *ft, | |
884 | struct bt_field_methods *methods) | |
885 | { | |
886 | BT_ASSERT(field); | |
887 | BT_ASSERT(ft); | |
888 | bt_object_init_unique(&field->base); | |
889 | field->methods = methods; | |
890 | field->type = bt_get(ft); | |
87d43dc1 JG |
891 | } |
892 | ||
273b65be | 893 | static |
839d52a5 | 894 | struct bt_field *bt_field_integer_create(struct bt_field_type *type) |
273b65be | 895 | { |
18acc6f8 PP |
896 | struct bt_field_integer *integer = |
897 | g_new0(struct bt_field_integer, 1); | |
273b65be | 898 | |
fc25abce PP |
899 | BT_LOGD("Creating integer field object: ft-addr=%p", type); |
900 | ||
901 | if (integer) { | |
18acc6f8 PP |
902 | bt_field_initialize((void *) integer, (void *) type, |
903 | &bt_field_integer_methods); | |
fc25abce | 904 | BT_LOGD("Created integer field object: addr=%p, ft-addr=%p", |
8deee039 | 905 | integer, type); |
fc25abce PP |
906 | } else { |
907 | BT_LOGE_STR("Failed to allocate one integer field."); | |
908 | } | |
909 | ||
8deee039 | 910 | return (void *) integer; |
273b65be JG |
911 | } |
912 | ||
913 | static | |
8deee039 | 914 | struct bt_field *bt_field_enumeration_create(struct bt_field_type *type) |
273b65be | 915 | { |
a6918753 PP |
916 | struct bt_field_enumeration *enumeration = g_new0( |
917 | struct bt_field_enumeration, 1); | |
273b65be | 918 | |
fc25abce PP |
919 | BT_LOGD("Creating enumeration field object: ft-addr=%p", type); |
920 | ||
921 | if (enumeration) { | |
18acc6f8 PP |
922 | bt_field_initialize((void *) enumeration, |
923 | (void *) type, &bt_field_enumeration_methods); | |
fc25abce | 924 | BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p", |
8deee039 | 925 | enumeration, type); |
fc25abce PP |
926 | } else { |
927 | BT_LOGE_STR("Failed to allocate one enumeration field."); | |
928 | } | |
929 | ||
8deee039 | 930 | return (void *) enumeration; |
273b65be JG |
931 | } |
932 | ||
933 | static | |
8deee039 | 934 | struct bt_field *bt_field_floating_point_create(struct bt_field_type *type) |
273b65be | 935 | { |
18acc6f8 | 936 | struct bt_field_floating_point *floating_point; |
273b65be | 937 | |
fc25abce | 938 | BT_LOGD("Creating floating point number field object: ft-addr=%p", type); |
18acc6f8 | 939 | floating_point = g_new0(struct bt_field_floating_point, 1); |
fc25abce PP |
940 | |
941 | if (floating_point) { | |
18acc6f8 PP |
942 | bt_field_initialize((void *) floating_point, |
943 | (void *) type, &bt_field_floating_point_methods); | |
fc25abce | 944 | BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p", |
8deee039 | 945 | floating_point, type); |
fc25abce PP |
946 | } else { |
947 | BT_LOGE_STR("Failed to allocate one floating point number field."); | |
948 | } | |
949 | ||
8deee039 | 950 | return (void *) floating_point; |
273b65be JG |
951 | } |
952 | ||
18acc6f8 PP |
953 | static inline |
954 | int bt_field_structure_initialize(struct bt_field *field, | |
955 | struct bt_field_type *type, | |
956 | struct bt_field_methods *methods, | |
957 | bt_field_create_func field_create_func, | |
a6918753 | 958 | GDestroyNotify field_release_func) |
8deee039 PP |
959 | { |
960 | int ret = 0; | |
18acc6f8 PP |
961 | struct bt_field_type_structure *structure_type = (void *) type; |
962 | struct bt_field_structure *structure = (void *) field; | |
9be89173 | 963 | size_t i; |
273b65be | 964 | |
18acc6f8 PP |
965 | BT_LOGD("Initializing structure field object: ft-addr=%p", type); |
966 | bt_field_initialize(field, type, methods); | |
a6918753 | 967 | structure->fields = g_ptr_array_new_with_free_func(field_release_func); |
8deee039 | 968 | g_ptr_array_set_size(structure->fields, structure_type->fields->len); |
9be89173 | 969 | |
a6918753 | 970 | /* Create all fields contained in the structure field. */ |
9be89173 | 971 | for (i = 0; i < structure_type->fields->len; i++) { |
18acc6f8 PP |
972 | struct bt_field *field; |
973 | struct bt_field_type_structure_field *struct_field = | |
974 | BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX( | |
a6918753 | 975 | structure_type, i); |
8deee039 | 976 | field = field_create_func(struct_field->type); |
9be89173 JG |
977 | if (!field) { |
978 | BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu", | |
8deee039 PP |
979 | g_quark_to_string(struct_field->name), i); |
980 | ret = -1; | |
9be89173 JG |
981 | goto end; |
982 | } | |
983 | ||
984 | g_ptr_array_index(structure->fields, i) = field; | |
985 | } | |
986 | ||
18acc6f8 | 987 | BT_LOGD("Initialized structure field object: addr=%p, ft-addr=%p", |
8deee039 PP |
988 | field, type); |
989 | ||
273b65be | 990 | end: |
9be89173 | 991 | return ret; |
273b65be JG |
992 | } |
993 | ||
8deee039 PP |
994 | static |
995 | struct bt_field *bt_field_structure_create(struct bt_field_type *type) | |
996 | { | |
18acc6f8 PP |
997 | struct bt_field_structure *structure = g_new0( |
998 | struct bt_field_structure, 1); | |
8deee039 PP |
999 | int iret; |
1000 | ||
1001 | BT_LOGD("Creating structure field object: ft-addr=%p", type); | |
1002 | ||
1003 | if (!structure) { | |
1004 | BT_LOGE_STR("Failed to allocate one structure field."); | |
1005 | goto end; | |
1006 | } | |
1007 | ||
18acc6f8 PP |
1008 | iret = bt_field_structure_initialize((void *) structure, |
1009 | (void *) type, &bt_field_structure_methods, | |
1010 | (bt_field_create_func) bt_field_create_recursive, | |
a6918753 | 1011 | (GDestroyNotify) bt_field_destroy_recursive); |
8deee039 PP |
1012 | if (iret) { |
1013 | BT_PUT(structure); | |
1014 | goto end; | |
1015 | } | |
1016 | ||
1017 | BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", | |
1018 | structure, type); | |
1019 | ||
1020 | end: | |
1021 | return (void *) structure; | |
1022 | } | |
1023 | ||
18acc6f8 PP |
1024 | static inline |
1025 | int bt_field_variant_initialize(struct bt_field *field, | |
1026 | struct bt_field_type *type, | |
1027 | struct bt_field_methods *methods, | |
1028 | bt_field_create_func field_create_func, | |
a6918753 PP |
1029 | GDestroyNotify field_release_func) |
1030 | { | |
1031 | int ret = 0; | |
18acc6f8 PP |
1032 | struct bt_field_type_variant *variant_type = (void *) type; |
1033 | struct bt_field_variant *variant = (void *) field; | |
a6918753 PP |
1034 | size_t i; |
1035 | ||
18acc6f8 PP |
1036 | BT_LOGD("Initializing variant field object: ft-addr=%p", type); |
1037 | bt_field_initialize(field, type, methods); | |
1038 | ret = bt_field_type_variant_update_choices(type); | |
a6918753 | 1039 | if (ret) { |
18acc6f8 | 1040 | BT_LOGE("Cannot update variant field type choices: " |
a6918753 PP |
1041 | "ret=%d", ret); |
1042 | goto end; | |
1043 | } | |
1044 | ||
1045 | variant->fields = g_ptr_array_new_with_free_func(field_release_func); | |
1046 | g_ptr_array_set_size(variant->fields, variant_type->choices->len); | |
1047 | ||
1048 | /* Create all fields contained in the variant field. */ | |
1049 | for (i = 0; i < variant_type->choices->len; i++) { | |
18acc6f8 PP |
1050 | struct bt_field *field; |
1051 | struct bt_field_type_variant_choice *var_choice = | |
1052 | BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX( | |
a6918753 PP |
1053 | variant_type, i); |
1054 | ||
1055 | field = field_create_func(var_choice->type); | |
1056 | if (!field) { | |
1057 | BT_LOGE("Failed to create variant field's member: name=\"%s\", index=%zu", | |
1058 | g_quark_to_string(var_choice->name), i); | |
1059 | ret = -1; | |
1060 | goto end; | |
1061 | } | |
1062 | ||
1063 | g_ptr_array_index(variant->fields, i) = field; | |
1064 | } | |
1065 | ||
18acc6f8 | 1066 | BT_LOGD("Initialized variant field object: addr=%p, ft-addr=%p", |
a6918753 PP |
1067 | field, type); |
1068 | ||
1069 | end: | |
1070 | return ret; | |
1071 | } | |
1072 | ||
18acc6f8 PP |
1073 | static inline |
1074 | int bt_field_string_initialize(struct bt_field *field, | |
1075 | struct bt_field_type *type, | |
1076 | struct bt_field_methods *methods) | |
e42dd763 PP |
1077 | { |
1078 | int ret = 0; | |
18acc6f8 | 1079 | struct bt_field_string *string = (void *) field; |
e42dd763 | 1080 | |
18acc6f8 PP |
1081 | BT_LOGD("Initializing string field object: ft-addr=%p", type); |
1082 | bt_field_initialize(field, type, methods); | |
e42dd763 PP |
1083 | string->buf = g_array_sized_new(FALSE, FALSE, sizeof(char), 1); |
1084 | if (!string->buf) { | |
1085 | ret = -1; | |
1086 | goto end; | |
1087 | } | |
1088 | ||
1089 | g_array_index(string->buf, char, 0) = '\0'; | |
18acc6f8 | 1090 | BT_LOGD("Initialized string field object: addr=%p, ft-addr=%p", |
e42dd763 PP |
1091 | field, type); |
1092 | ||
1093 | end: | |
1094 | return ret; | |
1095 | } | |
1096 | ||
273b65be | 1097 | static |
839d52a5 | 1098 | struct bt_field *bt_field_variant_create(struct bt_field_type *type) |
273b65be | 1099 | { |
18acc6f8 PP |
1100 | struct bt_field_variant *variant = g_new0( |
1101 | struct bt_field_variant, 1); | |
a6918753 | 1102 | int iret; |
fc25abce PP |
1103 | |
1104 | BT_LOGD("Creating variant field object: ft-addr=%p", type); | |
1105 | ||
a6918753 | 1106 | if (!variant) { |
fc25abce | 1107 | BT_LOGE_STR("Failed to allocate one variant field."); |
a6918753 PP |
1108 | goto end; |
1109 | } | |
1110 | ||
18acc6f8 PP |
1111 | iret = bt_field_variant_initialize((void *) variant, |
1112 | (void *) type, &bt_field_variant_methods, | |
1113 | (bt_field_create_func) bt_field_create_recursive, | |
a6918753 PP |
1114 | (GDestroyNotify) bt_field_destroy_recursive); |
1115 | if (iret) { | |
1116 | BT_PUT(variant); | |
1117 | goto end; | |
fc25abce PP |
1118 | } |
1119 | ||
a6918753 PP |
1120 | BT_LOGD("Created variant field object: addr=%p, ft-addr=%p", |
1121 | variant, type); | |
1122 | ||
1123 | end: | |
8deee039 | 1124 | return (void *) variant; |
273b65be JG |
1125 | } |
1126 | ||
18acc6f8 PP |
1127 | static inline |
1128 | int bt_field_array_initialize(struct bt_field *field, | |
1129 | struct bt_field_type *type, | |
1130 | struct bt_field_methods *methods, | |
1131 | bt_field_create_func field_create_func, | |
a6918753 | 1132 | GDestroyNotify field_destroy_func) |
273b65be | 1133 | { |
18acc6f8 PP |
1134 | struct bt_field_type_array *array_type = (void *) type; |
1135 | struct bt_field_array *array = (void *) field; | |
273b65be | 1136 | unsigned int array_length; |
8deee039 | 1137 | int ret = 0; |
a6918753 | 1138 | uint64_t i; |
273b65be | 1139 | |
18acc6f8 | 1140 | BT_LOGD("Initializing array field object: ft-addr=%p", type); |
8b45963b | 1141 | BT_ASSERT(type); |
18acc6f8 | 1142 | bt_field_initialize(field, type, methods); |
273b65be | 1143 | array_length = array_type->length; |
fe0fe95c | 1144 | array->elements = g_ptr_array_sized_new(array_length); |
273b65be | 1145 | if (!array->elements) { |
8deee039 PP |
1146 | ret = -1; |
1147 | goto end; | |
273b65be JG |
1148 | } |
1149 | ||
a6918753 | 1150 | g_ptr_array_set_free_func(array->elements, field_destroy_func); |
273b65be | 1151 | g_ptr_array_set_size(array->elements, array_length); |
a6918753 PP |
1152 | |
1153 | for (i = 0; i < array_length; i++) { | |
1154 | array->elements->pdata[i] = field_create_func( | |
1155 | array_type->element_ft); | |
1156 | if (!array->elements->pdata[i]) { | |
1157 | ret = -1; | |
1158 | goto end; | |
1159 | } | |
1160 | } | |
1161 | ||
18acc6f8 | 1162 | BT_LOGD("Initialized array field object: addr=%p, ft-addr=%p", |
8deee039 | 1163 | field, type); |
273b65be | 1164 | |
8deee039 PP |
1165 | end: |
1166 | return ret; | |
273b65be JG |
1167 | } |
1168 | ||
1169 | static | |
8deee039 | 1170 | struct bt_field *bt_field_array_create(struct bt_field_type *type) |
273b65be | 1171 | { |
18acc6f8 PP |
1172 | struct bt_field_array *array = |
1173 | g_new0(struct bt_field_array, 1); | |
8deee039 | 1174 | int ret; |
fc25abce | 1175 | |
8deee039 PP |
1176 | BT_LOGD("Creating array field object: ft-addr=%p", type); |
1177 | BT_ASSERT(type); | |
fc25abce | 1178 | |
8deee039 PP |
1179 | if (!array) { |
1180 | BT_LOGE_STR("Failed to allocate one array field."); | |
1181 | goto end; | |
fc25abce PP |
1182 | } |
1183 | ||
18acc6f8 PP |
1184 | ret = bt_field_array_initialize((void *) array, |
1185 | (void *) type, &bt_field_array_methods, | |
1186 | (bt_field_create_func) bt_field_create_recursive, | |
a6918753 | 1187 | (GDestroyNotify) bt_field_destroy_recursive); |
8deee039 PP |
1188 | if (ret) { |
1189 | BT_PUT(array); | |
1190 | goto end; | |
1191 | } | |
273b65be | 1192 | |
8deee039 PP |
1193 | BT_LOGD("Created array field object: addr=%p, ft-addr=%p", |
1194 | array, type); | |
273b65be | 1195 | |
8deee039 PP |
1196 | end: |
1197 | return (void *) array; | |
273b65be JG |
1198 | } |
1199 | ||
18acc6f8 PP |
1200 | static inline |
1201 | int bt_field_sequence_initialize(struct bt_field *field, | |
1202 | struct bt_field_type *type, | |
1203 | struct bt_field_methods *methods, | |
a6918753 PP |
1204 | GDestroyNotify field_destroy_func) |
1205 | { | |
18acc6f8 | 1206 | struct bt_field_sequence *sequence = (void *) field; |
a6918753 PP |
1207 | int ret = 0; |
1208 | ||
18acc6f8 | 1209 | BT_LOGD("Initializing sequence field object: ft-addr=%p", type); |
a6918753 | 1210 | BT_ASSERT(type); |
18acc6f8 | 1211 | bt_field_initialize(field, type, methods); |
a6918753 PP |
1212 | sequence->elements = g_ptr_array_new(); |
1213 | if (!sequence->elements) { | |
1214 | ret = -1; | |
1215 | goto end; | |
1216 | } | |
1217 | ||
1218 | g_ptr_array_set_free_func(sequence->elements, field_destroy_func); | |
18acc6f8 | 1219 | BT_LOGD("Initialized sequence field object: addr=%p, ft-addr=%p", |
a6918753 PP |
1220 | field, type); |
1221 | ||
1222 | end: | |
1223 | return ret; | |
1224 | } | |
1225 | ||
273b65be | 1226 | static |
8deee039 | 1227 | struct bt_field *bt_field_sequence_create(struct bt_field_type *type) |
273b65be | 1228 | { |
18acc6f8 PP |
1229 | struct bt_field_sequence *sequence = |
1230 | g_new0(struct bt_field_sequence, 1); | |
a6918753 | 1231 | int ret; |
273b65be | 1232 | |
8deee039 | 1233 | BT_LOGD("Creating sequence field object: ft-addr=%p", type); |
a6918753 | 1234 | BT_ASSERT(type); |
273b65be | 1235 | |
a6918753 | 1236 | if (!sequence) { |
8deee039 | 1237 | BT_LOGE_STR("Failed to allocate one sequence field."); |
a6918753 | 1238 | goto end; |
4fef87ab | 1239 | } |
8deee039 | 1240 | |
18acc6f8 PP |
1241 | ret = bt_field_sequence_initialize((void *) sequence, |
1242 | (void *) type, &bt_field_sequence_methods, | |
a6918753 PP |
1243 | (GDestroyNotify) bt_field_destroy_recursive); |
1244 | if (ret) { | |
1245 | BT_PUT(sequence); | |
1246 | goto end; | |
1247 | } | |
1248 | ||
1249 | BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p", | |
1250 | sequence, type); | |
1251 | ||
1252 | end: | |
8deee039 | 1253 | return (void *) sequence; |
273b65be JG |
1254 | } |
1255 | ||
1256 | static | |
8deee039 | 1257 | struct bt_field *bt_field_string_create(struct bt_field_type *type) |
273b65be | 1258 | { |
18acc6f8 PP |
1259 | struct bt_field_string *string = g_new0( |
1260 | struct bt_field_string, 1); | |
fc25abce | 1261 | |
8deee039 PP |
1262 | BT_LOGD("Creating string field object: ft-addr=%p", type); |
1263 | ||
1264 | if (string) { | |
18acc6f8 PP |
1265 | bt_field_string_initialize((void *) string, |
1266 | (void *) type, &bt_field_string_methods); | |
8deee039 PP |
1267 | BT_LOGD("Created string field object: addr=%p, ft-addr=%p", |
1268 | string, type); | |
1269 | } else { | |
1270 | BT_LOGE_STR("Failed to allocate one string field."); | |
9b2b7163 | 1271 | } |
8deee039 PP |
1272 | |
1273 | return (void *) string; | |
273b65be JG |
1274 | } |
1275 | ||
18acc6f8 PP |
1276 | static |
1277 | int bt_field_generic_validate(struct bt_field *field) | |
273b65be | 1278 | { |
da2f6971 | 1279 | return (field && field->payload_set) ? 0 : -1; |
273b65be JG |
1280 | } |
1281 | ||
18acc6f8 PP |
1282 | static |
1283 | int bt_field_structure_validate_recursive(struct bt_field *field) | |
273b65be | 1284 | { |
fc25abce | 1285 | int64_t i; |
273b65be | 1286 | int ret = 0; |
18acc6f8 | 1287 | struct bt_field_structure *structure = (void *) field; |
273b65be | 1288 | |
8b45963b | 1289 | BT_ASSERT(field); |
8b45963b | 1290 | |
273b65be | 1291 | for (i = 0; i < structure->fields->len; i++) { |
18acc6f8 | 1292 | ret = bt_field_validate_recursive( |
8b45963b | 1293 | (void *) structure->fields->pdata[i]); |
fc25abce | 1294 | |
273b65be | 1295 | if (ret) { |
fc25abce | 1296 | int this_ret; |
6ce12048 | 1297 | const char *name; |
6ce12048 | 1298 | |
18acc6f8 | 1299 | this_ret = bt_field_type_structure_borrow_field_by_index( |
8b45963b PP |
1300 | field->type, &name, NULL, i); |
1301 | BT_ASSERT(this_ret == 0); | |
1302 | BT_ASSERT_PRE_MSG("Invalid structure field's field: " | |
18acc6f8 PP |
1303 | "%![struct-field-]+f, field-name=\"%s\", " |
1304 | "index=%" PRId64 ", %![field-]+f", | |
8b45963b | 1305 | field, name, i, structure->fields->pdata[i]); |
273b65be JG |
1306 | goto end; |
1307 | } | |
1308 | } | |
8b45963b | 1309 | |
273b65be JG |
1310 | end: |
1311 | return ret; | |
1312 | } | |
1313 | ||
18acc6f8 PP |
1314 | static |
1315 | int bt_field_variant_validate_recursive(struct bt_field *field) | |
273b65be JG |
1316 | { |
1317 | int ret = 0; | |
18acc6f8 | 1318 | struct bt_field_variant *variant = (void *) field; |
273b65be | 1319 | |
8b45963b | 1320 | BT_ASSERT(field); |
a6918753 PP |
1321 | |
1322 | if (!variant->current_field) { | |
1323 | ret = -1; | |
1324 | goto end; | |
fc25abce | 1325 | } |
8b45963b | 1326 | |
18acc6f8 | 1327 | ret = bt_field_validate_recursive(variant->current_field); |
a6918753 PP |
1328 | |
1329 | end: | |
273b65be JG |
1330 | return ret; |
1331 | } | |
1332 | ||
18acc6f8 PP |
1333 | static |
1334 | int bt_field_array_validate_recursive(struct bt_field *field) | |
273b65be | 1335 | { |
fc25abce | 1336 | int64_t i; |
273b65be | 1337 | int ret = 0; |
18acc6f8 | 1338 | struct bt_field_array *array = (void *) field; |
273b65be | 1339 | |
8b45963b | 1340 | BT_ASSERT(field); |
8deee039 | 1341 | |
273b65be | 1342 | for (i = 0; i < array->elements->len; i++) { |
18acc6f8 | 1343 | ret = bt_field_validate_recursive((void *) array->elements->pdata[i]); |
273b65be | 1344 | if (ret) { |
8b45963b | 1345 | BT_ASSERT_PRE_MSG("Invalid array field's element field: " |
18acc6f8 PP |
1346 | "%![array-field-]+f, " PRId64 ", " |
1347 | "%![elem-field-]+f", | |
8b45963b | 1348 | field, i, array->elements->pdata[i]); |
273b65be JG |
1349 | goto end; |
1350 | } | |
1351 | } | |
8b45963b | 1352 | |
273b65be JG |
1353 | end: |
1354 | return ret; | |
1355 | } | |
1356 | ||
18acc6f8 PP |
1357 | static |
1358 | int bt_field_sequence_validate_recursive(struct bt_field *field) | |
273b65be JG |
1359 | { |
1360 | size_t i; | |
1361 | int ret = 0; | |
18acc6f8 | 1362 | struct bt_field_sequence *sequence = (void *) field; |
273b65be | 1363 | |
8b45963b | 1364 | BT_ASSERT(field); |
8deee039 | 1365 | |
273b65be | 1366 | for (i = 0; i < sequence->elements->len; i++) { |
18acc6f8 | 1367 | ret = bt_field_validate_recursive( |
8b45963b | 1368 | (void *) sequence->elements->pdata[i]); |
273b65be | 1369 | if (ret) { |
8b45963b | 1370 | BT_ASSERT_PRE_MSG("Invalid sequence field's element field: " |
18acc6f8 PP |
1371 | "%![seq-field-]+f, " PRId64 ", " |
1372 | "%![elem-field-]+f", | |
8b45963b | 1373 | field, i, sequence->elements->pdata[i]); |
273b65be JG |
1374 | goto end; |
1375 | } | |
1376 | } | |
1377 | end: | |
1378 | return ret; | |
1379 | } | |
1380 | ||
18acc6f8 PP |
1381 | static |
1382 | void bt_field_generic_reset(struct bt_field *field) | |
12c8a1a3 | 1383 | { |
8b45963b | 1384 | BT_ASSERT(field); |
a745c331 | 1385 | field->payload_set = false; |
12c8a1a3 JG |
1386 | } |
1387 | ||
18acc6f8 PP |
1388 | static |
1389 | void bt_field_structure_reset_recursive(struct bt_field *field) | |
12c8a1a3 | 1390 | { |
fc25abce | 1391 | int64_t i; |
18acc6f8 | 1392 | struct bt_field_structure *structure = (void *) field; |
12c8a1a3 | 1393 | |
8b45963b | 1394 | BT_ASSERT(field); |
8b45963b | 1395 | |
12c8a1a3 | 1396 | for (i = 0; i < structure->fields->len; i++) { |
18acc6f8 | 1397 | struct bt_field *member = structure->fields->pdata[i]; |
12c8a1a3 JG |
1398 | |
1399 | if (!member) { | |
1400 | /* | |
8b45963b PP |
1401 | * Structure members are lazily initialized; |
1402 | * skip if this member has not been allocated | |
1403 | * yet. | |
12c8a1a3 JG |
1404 | */ |
1405 | continue; | |
1406 | } | |
1407 | ||
18acc6f8 | 1408 | bt_field_reset_recursive(member); |
12c8a1a3 | 1409 | } |
12c8a1a3 JG |
1410 | } |
1411 | ||
18acc6f8 PP |
1412 | static |
1413 | void bt_field_variant_reset_recursive(struct bt_field *field) | |
12c8a1a3 | 1414 | { |
18acc6f8 | 1415 | struct bt_field_variant *variant = (void *) field; |
12c8a1a3 | 1416 | |
8b45963b | 1417 | BT_ASSERT(field); |
a6918753 | 1418 | variant->current_field = NULL; |
12c8a1a3 JG |
1419 | } |
1420 | ||
18acc6f8 PP |
1421 | static |
1422 | void bt_field_array_reset_recursive(struct bt_field *field) | |
12c8a1a3 JG |
1423 | { |
1424 | size_t i; | |
18acc6f8 | 1425 | struct bt_field_array *array = (void *) field; |
12c8a1a3 | 1426 | |
8b45963b | 1427 | BT_ASSERT(field); |
8b45963b | 1428 | |
12c8a1a3 | 1429 | for (i = 0; i < array->elements->len; i++) { |
18acc6f8 | 1430 | struct bt_field *member = array->elements->pdata[i]; |
12c8a1a3 JG |
1431 | |
1432 | if (!member) { | |
1433 | /* | |
8b45963b PP |
1434 | * Array elements are lazily initialized; skip |
1435 | * if this member has not been allocated yet. | |
12c8a1a3 JG |
1436 | */ |
1437 | continue; | |
1438 | } | |
1439 | ||
18acc6f8 | 1440 | bt_field_reset_recursive(member); |
12c8a1a3 | 1441 | } |
12c8a1a3 JG |
1442 | } |
1443 | ||
18acc6f8 PP |
1444 | static |
1445 | void bt_field_sequence_reset_recursive(struct bt_field *field) | |
12c8a1a3 | 1446 | { |
18acc6f8 | 1447 | struct bt_field_sequence *sequence = (void *) field; |
a6918753 | 1448 | uint64_t i; |
12c8a1a3 | 1449 | |
8b45963b | 1450 | BT_ASSERT(field); |
8b45963b | 1451 | |
a6918753 PP |
1452 | for (i = 0; i < sequence->elements->len; i++) { |
1453 | if (sequence->elements->pdata[i]) { | |
18acc6f8 | 1454 | bt_field_reset_recursive( |
a6918753 PP |
1455 | sequence->elements->pdata[i]); |
1456 | } | |
12c8a1a3 | 1457 | } |
8b45963b | 1458 | |
a6918753 | 1459 | sequence->length = 0; |
12c8a1a3 JG |
1460 | } |
1461 | ||
18acc6f8 PP |
1462 | static |
1463 | void bt_field_generic_set_is_frozen(struct bt_field *field, | |
a6918753 | 1464 | bool is_frozen) |
918be005 | 1465 | { |
a6918753 | 1466 | field->frozen = is_frozen; |
918be005 PP |
1467 | } |
1468 | ||
18acc6f8 PP |
1469 | static |
1470 | void bt_field_structure_set_is_frozen_recursive( | |
1471 | struct bt_field *field, bool is_frozen) | |
918be005 | 1472 | { |
a6918753 | 1473 | uint64_t i; |
18acc6f8 | 1474 | struct bt_field_structure *structure_field = (void *) field; |
918be005 | 1475 | |
fc25abce PP |
1476 | BT_LOGD("Freezing structure field object: addr=%p", field); |
1477 | ||
918be005 | 1478 | for (i = 0; i < structure_field->fields->len; i++) { |
18acc6f8 | 1479 | struct bt_field *struct_field = |
918be005 PP |
1480 | g_ptr_array_index(structure_field->fields, i); |
1481 | ||
fc25abce | 1482 | BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64, |
a6918753 | 1483 | struct_field, i); |
18acc6f8 | 1484 | bt_field_set_is_frozen_recursive(struct_field, |
a6918753 | 1485 | is_frozen); |
918be005 PP |
1486 | } |
1487 | ||
18acc6f8 | 1488 | bt_field_generic_set_is_frozen(field, is_frozen); |
918be005 PP |
1489 | } |
1490 | ||
18acc6f8 PP |
1491 | static |
1492 | void bt_field_variant_set_is_frozen_recursive( | |
1493 | struct bt_field *field, bool is_frozen) | |
918be005 | 1494 | { |
a6918753 | 1495 | uint64_t i; |
18acc6f8 | 1496 | struct bt_field_variant *variant_field = (void *) field; |
918be005 | 1497 | |
fc25abce | 1498 | BT_LOGD("Freezing variant field object: addr=%p", field); |
a6918753 PP |
1499 | |
1500 | for (i = 0; i < variant_field->fields->len; i++) { | |
18acc6f8 | 1501 | struct bt_field *var_field = |
a6918753 PP |
1502 | g_ptr_array_index(variant_field->fields, i); |
1503 | ||
1504 | BT_LOGD("Freezing variant field's field: field-addr=%p, index=%" PRId64, | |
1505 | var_field, i); | |
18acc6f8 | 1506 | bt_field_set_is_frozen_recursive(var_field, is_frozen); |
a6918753 PP |
1507 | } |
1508 | ||
18acc6f8 | 1509 | bt_field_generic_set_is_frozen(field, is_frozen); |
918be005 PP |
1510 | } |
1511 | ||
18acc6f8 PP |
1512 | static |
1513 | void bt_field_array_set_is_frozen_recursive( | |
1514 | struct bt_field *field, bool is_frozen) | |
918be005 | 1515 | { |
fc25abce | 1516 | int64_t i; |
18acc6f8 | 1517 | struct bt_field_array *array_field = (void *) field; |
918be005 | 1518 | |
fc25abce PP |
1519 | BT_LOGD("Freezing array field object: addr=%p", field); |
1520 | ||
918be005 | 1521 | for (i = 0; i < array_field->elements->len; i++) { |
18acc6f8 | 1522 | struct bt_field *elem_field = |
918be005 PP |
1523 | g_ptr_array_index(array_field->elements, i); |
1524 | ||
fc25abce PP |
1525 | BT_LOGD("Freezing array field object's element field: " |
1526 | "element-field-addr=%p, index=%" PRId64, | |
1527 | elem_field, i); | |
18acc6f8 | 1528 | bt_field_set_is_frozen_recursive(elem_field, is_frozen); |
918be005 PP |
1529 | } |
1530 | ||
18acc6f8 | 1531 | bt_field_generic_set_is_frozen(field, is_frozen); |
918be005 PP |
1532 | } |
1533 | ||
18acc6f8 PP |
1534 | static |
1535 | void bt_field_sequence_set_is_frozen_recursive( | |
1536 | struct bt_field *field, bool is_frozen) | |
918be005 | 1537 | { |
fc25abce | 1538 | int64_t i; |
18acc6f8 | 1539 | struct bt_field_sequence *sequence_field = (void *) field; |
918be005 | 1540 | |
fc25abce | 1541 | BT_LOGD("Freezing sequence field object: addr=%p", field); |
918be005 | 1542 | |
a6918753 | 1543 | for (i = 0; i < sequence_field->length; i++) { |
18acc6f8 | 1544 | struct bt_field *elem_field = |
918be005 PP |
1545 | g_ptr_array_index(sequence_field->elements, i); |
1546 | ||
fc25abce PP |
1547 | BT_LOGD("Freezing sequence field object's element field: " |
1548 | "element-field-addr=%p, index=%" PRId64, | |
1549 | elem_field, i); | |
18acc6f8 | 1550 | bt_field_set_is_frozen_recursive(elem_field, is_frozen); |
918be005 PP |
1551 | } |
1552 | ||
18acc6f8 | 1553 | bt_field_generic_set_is_frozen(field, is_frozen); |
918be005 PP |
1554 | } |
1555 | ||
1556 | BT_HIDDEN | |
18acc6f8 | 1557 | void _bt_field_set_is_frozen_recursive(struct bt_field *field, |
a6918753 | 1558 | bool is_frozen) |
918be005 PP |
1559 | { |
1560 | if (!field) { | |
1561 | goto end; | |
1562 | } | |
1563 | ||
a6918753 PP |
1564 | BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d", |
1565 | field, is_frozen); | |
18acc6f8 | 1566 | BT_ASSERT(bt_field_type_has_known_id(field->type)); |
a6918753 PP |
1567 | BT_ASSERT(field->methods->set_is_frozen); |
1568 | field->methods->set_is_frozen(field, is_frozen); | |
8deee039 | 1569 | |
918be005 PP |
1570 | end: |
1571 | return; | |
1572 | } | |
76f869ab | 1573 | |
18acc6f8 PP |
1574 | static |
1575 | bt_bool bt_field_generic_is_set(struct bt_field *field) | |
76f869ab JG |
1576 | { |
1577 | return field && field->payload_set; | |
1578 | } | |
1579 | ||
18acc6f8 PP |
1580 | static |
1581 | bt_bool bt_field_structure_is_set_recursive( | |
1582 | struct bt_field *field) | |
76f869ab | 1583 | { |
53d65c1d | 1584 | bt_bool is_set = BT_FALSE; |
76f869ab | 1585 | size_t i; |
18acc6f8 | 1586 | struct bt_field_structure *structure = (void *) field; |
76f869ab | 1587 | |
8b45963b | 1588 | BT_ASSERT(field); |
8deee039 | 1589 | |
76f869ab | 1590 | for (i = 0; i < structure->fields->len; i++) { |
18acc6f8 | 1591 | is_set = bt_field_is_set_recursive( |
ab706977 | 1592 | structure->fields->pdata[i]); |
53d65c1d | 1593 | if (!is_set) { |
76f869ab JG |
1594 | goto end; |
1595 | } | |
1596 | } | |
8deee039 | 1597 | |
76f869ab | 1598 | end: |
53d65c1d | 1599 | return is_set; |
76f869ab JG |
1600 | } |
1601 | ||
18acc6f8 PP |
1602 | static |
1603 | bt_bool bt_field_variant_is_set_recursive(struct bt_field *field) | |
76f869ab | 1604 | { |
18acc6f8 | 1605 | struct bt_field_variant *variant = (void *) field; |
a6918753 | 1606 | bt_bool is_set = BT_FALSE; |
76f869ab | 1607 | |
8b45963b | 1608 | BT_ASSERT(field); |
a6918753 PP |
1609 | |
1610 | if (variant->current_field) { | |
18acc6f8 | 1611 | is_set = bt_field_is_set_recursive( |
a6918753 PP |
1612 | variant->current_field); |
1613 | } | |
1614 | ||
1615 | return is_set; | |
76f869ab JG |
1616 | } |
1617 | ||
18acc6f8 PP |
1618 | static |
1619 | bt_bool bt_field_array_is_set_recursive(struct bt_field *field) | |
76f869ab JG |
1620 | { |
1621 | size_t i; | |
53d65c1d | 1622 | bt_bool is_set = BT_FALSE; |
18acc6f8 | 1623 | struct bt_field_array *array = (void *) field; |
76f869ab | 1624 | |
8b45963b | 1625 | BT_ASSERT(field); |
8deee039 | 1626 | |
76f869ab | 1627 | for (i = 0; i < array->elements->len; i++) { |
18acc6f8 | 1628 | is_set = bt_field_is_set_recursive(array->elements->pdata[i]); |
53d65c1d | 1629 | if (!is_set) { |
76f869ab JG |
1630 | goto end; |
1631 | } | |
1632 | } | |
8deee039 | 1633 | |
76f869ab | 1634 | end: |
53d65c1d | 1635 | return is_set; |
76f869ab JG |
1636 | } |
1637 | ||
18acc6f8 PP |
1638 | static |
1639 | bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field) | |
76f869ab JG |
1640 | { |
1641 | size_t i; | |
53d65c1d | 1642 | bt_bool is_set = BT_FALSE; |
18acc6f8 | 1643 | struct bt_field_sequence *sequence = (void *) field; |
76f869ab | 1644 | |
8b45963b | 1645 | BT_ASSERT(field); |
8deee039 | 1646 | |
7d7fae6d JG |
1647 | if (!sequence->elements) { |
1648 | goto end; | |
1649 | } | |
1650 | ||
76f869ab | 1651 | for (i = 0; i < sequence->elements->len; i++) { |
18acc6f8 | 1652 | is_set = bt_field_is_set_recursive( |
8deee039 | 1653 | sequence->elements->pdata[i]); |
53d65c1d | 1654 | if (!is_set) { |
76f869ab JG |
1655 | goto end; |
1656 | } | |
1657 | } | |
8deee039 | 1658 | |
76f869ab | 1659 | end: |
53d65c1d | 1660 | return is_set; |
76f869ab | 1661 | } |