assert-pre-internal.h: add BT_ASSERT_PRE_VALID_INDEX()
[babeltrace.git] / lib / ctf-ir / fields.c
CommitLineData
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
3dca2276 32#include <babeltrace/assert-pre-internal.h>
cb6f1f7d 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>
f6ccaed9 41#include <babeltrace/assert-internal.h>
fc25abce 42#include <inttypes.h>
273b65be 43
312c056a
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
cb6f1f7d
PP
50static
51int bt_field_generic_validate(struct bt_field *field);
52
53static
54int bt_field_structure_validate_recursive(struct bt_field *field);
55
56static
57int bt_field_variant_validate_recursive(struct bt_field *field);
58
59static
60int bt_field_array_validate_recursive(struct bt_field *field);
61
62static
63int bt_field_sequence_validate_recursive(struct bt_field *field);
64
65static
66void bt_field_generic_reset(struct bt_field *field);
67
68static
69void bt_field_structure_reset_recursive(struct bt_field *field);
70
71static
72void bt_field_variant_reset_recursive(struct bt_field *field);
73
74static
75void bt_field_array_reset_recursive(struct bt_field *field);
76
77static
78void bt_field_sequence_reset_recursive(struct bt_field *field);
79
80static
81void bt_field_generic_set_is_frozen(struct bt_field *field,
82 bool is_frozen);
83
84static
85void bt_field_structure_set_is_frozen_recursive(
86 struct bt_field *field, bool is_frozen);
87
88static
89void bt_field_variant_set_is_frozen_recursive(
90 struct bt_field *field, bool is_frozen);
91
92static
93void bt_field_array_set_is_frozen_recursive(
94 struct bt_field *field, bool is_frozen);
95
96static
97void bt_field_sequence_set_is_frozen_recursive(
98 struct bt_field *field, bool is_frozen);
99
100static
101bt_bool bt_field_generic_is_set(struct bt_field *field);
102
103static
104bt_bool bt_field_structure_is_set_recursive(
105 struct bt_field *field);
106
107static
108bt_bool bt_field_variant_is_set_recursive(struct bt_field *field);
109
110static
111bt_bool bt_field_array_is_set_recursive(struct bt_field *field);
112
113static
114bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field);
115
116static 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,
3dca2276 121};
273b65be 122
cb6f1f7d
PP
123static 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
cb6f1f7d
PP
130static 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
cb6f1f7d
PP
137static 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
cb6f1f7d
PP
144static 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
cb6f1f7d
PP
151static 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
cb6f1f7d
PP
158static 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
cb6f1f7d
PP
165static 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 172static
3dca2276 173struct bt_field *bt_field_integer_create(struct bt_field_type *);
76f869ab 174
3dca2276
PP
175static
176struct bt_field *bt_field_enumeration_create(struct bt_field_type *);
177
178static
179struct bt_field *bt_field_floating_point_create(struct bt_field_type *);
180
181static
182struct bt_field *bt_field_structure_create(struct bt_field_type *);
183
184static
185struct bt_field *bt_field_variant_create(struct bt_field_type *);
186
187static
188struct bt_field *bt_field_array_create(struct bt_field_type *);
f6ccaed9 189
3dca2276
PP
190static
191struct bt_field *bt_field_sequence_create(struct bt_field_type *);
f6ccaed9 192
3dca2276
PP
193static
194struct bt_field *bt_field_string_create(struct bt_field_type *);
f6ccaed9 195
3dca2276
PP
196static
197struct 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};
f6ccaed9 207
312c056a
PP
208static
209void bt_field_integer_destroy(struct bt_field *field);
210
211static
212void bt_field_enumeration_destroy(struct bt_field *field);
213
214static
215void bt_field_floating_point_destroy(struct bt_field *field);
216
217static
218void bt_field_structure_destroy_recursive(struct bt_field *field);
219
220static
221void bt_field_variant_destroy_recursive(struct bt_field *field);
222
223static
224void bt_field_array_destroy_recursive(struct bt_field *field);
225
226static
227void bt_field_sequence_destroy_recursive(struct bt_field *field);
228
229static
230void bt_field_string_destroy(struct bt_field *field);
231
232static
233void (* 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
cb6f1f7d
PP
244BT_ASSERT_PRE_FUNC
245static 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
262BT_ASSERT_PRE_FUNC
263static 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
312c056a
PP
279BT_HIDDEN
280struct bt_field *bt_field_create_recursive(struct bt_field_type *type)
273b65be 281{
50842bdc
PP
282 struct bt_field *field = NULL;
283 enum bt_field_type_id type_id;
273b65be 284
f6ccaed9 285 BT_ASSERT_PRE_NON_NULL(type, "Field type");
cb6f1f7d
PP
286 BT_ASSERT(bt_field_type_has_known_id((void *) type));
287 BT_ASSERT_PRE(bt_field_type_validate((void *) type) == 0,
f6ccaed9 288 "Field type is invalid: %!+F", type);
50842bdc 289 type_id = bt_field_type_get_type_id(type);
273b65be
JG
290 field = field_create_funcs[type_id](type);
291 if (!field) {
3dca2276 292 goto end;
273b65be
JG
293 }
294
50842bdc 295 bt_field_type_freeze(type);
273b65be 296
3dca2276
PP
297end:
298 return field;
273b65be
JG
299}
300
094ff7c0 301struct bt_field_type *bt_field_borrow_type(struct bt_field *field)
cd95e351 302{
cb6f1f7d
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
50842bdc 310enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
4ebcc695 311{
f6ccaed9 312 BT_ASSERT_PRE_NON_NULL(field, "Field");
cb6f1f7d 313 return field->type->id;
4ebcc695
PP
314}
315
312c056a 316int64_t bt_field_sequence_get_length(struct bt_field *field)
2e8876d3 317{
cb6f1f7d
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;
2e8876d3
PP
324}
325
312c056a 326int bt_field_sequence_set_length(struct bt_field *field, uint64_t length)
273b65be 327{
cb6f1f7d
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
363end:
364 return ret;
273b65be
JG
365}
366
094ff7c0 367struct bt_field *bt_field_structure_borrow_field_by_index(
50842bdc 368 struct bt_field *field, uint64_t index)
cd95e351 369{
cb6f1f7d
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];
f6ccaed9 380}
fc25abce 381
094ff7c0 382struct bt_field *bt_field_structure_borrow_field_by_name(
3dca2276 383 struct bt_field *field, const char *name)
f6ccaed9 384{
cb6f1f7d
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
411error:
412 return ret;
cd95e351
JG
413}
414
094ff7c0 415struct bt_field *bt_field_array_borrow_field(
3dca2276 416 struct bt_field *field, uint64_t index)
273b65be 417{
cb6f1f7d
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];
3dca2276 428}
f6ccaed9 429
094ff7c0 430struct bt_field *bt_field_sequence_borrow_field(
3dca2276
PP
431 struct bt_field *field, uint64_t index)
432{
cb6f1f7d
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
094ff7c0 445struct bt_field *bt_field_variant_borrow_current_field(
cb6f1f7d 446 struct bt_field *field)
3f4a108d 447{
cb6f1f7d
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
458static inline
459int 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
483end:
484 return ret;
3f4a108d
PP
485}
486
312c056a
PP
487int bt_field_variant_set_tag_signed(struct bt_field *variant_field,
488 int64_t tag)
f78d67fb 489{
cb6f1f7d 490 return bt_field_variant_set_tag((void *) variant_field,
312c056a
PP
491 (uint64_t) tag, true);
492}
493
494int bt_field_variant_set_tag_unsigned(struct bt_field *variant_field,
495 uint64_t tag)
496{
cb6f1f7d 497 return bt_field_variant_set_tag((void *) variant_field,
312c056a 498 (uint64_t) tag, false);
f78d67fb
JG
499}
500
cb6f1f7d 501int bt_field_variant_get_tag_signed(struct bt_field *field,
312c056a 502 int64_t *tag)
273b65be 503{
cb6f1f7d
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;
312c056a
PP
513}
514
cb6f1f7d 515int bt_field_variant_get_tag_unsigned(struct bt_field *field,
312c056a
PP
516 uint64_t *tag)
517{
cb6f1f7d
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
50842bdc
PP
529struct bt_field_type_enumeration_mapping_iterator *
530bt_field_enumeration_get_mappings(struct bt_field *field)
cd95e351 531{
312c056a 532 struct bt_field_enumeration *enum_field = (void *) field;
cb6f1f7d
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;
312c056a 536
cb6f1f7d
PP
537 BT_ASSERT(field);
538 BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_ENUM);
539 BT_ASSERT(field->payload_set);
312c056a 540 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
cb6f1f7d 541 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID((struct bt_field *) field,
312c056a 542 BT_FIELD_TYPE_ID_ENUM, "Field");
cb6f1f7d 543 BT_ASSERT_PRE_FIELD_IS_SET((struct bt_field *) field,
312c056a 544 "Enumeration field");
cb6f1f7d
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;
312c056a
PP
559}
560
561BT_ASSERT_PRE_FUNC
562static inline
cb6f1f7d 563struct bt_field_type_integer *get_int_enum_int_ft(
312c056a
PP
564 struct bt_field *field)
565{
cb6f1f7d
PP
566 struct bt_field_integer *int_field = (void *) field;
567 struct bt_field_type_integer *int_ft = NULL;
312c056a
PP
568
569 if (int_field->common.type->id == BT_FIELD_TYPE_ID_INTEGER) {
cb6f1f7d 570 int_ft = (void *) int_field->common.type;
312c056a 571 } else if (int_field->common.type->id == BT_FIELD_TYPE_ID_ENUM) {
cb6f1f7d
PP
572 struct bt_field_type_enumeration *enum_ft =
573 (void *) int_field->common.type;
312c056a 574 int_ft = enum_ft->container_ft;
cb6f1f7d
PP
575 } else {
576 abort();
312c056a
PP
577 }
578
579 BT_ASSERT(int_ft);
580 return int_ft;
cd95e351
JG
581}
582
3dca2276 583int bt_field_integer_signed_get_value(struct bt_field *field, int64_t *value)
cd95e351 584{
cb6f1f7d 585 struct bt_field_integer *integer = (void *) field;
312c056a
PP
586
587 BT_ASSERT_PRE_NON_NULL(field, "Integer/enumeration field");
588 BT_ASSERT_PRE_NON_NULL(value, "Value");
cb6f1f7d 589 BT_ASSERT_PRE_FIELD_IS_SET(field,
312c056a 590 "Integer/enumeration field");
cb6f1f7d
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)),
312c056a
PP
594 "Field's type is unsigned: %!+f", field);
595 *value = integer->payload.signd;
596 return 0;
cd95e351
JG
597}
598
312c056a 599int bt_field_integer_signed_set_value(struct bt_field *field, int64_t value)
273b65be 600{
312c056a 601 int ret = 0;
cb6f1f7d 602 struct bt_field_integer *integer = (void *) field;
312c056a
PP
603
604 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
cb6f1f7d
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)),
312c056a
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
312c056a 619int bt_field_integer_unsigned_get_value(struct bt_field *field, uint64_t *value)
cd95e351 620{
cb6f1f7d 621 struct bt_field_integer *integer = (void *) field;
312c056a
PP
622
623 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
624 BT_ASSERT_PRE_NON_NULL(value, "Value");
cb6f1f7d
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)),
312c056a
PP
629 "Field's type is signed: %!+f", field);
630 *value = integer->payload.unsignd;
631 return 0;
cd95e351
JG
632}
633
312c056a
PP
634int bt_field_integer_unsigned_set_value(struct bt_field *field,
635 uint64_t value)
273b65be 636{
cb6f1f7d 637 struct bt_field_integer *integer = (void *) field;
312c056a
PP
638
639 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
cb6f1f7d
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)),
312c056a
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;
f6ccaed9
PP
652}
653
3dca2276
PP
654int bt_field_floating_point_get_value(struct bt_field *field,
655 double *value)
f6ccaed9 656{
cb6f1f7d
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
3dca2276
PP
668int bt_field_floating_point_set_value(struct bt_field *field,
669 double value)
cd95e351 670{
cb6f1f7d
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;
f6ccaed9 680}
fc25abce 681
3dca2276 682const char *bt_field_string_get_value(struct bt_field *field)
f6ccaed9 683{
cb6f1f7d
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
3dca2276 693int bt_field_string_set_value(struct bt_field *field, const char *value)
273b65be 694{
cb6f1f7d
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
3dca2276 705int bt_field_string_append(struct bt_field *field, const char *value)
cd95e351 706{
cb6f1f7d
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
3dca2276
PP
712int bt_field_string_append_len(struct bt_field *field,
713 const char *value, unsigned int length)
273b65be 714{
cb6f1f7d
PP
715 struct bt_field_string *string_field = (void *) field;
716 char *data;
717 size_t new_size;
273b65be 718
cb6f1f7d
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");
312c056a 724
cb6f1f7d
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
cb6f1f7d
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
cb6f1f7d
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}
3dca2276 743
cb6f1f7d
PP
744int 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
757static inline
758void 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
312c056a
PP
765static
766void bt_field_integer_destroy(struct bt_field *field)
3dca2276 767{
cb6f1f7d 768 BT_ASSERT(field);
312c056a 769 BT_LOGD("Destroying integer field object: addr=%p", field);
cb6f1f7d 770 bt_field_finalize(field);
312c056a 771 g_free(field);
3dca2276 772}
f98c6554 773
312c056a
PP
774static
775void bt_field_floating_point_destroy(struct bt_field *field)
3dca2276 776{
cb6f1f7d 777 BT_ASSERT(field);
312c056a 778 BT_LOGD("Destroying floating point field object: addr=%p", field);
cb6f1f7d 779 bt_field_finalize(field);
312c056a 780 g_free(field);
f98c6554
PP
781}
782
312c056a
PP
783static
784void bt_field_enumeration_destroy(struct bt_field *field)
273b65be 785{
312c056a 786 BT_LOGD("Destroying enumeration field object: addr=%p", field);
cb6f1f7d 787 bt_field_finalize((void *) field);
312c056a 788 g_free(field);
3dca2276 789}
273b65be 790
312c056a
PP
791static
792void bt_field_structure_destroy_recursive(struct bt_field *field)
3dca2276 793{
cb6f1f7d
PP
794 struct bt_field_structure *structure = (void *) field;
795
796 BT_ASSERT(field);
312c056a 797 BT_LOGD("Destroying structure field object: addr=%p", field);
cb6f1f7d
PP
798 bt_field_finalize(field);
799
800 if (structure->fields) {
801 g_ptr_array_free(structure->fields, TRUE);
802 }
803
312c056a 804 g_free(field);
273b65be
JG
805}
806
312c056a
PP
807static
808void bt_field_variant_destroy_recursive(struct bt_field *field)
3dca2276 809{
cb6f1f7d
PP
810 struct bt_field_variant *variant = (void *) field;
811
812 BT_ASSERT(field);
312c056a 813 BT_LOGD("Destroying variant field object: addr=%p", field);
cb6f1f7d
PP
814 bt_field_finalize(field);
815
816 if (variant->fields) {
817 g_ptr_array_free(variant->fields, TRUE);
818 }
819
312c056a 820 g_free(field);
f6ccaed9 821}
12c8a1a3 822
312c056a
PP
823static
824void bt_field_array_destroy_recursive(struct bt_field *field)
f6ccaed9 825{
cb6f1f7d
PP
826 struct bt_field_array *array = (void *) field;
827
828 BT_ASSERT(field);
312c056a 829 BT_LOGD("Destroying array field object: addr=%p", field);
cb6f1f7d
PP
830 bt_field_finalize(field);
831
832 if (array->elements) {
833 g_ptr_array_free(array->elements, TRUE);
834 }
835
312c056a 836 g_free(field);
12c8a1a3
JG
837}
838
312c056a
PP
839static
840void bt_field_sequence_destroy_recursive(struct bt_field *field)
273b65be 841{
cb6f1f7d
PP
842 struct bt_field_sequence *sequence = (void *) field;
843
844 BT_ASSERT(field);
312c056a 845 BT_LOGD("Destroying sequence field object: addr=%p", field);
cb6f1f7d
PP
846 bt_field_finalize(field);
847
848 if (sequence->elements) {
849 g_ptr_array_free(sequence->elements, TRUE);
850 }
312c056a 851 g_free(field);
273b65be
JG
852}
853
312c056a
PP
854static
855void bt_field_string_destroy(struct bt_field *field)
76f869ab 856{
cb6f1f7d
PP
857 struct bt_field_string *string = (void *) field;
858
312c056a 859 BT_LOGD("Destroying string field object: addr=%p", field);
cb6f1f7d
PP
860 BT_ASSERT(field);
861 bt_field_finalize(field);
862
863 if (string->buf) {
864 g_array_free(string->buf, TRUE);
865 }
866
312c056a 867 g_free(field);
76f869ab
JG
868}
869
3dca2276 870BT_HIDDEN
312c056a 871void bt_field_destroy_recursive(struct bt_field *field)
87d43dc1 872{
312c056a
PP
873 if (!field) {
874 return;
87d43dc1 875 }
f6ccaed9 876
cb6f1f7d
PP
877 BT_ASSERT(bt_field_type_has_known_id((void *) field->type));
878 field_destroy_funcs[field->type->id](field);
879}
880
881static inline
882void 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 893static
50842bdc 894struct bt_field *bt_field_integer_create(struct bt_field_type *type)
273b65be 895{
cb6f1f7d
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) {
cb6f1f7d
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",
3dca2276 905 integer, type);
fc25abce
PP
906 } else {
907 BT_LOGE_STR("Failed to allocate one integer field.");
908 }
909
3dca2276 910 return (void *) integer;
273b65be
JG
911}
912
913static
3dca2276 914struct bt_field *bt_field_enumeration_create(struct bt_field_type *type)
273b65be 915{
312c056a
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) {
cb6f1f7d
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",
3dca2276 925 enumeration, type);
fc25abce
PP
926 } else {
927 BT_LOGE_STR("Failed to allocate one enumeration field.");
928 }
929
3dca2276 930 return (void *) enumeration;
273b65be
JG
931}
932
933static
3dca2276 934struct bt_field *bt_field_floating_point_create(struct bt_field_type *type)
273b65be 935{
cb6f1f7d 936 struct bt_field_floating_point *floating_point;
273b65be 937
fc25abce 938 BT_LOGD("Creating floating point number field object: ft-addr=%p", type);
cb6f1f7d 939 floating_point = g_new0(struct bt_field_floating_point, 1);
fc25abce
PP
940
941 if (floating_point) {
cb6f1f7d
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",
3dca2276 945 floating_point, type);
fc25abce
PP
946 } else {
947 BT_LOGE_STR("Failed to allocate one floating point number field.");
948 }
949
3dca2276 950 return (void *) floating_point;
273b65be
JG
951}
952
cb6f1f7d
PP
953static inline
954int 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,
312c056a 958 GDestroyNotify field_release_func)
3dca2276
PP
959{
960 int ret = 0;
cb6f1f7d
PP
961 struct bt_field_type_structure *structure_type = (void *) type;
962 struct bt_field_structure *structure = (void *) field;
c58b9c62 963 size_t i;
273b65be 964
cb6f1f7d
PP
965 BT_LOGD("Initializing structure field object: ft-addr=%p", type);
966 bt_field_initialize(field, type, methods);
312c056a 967 structure->fields = g_ptr_array_new_with_free_func(field_release_func);
3dca2276 968 g_ptr_array_set_size(structure->fields, structure_type->fields->len);
c58b9c62 969
312c056a 970 /* Create all fields contained in the structure field. */
c58b9c62 971 for (i = 0; i < structure_type->fields->len; i++) {
cb6f1f7d
PP
972 struct bt_field *field;
973 struct bt_field_type_structure_field *struct_field =
974 BT_FIELD_TYPE_STRUCTURE_FIELD_AT_INDEX(
312c056a 975 structure_type, i);
3dca2276 976 field = field_create_func(struct_field->type);
c58b9c62
JG
977 if (!field) {
978 BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu",
3dca2276
PP
979 g_quark_to_string(struct_field->name), i);
980 ret = -1;
c58b9c62
JG
981 goto end;
982 }
983
984 g_ptr_array_index(structure->fields, i) = field;
985 }
986
cb6f1f7d 987 BT_LOGD("Initialized structure field object: addr=%p, ft-addr=%p",
3dca2276
PP
988 field, type);
989
273b65be 990end:
c58b9c62 991 return ret;
273b65be
JG
992}
993
3dca2276
PP
994static
995struct bt_field *bt_field_structure_create(struct bt_field_type *type)
996{
cb6f1f7d
PP
997 struct bt_field_structure *structure = g_new0(
998 struct bt_field_structure, 1);
3dca2276
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
cb6f1f7d
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,
312c056a 1011 (GDestroyNotify) bt_field_destroy_recursive);
3dca2276
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
1020end:
1021 return (void *) structure;
1022}
1023
cb6f1f7d
PP
1024static inline
1025int 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,
312c056a
PP
1029 GDestroyNotify field_release_func)
1030{
1031 int ret = 0;
cb6f1f7d
PP
1032 struct bt_field_type_variant *variant_type = (void *) type;
1033 struct bt_field_variant *variant = (void *) field;
312c056a
PP
1034 size_t i;
1035
cb6f1f7d
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);
312c056a 1039 if (ret) {
cb6f1f7d 1040 BT_LOGE("Cannot update variant field type choices: "
312c056a
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++) {
cb6f1f7d
PP
1050 struct bt_field *field;
1051 struct bt_field_type_variant_choice *var_choice =
1052 BT_FIELD_TYPE_VARIANT_CHOICE_AT_INDEX(
312c056a
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
cb6f1f7d 1066 BT_LOGD("Initialized variant field object: addr=%p, ft-addr=%p",
312c056a
PP
1067 field, type);
1068
1069end:
1070 return ret;
1071}
1072
cb6f1f7d
PP
1073static inline
1074int bt_field_string_initialize(struct bt_field *field,
1075 struct bt_field_type *type,
1076 struct bt_field_methods *methods)
4d4b475d
PP
1077{
1078 int ret = 0;
cb6f1f7d 1079 struct bt_field_string *string = (void *) field;
4d4b475d 1080
cb6f1f7d
PP
1081 BT_LOGD("Initializing string field object: ft-addr=%p", type);
1082 bt_field_initialize(field, type, methods);
4d4b475d
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';
cb6f1f7d 1090 BT_LOGD("Initialized string field object: addr=%p, ft-addr=%p",
4d4b475d
PP
1091 field, type);
1092
1093end:
1094 return ret;
1095}
1096
273b65be 1097static
50842bdc 1098struct bt_field *bt_field_variant_create(struct bt_field_type *type)
273b65be 1099{
cb6f1f7d
PP
1100 struct bt_field_variant *variant = g_new0(
1101 struct bt_field_variant, 1);
312c056a 1102 int iret;
fc25abce
PP
1103
1104 BT_LOGD("Creating variant field object: ft-addr=%p", type);
1105
312c056a 1106 if (!variant) {
fc25abce 1107 BT_LOGE_STR("Failed to allocate one variant field.");
312c056a
PP
1108 goto end;
1109 }
1110
cb6f1f7d
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,
312c056a
PP
1114 (GDestroyNotify) bt_field_destroy_recursive);
1115 if (iret) {
1116 BT_PUT(variant);
1117 goto end;
fc25abce
PP
1118 }
1119
312c056a
PP
1120 BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
1121 variant, type);
1122
1123end:
3dca2276 1124 return (void *) variant;
273b65be
JG
1125}
1126
cb6f1f7d
PP
1127static inline
1128int 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,
312c056a 1132 GDestroyNotify field_destroy_func)
273b65be 1133{
cb6f1f7d
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;
3dca2276 1137 int ret = 0;
312c056a 1138 uint64_t i;
273b65be 1139
cb6f1f7d 1140 BT_LOGD("Initializing array field object: ft-addr=%p", type);
f6ccaed9 1141 BT_ASSERT(type);
cb6f1f7d 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) {
3dca2276
PP
1146 ret = -1;
1147 goto end;
273b65be
JG
1148 }
1149
312c056a 1150 g_ptr_array_set_free_func(array->elements, field_destroy_func);
273b65be 1151 g_ptr_array_set_size(array->elements, array_length);
312c056a
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
cb6f1f7d 1162 BT_LOGD("Initialized array field object: addr=%p, ft-addr=%p",
3dca2276 1163 field, type);
273b65be 1164
3dca2276
PP
1165end:
1166 return ret;
273b65be
JG
1167}
1168
1169static
3dca2276 1170struct bt_field *bt_field_array_create(struct bt_field_type *type)
273b65be 1171{
cb6f1f7d
PP
1172 struct bt_field_array *array =
1173 g_new0(struct bt_field_array, 1);
3dca2276 1174 int ret;
fc25abce 1175
3dca2276
PP
1176 BT_LOGD("Creating array field object: ft-addr=%p", type);
1177 BT_ASSERT(type);
fc25abce 1178
3dca2276
PP
1179 if (!array) {
1180 BT_LOGE_STR("Failed to allocate one array field.");
1181 goto end;
fc25abce
PP
1182 }
1183
cb6f1f7d
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,
312c056a 1187 (GDestroyNotify) bt_field_destroy_recursive);
3dca2276
PP
1188 if (ret) {
1189 BT_PUT(array);
1190 goto end;
1191 }
273b65be 1192
3dca2276
PP
1193 BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
1194 array, type);
273b65be 1195
3dca2276
PP
1196end:
1197 return (void *) array;
273b65be
JG
1198}
1199
cb6f1f7d
PP
1200static inline
1201int bt_field_sequence_initialize(struct bt_field *field,
1202 struct bt_field_type *type,
1203 struct bt_field_methods *methods,
312c056a
PP
1204 GDestroyNotify field_destroy_func)
1205{
cb6f1f7d 1206 struct bt_field_sequence *sequence = (void *) field;
312c056a
PP
1207 int ret = 0;
1208
cb6f1f7d 1209 BT_LOGD("Initializing sequence field object: ft-addr=%p", type);
312c056a 1210 BT_ASSERT(type);
cb6f1f7d 1211 bt_field_initialize(field, type, methods);
312c056a
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);
cb6f1f7d 1219 BT_LOGD("Initialized sequence field object: addr=%p, ft-addr=%p",
312c056a
PP
1220 field, type);
1221
1222end:
1223 return ret;
1224}
1225
273b65be 1226static
3dca2276 1227struct bt_field *bt_field_sequence_create(struct bt_field_type *type)
273b65be 1228{
cb6f1f7d
PP
1229 struct bt_field_sequence *sequence =
1230 g_new0(struct bt_field_sequence, 1);
312c056a 1231 int ret;
273b65be 1232
3dca2276 1233 BT_LOGD("Creating sequence field object: ft-addr=%p", type);
312c056a 1234 BT_ASSERT(type);
273b65be 1235
312c056a 1236 if (!sequence) {
3dca2276 1237 BT_LOGE_STR("Failed to allocate one sequence field.");
312c056a 1238 goto end;
4fef87ab 1239 }
3dca2276 1240
cb6f1f7d
PP
1241 ret = bt_field_sequence_initialize((void *) sequence,
1242 (void *) type, &bt_field_sequence_methods,
312c056a
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
1252end:
3dca2276 1253 return (void *) sequence;
273b65be
JG
1254}
1255
1256static
3dca2276 1257struct bt_field *bt_field_string_create(struct bt_field_type *type)
273b65be 1258{
cb6f1f7d
PP
1259 struct bt_field_string *string = g_new0(
1260 struct bt_field_string, 1);
fc25abce 1261
3dca2276
PP
1262 BT_LOGD("Creating string field object: ft-addr=%p", type);
1263
1264 if (string) {
cb6f1f7d
PP
1265 bt_field_string_initialize((void *) string,
1266 (void *) type, &bt_field_string_methods);
3dca2276
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 }
3dca2276
PP
1272
1273 return (void *) string;
273b65be
JG
1274}
1275
cb6f1f7d
PP
1276static
1277int bt_field_generic_validate(struct bt_field *field)
273b65be 1278{
da2f6971 1279 return (field && field->payload_set) ? 0 : -1;
273b65be
JG
1280}
1281
cb6f1f7d
PP
1282static
1283int bt_field_structure_validate_recursive(struct bt_field *field)
273b65be 1284{
fc25abce 1285 int64_t i;
273b65be 1286 int ret = 0;
cb6f1f7d 1287 struct bt_field_structure *structure = (void *) field;
273b65be 1288
f6ccaed9 1289 BT_ASSERT(field);
f6ccaed9 1290
273b65be 1291 for (i = 0; i < structure->fields->len; i++) {
cb6f1f7d 1292 ret = bt_field_validate_recursive(
f6ccaed9 1293 (void *) structure->fields->pdata[i]);
fc25abce 1294
273b65be 1295 if (ret) {
fc25abce 1296 int this_ret;
6ce12048 1297 const char *name;
6ce12048 1298
cb6f1f7d 1299 this_ret = bt_field_type_structure_borrow_field_by_index(
f6ccaed9
PP
1300 field->type, &name, NULL, i);
1301 BT_ASSERT(this_ret == 0);
1302 BT_ASSERT_PRE_MSG("Invalid structure field's field: "
cb6f1f7d
PP
1303 "%![struct-field-]+f, field-name=\"%s\", "
1304 "index=%" PRId64 ", %![field-]+f",
f6ccaed9 1305 field, name, i, structure->fields->pdata[i]);
273b65be
JG
1306 goto end;
1307 }
1308 }
f6ccaed9 1309
273b65be
JG
1310end:
1311 return ret;
1312}
1313
cb6f1f7d
PP
1314static
1315int bt_field_variant_validate_recursive(struct bt_field *field)
273b65be
JG
1316{
1317 int ret = 0;
cb6f1f7d 1318 struct bt_field_variant *variant = (void *) field;
273b65be 1319
f6ccaed9 1320 BT_ASSERT(field);
312c056a
PP
1321
1322 if (!variant->current_field) {
1323 ret = -1;
1324 goto end;
fc25abce 1325 }
f6ccaed9 1326
cb6f1f7d 1327 ret = bt_field_validate_recursive(variant->current_field);
312c056a
PP
1328
1329end:
273b65be
JG
1330 return ret;
1331}
1332
cb6f1f7d
PP
1333static
1334int bt_field_array_validate_recursive(struct bt_field *field)
273b65be 1335{
fc25abce 1336 int64_t i;
273b65be 1337 int ret = 0;
cb6f1f7d 1338 struct bt_field_array *array = (void *) field;
273b65be 1339
f6ccaed9 1340 BT_ASSERT(field);
3dca2276 1341
273b65be 1342 for (i = 0; i < array->elements->len; i++) {
cb6f1f7d 1343 ret = bt_field_validate_recursive((void *) array->elements->pdata[i]);
273b65be 1344 if (ret) {
f6ccaed9 1345 BT_ASSERT_PRE_MSG("Invalid array field's element field: "
cb6f1f7d
PP
1346 "%![array-field-]+f, " PRId64 ", "
1347 "%![elem-field-]+f",
f6ccaed9 1348 field, i, array->elements->pdata[i]);
273b65be
JG
1349 goto end;
1350 }
1351 }
f6ccaed9 1352
273b65be
JG
1353end:
1354 return ret;
1355}
1356
cb6f1f7d
PP
1357static
1358int bt_field_sequence_validate_recursive(struct bt_field *field)
273b65be
JG
1359{
1360 size_t i;
1361 int ret = 0;
cb6f1f7d 1362 struct bt_field_sequence *sequence = (void *) field;
273b65be 1363
f6ccaed9 1364 BT_ASSERT(field);
3dca2276 1365
273b65be 1366 for (i = 0; i < sequence->elements->len; i++) {
cb6f1f7d 1367 ret = bt_field_validate_recursive(
f6ccaed9 1368 (void *) sequence->elements->pdata[i]);
273b65be 1369 if (ret) {
f6ccaed9 1370 BT_ASSERT_PRE_MSG("Invalid sequence field's element field: "
cb6f1f7d
PP
1371 "%![seq-field-]+f, " PRId64 ", "
1372 "%![elem-field-]+f",
f6ccaed9 1373 field, i, sequence->elements->pdata[i]);
273b65be
JG
1374 goto end;
1375 }
1376 }
1377end:
1378 return ret;
1379}
1380
cb6f1f7d
PP
1381static
1382void bt_field_generic_reset(struct bt_field *field)
12c8a1a3 1383{
f6ccaed9 1384 BT_ASSERT(field);
d990a4fb 1385 field->payload_set = false;
12c8a1a3
JG
1386}
1387
cb6f1f7d
PP
1388static
1389void bt_field_structure_reset_recursive(struct bt_field *field)
12c8a1a3 1390{
fc25abce 1391 int64_t i;
cb6f1f7d 1392 struct bt_field_structure *structure = (void *) field;
12c8a1a3 1393
f6ccaed9 1394 BT_ASSERT(field);
f6ccaed9 1395
12c8a1a3 1396 for (i = 0; i < structure->fields->len; i++) {
cb6f1f7d 1397 struct bt_field *member = structure->fields->pdata[i];
12c8a1a3
JG
1398
1399 if (!member) {
1400 /*
f6ccaed9
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
cb6f1f7d 1408 bt_field_reset_recursive(member);
12c8a1a3 1409 }
12c8a1a3
JG
1410}
1411
cb6f1f7d
PP
1412static
1413void bt_field_variant_reset_recursive(struct bt_field *field)
12c8a1a3 1414{
cb6f1f7d 1415 struct bt_field_variant *variant = (void *) field;
12c8a1a3 1416
f6ccaed9 1417 BT_ASSERT(field);
312c056a 1418 variant->current_field = NULL;
12c8a1a3
JG
1419}
1420
cb6f1f7d
PP
1421static
1422void bt_field_array_reset_recursive(struct bt_field *field)
12c8a1a3
JG
1423{
1424 size_t i;
cb6f1f7d 1425 struct bt_field_array *array = (void *) field;
12c8a1a3 1426
f6ccaed9 1427 BT_ASSERT(field);
f6ccaed9 1428
12c8a1a3 1429 for (i = 0; i < array->elements->len; i++) {
cb6f1f7d 1430 struct bt_field *member = array->elements->pdata[i];
12c8a1a3
JG
1431
1432 if (!member) {
1433 /*
f6ccaed9
PP
1434 * Array elements are lazily initialized; skip
1435 * if this member has not been allocated yet.
12c8a1a3
JG
1436 */
1437 continue;
1438 }
1439
cb6f1f7d 1440 bt_field_reset_recursive(member);
12c8a1a3 1441 }
12c8a1a3
JG
1442}
1443
cb6f1f7d
PP
1444static
1445void bt_field_sequence_reset_recursive(struct bt_field *field)
12c8a1a3 1446{
cb6f1f7d 1447 struct bt_field_sequence *sequence = (void *) field;
312c056a 1448 uint64_t i;
12c8a1a3 1449
f6ccaed9 1450 BT_ASSERT(field);
f6ccaed9 1451
312c056a
PP
1452 for (i = 0; i < sequence->elements->len; i++) {
1453 if (sequence->elements->pdata[i]) {
cb6f1f7d 1454 bt_field_reset_recursive(
312c056a
PP
1455 sequence->elements->pdata[i]);
1456 }
12c8a1a3 1457 }
f6ccaed9 1458
312c056a 1459 sequence->length = 0;
12c8a1a3
JG
1460}
1461
cb6f1f7d
PP
1462static
1463void bt_field_generic_set_is_frozen(struct bt_field *field,
312c056a 1464 bool is_frozen)
918be005 1465{
312c056a 1466 field->frozen = is_frozen;
918be005
PP
1467}
1468
cb6f1f7d
PP
1469static
1470void bt_field_structure_set_is_frozen_recursive(
1471 struct bt_field *field, bool is_frozen)
918be005 1472{
312c056a 1473 uint64_t i;
cb6f1f7d 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++) {
cb6f1f7d 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,
312c056a 1483 struct_field, i);
cb6f1f7d 1484 bt_field_set_is_frozen_recursive(struct_field,
312c056a 1485 is_frozen);
918be005
PP
1486 }
1487
cb6f1f7d 1488 bt_field_generic_set_is_frozen(field, is_frozen);
918be005
PP
1489}
1490
cb6f1f7d
PP
1491static
1492void bt_field_variant_set_is_frozen_recursive(
1493 struct bt_field *field, bool is_frozen)
918be005 1494{
312c056a 1495 uint64_t i;
cb6f1f7d 1496 struct bt_field_variant *variant_field = (void *) field;
918be005 1497
fc25abce 1498 BT_LOGD("Freezing variant field object: addr=%p", field);
312c056a
PP
1499
1500 for (i = 0; i < variant_field->fields->len; i++) {
cb6f1f7d 1501 struct bt_field *var_field =
312c056a
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);
cb6f1f7d 1506 bt_field_set_is_frozen_recursive(var_field, is_frozen);
312c056a
PP
1507 }
1508
cb6f1f7d 1509 bt_field_generic_set_is_frozen(field, is_frozen);
918be005
PP
1510}
1511
cb6f1f7d
PP
1512static
1513void bt_field_array_set_is_frozen_recursive(
1514 struct bt_field *field, bool is_frozen)
918be005 1515{
fc25abce 1516 int64_t i;
cb6f1f7d 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++) {
cb6f1f7d 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);
cb6f1f7d 1528 bt_field_set_is_frozen_recursive(elem_field, is_frozen);
918be005
PP
1529 }
1530
cb6f1f7d 1531 bt_field_generic_set_is_frozen(field, is_frozen);
918be005
PP
1532}
1533
cb6f1f7d
PP
1534static
1535void bt_field_sequence_set_is_frozen_recursive(
1536 struct bt_field *field, bool is_frozen)
918be005 1537{
fc25abce 1538 int64_t i;
cb6f1f7d 1539 struct bt_field_sequence *sequence_field = (void *) field;
918be005 1540
fc25abce 1541 BT_LOGD("Freezing sequence field object: addr=%p", field);
918be005 1542
312c056a 1543 for (i = 0; i < sequence_field->length; i++) {
cb6f1f7d 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);
cb6f1f7d 1550 bt_field_set_is_frozen_recursive(elem_field, is_frozen);
918be005
PP
1551 }
1552
cb6f1f7d 1553 bt_field_generic_set_is_frozen(field, is_frozen);
918be005
PP
1554}
1555
1556BT_HIDDEN
cb6f1f7d 1557void _bt_field_set_is_frozen_recursive(struct bt_field *field,
312c056a 1558 bool is_frozen)
918be005
PP
1559{
1560 if (!field) {
1561 goto end;
1562 }
1563
312c056a
PP
1564 BT_LOGD("Setting field object's frozen state: addr=%p, is-frozen=%d",
1565 field, is_frozen);
cb6f1f7d 1566 BT_ASSERT(bt_field_type_has_known_id(field->type));
312c056a
PP
1567 BT_ASSERT(field->methods->set_is_frozen);
1568 field->methods->set_is_frozen(field, is_frozen);
3dca2276 1569
918be005
PP
1570end:
1571 return;
1572}
76f869ab 1573
cb6f1f7d
PP
1574static
1575bt_bool bt_field_generic_is_set(struct bt_field *field)
76f869ab
JG
1576{
1577 return field && field->payload_set;
1578}
1579
cb6f1f7d
PP
1580static
1581bt_bool bt_field_structure_is_set_recursive(
1582 struct bt_field *field)
76f869ab 1583{
d4bf905a 1584 bt_bool is_set = BT_FALSE;
76f869ab 1585 size_t i;
cb6f1f7d 1586 struct bt_field_structure *structure = (void *) field;
76f869ab 1587
f6ccaed9 1588 BT_ASSERT(field);
3dca2276 1589
76f869ab 1590 for (i = 0; i < structure->fields->len; i++) {
cb6f1f7d 1591 is_set = bt_field_is_set_recursive(
f1367c62 1592 structure->fields->pdata[i]);
d4bf905a 1593 if (!is_set) {
76f869ab
JG
1594 goto end;
1595 }
1596 }
3dca2276 1597
76f869ab 1598end:
d4bf905a 1599 return is_set;
76f869ab
JG
1600}
1601
cb6f1f7d
PP
1602static
1603bt_bool bt_field_variant_is_set_recursive(struct bt_field *field)
76f869ab 1604{
cb6f1f7d 1605 struct bt_field_variant *variant = (void *) field;
312c056a 1606 bt_bool is_set = BT_FALSE;
76f869ab 1607
f6ccaed9 1608 BT_ASSERT(field);
312c056a
PP
1609
1610 if (variant->current_field) {
cb6f1f7d 1611 is_set = bt_field_is_set_recursive(
312c056a
PP
1612 variant->current_field);
1613 }
1614
1615 return is_set;
76f869ab
JG
1616}
1617
cb6f1f7d
PP
1618static
1619bt_bool bt_field_array_is_set_recursive(struct bt_field *field)
76f869ab
JG
1620{
1621 size_t i;
d4bf905a 1622 bt_bool is_set = BT_FALSE;
cb6f1f7d 1623 struct bt_field_array *array = (void *) field;
76f869ab 1624
f6ccaed9 1625 BT_ASSERT(field);
3dca2276 1626
76f869ab 1627 for (i = 0; i < array->elements->len; i++) {
cb6f1f7d 1628 is_set = bt_field_is_set_recursive(array->elements->pdata[i]);
d4bf905a 1629 if (!is_set) {
76f869ab
JG
1630 goto end;
1631 }
1632 }
3dca2276 1633
76f869ab 1634end:
d4bf905a 1635 return is_set;
76f869ab
JG
1636}
1637
cb6f1f7d
PP
1638static
1639bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field)
76f869ab
JG
1640{
1641 size_t i;
d4bf905a 1642 bt_bool is_set = BT_FALSE;
cb6f1f7d 1643 struct bt_field_sequence *sequence = (void *) field;
76f869ab 1644
f6ccaed9 1645 BT_ASSERT(field);
3dca2276 1646
6ead1648
JG
1647 if (!sequence->elements) {
1648 goto end;
1649 }
1650
76f869ab 1651 for (i = 0; i < sequence->elements->len; i++) {
cb6f1f7d 1652 is_set = bt_field_is_set_recursive(
3dca2276 1653 sequence->elements->pdata[i]);
d4bf905a 1654 if (!is_set) {
76f869ab
JG
1655 goto end;
1656 }
1657 }
3dca2276 1658
76f869ab 1659end:
d4bf905a 1660 return is_set;
76f869ab 1661}
This page took 0.140551 seconds and 4 git commands to generate.