Add internal BT_ASSERT() and BT_ASSERT_PRE() helpers
[babeltrace.git] / lib / ctf-ir / fields.c
1 /*
2 * fields.c
3 *
4 * Babeltrace CTF IR - Event Fields
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
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
29 #define BT_LOG_TAG "FIELDS"
30 #include <babeltrace/lib-logging-internal.h>
31
32 #include <babeltrace/ctf-ir/fields-internal.h>
33 #include <babeltrace/ctf-ir/field-types-internal.h>
34 #include <babeltrace/ctf-writer/serialize-internal.h>
35 #include <babeltrace/object-internal.h>
36 #include <babeltrace/ref.h>
37 #include <babeltrace/compiler-internal.h>
38 #include <babeltrace/compat/fcntl-internal.h>
39 #include <babeltrace/align-internal.h>
40 #include <inttypes.h>
41
42 static
43 struct bt_field *bt_field_integer_create(struct bt_field_type *);
44 static
45 struct bt_field *bt_field_enumeration_create(
46 struct bt_field_type *);
47 static
48 struct bt_field *bt_field_floating_point_create(
49 struct bt_field_type *);
50 static
51 struct bt_field *bt_field_structure_create(
52 struct bt_field_type *);
53 static
54 struct bt_field *bt_field_variant_create(
55 struct bt_field_type *);
56 static
57 struct bt_field *bt_field_array_create(
58 struct bt_field_type *);
59 static
60 struct bt_field *bt_field_sequence_create(
61 struct bt_field_type *);
62 static
63 struct bt_field *bt_field_string_create(struct bt_field_type *);
64
65 static
66 void bt_field_destroy(struct bt_object *);
67 static
68 void bt_field_integer_destroy(struct bt_field *);
69 static
70 void bt_field_enumeration_destroy(struct bt_field *);
71 static
72 void bt_field_floating_point_destroy(struct bt_field *);
73 static
74 void bt_field_structure_destroy(struct bt_field *);
75 static
76 void bt_field_variant_destroy(struct bt_field *);
77 static
78 void bt_field_array_destroy(struct bt_field *);
79 static
80 void bt_field_sequence_destroy(struct bt_field *);
81 static
82 void bt_field_string_destroy(struct bt_field *);
83
84 static
85 int bt_field_generic_validate(struct bt_field *);
86 static
87 int bt_field_structure_validate(struct bt_field *);
88 static
89 int bt_field_variant_validate(struct bt_field *);
90 static
91 int bt_field_enumeration_validate(struct bt_field *);
92 static
93 int bt_field_array_validate(struct bt_field *);
94 static
95 int bt_field_sequence_validate(struct bt_field *);
96
97 static
98 int bt_field_generic_reset(struct bt_field *);
99 static
100 int bt_field_structure_reset(struct bt_field *);
101 static
102 int bt_field_variant_reset(struct bt_field *);
103 static
104 int bt_field_enumeration_reset(struct bt_field *);
105 static
106 int bt_field_array_reset(struct bt_field *);
107 static
108 int bt_field_sequence_reset(struct bt_field *);
109 static
110 int bt_field_string_reset(struct bt_field *);
111
112 static
113 int bt_field_integer_serialize(struct bt_field *,
114 struct bt_stream_pos *, enum bt_byte_order);
115 static
116 int bt_field_enumeration_serialize(struct bt_field *,
117 struct bt_stream_pos *, enum bt_byte_order);
118 static
119 int bt_field_floating_point_serialize(struct bt_field *,
120 struct bt_stream_pos *, enum bt_byte_order);
121 static
122 int bt_field_structure_serialize(struct bt_field *,
123 struct bt_stream_pos *, enum bt_byte_order);
124 static
125 int bt_field_variant_serialize(struct bt_field *,
126 struct bt_stream_pos *, enum bt_byte_order);
127 static
128 int bt_field_array_serialize(struct bt_field *,
129 struct bt_stream_pos *, enum bt_byte_order);
130 static
131 int bt_field_sequence_serialize(struct bt_field *,
132 struct bt_stream_pos *, enum bt_byte_order);
133 static
134 int bt_field_string_serialize(struct bt_field *,
135 struct bt_stream_pos *, enum bt_byte_order);
136
137 static
138 int bt_field_integer_copy(struct bt_field *, struct bt_field *);
139 static
140 int bt_field_enumeration_copy(struct bt_field *, struct bt_field *);
141 static
142 int bt_field_floating_point_copy(struct bt_field *,
143 struct bt_field *);
144 static
145 int bt_field_structure_copy(struct bt_field *, struct bt_field *);
146 static
147 int bt_field_variant_copy(struct bt_field *, struct bt_field *);
148 static
149 int bt_field_array_copy(struct bt_field *, struct bt_field *);
150 static
151 int bt_field_sequence_copy(struct bt_field *, struct bt_field *);
152 static
153 int bt_field_string_copy(struct bt_field *, struct bt_field *);
154
155 static
156 void generic_field_freeze(struct bt_field *);
157 static
158 void bt_field_enumeration_freeze(struct bt_field *);
159 static
160 void bt_field_structure_freeze(struct bt_field *);
161 static
162 void bt_field_variant_freeze(struct bt_field *);
163 static
164 void bt_field_array_freeze(struct bt_field *);
165 static
166 void bt_field_sequence_freeze(struct bt_field *);
167
168 static
169 bt_bool bt_field_generic_is_set(struct bt_field *);
170 static
171 bt_bool bt_field_structure_is_set(struct bt_field *);
172 static
173 bt_bool bt_field_variant_is_set(struct bt_field *);
174 static
175 bt_bool bt_field_enumeration_is_set(struct bt_field *);
176 static
177 bt_bool bt_field_array_is_set(struct bt_field *);
178 static
179 bt_bool bt_field_sequence_is_set(struct bt_field *);
180
181 static
182 int increase_packet_size(struct bt_stream_pos *pos);
183
184 static
185 struct bt_field *(* const field_create_funcs[])(
186 struct bt_field_type *) = {
187 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create,
188 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create,
189 [BT_FIELD_TYPE_ID_FLOAT] =
190 bt_field_floating_point_create,
191 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create,
192 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create,
193 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create,
194 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create,
195 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create,
196 };
197
198 static
199 void (* const field_destroy_funcs[])(struct bt_field *) = {
200 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy,
201 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy,
202 [BT_FIELD_TYPE_ID_FLOAT] =
203 bt_field_floating_point_destroy,
204 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy,
205 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy,
206 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy,
207 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy,
208 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy,
209 };
210
211 static
212 int (* const field_validate_funcs[])(struct bt_field *) = {
213 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_validate,
214 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_validate,
215 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_validate,
216 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_validate,
217 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_validate,
218 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_validate,
219 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_validate,
220 [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_validate,
221 };
222
223 static
224 int (* const field_reset_funcs[])(struct bt_field *) = {
225 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_reset,
226 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_reset,
227 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_reset,
228 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_reset,
229 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_reset,
230 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_reset,
231 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_reset,
232 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_reset,
233 };
234
235 static
236 int (* const field_serialize_funcs[])(struct bt_field *,
237 struct bt_stream_pos *, enum bt_byte_order) = {
238 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_serialize,
239 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_serialize,
240 [BT_FIELD_TYPE_ID_FLOAT] =
241 bt_field_floating_point_serialize,
242 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_serialize,
243 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_serialize,
244 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_serialize,
245 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_serialize,
246 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_serialize,
247 };
248
249 static
250 int (* const field_copy_funcs[])(struct bt_field *,
251 struct bt_field *) = {
252 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_copy,
253 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_copy,
254 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_copy,
255 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_copy,
256 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_copy,
257 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_copy,
258 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_copy,
259 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_copy,
260 };
261
262 static
263 void (* const field_freeze_funcs[])(struct bt_field *) = {
264 [BT_FIELD_TYPE_ID_INTEGER] = generic_field_freeze,
265 [BT_FIELD_TYPE_ID_FLOAT] = generic_field_freeze,
266 [BT_FIELD_TYPE_ID_STRING] = generic_field_freeze,
267 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_freeze,
268 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_freeze,
269 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_freeze,
270 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_freeze,
271 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_freeze,
272 };
273
274 static
275 bt_bool (* const field_is_set_funcs[])(struct bt_field *) = {
276 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_is_set,
277 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_is_set,
278 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_is_set,
279 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_is_set,
280 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_is_set,
281 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_is_set,
282 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_is_set,
283 [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_is_set,
284 };
285
286 struct bt_field *bt_field_create(struct bt_field_type *type)
287 {
288 struct bt_field *field = NULL;
289 enum bt_field_type_id type_id;
290 int ret;
291
292 if (!type) {
293 BT_LOGW_STR("Invalid parameter: field type is NULL.");
294 goto error;
295 }
296
297 type_id = bt_field_type_get_type_id(type);
298 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN ||
299 type_id >= BT_FIELD_TYPE_ID_NR) {
300 BT_LOGW("Invalid parameter: unknown field type ID: "
301 "ft-addr=%p, ft-id=%d", type, type_id);
302 goto error;
303 }
304
305 /* Field class MUST be valid */
306 ret = bt_field_type_validate(type);
307 if (ret) {
308 /* Invalid */
309 BT_LOGW("Invalid parameter: field type is invalid: "
310 "ft-addr=%p", type);
311 goto error;
312 }
313
314 field = field_create_funcs[type_id](type);
315 if (!field) {
316 goto error;
317 }
318
319 /* The type's declaration can't change after this point */
320 bt_field_type_freeze(type);
321 bt_get(type);
322 bt_object_init(field, bt_field_destroy);
323 field->type = type;
324 error:
325 return field;
326 }
327
328 /* Pre-2.0 CTF writer backward compatibility */
329 void bt_ctf_field_get(struct bt_field *field)
330 {
331 bt_get(field);
332 }
333
334 /* Pre-2.0 CTF writer backward compatibility */
335 void bt_ctf_field_put(struct bt_field *field)
336 {
337 bt_put(field);
338 }
339
340 struct bt_field_type *bt_field_get_type(struct bt_field *field)
341 {
342 struct bt_field_type *ret = NULL;
343
344 if (!field) {
345 BT_LOGW_STR("Invalid parameter: field is NULL.");
346 goto end;
347 }
348
349 ret = field->type;
350 bt_get(ret);
351 end:
352 return ret;
353 }
354
355 enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
356 {
357 enum bt_field_type_id ret = BT_FIELD_TYPE_ID_UNKNOWN;
358
359 if (!field) {
360 BT_LOGW_STR("Invalid parameter: field is NULL.");
361 goto end;
362 }
363
364 ret = bt_field_type_get_type_id(field->type);
365 end:
366 return ret;
367 }
368
369 bt_bool bt_field_is_integer(struct bt_field *field)
370 {
371 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_INTEGER;
372 }
373
374 bt_bool bt_field_is_floating_point(struct bt_field *field)
375 {
376 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_FLOAT;
377 }
378
379 bt_bool bt_field_is_enumeration(struct bt_field *field)
380 {
381 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ENUM;
382 }
383
384 bt_bool bt_field_is_string(struct bt_field *field)
385 {
386 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING;
387 }
388
389 bt_bool bt_field_is_structure(struct bt_field *field)
390 {
391 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRUCT;
392 }
393
394 bt_bool bt_field_is_array(struct bt_field *field)
395 {
396 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ARRAY;
397 }
398
399 bt_bool bt_field_is_sequence(struct bt_field *field)
400 {
401 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SEQUENCE;
402 }
403
404 bt_bool bt_field_is_variant(struct bt_field *field)
405 {
406 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT;
407 }
408
409 BT_HIDDEN
410 int64_t bt_field_sequence_get_int_length(struct bt_field *field)
411 {
412 struct bt_field_sequence *sequence;
413 int64_t ret;
414
415 assert(field);
416 assert(bt_field_type_get_type_id(field->type) ==
417 BT_FIELD_TYPE_ID_SEQUENCE);
418 sequence = container_of(field, struct bt_field_sequence, parent);
419 if (!sequence->length) {
420 ret = -1;
421 goto end;
422 }
423
424 ret = (int64_t) sequence->elements->len;
425
426 end:
427 return ret;
428 }
429
430 struct bt_field *bt_field_sequence_get_length(
431 struct bt_field *field)
432 {
433 struct bt_field *ret = NULL;
434 struct bt_field_sequence *sequence;
435
436 if (!field) {
437 BT_LOGW_STR("Invalid parameter: field is NULL.");
438 goto end;
439 }
440
441 if (bt_field_type_get_type_id(field->type) !=
442 BT_FIELD_TYPE_ID_SEQUENCE) {
443 BT_LOGW("Invalid parameter: field's type is not a sequence field type: "
444 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
445 field->type,
446 bt_field_type_id_string(field->type->id));
447 goto end;
448 }
449
450 sequence = container_of(field, struct bt_field_sequence, parent);
451 ret = sequence->length;
452 bt_get(ret);
453 end:
454 return ret;
455 }
456
457 int bt_field_sequence_set_length(struct bt_field *field,
458 struct bt_field *length_field)
459 {
460 int ret = 0;
461 struct bt_field_type_integer *length_type;
462 struct bt_field_integer *length;
463 struct bt_field_sequence *sequence;
464 uint64_t sequence_length;
465
466 if (!field) {
467 BT_LOGW_STR("Invalid parameter: field is NULL.");
468 ret = -1;
469 goto end;
470 }
471
472 if (!length_field) {
473 BT_LOGW_STR("Invalid parameter: length field is NULL.");
474 ret = -1;
475 goto end;
476 }
477
478 if (field->frozen) {
479 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
480 field);
481 ret = -1;
482 goto end;
483 }
484
485 if (bt_field_type_get_type_id(length_field->type) !=
486 BT_FIELD_TYPE_ID_INTEGER) {
487 BT_LOGW("Invalid parameter: length field's type is not an integer field type: "
488 "field-addr=%p, length-field-addr=%p, length-ft-addr=%p, length-ft-id=%s",
489 field, length_field, length_field->type,
490 bt_field_type_id_string(length_field->type->id));
491 ret = -1;
492 goto end;
493 }
494
495 length_type = container_of(length_field->type,
496 struct bt_field_type_integer, parent);
497 /* The length field must be unsigned */
498 if (length_type->is_signed) {
499 BT_LOGW("Invalid parameter: length field's type is signed: "
500 "field-addr=%p, length-field-addr=%p, "
501 "length-field-ft-addr=%p", field, length_field,
502 length_field->type);
503 ret = -1;
504 goto end;
505 }
506
507 if (!bt_field_is_set(length_field)) {
508 BT_LOGW("Invalid parameter: length field's value is not set: "
509 "field-addr=%p, length-field-addr=%p, "
510 "length-field-ft-addr=%p", field, length_field,
511 length_field->type);
512 ret = -1;
513 goto end;
514 }
515
516 length = container_of(length_field, struct bt_field_integer,
517 parent);
518 sequence_length = length->payload.unsignd;
519 sequence = container_of(field, struct bt_field_sequence, parent);
520 if (sequence->elements) {
521 g_ptr_array_free(sequence->elements, TRUE);
522 bt_put(sequence->length);
523 }
524
525 sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
526 if (!sequence->elements) {
527 BT_LOGE_STR("Failed to allocate a GPtrArray.");
528 ret = -1;
529 goto end;
530 }
531
532 g_ptr_array_set_free_func(sequence->elements,
533 (GDestroyNotify) bt_put);
534 g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
535 bt_get(length_field);
536 sequence->length = length_field;
537 bt_field_freeze(length_field);
538 end:
539 return ret;
540 }
541
542 struct bt_field *bt_field_structure_get_field_by_name(
543 struct bt_field *field, const char *name)
544 {
545 struct bt_field *ret = NULL;
546 GQuark field_quark;
547 struct bt_field_structure *structure;
548 size_t index;
549 GHashTable *field_name_to_index;
550
551 if (!field) {
552 BT_LOGW_STR("Invalid parameter: field is NULL.");
553 goto error;
554 }
555
556 if (!name) {
557 BT_LOGW_STR("Invalid parameter: field name is NULL.");
558 goto error;
559 }
560
561 if (bt_field_type_get_type_id(field->type) !=
562 BT_FIELD_TYPE_ID_STRUCT) {
563 BT_LOGW("Invalid parameter: field's type is not a structure field type: "
564 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
565 field->type,
566 bt_field_type_id_string(field->type->id));
567 goto error;
568 }
569
570 field_name_to_index =
571 container_of(field->type, struct bt_field_type_structure,
572 parent)->field_name_to_index;
573 field_quark = g_quark_from_string(name);
574 structure = container_of(field, struct bt_field_structure, parent);
575 if (!g_hash_table_lookup_extended(field_name_to_index,
576 GUINT_TO_POINTER(field_quark),
577 NULL, (gpointer *)&index)) {
578 BT_LOGV("Invalid parameter: no such field in structure field's type: "
579 "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
580 field, field->type, name);
581 goto error;
582 }
583
584 ret = bt_get(structure->fields->pdata[index]);
585 assert(ret);
586 error:
587 return ret;
588 }
589
590 struct bt_field *bt_field_structure_get_field_by_index(
591 struct bt_field *field, uint64_t index)
592 {
593 struct bt_field_structure *structure;
594 struct bt_field *ret = NULL;
595
596 if (!field) {
597 BT_LOGW_STR("Invalid parameter: field is NULL.");
598 goto end;
599 }
600
601 if (bt_field_type_get_type_id(field->type) !=
602 BT_FIELD_TYPE_ID_STRUCT) {
603 BT_LOGW("Invalid parameter: field's type is not a structure field type: "
604 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
605 field->type,
606 bt_field_type_id_string(field->type->id));
607 goto end;
608 }
609
610 structure = container_of(field, struct bt_field_structure, parent);
611 if (index >= structure->fields->len) {
612 BT_LOGW("Invalid parameter: index is out of bounds: "
613 "addr=%p, index=%" PRIu64 ", count=%u",
614 field, index, structure->fields->len);
615 goto end;
616 }
617
618 ret = bt_get(structure->fields->pdata[index]);
619 end:
620 return ret;
621 }
622
623 int bt_field_structure_set_field_by_name(struct bt_field *field,
624 const char *name, struct bt_field *value)
625 {
626 int ret = 0;
627 GQuark field_quark;
628 struct bt_field_structure *structure;
629 struct bt_field_type *expected_field_type = NULL;
630 size_t index;
631 GHashTable *field_name_to_index;
632
633 if (!field) {
634 BT_LOGW_STR("Invalid parameter: structure field is NULL.");
635 ret = -1;
636 goto end;
637 }
638
639 if (!name) {
640 BT_LOGW_STR("Invalid parameter: field name is NULL.");
641 ret = -1;
642 goto end;
643 }
644
645 if (!value) {
646 BT_LOGW_STR("Invalid parameter: field is NULL.");
647 ret = -1;
648 goto end;
649 }
650
651 if (bt_field_type_get_type_id(field->type) !=
652 BT_FIELD_TYPE_ID_STRUCT) {
653 BT_LOGW("Invalid parameter: field's type is not a structure field type: "
654 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
655 field->type,
656 bt_field_type_id_string(field->type->id));
657 ret = -1;
658 goto end;
659 }
660
661 field_quark = g_quark_from_string(name);
662 structure = container_of(field, struct bt_field_structure, parent);
663 expected_field_type =
664 bt_field_type_structure_get_field_type_by_name(field->type,
665 name);
666
667 if (bt_field_type_compare(expected_field_type, value->type)) {
668 BT_LOGW("Invalid parameter: field type of field to set is different from the expected field type: "
669 "struct-field-addr=%p, field-addr=%p, "
670 "field-ft-addr=%p, expected-ft-addr=%p",
671 field, value, value->type, expected_field_type);
672 ret = -1;
673 goto end;
674 }
675
676 field_name_to_index =
677 container_of(field->type, struct bt_field_type_structure,
678 parent)->field_name_to_index;
679 if (!g_hash_table_lookup_extended(field_name_to_index,
680 GUINT_TO_POINTER(field_quark), NULL,
681 (gpointer *) &index)) {
682 BT_LOGV("Invalid parameter: no such field in structure field's type: "
683 "struct-field-addr=%p, struct-ft-addr=%p, "
684 "field-ft-addr=%p, name=\"%s\"",
685 field, field->type, value->type, name);
686 ret = -1;
687 goto end;
688 }
689 bt_get(value);
690 BT_MOVE(structure->fields->pdata[index], value);
691 end:
692 if (expected_field_type) {
693 bt_put(expected_field_type);
694 }
695 return ret;
696 }
697
698 struct bt_field *bt_field_array_get_field(struct bt_field *field,
699 uint64_t index)
700 {
701 struct bt_field *new_field = NULL;
702 struct bt_field_type *field_type = NULL;
703 struct bt_field_array *array;
704
705 if (!field) {
706 BT_LOGW_STR("Invalid parameter: field is NULL.");
707 goto end;
708 }
709
710 if (bt_field_type_get_type_id(field->type) !=
711 BT_FIELD_TYPE_ID_ARRAY) {
712 BT_LOGW("Invalid parameter: field's type is not an array field type: "
713 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
714 field->type,
715 bt_field_type_id_string(field->type->id));
716 goto end;
717 }
718
719 array = container_of(field, struct bt_field_array, parent);
720 if (index >= array->elements->len) {
721 BT_LOGW("Invalid parameter: index is out of bounds: "
722 "addr=%p, index=%" PRIu64 ", count=%u",
723 field, index, array->elements->len);
724 goto end;
725 }
726
727 field_type = bt_field_type_array_get_element_type(field->type);
728 if (array->elements->pdata[(size_t)index]) {
729 new_field = array->elements->pdata[(size_t)index];
730 goto end;
731 }
732
733 /* We don't want to modify this field if it's frozen */
734 if (field->frozen) {
735 /*
736 * Not logging a warning here because the user could
737 * legitimately check if a array field is set with
738 * this function: if the preconditions are satisfied,
739 * a NULL return value means this.
740 */
741 BT_LOGV("Not creating a field because array field is frozen: "
742 "array-field-addr=%p, index=%" PRIu64, field, index);
743 goto end;
744 }
745
746 new_field = bt_field_create(field_type);
747 array->elements->pdata[(size_t)index] = new_field;
748 end:
749 if (field_type) {
750 bt_put(field_type);
751 }
752 if (new_field) {
753 bt_get(new_field);
754 }
755 return new_field;
756 }
757
758 struct bt_field *bt_field_sequence_get_field(struct bt_field *field,
759 uint64_t index)
760 {
761 struct bt_field *new_field = NULL;
762 struct bt_field_type *field_type = NULL;
763 struct bt_field_sequence *sequence;
764
765 if (!field) {
766 BT_LOGW_STR("Invalid parameter: field is NULL.");
767 goto end;
768 }
769
770 if (bt_field_type_get_type_id(field->type) !=
771 BT_FIELD_TYPE_ID_SEQUENCE) {
772 BT_LOGW("Invalid parameter: field's type is not a sequence field type: "
773 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
774 field->type,
775 bt_field_type_id_string(field->type->id));
776 goto end;
777 }
778
779 sequence = container_of(field, struct bt_field_sequence, parent);
780 if (!sequence->elements) {
781 BT_LOGV("Sequence field's elements do not exist: addr=%p",
782 field);
783 goto end;
784 }
785
786 if (index >= sequence->elements->len) {
787 BT_LOGW("Invalid parameter: index is out of bounds: "
788 "addr=%p, index=%" PRIu64 ", count=%u",
789 field, index, sequence->elements->len);
790 goto end;
791 }
792
793 field_type = bt_field_type_sequence_get_element_type(field->type);
794 if (sequence->elements->pdata[(size_t) index]) {
795 new_field = sequence->elements->pdata[(size_t) index];
796 goto end;
797 }
798
799 /* We don't want to modify this field if it's frozen */
800 if (field->frozen) {
801 /*
802 * Not logging a warning here because the user could
803 * legitimately check if a sequence field is set with
804 * this function: if the preconditions are satisfied,
805 * a NULL return value means this.
806 */
807 BT_LOGV("Not creating a field because sequence field is frozen: "
808 "sequence-field-addr=%p, index=%" PRIu64, field, index);
809 goto end;
810 }
811
812 new_field = bt_field_create(field_type);
813 sequence->elements->pdata[(size_t) index] = new_field;
814 end:
815 if (field_type) {
816 bt_put(field_type);
817 }
818 if (new_field) {
819 bt_get(new_field);
820 }
821 return new_field;
822 }
823
824 struct bt_field *bt_field_variant_get_field(struct bt_field *field,
825 struct bt_field *tag_field)
826 {
827 struct bt_field *new_field = NULL;
828 struct bt_field_variant *variant;
829 struct bt_field_type_variant *variant_type;
830 struct bt_field_type *field_type;
831 struct bt_field *tag_enum = NULL;
832 struct bt_field_integer *tag_enum_integer;
833 int64_t tag_enum_value;
834
835 if (!field) {
836 BT_LOGW_STR("Invalid parameter: field is NULL.");
837 goto end;
838 }
839
840 if (!tag_field) {
841 BT_LOGW_STR("Invalid parameter: tag field is NULL.");
842 goto end;
843 }
844
845 if (bt_field_type_get_type_id(field->type) !=
846 BT_FIELD_TYPE_ID_VARIANT) {
847 BT_LOGW("Invalid parameter: field's type is not a variant field type: "
848 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
849 field->type,
850 bt_field_type_id_string(field->type->id));
851 goto end;
852 }
853
854 if (bt_field_type_get_type_id(tag_field->type) !=
855 BT_FIELD_TYPE_ID_ENUM) {
856 BT_LOGW("Invalid parameter: tag field's type is not an enumeration field type: "
857 "field-addr=%p, ft-addr=%p, ft-id=%s", tag_field,
858 tag_field->type,
859 bt_field_type_id_string(tag_field->type->id));
860 goto end;
861 }
862
863 variant = container_of(field, struct bt_field_variant, parent);
864 variant_type = container_of(field->type,
865 struct bt_field_type_variant, parent);
866 tag_enum = bt_field_enumeration_get_container(tag_field);
867 if (!tag_enum) {
868 goto end;
869 }
870
871 tag_enum_integer = container_of(tag_enum, struct bt_field_integer,
872 parent);
873
874 if (bt_field_validate(tag_field) < 0) {
875 BT_LOGW("Invalid parameter: tag field is invalid: "
876 "variant-field-addr=%p, tag-field-addr=%p",
877 field, tag_field);
878 goto end;
879 }
880
881 tag_enum_value = tag_enum_integer->payload.signd;
882
883 /*
884 * If the variant currently has a tag and a payload, and if the
885 * requested tag value is the same as the current one, return
886 * the current payload instead of creating a fresh one.
887 */
888 if (variant->tag && variant->payload) {
889 struct bt_field *cur_tag_container = NULL;
890 struct bt_field_integer *cur_tag_enum_integer;
891 int64_t cur_tag_value;
892
893 cur_tag_container =
894 bt_field_enumeration_get_container(variant->tag);
895 assert(cur_tag_container);
896 cur_tag_enum_integer = container_of(cur_tag_container,
897 struct bt_field_integer, parent);
898 bt_put(cur_tag_container);
899 cur_tag_value = cur_tag_enum_integer->payload.signd;
900
901 if (cur_tag_value == tag_enum_value) {
902 new_field = variant->payload;
903 bt_get(new_field);
904 goto end;
905 }
906 }
907
908 /* We don't want to modify this field if it's frozen */
909 if (field->frozen) {
910 /*
911 * Not logging a warning here because the user could
912 * legitimately check if a variant field is set with
913 * this function: if the preconditions are satisfied,
914 * a NULL return value means this.
915 */
916 BT_LOGV("Not creating a field because variant field is frozen: "
917 "variant-field-addr=%p, tag-field-addr=%p",
918 field, tag_field);
919 goto end;
920 }
921
922 field_type = bt_field_type_variant_get_field_type_signed(
923 variant_type, tag_enum_value);
924 if (!field_type) {
925 BT_LOGW("Cannot get variant field type's field: "
926 "variant-field-addr=%p, variant-ft-addr=%p, "
927 "tag-value-signed=%" PRId64,
928 field, variant_type, tag_enum_value);
929 goto end;
930 }
931
932 new_field = bt_field_create(field_type);
933 if (!new_field) {
934 BT_LOGW("Cannot create field: "
935 "variant-field-addr=%p, variant-ft-addr=%p, "
936 "field-ft-addr=%p", field, field->type, field_type);
937 goto end;
938 }
939
940 bt_put(variant->tag);
941 bt_put(variant->payload);
942 bt_get(new_field);
943 bt_get(tag_field);
944 variant->tag = tag_field;
945 variant->payload = new_field;
946 end:
947 bt_put(tag_enum);
948 return new_field;
949 }
950
951 struct bt_field *bt_field_variant_get_current_field(
952 struct bt_field *variant_field)
953 {
954 struct bt_field *current_field = NULL;
955 struct bt_field_variant *variant;
956
957 if (!variant_field) {
958 BT_LOGW_STR("Invalid parameter: field is NULL.");
959 goto end;
960 }
961
962 if (bt_field_type_get_type_id(variant_field->type) !=
963 BT_FIELD_TYPE_ID_VARIANT) {
964 BT_LOGW("Invalid parameter: field's type is not a variant field type: "
965 "field-addr=%p, ft-addr=%p, ft-id=%s", variant_field,
966 variant_field->type,
967 bt_field_type_id_string(variant_field->type->id));
968 goto end;
969 }
970
971 variant = container_of(variant_field, struct bt_field_variant,
972 parent);
973
974 if (variant->payload) {
975 current_field = variant->payload;
976 bt_get(current_field);
977 goto end;
978 }
979
980 end:
981 return current_field;
982 }
983
984 struct bt_field *bt_field_variant_get_tag(
985 struct bt_field *variant_field)
986 {
987 struct bt_field *tag = NULL;
988 struct bt_field_variant *variant;
989
990 if (!variant_field) {
991 BT_LOGW_STR("Invalid parameter: field is NULL.");
992 goto end;
993 }
994
995 if (bt_field_type_get_type_id(variant_field->type) !=
996 BT_FIELD_TYPE_ID_VARIANT) {
997 BT_LOGW("Invalid parameter: field's type is not a variant field type: "
998 "field-addr=%p, ft-addr=%p, ft-id=%s", variant_field,
999 variant_field->type,
1000 bt_field_type_id_string(variant_field->type->id));
1001 goto end;
1002 }
1003
1004 variant = container_of(variant_field, struct bt_field_variant,
1005 parent);
1006 if (variant->tag) {
1007 tag = bt_get(variant->tag);
1008 }
1009 end:
1010 return tag;
1011 }
1012
1013 struct bt_field *bt_field_enumeration_get_container(
1014 struct bt_field *field)
1015 {
1016 struct bt_field *container = NULL;
1017 struct bt_field_enumeration *enumeration;
1018
1019 if (!field) {
1020 BT_LOGW_STR("Invalid parameter: field is NULL.");
1021 goto end;
1022 }
1023
1024 if (bt_field_type_get_type_id(field->type) !=
1025 BT_FIELD_TYPE_ID_ENUM) {
1026 BT_LOGW("Invalid parameter: field's type is not an enumeration field type: "
1027 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1028 field->type,
1029 bt_field_type_id_string(field->type->id));
1030 goto end;
1031 }
1032
1033 enumeration = container_of(field, struct bt_field_enumeration,
1034 parent);
1035 if (!enumeration->payload) {
1036 /* We don't want to modify this field if it's frozen */
1037 if (field->frozen) {
1038 /*
1039 * Not logging a warning here because the user
1040 * could legitimately check if an enumeration's
1041 * container field is set with this function: if
1042 * the preconditions are satisfied, a NULL
1043 * return value means this.
1044 */
1045 BT_LOGV("Not creating a field because enumeration field is frozen: "
1046 "enum-field-addr=%p", field);
1047 goto end;
1048 }
1049
1050 struct bt_field_type_enumeration *enumeration_type =
1051 container_of(field->type,
1052 struct bt_field_type_enumeration, parent);
1053 enumeration->payload =
1054 bt_field_create(enumeration_type->container);
1055 }
1056
1057 container = enumeration->payload;
1058 bt_get(container);
1059 end:
1060 return container;
1061 }
1062
1063 struct bt_field_type_enumeration_mapping_iterator *
1064 bt_field_enumeration_get_mappings(struct bt_field *field)
1065 {
1066 int ret;
1067 struct bt_field *container = NULL;
1068 struct bt_field_type *container_type = NULL;
1069 struct bt_field_type_integer *integer_type = NULL;
1070 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
1071
1072 container = bt_field_enumeration_get_container(field);
1073 if (!container) {
1074 BT_LOGW("Invalid parameter: enumeration field has no container field: "
1075 "addr=%p", field);
1076 goto end;
1077 }
1078
1079 container_type = bt_field_get_type(container);
1080 assert(container_type);
1081 integer_type = container_of(container_type,
1082 struct bt_field_type_integer, parent);
1083
1084 if (!integer_type->is_signed) {
1085 uint64_t value;
1086
1087 ret = bt_field_unsigned_integer_get_value(container,
1088 &value);
1089 if (ret) {
1090 BT_LOGW("Cannot get value from signed enumeration field's payload field: "
1091 "enum-field-addr=%p, payload-field-addr=%p",
1092 field, container);
1093 goto error_put_container_type;
1094 }
1095 iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(
1096 field->type, value);
1097 } else {
1098 int64_t value;
1099
1100 ret = bt_field_signed_integer_get_value(container,
1101 &value);
1102 if (ret) {
1103 BT_LOGW("Cannot get value from unsigned enumeration field's payload field: "
1104 "enum-field-addr=%p, payload-field-addr=%p",
1105 field, container);
1106 goto error_put_container_type;
1107 }
1108 iter = bt_field_type_enumeration_find_mappings_by_signed_value(
1109 field->type, value);
1110 }
1111
1112 error_put_container_type:
1113 bt_put(container_type);
1114 bt_put(container);
1115 end:
1116 return iter;
1117 }
1118
1119 int bt_field_signed_integer_get_value(struct bt_field *field,
1120 int64_t *value)
1121 {
1122 int ret = 0;
1123 struct bt_field_integer *integer;
1124 struct bt_field_type_integer *integer_type;
1125
1126 if (!field) {
1127 BT_LOGW_STR("Invalid parameter: field is NULL.");
1128 ret = -1;
1129 goto end;
1130 }
1131
1132 if (!value) {
1133 BT_LOGW_STR("Invalid parameter: value is NULL.");
1134 ret = -1;
1135 goto end;
1136 }
1137
1138 if (!field->payload_set) {
1139 BT_LOGV("Field's payload is not set: addr=%p", field);
1140 ret = -1;
1141 goto end;
1142 }
1143
1144 if (bt_field_type_get_type_id(field->type) !=
1145 BT_FIELD_TYPE_ID_INTEGER) {
1146 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1147 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1148 field->type,
1149 bt_field_type_id_string(field->type->id));
1150 ret = -1;
1151 goto end;
1152 }
1153
1154 integer_type = container_of(field->type,
1155 struct bt_field_type_integer, parent);
1156 if (!integer_type->is_signed) {
1157 BT_LOGW("Invalid parameter: integer field's type is not signed: "
1158 "field-addr=%p, ft-addr=%p", field, field->type);
1159 ret = -1;
1160 goto end;
1161 }
1162
1163 integer = container_of(field,
1164 struct bt_field_integer, parent);
1165 *value = integer->payload.signd;
1166 end:
1167 return ret;
1168 }
1169
1170 int bt_field_signed_integer_set_value(struct bt_field *field,
1171 int64_t value)
1172 {
1173 int ret = 0;
1174 struct bt_field_integer *integer;
1175 struct bt_field_type_integer *integer_type;
1176 unsigned int size;
1177 int64_t min_value, max_value;
1178
1179 if (!field) {
1180 BT_LOGW_STR("Invalid parameter: field is NULL.");
1181 ret = -1;
1182 goto end;
1183 }
1184
1185 if (field->frozen) {
1186 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1187 field);
1188 ret = -1;
1189 goto end;
1190 }
1191
1192 if (bt_field_type_get_type_id(field->type) !=
1193 BT_FIELD_TYPE_ID_INTEGER) {
1194 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1195 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1196 field->type,
1197 bt_field_type_id_string(field->type->id));
1198 ret = -1;
1199 goto end;
1200 }
1201
1202 integer = container_of(field, struct bt_field_integer, parent);
1203 integer_type = container_of(field->type,
1204 struct bt_field_type_integer, parent);
1205 if (!integer_type->is_signed) {
1206 BT_LOGW("Invalid parameter: integer field's type is not signed: "
1207 "field-addr=%p, ft-addr=%p", field, field->type);
1208 ret = -1;
1209 goto end;
1210 }
1211
1212 size = integer_type->size;
1213 min_value = -(1ULL << (size - 1));
1214 max_value = (1ULL << (size - 1)) - 1;
1215 if (value < min_value || value > max_value) {
1216 BT_LOGW("Invalid parameter: value is out of bounds: "
1217 "addr=%p, value=%" PRId64 ", "
1218 "min-value=%" PRId64 ", max-value=%" PRId64,
1219 field, value, min_value, max_value);
1220 ret = -1;
1221 goto end;
1222 }
1223
1224 integer->payload.signd = value;
1225 integer->parent.payload_set = true;
1226 end:
1227 return ret;
1228 }
1229
1230 int bt_field_unsigned_integer_get_value(struct bt_field *field,
1231 uint64_t *value)
1232 {
1233 int ret = 0;
1234 struct bt_field_integer *integer;
1235 struct bt_field_type_integer *integer_type;
1236
1237 if (!field) {
1238 BT_LOGW_STR("Invalid parameter: field is NULL.");
1239 ret = -1;
1240 goto end;
1241 }
1242
1243 if (!value) {
1244 BT_LOGW_STR("Invalid parameter: value is NULL.");
1245 ret = -1;
1246 goto end;
1247 }
1248
1249 if (!field->payload_set) {
1250 BT_LOGV("Field's payload is not set: addr=%p", field);
1251 ret = -1;
1252 goto end;
1253 }
1254
1255 if (bt_field_type_get_type_id(field->type) !=
1256 BT_FIELD_TYPE_ID_INTEGER) {
1257 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1258 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1259 field->type,
1260 bt_field_type_id_string(field->type->id));
1261 ret = -1;
1262 goto end;
1263 }
1264
1265 integer_type = container_of(field->type,
1266 struct bt_field_type_integer, parent);
1267 if (integer_type->is_signed) {
1268 BT_LOGW("Invalid parameter: integer field's type is signed: "
1269 "field-addr=%p, ft-addr=%p", field, field->type);
1270 ret = -1;
1271 goto end;
1272 }
1273
1274 integer = container_of(field,
1275 struct bt_field_integer, parent);
1276 *value = integer->payload.unsignd;
1277 end:
1278 return ret;
1279 }
1280
1281 int bt_field_unsigned_integer_set_value(struct bt_field *field,
1282 uint64_t value)
1283 {
1284 int ret = 0;
1285 struct bt_field_integer *integer;
1286 struct bt_field_type_integer *integer_type;
1287 unsigned int size;
1288 uint64_t max_value;
1289
1290 if (!field) {
1291 BT_LOGW_STR("Invalid parameter: field is NULL.");
1292 ret = -1;
1293 goto end;
1294 }
1295
1296 if (field->frozen) {
1297 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1298 field);
1299 ret = -1;
1300 goto end;
1301 }
1302
1303 if (bt_field_type_get_type_id(field->type) !=
1304 BT_FIELD_TYPE_ID_INTEGER) {
1305 BT_LOGW("Invalid parameter: field's type is not an integer field type: "
1306 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1307 field->type,
1308 bt_field_type_id_string(field->type->id));
1309 ret = -1;
1310 goto end;
1311 }
1312
1313 integer = container_of(field, struct bt_field_integer, parent);
1314 integer_type = container_of(field->type,
1315 struct bt_field_type_integer, parent);
1316 if (integer_type->is_signed) {
1317 BT_LOGW("Invalid parameter: integer field's type is signed: "
1318 "field-addr=%p, ft-addr=%p", field, field->type);
1319 ret = -1;
1320 goto end;
1321 }
1322
1323 size = integer_type->size;
1324 max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
1325 if (value > max_value) {
1326 BT_LOGW("Invalid parameter: value is out of bounds: "
1327 "addr=%p, value=%" PRIu64 ", "
1328 "min-value=%" PRIu64 ", max-value=%" PRIu64,
1329 field, value, (uint64_t) 0, max_value);
1330 ret = -1;
1331 goto end;
1332 }
1333
1334 integer->payload.unsignd = value;
1335 integer->parent.payload_set = true;
1336 end:
1337 return ret;
1338 }
1339
1340 int bt_field_floating_point_get_value(struct bt_field *field,
1341 double *value)
1342 {
1343 int ret = 0;
1344 struct bt_field_floating_point *floating_point;
1345
1346 if (!field) {
1347 BT_LOGW_STR("Invalid parameter: field is NULL.");
1348 ret = -1;
1349 goto end;
1350 }
1351
1352 if (!value) {
1353 BT_LOGW_STR("Invalid parameter: value is NULL.");
1354 ret = -1;
1355 goto end;
1356 }
1357
1358 if (!field->payload_set) {
1359 BT_LOGV("Field's payload is not set: addr=%p", field);
1360 ret = -1;
1361 goto end;
1362 }
1363
1364 if (bt_field_type_get_type_id(field->type) !=
1365 BT_FIELD_TYPE_ID_FLOAT) {
1366 BT_LOGW("Invalid parameter: field's type is not a floating point number field type: "
1367 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1368 field->type,
1369 bt_field_type_id_string(field->type->id));
1370 ret = -1;
1371 goto end;
1372 }
1373
1374 floating_point = container_of(field,
1375 struct bt_field_floating_point, parent);
1376 *value = floating_point->payload;
1377 end:
1378 return ret;
1379 }
1380
1381 int bt_field_floating_point_set_value(struct bt_field *field,
1382 double value)
1383 {
1384 int ret = 0;
1385 struct bt_field_floating_point *floating_point;
1386
1387 if (!field) {
1388 BT_LOGW_STR("Invalid parameter: field is NULL.");
1389 ret = -1;
1390 goto end;
1391 }
1392
1393 if (field->frozen) {
1394 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1395 field);
1396 ret = -1;
1397 goto end;
1398 }
1399
1400 if (bt_field_type_get_type_id(field->type) !=
1401 BT_FIELD_TYPE_ID_FLOAT) {
1402 BT_LOGW("Invalid parameter: field's type is not a floating point number field type: "
1403 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1404 field->type,
1405 bt_field_type_id_string(field->type->id));
1406 ret = -1;
1407 goto end;
1408 }
1409
1410 floating_point = container_of(field, struct bt_field_floating_point,
1411 parent);
1412 floating_point->payload = value;
1413 floating_point->parent.payload_set = true;
1414 end:
1415 return ret;
1416 }
1417
1418 const char *bt_field_string_get_value(struct bt_field *field)
1419 {
1420 const char *ret = NULL;
1421 struct bt_field_string *string;
1422
1423 if (!field) {
1424 BT_LOGW_STR("Invalid parameter: field is NULL.");
1425 goto end;
1426 }
1427
1428 if (!field->payload_set) {
1429 BT_LOGV("Field's payload is not set: addr=%p", field);
1430 goto end;
1431 }
1432
1433 if (bt_field_type_get_type_id(field->type) !=
1434 BT_FIELD_TYPE_ID_STRING) {
1435 BT_LOGW("Invalid parameter: field's type is not a string field type: "
1436 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1437 field->type,
1438 bt_field_type_id_string(field->type->id));
1439 goto end;
1440 }
1441
1442 string = container_of(field,
1443 struct bt_field_string, parent);
1444 ret = string->payload->str;
1445 end:
1446 return ret;
1447 }
1448
1449 int bt_field_string_set_value(struct bt_field *field,
1450 const char *value)
1451 {
1452 int ret = 0;
1453 struct bt_field_string *string;
1454
1455 if (!field) {
1456 BT_LOGW_STR("Invalid parameter: field is NULL.");
1457 ret = -1;
1458 goto end;
1459 }
1460
1461 if (!value) {
1462 BT_LOGW_STR("Invalid parameter: value is NULL.");
1463 ret = -1;
1464 goto end;
1465 }
1466
1467 if (field->frozen) {
1468 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1469 field);
1470 ret = -1;
1471 goto end;
1472 }
1473
1474 if (bt_field_type_get_type_id(field->type) !=
1475 BT_FIELD_TYPE_ID_STRING) {
1476 BT_LOGW("Invalid parameter: field's type is not a string field type: "
1477 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1478 field->type,
1479 bt_field_type_id_string(field->type->id));
1480 ret = -1;
1481 goto end;
1482 }
1483
1484 string = container_of(field, struct bt_field_string, parent);
1485 if (string->payload) {
1486 g_string_assign(string->payload, value);
1487 } else {
1488 string->payload = g_string_new(value);
1489 }
1490
1491 string->parent.payload_set = true;
1492 end:
1493 return ret;
1494 }
1495
1496 int bt_field_string_append(struct bt_field *field,
1497 const char *value)
1498 {
1499 int ret = 0;
1500 struct bt_field_string *string_field;
1501
1502 if (!field) {
1503 BT_LOGW_STR("Invalid parameter: field is NULL.");
1504 ret = -1;
1505 goto end;
1506 }
1507
1508 if (!value) {
1509 BT_LOGW_STR("Invalid parameter: value is NULL.");
1510 ret = -1;
1511 goto end;
1512 }
1513
1514 if (field->frozen) {
1515 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1516 field);
1517 ret = -1;
1518 goto end;
1519 }
1520
1521 if (bt_field_type_get_type_id(field->type) !=
1522 BT_FIELD_TYPE_ID_STRING) {
1523 BT_LOGW("Invalid parameter: field's type is not a string field type: "
1524 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1525 field->type,
1526 bt_field_type_id_string(field->type->id));
1527 ret = -1;
1528 goto end;
1529 }
1530
1531 string_field = container_of(field, struct bt_field_string, parent);
1532
1533 if (string_field->payload) {
1534 g_string_append(string_field->payload, value);
1535 } else {
1536 string_field->payload = g_string_new(value);
1537 }
1538
1539 string_field->parent.payload_set = true;
1540
1541 end:
1542 return ret;
1543 }
1544
1545 int bt_field_string_append_len(struct bt_field *field,
1546 const char *value, unsigned int length)
1547 {
1548 int i;
1549 int ret = 0;
1550 unsigned int effective_length = length;
1551 struct bt_field_string *string_field;
1552
1553 if (!field) {
1554 BT_LOGW_STR("Invalid parameter: field is NULL.");
1555 ret = -1;
1556 goto end;
1557 }
1558
1559 if (!value) {
1560 BT_LOGW_STR("Invalid parameter: value is NULL.");
1561 ret = -1;
1562 goto end;
1563 }
1564
1565 if (field->frozen) {
1566 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1567 field);
1568 ret = -1;
1569 goto end;
1570 }
1571
1572 if (bt_field_type_get_type_id(field->type) !=
1573 BT_FIELD_TYPE_ID_STRING) {
1574 BT_LOGW("Invalid parameter: field's type is not a string field type: "
1575 "field-addr=%p, ft-addr=%p, ft-id=%s", field,
1576 field->type,
1577 bt_field_type_id_string(field->type->id));
1578 ret = -1;
1579 goto end;
1580 }
1581
1582 string_field = container_of(field, struct bt_field_string, parent);
1583
1584 /* make sure no null bytes are appended */
1585 for (i = 0; i < length; ++i) {
1586 if (value[i] == '\0') {
1587 effective_length = i;
1588 break;
1589 }
1590 }
1591
1592 if (string_field->payload) {
1593 g_string_append_len(string_field->payload, value,
1594 effective_length);
1595 } else {
1596 string_field->payload = g_string_new_len(value,
1597 effective_length);
1598 }
1599
1600 string_field->parent.payload_set = true;
1601
1602 end:
1603 return ret;
1604 }
1605
1606 BT_HIDDEN
1607 int bt_field_validate(struct bt_field *field)
1608 {
1609 int ret = 0;
1610 enum bt_field_type_id type_id;
1611
1612 if (!field) {
1613 BT_LOGD_STR("Invalid parameter: field is NULL.");
1614 ret = -1;
1615 goto end;
1616 }
1617
1618 type_id = bt_field_type_get_type_id(field->type);
1619 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_FIELD_TYPE_ID_NR) {
1620 BT_LOGW("Invalid parameter: unknown field type ID: "
1621 "addr=%p, ft-addr=%p, ft-id=%d",
1622 field, field->type, type_id);
1623 ret = -1;
1624 goto end;
1625 }
1626
1627 ret = field_validate_funcs[type_id](field);
1628 end:
1629 return ret;
1630 }
1631
1632 int bt_field_reset(struct bt_field *field)
1633 {
1634 int ret = 0;
1635 enum bt_field_type_id type_id;
1636
1637 if (!field) {
1638 BT_LOGD_STR("Invalid parameter: field is NULL.");
1639 ret = -1;
1640 goto end;
1641 }
1642
1643 if (field->frozen) {
1644 BT_LOGW("Invalid parameter: field is frozen: addr=%p",
1645 field);
1646 ret = -1;
1647 goto end;
1648 }
1649
1650 type_id = bt_field_type_get_type_id(field->type);
1651 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_FIELD_TYPE_ID_NR) {
1652 BT_LOGW("Invalid parameter: unknown field type ID: "
1653 "addr=%p, ft-addr=%p, ft-id=%d",
1654 field, field->type, type_id);
1655 ret = -1;
1656 goto end;
1657 }
1658
1659 ret = field_reset_funcs[type_id](field);
1660 end:
1661 return ret;
1662 }
1663
1664 BT_HIDDEN
1665 int bt_field_serialize(struct bt_field *field,
1666 struct bt_stream_pos *pos,
1667 enum bt_byte_order native_byte_order)
1668 {
1669 int ret = 0;
1670 enum bt_field_type_id type_id;
1671
1672 assert(pos);
1673
1674 if (!field) {
1675 BT_LOGD_STR("Invalid parameter: field is NULL.");
1676 ret = -1;
1677 goto end;
1678 }
1679
1680 type_id = bt_field_type_get_type_id(field->type);
1681 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_FIELD_TYPE_ID_NR) {
1682 BT_LOGW("Invalid parameter: unknown field type ID: "
1683 "addr=%p, ft-addr=%p, ft-id=%d",
1684 field, field->type, type_id);
1685 ret = -1;
1686 goto end;
1687 }
1688
1689 ret = field_serialize_funcs[type_id](field, pos, native_byte_order);
1690 end:
1691 return ret;
1692 }
1693
1694 bt_bool bt_field_is_set(struct bt_field *field)
1695 {
1696 bt_bool is_set = BT_FALSE;
1697 enum bt_field_type_id type_id;
1698
1699 if (!field) {
1700 goto end;
1701 }
1702
1703 type_id = bt_field_type_get_type_id(field->type);
1704 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_FIELD_TYPE_ID_NR) {
1705 BT_LOGW("Invalid parameter: unknown field type ID: "
1706 "field-addr=%p, ft-addr=%p, ft-id=%d",
1707 field, field->type, type_id);
1708 goto end;
1709 }
1710
1711 is_set = field_is_set_funcs[type_id](field);
1712 end:
1713 return is_set;
1714 }
1715
1716 struct bt_field *bt_field_copy(struct bt_field *field)
1717 {
1718 int ret;
1719 struct bt_field *copy = NULL;
1720 enum bt_field_type_id type_id;
1721
1722 if (!field) {
1723 BT_LOGW_STR("Invalid parameter: field is NULL.");
1724 goto end;
1725 }
1726
1727 type_id = bt_field_type_get_type_id(field->type);
1728 if (type_id <= BT_FIELD_TYPE_ID_UNKNOWN || type_id >= BT_FIELD_TYPE_ID_NR) {
1729 BT_LOGW("Invalid parameter: unknown field type ID: "
1730 "field-addr=%p, ft-addr=%p, ft-id=%d",
1731 field, field->type, type_id);
1732 goto end;
1733 }
1734
1735 copy = bt_field_create(field->type);
1736 if (!copy) {
1737 BT_LOGW("Cannot create field: ft-addr=%p", field->type);
1738 goto end;
1739 }
1740
1741 copy->payload_set = field->payload_set;
1742 ret = field_copy_funcs[type_id](field, copy);
1743 if (ret) {
1744 bt_put(copy);
1745 copy = NULL;
1746 }
1747 end:
1748 return copy;
1749 }
1750
1751 static
1752 struct bt_field *bt_field_integer_create(struct bt_field_type *type)
1753 {
1754 struct bt_field_integer *integer = g_new0(
1755 struct bt_field_integer, 1);
1756
1757 BT_LOGD("Creating integer field object: ft-addr=%p", type);
1758
1759 if (integer) {
1760 BT_LOGD("Created integer field object: addr=%p, ft-addr=%p",
1761 &integer->parent, type);
1762 } else {
1763 BT_LOGE_STR("Failed to allocate one integer field.");
1764 }
1765
1766 return integer ? &integer->parent : NULL;
1767 }
1768
1769 static
1770 struct bt_field *bt_field_enumeration_create(
1771 struct bt_field_type *type)
1772 {
1773 struct bt_field_enumeration *enumeration = g_new0(
1774 struct bt_field_enumeration, 1);
1775
1776 BT_LOGD("Creating enumeration field object: ft-addr=%p", type);
1777
1778 if (enumeration) {
1779 BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p",
1780 &enumeration->parent, type);
1781 } else {
1782 BT_LOGE_STR("Failed to allocate one enumeration field.");
1783 }
1784
1785 return enumeration ? &enumeration->parent : NULL;
1786 }
1787
1788 static
1789 struct bt_field *bt_field_floating_point_create(
1790 struct bt_field_type *type)
1791 {
1792 struct bt_field_floating_point *floating_point;
1793
1794 BT_LOGD("Creating floating point number field object: ft-addr=%p", type);
1795 floating_point = g_new0(struct bt_field_floating_point, 1);
1796
1797 if (floating_point) {
1798 BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p",
1799 &floating_point->parent, type);
1800 } else {
1801 BT_LOGE_STR("Failed to allocate one floating point number field.");
1802 }
1803
1804 return floating_point ? &floating_point->parent : NULL;
1805 }
1806
1807 static
1808 struct bt_field *bt_field_structure_create(
1809 struct bt_field_type *type)
1810 {
1811 struct bt_field_type_structure *structure_type = container_of(type,
1812 struct bt_field_type_structure, parent);
1813 struct bt_field_structure *structure = g_new0(
1814 struct bt_field_structure, 1);
1815 struct bt_field *ret = NULL;
1816 size_t i;
1817
1818 BT_LOGD("Creating structure field object: ft-addr=%p", type);
1819
1820 if (!structure) {
1821 BT_LOGE_STR("Failed to allocate one structure field.");
1822 goto end;
1823 }
1824
1825 structure->fields = g_ptr_array_new_with_free_func(
1826 (GDestroyNotify) bt_put);
1827 g_ptr_array_set_size(structure->fields,
1828 structure_type->fields->len);
1829
1830 /* Create all fields contained by the structure field. */
1831 for (i = 0; i < structure_type->fields->len; i++) {
1832 struct bt_field *field;
1833 struct structure_field *field_type =
1834 g_ptr_array_index(structure_type->fields, i);
1835
1836 field = bt_field_create(field_type->type);
1837 if (!field) {
1838 BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu",
1839 g_quark_to_string(field_type->name), i);
1840 bt_field_structure_destroy(&structure->parent);
1841 goto end;
1842 }
1843
1844 g_ptr_array_index(structure->fields, i) = field;
1845 }
1846
1847 ret = &structure->parent;
1848 BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", ret,
1849 type);
1850 end:
1851 return ret;
1852 }
1853
1854 static
1855 struct bt_field *bt_field_variant_create(struct bt_field_type *type)
1856 {
1857 struct bt_field_variant *variant = g_new0(
1858 struct bt_field_variant, 1);
1859
1860 BT_LOGD("Creating variant field object: ft-addr=%p", type);
1861
1862 if (variant) {
1863 BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
1864 &variant->parent, type);
1865 } else {
1866 BT_LOGE_STR("Failed to allocate one variant field.");
1867 }
1868
1869 return variant ? &variant->parent : NULL;
1870 }
1871
1872 static
1873 struct bt_field *bt_field_array_create(struct bt_field_type *type)
1874 {
1875 struct bt_field_array *array = g_new0(struct bt_field_array, 1);
1876 struct bt_field_type_array *array_type;
1877 unsigned int array_length;
1878
1879 BT_LOGD("Creating array field object: ft-addr=%p", type);
1880 assert(type);
1881
1882 if (!array) {
1883 BT_LOGE_STR("Failed to allocate one array field.");
1884 goto error;
1885 }
1886
1887 array_type = container_of(type, struct bt_field_type_array, parent);
1888 array_length = array_type->length;
1889 array->elements = g_ptr_array_sized_new(array_length);
1890 if (!array->elements) {
1891 goto error;
1892 }
1893
1894 g_ptr_array_set_free_func(array->elements,
1895 (GDestroyNotify) bt_put);
1896 g_ptr_array_set_size(array->elements, array_length);
1897 BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
1898 &array->parent, type);
1899 return &array->parent;
1900 error:
1901 g_free(array);
1902 return NULL;
1903 }
1904
1905 static
1906 struct bt_field *bt_field_sequence_create(
1907 struct bt_field_type *type)
1908 {
1909 struct bt_field_sequence *sequence = g_new0(
1910 struct bt_field_sequence, 1);
1911
1912 BT_LOGD("Creating sequence field object: ft-addr=%p", type);
1913
1914 if (sequence) {
1915 BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
1916 &sequence->parent, type);
1917 } else {
1918 BT_LOGE_STR("Failed to allocate one sequence field.");
1919 }
1920
1921 return sequence ? &sequence->parent : NULL;
1922 }
1923
1924 static
1925 struct bt_field *bt_field_string_create(struct bt_field_type *type)
1926 {
1927 struct bt_field_string *string = g_new0(
1928 struct bt_field_string, 1);
1929
1930 BT_LOGD("Creating string field object: ft-addr=%p", type);
1931
1932 if (string) {
1933 BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
1934 &string->parent, type);
1935 } else {
1936 BT_LOGE_STR("Failed to allocate one string field.");
1937 }
1938
1939 return string ? &string->parent : NULL;
1940 }
1941
1942 static
1943 void bt_field_destroy(struct bt_object *obj)
1944 {
1945 struct bt_field *field;
1946 struct bt_field_type *type;
1947 enum bt_field_type_id type_id;
1948
1949 field = container_of(obj, struct bt_field, base);
1950 type = field->type;
1951 type_id = bt_field_type_get_type_id(type);
1952 assert(type_id > BT_FIELD_TYPE_ID_UNKNOWN &&
1953 type_id < BT_FIELD_TYPE_ID_NR);
1954 field_destroy_funcs[type_id](field);
1955 BT_LOGD_STR("Putting field's type.");
1956 bt_put(type);
1957 }
1958
1959 static
1960 void bt_field_integer_destroy(struct bt_field *field)
1961 {
1962 struct bt_field_integer *integer;
1963
1964 if (!field) {
1965 return;
1966 }
1967
1968 BT_LOGD("Destroying integer field object: addr=%p", field);
1969 integer = container_of(field, struct bt_field_integer, parent);
1970 g_free(integer);
1971 }
1972
1973 static
1974 void bt_field_enumeration_destroy(struct bt_field *field)
1975 {
1976 struct bt_field_enumeration *enumeration;
1977
1978 if (!field) {
1979 return;
1980 }
1981
1982 BT_LOGD("Destroying enumeration field object: addr=%p", field);
1983 enumeration = container_of(field, struct bt_field_enumeration,
1984 parent);
1985 BT_LOGD_STR("Putting payload field.");
1986 bt_put(enumeration->payload);
1987 g_free(enumeration);
1988 }
1989
1990 static
1991 void bt_field_floating_point_destroy(struct bt_field *field)
1992 {
1993 struct bt_field_floating_point *floating_point;
1994
1995 if (!field) {
1996 return;
1997 }
1998
1999 BT_LOGD("Destroying floating point number field object: addr=%p", field);
2000 floating_point = container_of(field, struct bt_field_floating_point,
2001 parent);
2002 g_free(floating_point);
2003 }
2004
2005 static
2006 void bt_field_structure_destroy(struct bt_field *field)
2007 {
2008 struct bt_field_structure *structure;
2009
2010 if (!field) {
2011 return;
2012 }
2013
2014 BT_LOGD("Destroying structure field object: addr=%p", field);
2015 structure = container_of(field, struct bt_field_structure, parent);
2016 g_ptr_array_free(structure->fields, TRUE);
2017 g_free(structure);
2018 }
2019
2020 static
2021 void bt_field_variant_destroy(struct bt_field *field)
2022 {
2023 struct bt_field_variant *variant;
2024
2025 if (!field) {
2026 return;
2027 }
2028
2029 BT_LOGD("Destroying variant field object: addr=%p", field);
2030 variant = container_of(field, struct bt_field_variant, parent);
2031 BT_LOGD_STR("Putting tag field.");
2032 bt_put(variant->tag);
2033 BT_LOGD_STR("Putting payload field.");
2034 bt_put(variant->payload);
2035 g_free(variant);
2036 }
2037
2038 static
2039 void bt_field_array_destroy(struct bt_field *field)
2040 {
2041 struct bt_field_array *array;
2042
2043 if (!field) {
2044 return;
2045 }
2046
2047 BT_LOGD("Destroying array field object: addr=%p", field);
2048 array = container_of(field, struct bt_field_array, parent);
2049 g_ptr_array_free(array->elements, TRUE);
2050 g_free(array);
2051 }
2052
2053 static
2054 void bt_field_sequence_destroy(struct bt_field *field)
2055 {
2056 struct bt_field_sequence *sequence;
2057
2058 if (!field) {
2059 return;
2060 }
2061
2062 BT_LOGD("Destroying sequence field object: addr=%p", field);
2063 sequence = container_of(field, struct bt_field_sequence, parent);
2064 if (sequence->elements) {
2065 g_ptr_array_free(sequence->elements, TRUE);
2066 }
2067 BT_LOGD_STR("Putting length field.");
2068 bt_put(sequence->length);
2069 g_free(sequence);
2070 }
2071
2072 static
2073 void bt_field_string_destroy(struct bt_field *field)
2074 {
2075 struct bt_field_string *string;
2076
2077 if (!field) {
2078 return;
2079 }
2080
2081 BT_LOGD("Destroying string field object: addr=%p", field);
2082 string = container_of(field, struct bt_field_string, parent);
2083 if (string->payload) {
2084 g_string_free(string->payload, TRUE);
2085 }
2086 g_free(string);
2087 }
2088
2089 static
2090 int bt_field_generic_validate(struct bt_field *field)
2091 {
2092 return (field && field->payload_set) ? 0 : -1;
2093 }
2094
2095 static
2096 int bt_field_enumeration_validate(struct bt_field *field)
2097 {
2098 int ret;
2099 struct bt_field_enumeration *enumeration;
2100
2101 if (!field) {
2102 BT_LOGD_STR("Invalid parameter: field is NULL.");
2103 ret = -1;
2104 goto end;
2105 }
2106
2107 enumeration = container_of(field, struct bt_field_enumeration,
2108 parent);
2109 if (!enumeration->payload) {
2110 BT_LOGW("Invalid enumeration field: payload is not set: "
2111 "addr=%p", field);
2112 ret = -1;
2113 goto end;
2114 }
2115
2116 ret = bt_field_validate(enumeration->payload);
2117 end:
2118 return ret;
2119 }
2120
2121 static
2122 int bt_field_structure_validate(struct bt_field *field)
2123 {
2124 int64_t i;
2125 int ret = 0;
2126 struct bt_field_structure *structure;
2127
2128 if (!field) {
2129 BT_LOGD_STR("Invalid parameter: field is NULL.");
2130 ret = -1;
2131 goto end;
2132 }
2133
2134 structure = container_of(field, struct bt_field_structure, parent);
2135 for (i = 0; i < structure->fields->len; i++) {
2136 struct bt_field *entry_field = structure->fields->pdata[i];
2137 ret = bt_field_validate(entry_field);
2138
2139 if (ret) {
2140 int this_ret;
2141 const char *name;
2142 struct bt_field_type *field_type =
2143 bt_field_get_type(field);
2144
2145 this_ret = bt_field_type_structure_get_field_by_index(
2146 field_type, &name, NULL, i);
2147 assert(this_ret == 0);
2148 BT_LOGW("Invalid structure field's field: "
2149 "struct-field-addr=%p, field-addr=%p, "
2150 "field-name=\"%s\", index=%" PRId64,
2151 field, entry_field, name, i);
2152 bt_put(field_type);
2153 goto end;
2154 }
2155 }
2156 end:
2157 return ret;
2158 }
2159
2160 static
2161 int bt_field_variant_validate(struct bt_field *field)
2162 {
2163 int ret = 0;
2164 struct bt_field_variant *variant;
2165
2166 if (!field) {
2167 BT_LOGD_STR("Invalid parameter: field is NULL.");
2168 ret = -1;
2169 goto end;
2170 }
2171
2172 variant = container_of(field, struct bt_field_variant, parent);
2173 ret = bt_field_validate(variant->payload);
2174 if (ret) {
2175 BT_LOGW("Invalid variant field's payload field: "
2176 "variant-field-addr=%p, variant-payload-field-addr=%p",
2177 field, variant->payload);
2178 }
2179 end:
2180 return ret;
2181 }
2182
2183 static
2184 int bt_field_array_validate(struct bt_field *field)
2185 {
2186 int64_t i;
2187 int ret = 0;
2188 struct bt_field_array *array;
2189
2190 if (!field) {
2191 BT_LOGD_STR("Invalid parameter: field is NULL.");
2192 ret = -1;
2193 goto end;
2194 }
2195
2196 array = container_of(field, struct bt_field_array, parent);
2197 for (i = 0; i < array->elements->len; i++) {
2198 struct bt_field *elem_field = array->elements->pdata[i];
2199
2200 ret = bt_field_validate(elem_field);
2201 if (ret) {
2202 BT_LOGW("Invalid array field's element field: "
2203 "array-field-addr=%p, field-addr=%p, "
2204 "index=%" PRId64, field, elem_field, i);
2205 goto end;
2206 }
2207 }
2208 end:
2209 return ret;
2210 }
2211
2212 static
2213 int bt_field_sequence_validate(struct bt_field *field)
2214 {
2215 size_t i;
2216 int ret = 0;
2217 struct bt_field_sequence *sequence;
2218
2219 if (!field) {
2220 BT_LOGD_STR("Invalid parameter: field is NULL.");
2221 ret = -1;
2222 goto end;
2223 }
2224
2225 sequence = container_of(field, struct bt_field_sequence, parent);
2226 for (i = 0; i < sequence->elements->len; i++) {
2227 struct bt_field *elem_field = sequence->elements->pdata[i];
2228
2229 ret = bt_field_validate(elem_field);
2230 if (ret) {
2231 BT_LOGW("Invalid sequence field's element field: "
2232 "sequence-field-addr=%p, field-addr=%p, "
2233 "index=%zu", field, elem_field, i);
2234 goto end;
2235 }
2236 }
2237 end:
2238 return ret;
2239 }
2240
2241 static
2242 int bt_field_generic_reset(struct bt_field *field)
2243 {
2244 int ret = 0;
2245
2246 if (!field) {
2247 BT_LOGD_STR("Invalid parameter: field is NULL.");
2248 ret = -1;
2249 goto end;
2250 }
2251
2252 field->payload_set = false;
2253 end:
2254 return ret;
2255 }
2256
2257 static
2258 int bt_field_enumeration_reset(struct bt_field *field)
2259 {
2260 int ret = 0;
2261 struct bt_field_enumeration *enumeration;
2262
2263 if (!field) {
2264 BT_LOGD_STR("Invalid parameter: field is NULL.");
2265 ret = -1;
2266 goto end;
2267 }
2268
2269 enumeration = container_of(field, struct bt_field_enumeration,
2270 parent);
2271 if (!enumeration->payload) {
2272 goto end;
2273 }
2274
2275 ret = bt_field_reset(enumeration->payload);
2276 end:
2277 return ret;
2278 }
2279
2280 static
2281 int bt_field_structure_reset(struct bt_field *field)
2282 {
2283 int64_t i;
2284 int ret = 0;
2285 struct bt_field_structure *structure;
2286
2287 if (!field) {
2288 BT_LOGD_STR("Invalid parameter: field is NULL.");
2289 ret = -1;
2290 goto end;
2291 }
2292
2293 structure = container_of(field, struct bt_field_structure, parent);
2294 for (i = 0; i < structure->fields->len; i++) {
2295 struct bt_field *member = structure->fields->pdata[i];
2296
2297 if (!member) {
2298 /*
2299 * Structure members are lazily initialized; skip if
2300 * this member has not been allocated yet.
2301 */
2302 continue;
2303 }
2304
2305 ret = bt_field_reset(member);
2306 if (ret) {
2307 BT_LOGE("Failed to reset structure field's field: "
2308 "struct-field-addr=%p, field-addr=%p, "
2309 "index=%" PRId64, field, member, i);
2310 goto end;
2311 }
2312 }
2313 end:
2314 return ret;
2315 }
2316
2317 static
2318 int bt_field_variant_reset(struct bt_field *field)
2319 {
2320 int ret = 0;
2321 struct bt_field_variant *variant;
2322
2323 if (!field) {
2324 BT_LOGD_STR("Invalid parameter: field is NULL.");
2325 ret = -1;
2326 goto end;
2327 }
2328
2329 variant = container_of(field, struct bt_field_variant, parent);
2330 BT_PUT(variant->tag);
2331 BT_PUT(variant->payload);
2332 end:
2333 return ret;
2334 }
2335
2336 static
2337 int bt_field_array_reset(struct bt_field *field)
2338 {
2339 size_t i;
2340 int ret = 0;
2341 struct bt_field_array *array;
2342
2343 if (!field) {
2344 BT_LOGD_STR("Invalid parameter: field is NULL.");
2345 ret = -1;
2346 goto end;
2347 }
2348
2349 array = container_of(field, struct bt_field_array, parent);
2350 for (i = 0; i < array->elements->len; i++) {
2351 struct bt_field *member = array->elements->pdata[i];
2352
2353 if (!member) {
2354 /*
2355 * Array elements are lazily initialized; skip if
2356 * this member has not been allocated yet.
2357 */
2358 continue;
2359 }
2360
2361 ret = bt_field_reset(member);
2362 if (ret) {
2363 BT_LOGE("Failed to reset array field's field: "
2364 "array-field-addr=%p, field-addr=%p, "
2365 "index=%zu", field, member, i);
2366 goto end;
2367 }
2368 }
2369 end:
2370 return ret;
2371 }
2372
2373 static
2374 int bt_field_sequence_reset(struct bt_field *field)
2375 {
2376 int ret = 0;
2377 struct bt_field_sequence *sequence;
2378
2379 if (!field) {
2380 BT_LOGD_STR("Invalid parameter: field is NULL.");
2381 ret = -1;
2382 goto end;
2383 }
2384
2385 sequence = container_of(field, struct bt_field_sequence, parent);
2386 if (sequence->elements) {
2387 g_ptr_array_free(sequence->elements, TRUE);
2388 sequence->elements = NULL;
2389 }
2390 BT_PUT(sequence->length);
2391 end:
2392 return ret;
2393 }
2394
2395 static
2396 int bt_field_string_reset(struct bt_field *field)
2397 {
2398 int ret = 0;
2399 struct bt_field_string *string;
2400
2401 if (!field) {
2402 BT_LOGD_STR("Invalid parameter: field is NULL.");
2403 ret = -1;
2404 goto end;
2405 }
2406
2407 ret = bt_field_generic_reset(field);
2408 if (ret) {
2409 goto end;
2410 }
2411
2412 string = container_of(field, struct bt_field_string, parent);
2413 if (string->payload) {
2414 g_string_truncate(string->payload, 0);
2415 }
2416 end:
2417 return ret;
2418 }
2419
2420 static
2421 int bt_field_integer_serialize(struct bt_field *field,
2422 struct bt_stream_pos *pos,
2423 enum bt_byte_order native_byte_order)
2424 {
2425 int ret = 0;
2426 struct bt_field_integer *integer = container_of(field,
2427 struct bt_field_integer, parent);
2428
2429 BT_LOGV("Serializing integer field: addr=%p, pos-offset=%" PRId64 ", "
2430 "native-bo=%s", field, pos->offset,
2431 bt_byte_order_string(native_byte_order));
2432
2433 if (!bt_field_generic_is_set(field)) {
2434 BT_LOGW_STR("Field's payload is not set.");
2435 ret = -1;
2436 goto end;
2437 }
2438 retry:
2439 ret = bt_field_integer_write(integer, pos, native_byte_order);
2440 if (ret == -EFAULT) {
2441 /*
2442 * The field is too large to fit in the current packet's
2443 * remaining space. Bump the packet size and retry.
2444 */
2445 ret = increase_packet_size(pos);
2446 if (ret) {
2447 BT_LOGE("Cannot increase packet size: ret=%d", ret);
2448 goto end;
2449 }
2450 goto retry;
2451 }
2452 end:
2453 return ret;
2454 }
2455
2456 static
2457 int bt_field_enumeration_serialize(struct bt_field *field,
2458 struct bt_stream_pos *pos,
2459 enum bt_byte_order native_byte_order)
2460 {
2461 struct bt_field_enumeration *enumeration = container_of(
2462 field, struct bt_field_enumeration, parent);
2463
2464 BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
2465 "native-bo=%s", field, pos->offset,
2466 bt_byte_order_string(native_byte_order));
2467 BT_LOGV_STR("Serializing enumeration field's payload field.");
2468 return bt_field_serialize(enumeration->payload, pos,
2469 native_byte_order);
2470 }
2471
2472 static
2473 int bt_field_floating_point_serialize(struct bt_field *field,
2474 struct bt_stream_pos *pos,
2475 enum bt_byte_order native_byte_order)
2476 {
2477 int ret = 0;
2478 struct bt_field_floating_point *floating_point = container_of(field,
2479 struct bt_field_floating_point, parent);
2480
2481 BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", "
2482 "native-bo=%s", field, pos->offset,
2483 bt_byte_order_string(native_byte_order));
2484
2485 if (!bt_field_generic_is_set(field)) {
2486 BT_LOGW_STR("Field's payload is not set.");
2487 ret = -1;
2488 goto end;
2489 }
2490 retry:
2491 ret = bt_field_floating_point_write(floating_point, pos,
2492 native_byte_order);
2493 if (ret == -EFAULT) {
2494 /*
2495 * The field is too large to fit in the current packet's
2496 * remaining space. Bump the packet size and retry.
2497 */
2498 ret = increase_packet_size(pos);
2499 if (ret) {
2500 BT_LOGE("Cannot increase packet size: ret=%d", ret);
2501 goto end;
2502 }
2503 goto retry;
2504 }
2505 end:
2506 return ret;
2507 }
2508
2509 static
2510 int bt_field_structure_serialize(struct bt_field *field,
2511 struct bt_stream_pos *pos,
2512 enum bt_byte_order native_byte_order)
2513 {
2514 int64_t i;
2515 int ret = 0;
2516 struct bt_field_structure *structure = container_of(
2517 field, struct bt_field_structure, parent);
2518
2519 BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", "
2520 "native-bo=%s", field, pos->offset,
2521 bt_byte_order_string(native_byte_order));
2522
2523 while (!bt_stream_pos_access_ok(pos,
2524 offset_align(pos->offset, field->type->alignment))) {
2525 ret = increase_packet_size(pos);
2526 if (ret) {
2527 BT_LOGE("Cannot increase packet size: ret=%d", ret);
2528 goto end;
2529 }
2530 }
2531
2532 if (!bt_stream_pos_align(pos, field->type->alignment)) {
2533 BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", "
2534 "align=%u", pos->offset, field->type->alignment);
2535 ret = -1;
2536 goto end;
2537 }
2538
2539 for (i = 0; i < structure->fields->len; i++) {
2540 struct bt_field *member = g_ptr_array_index(
2541 structure->fields, i);
2542 const char *field_name = NULL;
2543
2544 if (BT_LOG_ON_WARN) {
2545 ret = bt_field_type_structure_get_field_by_index(
2546 field->type, &field_name, NULL, i);
2547 assert(ret == 0);
2548 }
2549
2550 BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", "
2551 "field-addr=%p, index=%" PRId64,
2552 pos->offset, member, i);
2553
2554 if (!member) {
2555 BT_LOGW("Cannot serialize structure field's field: field is not set: "
2556 "struct-field-addr=%p, "
2557 "field-name=\"%s\", index=%" PRId64,
2558 field, field_name, i);
2559 ret = -1;
2560 goto end;
2561 }
2562
2563 ret = bt_field_serialize(member, pos, native_byte_order);
2564 if (ret) {
2565 BT_LOGW("Cannot serialize structure field's field: "
2566 "struct-field-addr=%p, field-addr=%p, "
2567 "field-name=\"%s\", index=%" PRId64,
2568 field->type, member, field_name, i);
2569 break;
2570 }
2571 }
2572 end:
2573 return ret;
2574 }
2575
2576 static
2577 int bt_field_variant_serialize(struct bt_field *field,
2578 struct bt_stream_pos *pos,
2579 enum bt_byte_order native_byte_order)
2580 {
2581 struct bt_field_variant *variant = container_of(
2582 field, struct bt_field_variant, parent);
2583
2584 BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", "
2585 "native-bo=%s", field, pos->offset,
2586 bt_byte_order_string(native_byte_order));
2587 BT_LOGV_STR("Serializing variant field's payload field.");
2588 return bt_field_serialize(variant->payload, pos,
2589 native_byte_order);
2590 }
2591
2592 static
2593 int bt_field_array_serialize(struct bt_field *field,
2594 struct bt_stream_pos *pos,
2595 enum bt_byte_order native_byte_order)
2596 {
2597 int64_t i;
2598 int ret = 0;
2599 struct bt_field_array *array = container_of(
2600 field, struct bt_field_array, parent);
2601
2602 BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", "
2603 "native-bo=%s", field, pos->offset,
2604 bt_byte_order_string(native_byte_order));
2605
2606 for (i = 0; i < array->elements->len; i++) {
2607 struct bt_field *elem_field =
2608 g_ptr_array_index(array->elements, i);
2609
2610 BT_LOGV("Serializing array field's element field: "
2611 "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
2612 pos->offset, elem_field, i);
2613 ret = bt_field_serialize(elem_field, pos,
2614 native_byte_order);
2615 if (ret) {
2616 BT_LOGW("Cannot serialize array field's element field: "
2617 "array-field-addr=%p, field-addr=%p, "
2618 "index=%" PRId64, field, elem_field, i);
2619 goto end;
2620 }
2621 }
2622 end:
2623 return ret;
2624 }
2625
2626 static
2627 int bt_field_sequence_serialize(struct bt_field *field,
2628 struct bt_stream_pos *pos,
2629 enum bt_byte_order native_byte_order)
2630 {
2631 int64_t i;
2632 int ret = 0;
2633 struct bt_field_sequence *sequence = container_of(
2634 field, struct bt_field_sequence, parent);
2635
2636 BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", "
2637 "native-bo=%s", field, pos->offset,
2638 bt_byte_order_string(native_byte_order));
2639
2640 for (i = 0; i < sequence->elements->len; i++) {
2641 struct bt_field *elem_field =
2642 g_ptr_array_index(sequence->elements, i);
2643
2644 BT_LOGV("Serializing sequence field's element field: "
2645 "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
2646 pos->offset, elem_field, i);
2647 ret = bt_field_serialize(elem_field, pos,
2648 native_byte_order);
2649 if (ret) {
2650 BT_LOGW("Cannot serialize sequence field's element field: "
2651 "sequence-field-addr=%p, field-addr=%p, "
2652 "index=%" PRId64, field, elem_field, i);
2653 goto end;
2654 }
2655 }
2656 end:
2657 return ret;
2658 }
2659
2660 static
2661 int bt_field_string_serialize(struct bt_field *field,
2662 struct bt_stream_pos *pos,
2663 enum bt_byte_order native_byte_order)
2664 {
2665 int64_t i;
2666 int ret = 0;
2667 struct bt_field_string *string = container_of(field,
2668 struct bt_field_string, parent);
2669 struct bt_field_type *character_type =
2670 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
2671 struct bt_field *character;
2672
2673 BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", "
2674 "native-bo=%s", field, pos->offset,
2675 bt_byte_order_string(native_byte_order));
2676
2677 BT_LOGV_STR("Creating character field from string field's character field type.");
2678 character = bt_field_create(character_type);
2679
2680 for (i = 0; i < string->payload->len + 1; i++) {
2681 const uint64_t chr = (uint64_t) string->payload->str[i];
2682
2683 ret = bt_field_unsigned_integer_set_value(character, chr);
2684 if (ret) {
2685 BT_LOGW("Cannot set character field's value: "
2686 "pos-offset=%" PRId64 ", field-addr=%p, "
2687 "index=%" PRId64 ", char-int=%" PRIu64,
2688 pos->offset, character, i, chr);
2689 goto end;
2690 }
2691
2692 BT_LOGV("Serializing string field's character field: "
2693 "pos-offset=%" PRId64 ", field-addr=%p, "
2694 "index=%" PRId64 ", char-int=%" PRIu64,
2695 pos->offset, character, i, chr);
2696 ret = bt_field_integer_serialize(character, pos,
2697 native_byte_order);
2698 if (ret) {
2699 BT_LOGW_STR("Cannot serialize character field.");
2700 goto end;
2701 }
2702 }
2703 end:
2704 bt_put(character);
2705 bt_put(character_type);
2706 return ret;
2707 }
2708
2709 static
2710 int bt_field_integer_copy(struct bt_field *src,
2711 struct bt_field *dst)
2712 {
2713 struct bt_field_integer *integer_src, *integer_dst;
2714
2715 BT_LOGD("Copying integer field: src-field-addr=%p, dst-field-addr=%p",
2716 src, dst);
2717 integer_src = container_of(src, struct bt_field_integer, parent);
2718 integer_dst = container_of(dst, struct bt_field_integer, parent);
2719 integer_dst->payload = integer_src->payload;
2720 BT_LOGD_STR("Copied integer field.");
2721 return 0;
2722 }
2723
2724 static
2725 int bt_field_enumeration_copy(struct bt_field *src,
2726 struct bt_field *dst)
2727 {
2728 int ret = 0;
2729 struct bt_field_enumeration *enum_src, *enum_dst;
2730
2731 BT_LOGD("Copying enumeration field: src-field-addr=%p, dst-field-addr=%p",
2732 src, dst);
2733 enum_src = container_of(src, struct bt_field_enumeration, parent);
2734 enum_dst = container_of(dst, struct bt_field_enumeration, parent);
2735
2736 if (enum_src->payload) {
2737 BT_LOGD_STR("Copying enumeration field's payload field.");
2738 enum_dst->payload = bt_field_copy(enum_src->payload);
2739 if (!enum_dst->payload) {
2740 BT_LOGE_STR("Cannot copy enumeration field's payload field.");
2741 ret = -1;
2742 goto end;
2743 }
2744 }
2745
2746 BT_LOGD_STR("Copied enumeration field.");
2747 end:
2748 return ret;
2749 }
2750
2751 static
2752 int bt_field_floating_point_copy(
2753 struct bt_field *src, struct bt_field *dst)
2754 {
2755 struct bt_field_floating_point *float_src, *float_dst;
2756
2757 BT_LOGD("Copying floating point number field: src-field-addr=%p, dst-field-addr=%p",
2758 src, dst);
2759 float_src = container_of(src, struct bt_field_floating_point,
2760 parent);
2761 float_dst = container_of(dst, struct bt_field_floating_point,
2762 parent);
2763 float_dst->payload = float_src->payload;
2764 BT_LOGD_STR("Copied floating point number field.");
2765 return 0;
2766 }
2767
2768 static
2769 int bt_field_structure_copy(struct bt_field *src,
2770 struct bt_field *dst)
2771 {
2772 int ret = 0;
2773 int64_t i;
2774 struct bt_field_structure *struct_src, *struct_dst;
2775
2776 BT_LOGD("Copying structure field: src-field-addr=%p, dst-field-addr=%p",
2777 src, dst);
2778 struct_src = container_of(src, struct bt_field_structure, parent);
2779 struct_dst = container_of(dst, struct bt_field_structure, parent);
2780
2781 g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len);
2782
2783 for (i = 0; i < struct_src->fields->len; i++) {
2784 struct bt_field *field =
2785 g_ptr_array_index(struct_src->fields, i);
2786 struct bt_field *field_copy = NULL;
2787
2788 if (field) {
2789 BT_LOGD("Copying structure field's field: src-field-addr=%p"
2790 "index=%" PRId64, field, i);
2791 field_copy = bt_field_copy(field);
2792 if (!field_copy) {
2793 BT_LOGE("Cannot copy structure field's field: "
2794 "src-field-addr=%p, index=%" PRId64,
2795 field, i);
2796 ret = -1;
2797 goto end;
2798 }
2799 }
2800
2801 BT_MOVE(g_ptr_array_index(struct_dst->fields, i), field_copy);
2802 }
2803
2804 BT_LOGD_STR("Copied structure field.");
2805
2806 end:
2807 return ret;
2808 }
2809
2810 static
2811 int bt_field_variant_copy(struct bt_field *src,
2812 struct bt_field *dst)
2813 {
2814 int ret = 0;
2815 struct bt_field_variant *variant_src, *variant_dst;
2816
2817 BT_LOGD("Copying variant field: src-field-addr=%p, dst-field-addr=%p",
2818 src, dst);
2819 variant_src = container_of(src, struct bt_field_variant, parent);
2820 variant_dst = container_of(dst, struct bt_field_variant, parent);
2821
2822 if (variant_src->tag) {
2823 BT_LOGD_STR("Copying variant field's tag field.");
2824 variant_dst->tag = bt_field_copy(variant_src->tag);
2825 if (!variant_dst->tag) {
2826 BT_LOGE_STR("Cannot copy variant field's tag field.");
2827 ret = -1;
2828 goto end;
2829 }
2830 }
2831 if (variant_src->payload) {
2832 BT_LOGD_STR("Copying variant field's payload field.");
2833 variant_dst->payload = bt_field_copy(variant_src->payload);
2834 if (!variant_dst->payload) {
2835 BT_LOGE_STR("Cannot copy variant field's payload field.");
2836 ret = -1;
2837 goto end;
2838 }
2839 }
2840
2841 BT_LOGD_STR("Copied variant field.");
2842
2843 end:
2844 return ret;
2845 }
2846
2847 static
2848 int bt_field_array_copy(struct bt_field *src,
2849 struct bt_field *dst)
2850 {
2851 int ret = 0;
2852 int64_t i;
2853 struct bt_field_array *array_src, *array_dst;
2854
2855 BT_LOGD("Copying array field: src-field-addr=%p, dst-field-addr=%p",
2856 src, dst);
2857 array_src = container_of(src, struct bt_field_array, parent);
2858 array_dst = container_of(dst, struct bt_field_array, parent);
2859
2860 g_ptr_array_set_size(array_dst->elements, array_src->elements->len);
2861 for (i = 0; i < array_src->elements->len; i++) {
2862 struct bt_field *field =
2863 g_ptr_array_index(array_src->elements, i);
2864 struct bt_field *field_copy = NULL;
2865
2866 if (field) {
2867 BT_LOGD("Copying array field's element field: field-addr=%p, "
2868 "index=%" PRId64, field, i);
2869 field_copy = bt_field_copy(field);
2870 if (!field_copy) {
2871 BT_LOGE("Cannot copy array field's element field: "
2872 "src-field-addr=%p, index=%" PRId64,
2873 field, i);
2874 ret = -1;
2875 goto end;
2876 }
2877 }
2878
2879 g_ptr_array_index(array_dst->elements, i) = field_copy;
2880 }
2881
2882 BT_LOGD_STR("Copied array field.");
2883
2884 end:
2885 return ret;
2886 }
2887
2888 static
2889 int bt_field_sequence_copy(struct bt_field *src,
2890 struct bt_field *dst)
2891 {
2892 int ret = 0;
2893 int64_t i;
2894 struct bt_field_sequence *sequence_src, *sequence_dst;
2895 struct bt_field *src_length;
2896 struct bt_field *dst_length;
2897
2898 BT_LOGD("Copying sequence field: src-field-addr=%p, dst-field-addr=%p",
2899 src, dst);
2900 sequence_src = container_of(src, struct bt_field_sequence, parent);
2901 sequence_dst = container_of(dst, struct bt_field_sequence, parent);
2902
2903 src_length = bt_field_sequence_get_length(src);
2904 if (!src_length) {
2905 /* no length set yet: keep destination sequence empty */
2906 goto end;
2907 }
2908
2909 /* copy source length */
2910 BT_LOGD_STR("Copying sequence field's length field.");
2911 dst_length = bt_field_copy(src_length);
2912 BT_PUT(src_length);
2913 if (!dst_length) {
2914 BT_LOGE_STR("Cannot copy sequence field's length field.");
2915 ret = -1;
2916 goto end;
2917 }
2918
2919 /* this will initialize the destination sequence's internal array */
2920 ret = bt_field_sequence_set_length(dst, dst_length);
2921 bt_put(dst_length);
2922 if (ret) {
2923 BT_LOGE("Cannot set sequence field copy's length field: "
2924 "dst-length-field-addr=%p", dst_length);
2925 ret = -1;
2926 goto end;
2927 }
2928
2929 assert(sequence_dst->elements->len == sequence_src->elements->len);
2930
2931 for (i = 0; i < sequence_src->elements->len; i++) {
2932 struct bt_field *field =
2933 g_ptr_array_index(sequence_src->elements, i);
2934 struct bt_field *field_copy = NULL;
2935
2936 if (field) {
2937 BT_LOGD("Copying sequence field's element field: field-addr=%p, "
2938 "index=%" PRId64, field, i);
2939 field_copy = bt_field_copy(field);
2940 if (!field_copy) {
2941 BT_LOGE("Cannot copy sequence field's element field: "
2942 "src-field-addr=%p, index=%" PRId64,
2943 field, i);
2944 ret = -1;
2945 goto end;
2946 }
2947 }
2948
2949 g_ptr_array_index(sequence_dst->elements, i) = field_copy;
2950 }
2951
2952 BT_LOGD_STR("Copied sequence field.");
2953
2954 end:
2955 return ret;
2956 }
2957
2958 static
2959 int bt_field_string_copy(struct bt_field *src,
2960 struct bt_field *dst)
2961 {
2962 int ret = 0;
2963 struct bt_field_string *string_src, *string_dst;
2964
2965 BT_LOGD("Copying string field: src-field-addr=%p, dst-field-addr=%p",
2966 src, dst);
2967 string_src = container_of(src, struct bt_field_string, parent);
2968 string_dst = container_of(dst, struct bt_field_string, parent);
2969
2970 if (string_src->payload) {
2971 string_dst->payload = g_string_new(string_src->payload->str);
2972 if (!string_dst->payload) {
2973 BT_LOGE_STR("Failed to allocate a GString.");
2974 ret = -1;
2975 goto end;
2976 }
2977 }
2978
2979 BT_LOGD_STR("Copied string field.");
2980
2981 end:
2982 return ret;
2983 }
2984
2985 static
2986 int increase_packet_size(struct bt_stream_pos *pos)
2987 {
2988 int ret;
2989
2990 assert(pos);
2991 BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", "
2992 "cur-packet-size=%" PRIu64,
2993 pos->offset, pos->packet_size);
2994 ret = munmap_align(pos->base_mma);
2995 if (ret) {
2996 BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
2997 ": ret=%d", ret);
2998 goto end;
2999 }
3000
3001 pos->packet_size += PACKET_LEN_INCREMENT;
3002 do {
3003 ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
3004 pos->packet_size / CHAR_BIT);
3005 } while (ret == EINTR);
3006 if (ret) {
3007 BT_LOGE_ERRNO("Failed to preallocate memory space",
3008 ": ret=%d", ret);
3009 errno = EINTR;
3010 ret = -1;
3011 goto end;
3012 }
3013
3014 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
3015 pos->flags, pos->fd, pos->mmap_offset);
3016 if (pos->base_mma == MAP_FAILED) {
3017 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
3018 ": ret=%d", ret);
3019 ret = -1;
3020 }
3021
3022 BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", "
3023 "new-packet-size=%" PRIu64,
3024 pos->offset, pos->packet_size);
3025 assert(pos->packet_size % 8 == 0);
3026
3027 end:
3028 return ret;
3029 }
3030
3031 static
3032 void generic_field_freeze(struct bt_field *field)
3033 {
3034 field->frozen = true;
3035 }
3036
3037 static
3038 void bt_field_enumeration_freeze(struct bt_field *field)
3039 {
3040 struct bt_field_enumeration *enum_field =
3041 container_of(field, struct bt_field_enumeration, parent);
3042
3043 BT_LOGD("Freezing enumeration field object: addr=%p", field);
3044 BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload);
3045 bt_field_freeze(enum_field->payload);
3046 generic_field_freeze(field);
3047 }
3048
3049 static
3050 void bt_field_structure_freeze(struct bt_field *field)
3051 {
3052 int64_t i;
3053 struct bt_field_structure *structure_field =
3054 container_of(field, struct bt_field_structure, parent);
3055
3056 BT_LOGD("Freezing structure field object: addr=%p", field);
3057
3058 for (i = 0; i < structure_field->fields->len; i++) {
3059 struct bt_field *field =
3060 g_ptr_array_index(structure_field->fields, i);
3061
3062 BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
3063 field, i);
3064 bt_field_freeze(field);
3065 }
3066
3067 generic_field_freeze(field);
3068 }
3069
3070 static
3071 void bt_field_variant_freeze(struct bt_field *field)
3072 {
3073 struct bt_field_variant *variant_field =
3074 container_of(field, struct bt_field_variant, parent);
3075
3076 BT_LOGD("Freezing variant field object: addr=%p", field);
3077 BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag);
3078 bt_field_freeze(variant_field->tag);
3079 BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload);
3080 bt_field_freeze(variant_field->payload);
3081 generic_field_freeze(field);
3082 }
3083
3084 static
3085 void bt_field_array_freeze(struct bt_field *field)
3086 {
3087 int64_t i;
3088 struct bt_field_array *array_field =
3089 container_of(field, struct bt_field_array, parent);
3090
3091 BT_LOGD("Freezing array field object: addr=%p", field);
3092
3093 for (i = 0; i < array_field->elements->len; i++) {
3094 struct bt_field *elem_field =
3095 g_ptr_array_index(array_field->elements, i);
3096
3097 BT_LOGD("Freezing array field object's element field: "
3098 "element-field-addr=%p, index=%" PRId64,
3099 elem_field, i);
3100 bt_field_freeze(elem_field);
3101 }
3102
3103 generic_field_freeze(field);
3104 }
3105
3106 static
3107 void bt_field_sequence_freeze(struct bt_field *field)
3108 {
3109 int64_t i;
3110 struct bt_field_sequence *sequence_field =
3111 container_of(field, struct bt_field_sequence, parent);
3112
3113 BT_LOGD("Freezing sequence field object: addr=%p", field);
3114 BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p",
3115 sequence_field->length);
3116 bt_field_freeze(sequence_field->length);
3117
3118 for (i = 0; i < sequence_field->elements->len; i++) {
3119 struct bt_field *elem_field =
3120 g_ptr_array_index(sequence_field->elements, i);
3121
3122 BT_LOGD("Freezing sequence field object's element field: "
3123 "element-field-addr=%p, index=%" PRId64,
3124 elem_field, i);
3125 bt_field_freeze(elem_field);
3126 }
3127
3128 generic_field_freeze(field);
3129 }
3130
3131 BT_HIDDEN
3132 void bt_field_freeze(struct bt_field *field)
3133 {
3134 enum bt_field_type_id type_id;
3135
3136 if (!field) {
3137 goto end;
3138 }
3139
3140 if (field->frozen) {
3141 goto end;
3142 }
3143
3144 BT_LOGD("Freezing field object: addr=%p", field);
3145 type_id = bt_field_get_type_id(field);
3146 assert(type_id > BT_FIELD_TYPE_ID_UNKNOWN &&
3147 type_id < BT_FIELD_TYPE_ID_NR);
3148 field_freeze_funcs[type_id](field);
3149 end:
3150 return;
3151 }
3152
3153 static
3154 bt_bool bt_field_generic_is_set(struct bt_field *field)
3155 {
3156 return field && field->payload_set;
3157 }
3158
3159 static
3160 bt_bool bt_field_enumeration_is_set(struct bt_field *field)
3161 {
3162 bt_bool is_set = BT_FALSE;
3163 struct bt_field_enumeration *enumeration;
3164
3165 if (!field) {
3166 goto end;
3167 }
3168
3169 enumeration = container_of(field, struct bt_field_enumeration,
3170 parent);
3171 if (!enumeration->payload) {
3172 goto end;
3173 }
3174
3175 is_set = bt_field_is_set(enumeration->payload);
3176 end:
3177 return is_set;
3178 }
3179
3180 static
3181 bt_bool bt_field_structure_is_set(struct bt_field *field)
3182 {
3183 bt_bool is_set = BT_FALSE;
3184 size_t i;
3185 struct bt_field_structure *structure;
3186
3187 if (!field) {
3188 goto end;
3189 }
3190
3191 structure = container_of(field, struct bt_field_structure, parent);
3192 for (i = 0; i < structure->fields->len; i++) {
3193 is_set = bt_field_is_set(
3194 structure->fields->pdata[i]);
3195 if (!is_set) {
3196 goto end;
3197 }
3198 }
3199 end:
3200 return is_set;
3201 }
3202
3203 static
3204 bt_bool bt_field_variant_is_set(struct bt_field *field)
3205 {
3206 bt_bool is_set = BT_FALSE;
3207 struct bt_field_variant *variant;
3208
3209 if (!field) {
3210 goto end;
3211 }
3212
3213 variant = container_of(field, struct bt_field_variant, parent);
3214 is_set = bt_field_is_set(variant->payload);
3215 end:
3216 return is_set;
3217 }
3218
3219 static
3220 bt_bool bt_field_array_is_set(struct bt_field *field)
3221 {
3222 size_t i;
3223 bt_bool is_set = BT_FALSE;
3224 struct bt_field_array *array;
3225
3226 if (!field) {
3227 goto end;
3228 }
3229
3230 array = container_of(field, struct bt_field_array, parent);
3231 for (i = 0; i < array->elements->len; i++) {
3232 is_set = bt_field_is_set(array->elements->pdata[i]);
3233 if (!is_set) {
3234 goto end;
3235 }
3236 }
3237 end:
3238 return is_set;
3239 }
3240
3241 static
3242 bt_bool bt_field_sequence_is_set(struct bt_field *field)
3243 {
3244 size_t i;
3245 bt_bool is_set = BT_FALSE;
3246 struct bt_field_sequence *sequence;
3247
3248 if (!field) {
3249 goto end;
3250 }
3251
3252 sequence = container_of(field, struct bt_field_sequence, parent);
3253 if (!sequence->elements) {
3254 goto end;
3255 }
3256
3257 for (i = 0; i < sequence->elements->len; i++) {
3258 is_set = bt_field_is_set(sequence->elements->pdata[i]);
3259 if (!is_set) {
3260 goto end;
3261 }
3262 }
3263 end:
3264 return is_set;
3265 }
This page took 0.116609 seconds and 5 git commands to generate.