Replace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()
[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 <babeltrace/assert-internal.h>
41 #include <babeltrace/assert-pre-internal.h>
42 #include <inttypes.h>
43
44 static
45 struct bt_field *bt_field_integer_create(struct bt_field_type *);
46 static
47 struct bt_field *bt_field_enumeration_create(struct bt_field_type *);
48 static
49 struct bt_field *bt_field_floating_point_create(struct bt_field_type *);
50 static
51 struct bt_field *bt_field_structure_create(struct bt_field_type *);
52 static
53 struct bt_field *bt_field_variant_create(struct bt_field_type *);
54 static
55 struct bt_field *bt_field_array_create(struct bt_field_type *);
56 static
57 struct bt_field *bt_field_sequence_create(struct bt_field_type *);
58 static
59 struct bt_field *bt_field_string_create(struct bt_field_type *);
60
61 static
62 void bt_field_destroy(struct bt_object *);
63 static
64 void bt_field_integer_destroy(struct bt_field *);
65 static
66 void bt_field_enumeration_destroy_recursive(struct bt_field *);
67 static
68 void bt_field_floating_point_destroy(struct bt_field *);
69 static
70 void bt_field_structure_destroy_recursive(struct bt_field *);
71 static
72 void bt_field_variant_destroy_recursive(struct bt_field *);
73 static
74 void bt_field_array_destroy_recursive(struct bt_field *);
75 static
76 void bt_field_sequence_destroy_recursive(struct bt_field *);
77 static
78 void bt_field_string_destroy(struct bt_field *);
79
80 static
81 int bt_field_generic_validate(struct bt_field *);
82 static
83 int bt_field_structure_validate_recursive(struct bt_field *);
84 static
85 int bt_field_variant_validate_recursive(struct bt_field *);
86 static
87 int bt_field_enumeration_validate_recursive(struct bt_field *);
88 static
89 int bt_field_array_validate_recursive(struct bt_field *);
90 static
91 int bt_field_sequence_validate_recursive(struct bt_field *);
92
93 static
94 void bt_field_generic_reset(struct bt_field *);
95 static
96 void bt_field_structure_reset_recursive(struct bt_field *);
97 static
98 void bt_field_variant_reset_recursive(struct bt_field *);
99 static
100 void bt_field_enumeration_reset_recursive(struct bt_field *);
101 static
102 void bt_field_array_reset_recursive(struct bt_field *);
103 static
104 void bt_field_sequence_reset_recursive(struct bt_field *);
105 static
106 void bt_field_string_reset_recursive(struct bt_field *);
107
108 static
109 int bt_field_integer_serialize(struct bt_field *,
110 struct bt_stream_pos *, enum bt_byte_order);
111 static
112 int bt_field_enumeration_serialize_recursive(struct bt_field *,
113 struct bt_stream_pos *, enum bt_byte_order);
114 static
115 int bt_field_floating_point_serialize(struct bt_field *,
116 struct bt_stream_pos *, enum bt_byte_order);
117 static
118 int bt_field_structure_serialize_recursive(struct bt_field *,
119 struct bt_stream_pos *, enum bt_byte_order);
120 static
121 int bt_field_variant_serialize_recursive(struct bt_field *,
122 struct bt_stream_pos *, enum bt_byte_order);
123 static
124 int bt_field_array_serialize_recursive(struct bt_field *,
125 struct bt_stream_pos *, enum bt_byte_order);
126 static
127 int bt_field_sequence_serialize_recursive(struct bt_field *,
128 struct bt_stream_pos *, enum bt_byte_order);
129 static
130 int bt_field_string_serialize(struct bt_field *,
131 struct bt_stream_pos *, enum bt_byte_order);
132
133 static
134 int bt_field_integer_copy(struct bt_field *, struct bt_field *);
135 static
136 int bt_field_enumeration_copy_recursive(struct bt_field *, struct bt_field *);
137 static
138 int bt_field_floating_point_copy(struct bt_field *, struct bt_field *);
139 static
140 int bt_field_structure_copy_recursive(struct bt_field *, struct bt_field *);
141 static
142 int bt_field_variant_copy_recursive(struct bt_field *, struct bt_field *);
143 static
144 int bt_field_array_copy_recursive(struct bt_field *, struct bt_field *);
145 static
146 int bt_field_sequence_copy_recursive(struct bt_field *, struct bt_field *);
147 static
148 int bt_field_string_copy_recursive(struct bt_field *, struct bt_field *);
149
150 static
151 void generic_field_freeze(struct bt_field *);
152 static
153 void bt_field_enumeration_freeze_recursive(struct bt_field *);
154 static
155 void bt_field_structure_freeze_recursive(struct bt_field *);
156 static
157 void bt_field_variant_freeze_recursive(struct bt_field *);
158 static
159 void bt_field_array_freeze_recursive(struct bt_field *);
160 static
161 void bt_field_sequence_freeze_recursive(struct bt_field *);
162
163 static
164 bt_bool bt_field_generic_is_set(struct bt_field *);
165 static
166 bt_bool bt_field_structure_is_set_recursive(struct bt_field *);
167 static
168 bt_bool bt_field_variant_is_set_recursive(struct bt_field *);
169 static
170 bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *);
171 static
172 bt_bool bt_field_array_is_set_recursive(struct bt_field *);
173 static
174 bt_bool bt_field_sequence_is_set_recursive(struct bt_field *);
175
176 static
177 int increase_packet_size(struct bt_stream_pos *pos);
178
179 static
180 struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = {
181 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create,
182 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create,
183 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create,
184 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create,
185 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create,
186 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create,
187 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create,
188 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create,
189 };
190
191 static
192 void (* const field_destroy_funcs[])(struct bt_field *) = {
193 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy,
194 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy_recursive,
195 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy,
196 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive,
197 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive,
198 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive,
199 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive,
200 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy,
201 };
202
203 static
204 int (* const field_validate_funcs[])(struct bt_field *) = {
205 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_validate,
206 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_validate_recursive,
207 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_validate,
208 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_validate_recursive,
209 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_validate_recursive,
210 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_validate_recursive,
211 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_validate_recursive,
212 [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_validate,
213 };
214
215 static
216 void (* const field_reset_funcs[])(struct bt_field *) = {
217 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_reset,
218 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_reset_recursive,
219 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_reset,
220 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_reset_recursive,
221 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_reset_recursive,
222 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_reset_recursive,
223 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_reset_recursive,
224 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_reset_recursive,
225 };
226
227 static
228 int (* const field_serialize_funcs[])(struct bt_field *,
229 struct bt_stream_pos *, enum bt_byte_order) = {
230 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_serialize,
231 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_serialize_recursive,
232 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_serialize,
233 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_serialize_recursive,
234 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_serialize_recursive,
235 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_serialize_recursive,
236 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_serialize_recursive,
237 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_serialize,
238 };
239
240 static
241 int (* const field_copy_funcs[])(struct bt_field *,
242 struct bt_field *) = {
243 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_copy,
244 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_copy_recursive,
245 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_copy,
246 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_copy_recursive,
247 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_copy_recursive,
248 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_copy_recursive,
249 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_copy_recursive,
250 [BT_FIELD_TYPE_ID_STRING] = bt_field_string_copy_recursive,
251 };
252
253 static
254 void (* const field_freeze_funcs[])(struct bt_field *) = {
255 [BT_FIELD_TYPE_ID_INTEGER] = generic_field_freeze,
256 [BT_FIELD_TYPE_ID_FLOAT] = generic_field_freeze,
257 [BT_FIELD_TYPE_ID_STRING] = generic_field_freeze,
258 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_freeze_recursive,
259 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_freeze_recursive,
260 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_freeze_recursive,
261 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_freeze_recursive,
262 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_freeze_recursive,
263 };
264
265 static
266 bt_bool (* const field_is_set_funcs[])(struct bt_field *) = {
267 [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_is_set,
268 [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_is_set_recursive,
269 [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_is_set,
270 [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_is_set_recursive,
271 [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_is_set_recursive,
272 [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_is_set_recursive,
273 [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_is_set_recursive,
274 [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_is_set,
275 };
276
277 BT_ASSERT_FUNC
278 static inline bool field_type_has_known_id(struct bt_field_type *ft)
279 {
280 return ft->id > BT_FIELD_TYPE_ID_UNKNOWN ||
281 ft->id < BT_FIELD_TYPE_ID_NR;
282 }
283
284 #define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name) \
285 BT_ASSERT_PRE((_field)->type->id == (_type_id), \
286 _name " has the wrong type ID: expected-type-id=%s, " \
287 "%![field-]+f", bt_field_type_id_string(_type_id), \
288 (_field))
289
290 #define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \
291 BT_ASSERT_PRE(bt_field_is_set_recursive(_field), \
292 _name " is not set: %!+f", (_field))
293
294 #define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \
295 BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+f", (_field))
296
297 struct bt_field *bt_field_create(struct bt_field_type *type)
298 {
299 struct bt_field *field = NULL;
300 enum bt_field_type_id type_id;
301
302 BT_ASSERT_PRE_NON_NULL(type, "Field type");
303 BT_ASSERT(field_type_has_known_id(type));
304 BT_ASSERT_PRE(bt_field_type_validate(type) == 0,
305 "Field type is invalid: %!+F", type);
306
307 type_id = bt_field_type_get_type_id(type);
308 field = field_create_funcs[type_id](type);
309 if (!field) {
310 goto error;
311 }
312
313 /* The type's declaration can't change after this point */
314 bt_field_type_freeze(type);
315 bt_get(type);
316 bt_object_init(field, bt_field_destroy);
317 field->type = type;
318 error:
319 return field;
320 }
321
322 /* Pre-2.0 CTF writer backward compatibility */
323 void bt_ctf_field_get(struct bt_field *field)
324 {
325 bt_get(field);
326 }
327
328 /* Pre-2.0 CTF writer backward compatibility */
329 void bt_ctf_field_put(struct bt_field *field)
330 {
331 bt_put(field);
332 }
333
334 struct bt_field_type *bt_field_get_type(struct bt_field *field)
335 {
336 struct bt_field_type *ret = NULL;
337
338 BT_ASSERT_PRE_NON_NULL(field, "Field");
339 ret = field->type;
340 bt_get(ret);
341 return ret;
342 }
343
344 enum bt_field_type_id bt_field_get_type_id(struct bt_field *field)
345 {
346 BT_ASSERT_PRE_NON_NULL(field, "Field");
347 return bt_field_type_get_type_id(field->type);
348 }
349
350 bt_bool bt_field_is_integer(struct bt_field *field)
351 {
352 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_INTEGER;
353 }
354
355 bt_bool bt_field_is_floating_point(struct bt_field *field)
356 {
357 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_FLOAT;
358 }
359
360 bt_bool bt_field_is_enumeration(struct bt_field *field)
361 {
362 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ENUM;
363 }
364
365 bt_bool bt_field_is_string(struct bt_field *field)
366 {
367 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING;
368 }
369
370 bt_bool bt_field_is_structure(struct bt_field *field)
371 {
372 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRUCT;
373 }
374
375 bt_bool bt_field_is_array(struct bt_field *field)
376 {
377 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ARRAY;
378 }
379
380 bt_bool bt_field_is_sequence(struct bt_field *field)
381 {
382 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SEQUENCE;
383 }
384
385 bt_bool bt_field_is_variant(struct bt_field *field)
386 {
387 return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT;
388 }
389
390 BT_HIDDEN
391 int64_t bt_field_sequence_get_int_length(struct bt_field *field)
392 {
393 struct bt_field_sequence *sequence;
394 int64_t ret;
395
396 BT_ASSERT(field);
397 BT_ASSERT(bt_field_type_get_type_id(field->type) ==
398 BT_FIELD_TYPE_ID_SEQUENCE);
399 sequence = container_of(field, struct bt_field_sequence, parent);
400 if (!sequence->length) {
401 ret = -1;
402 goto end;
403 }
404
405 ret = (int64_t) sequence->elements->len;
406
407 end:
408 return ret;
409 }
410
411 struct bt_field *bt_field_sequence_get_length(
412 struct bt_field *field)
413 {
414 struct bt_field *ret = NULL;
415 struct bt_field_sequence *sequence;
416
417 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
418 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
419 "Field");
420 sequence = container_of(field, struct bt_field_sequence, parent);
421 ret = sequence->length;
422 bt_get(ret);
423 return ret;
424 }
425
426 int bt_field_sequence_set_length(struct bt_field *field,
427 struct bt_field *length_field)
428 {
429 int ret = 0;
430 struct bt_field_integer *length;
431 struct bt_field_sequence *sequence;
432 uint64_t sequence_length;
433
434 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
435 BT_ASSERT_PRE_NON_NULL(length_field, "Length field");
436 BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field");
437 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(length_field, BT_FIELD_TYPE_ID_INTEGER,
438 "Length field");
439 BT_ASSERT_PRE(!bt_field_type_integer_is_signed(length_field->type),
440 "Length field's type is signed: %!+f", length_field);
441 BT_ASSERT_PRE_FIELD_IS_SET(length_field, "Length field");
442
443 length = container_of(length_field, struct bt_field_integer,
444 parent);
445 sequence_length = length->payload.unsignd;
446 sequence = container_of(field, struct bt_field_sequence, parent);
447 if (sequence->elements) {
448 g_ptr_array_free(sequence->elements, TRUE);
449 bt_put(sequence->length);
450 }
451
452 sequence->elements = g_ptr_array_sized_new((size_t) sequence_length);
453 if (!sequence->elements) {
454 BT_LOGE_STR("Failed to allocate a GPtrArray.");
455 ret = -1;
456 goto end;
457 }
458
459 g_ptr_array_set_free_func(sequence->elements,
460 (GDestroyNotify) bt_put);
461 g_ptr_array_set_size(sequence->elements, (size_t) sequence_length);
462 bt_get(length_field);
463 sequence->length = length_field;
464 bt_field_freeze_recursive(length_field);
465
466 end:
467 return ret;
468 }
469
470 struct bt_field *bt_field_structure_get_field_by_name(
471 struct bt_field *field, const char *name)
472 {
473 struct bt_field *ret = NULL;
474 GQuark field_quark;
475 struct bt_field_structure *structure;
476 size_t index;
477 GHashTable *field_name_to_index;
478
479 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
480 BT_ASSERT_PRE_NON_NULL(name, "Field name");
481 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field");
482 field_name_to_index =
483 container_of(field->type, struct bt_field_type_structure,
484 parent)->field_name_to_index;
485 field_quark = g_quark_from_string(name);
486 structure = container_of(field, struct bt_field_structure, parent);
487 if (!g_hash_table_lookup_extended(field_name_to_index,
488 GUINT_TO_POINTER(field_quark),
489 NULL, (gpointer *)&index)) {
490 BT_LOGV("Invalid parameter: no such field in structure field's type: "
491 "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"",
492 field, field->type, name);
493 goto error;
494 }
495
496 ret = bt_get(structure->fields->pdata[index]);
497 BT_ASSERT(ret);
498
499 error:
500 return ret;
501 }
502
503 struct bt_field *bt_field_structure_get_field_by_index(
504 struct bt_field *field, uint64_t index)
505 {
506 struct bt_field_structure *structure;
507 struct bt_field *ret = NULL;
508
509 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
510 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field");
511 structure = container_of(field, struct bt_field_structure, parent);
512 BT_ASSERT_PRE(index < structure->fields->len,
513 "Index is out of bound: %![struct-field-]+f, "
514 "index=%" PRIu64 ", count=%u", field, index,
515 structure->fields->len);
516 ret = bt_get(structure->fields->pdata[index]);
517 return ret;
518 }
519
520 BT_ASSERT_PRE_FUNC
521 static inline bool field_to_set_has_expected_type(struct bt_field *struct_field,
522 const char *name, struct bt_field *value)
523 {
524 bool ret = true;
525 struct bt_field_type *expected_field_type = NULL;
526
527 expected_field_type =
528 bt_field_type_structure_get_field_type_by_name(
529 struct_field->type, name);
530
531 if (bt_field_type_compare(expected_field_type, value->type)) {
532 BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: "
533 "%![value-ft-]+F, %![expected-ft-]+F", value->type,
534 expected_field_type);
535 ret = false;
536 goto end;
537 }
538
539 end:
540 bt_put(expected_field_type);
541 return ret;
542 }
543
544 int bt_field_structure_set_field_by_name(struct bt_field *field,
545 const char *name, struct bt_field *value)
546 {
547 int ret = 0;
548 GQuark field_quark;
549 struct bt_field_structure *structure;
550 size_t index;
551 GHashTable *field_name_to_index;
552
553 BT_ASSERT_PRE_NON_NULL(field, "Structure field");
554 BT_ASSERT_PRE_NON_NULL(name, "Field name");
555 BT_ASSERT_PRE_NON_NULL(value, "Value field");
556 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT,
557 "Parent field");
558 BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value),
559 "Value field's type is different from the expected field type.");
560 field_quark = g_quark_from_string(name);
561 structure = container_of(field, struct bt_field_structure, parent);
562 field_name_to_index =
563 container_of(field->type, struct bt_field_type_structure,
564 parent)->field_name_to_index;
565 if (!g_hash_table_lookup_extended(field_name_to_index,
566 GUINT_TO_POINTER(field_quark), NULL,
567 (gpointer *) &index)) {
568 BT_LOGV("Invalid parameter: no such field in structure field's type: "
569 "struct-field-addr=%p, struct-ft-addr=%p, "
570 "field-ft-addr=%p, name=\"%s\"",
571 field, field->type, value->type, name);
572 ret = -1;
573 goto end;
574 }
575 bt_get(value);
576 BT_MOVE(structure->fields->pdata[index], value);
577
578 end:
579 return ret;
580 }
581
582 struct bt_field *bt_field_array_get_field(struct bt_field *field,
583 uint64_t index)
584 {
585 struct bt_field *new_field = NULL;
586 struct bt_field_type *field_type = NULL;
587 struct bt_field_array *array;
588
589 BT_ASSERT_PRE_NON_NULL(field, "Array field");
590 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field");
591 array = container_of(field, struct bt_field_array, parent);
592 BT_ASSERT_PRE(index < array->elements->len,
593 "Index is out of bound: %![array-field-]+f, "
594 "index=%" PRIu64 ", count=%u", field,
595 index, array->elements->len);
596
597 field_type = bt_field_type_array_get_element_type(field->type);
598 if (array->elements->pdata[(size_t) index]) {
599 new_field = array->elements->pdata[(size_t) index];
600 goto end;
601 }
602
603 /* We don't want to modify this field if it's frozen */
604 BT_ASSERT_PRE_FIELD_HOT(field, "Array field");
605 new_field = bt_field_create(field_type);
606 array->elements->pdata[(size_t)index] = new_field;
607
608 end:
609 bt_put(field_type);
610 bt_get(new_field);
611 return new_field;
612 }
613
614 struct bt_field *bt_field_sequence_get_field(struct bt_field *field,
615 uint64_t index)
616 {
617 struct bt_field *new_field = NULL;
618 struct bt_field_type *field_type = NULL;
619 struct bt_field_sequence *sequence;
620
621 BT_ASSERT_PRE_NON_NULL(field, "Sequence field");
622 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE,
623 "Field");
624 sequence = container_of(field, struct bt_field_sequence, parent);
625 BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array");
626 BT_ASSERT_PRE(index < sequence->elements->len,
627 "Index is out of bound: %![seq-field-]+f, "
628 "index=%" PRIu64 ", count=%u", field, index,
629 sequence->elements->len);
630 field_type = bt_field_type_sequence_get_element_type(field->type);
631 if (sequence->elements->pdata[(size_t) index]) {
632 new_field = sequence->elements->pdata[(size_t) index];
633 goto end;
634 }
635
636 /* We don't want to modify this field if it's frozen */
637 BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field");
638 new_field = bt_field_create(field_type);
639 sequence->elements->pdata[(size_t) index] = new_field;
640
641 end:
642 bt_put(field_type);
643 bt_get(new_field);
644 return new_field;
645 }
646
647 struct bt_field *bt_field_variant_get_field(struct bt_field *field,
648 struct bt_field *tag_field)
649 {
650 struct bt_field *new_field = NULL;
651 struct bt_field_variant *variant;
652 struct bt_field_type_variant *variant_type;
653 struct bt_field_type *field_type;
654 struct bt_field *tag_enum = NULL;
655 struct bt_field_integer *tag_enum_integer;
656 int64_t tag_enum_value;
657
658 BT_ASSERT_PRE_NON_NULL(field, "Variant field");
659 BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field");
660 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT,
661 "Variant field");
662 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM,
663 "Tag field");
664 variant = container_of(field, struct bt_field_variant, parent);
665 variant_type = container_of(field->type,
666 struct bt_field_type_variant, parent);
667 tag_enum = bt_field_enumeration_get_container(tag_field);
668 BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container");
669 tag_enum_integer = container_of(tag_enum, struct bt_field_integer,
670 parent);
671 BT_ASSERT_PRE(bt_field_validate_recursive(tag_field) == 0,
672 "Tag field is invalid: %!+f", tag_field);
673 tag_enum_value = tag_enum_integer->payload.signd;
674
675 /*
676 * If the variant currently has a tag and a payload, and if the
677 * requested tag value is the same as the current one, return
678 * the current payload instead of creating a fresh one.
679 */
680 if (variant->tag && variant->payload) {
681 struct bt_field *cur_tag_container = NULL;
682 struct bt_field_integer *cur_tag_enum_integer;
683 int64_t cur_tag_value;
684
685 cur_tag_container =
686 bt_field_enumeration_get_container(variant->tag);
687 BT_ASSERT(cur_tag_container);
688 cur_tag_enum_integer = container_of(cur_tag_container,
689 struct bt_field_integer, parent);
690 bt_put(cur_tag_container);
691 cur_tag_value = cur_tag_enum_integer->payload.signd;
692
693 if (cur_tag_value == tag_enum_value) {
694 new_field = variant->payload;
695 bt_get(new_field);
696 goto end;
697 }
698 }
699
700 /* We don't want to modify this field if it's frozen */
701 BT_ASSERT_PRE_FIELD_HOT(field, "Variant field");
702 field_type = bt_field_type_variant_get_field_type_signed(
703 variant_type, tag_enum_value);
704
705 /* It's the caller's job to make sure the tag's value is valid */
706 BT_ASSERT_PRE(field_type,
707 "Variant field's type does not contain a field type for "
708 "this tag value: tag-value-signed=%" PRId64 ", "
709 "%![var-ft-]+F, %![tag-field-]+f", tag_enum_value,
710 variant_type, tag_field);
711
712 new_field = bt_field_create(field_type);
713 if (!new_field) {
714 BT_LOGW("Cannot create field: "
715 "variant-field-addr=%p, variant-ft-addr=%p, "
716 "field-ft-addr=%p", field, field->type, field_type);
717 goto end;
718 }
719
720 bt_put(variant->tag);
721 bt_put(variant->payload);
722 bt_get(new_field);
723 bt_get(tag_field);
724 variant->tag = tag_field;
725 variant->payload = new_field;
726
727 end:
728 bt_put(tag_enum);
729 return new_field;
730 }
731
732 struct bt_field *bt_field_variant_get_current_field(
733 struct bt_field *variant_field)
734 {
735 struct bt_field_variant *variant;
736
737 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
738 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT,
739 "Field");
740 variant = container_of(variant_field, struct bt_field_variant,
741 parent);
742 return bt_get(variant->payload);
743 }
744
745 struct bt_field *bt_field_variant_get_tag(struct bt_field *variant_field)
746 {
747 struct bt_field_variant *variant;
748
749 BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field");
750 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT,
751 "Field");
752 variant = container_of(variant_field, struct bt_field_variant,
753 parent);
754 return bt_get(variant->tag);
755 }
756
757 struct bt_field *bt_field_enumeration_get_container(struct bt_field *field)
758 {
759 struct bt_field *container = NULL;
760 struct bt_field_enumeration *enumeration;
761
762 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
763 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field");
764 enumeration = container_of(field, struct bt_field_enumeration,
765 parent);
766 if (!enumeration->payload) {
767 struct bt_field_type_enumeration *enumeration_type;
768
769 /* We don't want to modify this field if it's frozen */
770 BT_ASSERT_PRE_FIELD_HOT(field, "Enumeration field");
771
772 enumeration_type = container_of(field->type,
773 struct bt_field_type_enumeration, parent);
774 enumeration->payload =
775 bt_field_create(enumeration_type->container);
776 }
777
778 container = enumeration->payload;
779 return bt_get(container);
780 }
781
782 struct bt_field_type_enumeration_mapping_iterator *
783 bt_field_enumeration_get_mappings(struct bt_field *field)
784 {
785 int ret;
786 struct bt_field *container = NULL;
787 struct bt_field_type_integer *integer_type = NULL;
788 struct bt_field_type_enumeration_mapping_iterator *iter = NULL;
789
790 BT_ASSERT_PRE_NON_NULL(field, "Enumeration field");
791 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field");
792 container = bt_field_enumeration_get_container(field);
793 BT_ASSERT_PRE(container,
794 "Enumeration field has no container field: %!+f", field);
795 BT_ASSERT(container->type);
796 integer_type = container_of(container->type,
797 struct bt_field_type_integer, parent);
798 BT_ASSERT_PRE_FIELD_IS_SET(container,
799 "Enumeration field's payload field");
800
801 if (!integer_type->is_signed) {
802 uint64_t value;
803
804 ret = bt_field_unsigned_integer_get_value(container, &value);
805 BT_ASSERT(ret == 0);
806 iter = bt_field_type_enumeration_find_mappings_by_unsigned_value(
807 field->type, value);
808 } else {
809 int64_t value;
810
811 ret = bt_field_signed_integer_get_value(container, &value);
812 BT_ASSERT(ret == 0);
813 iter = bt_field_type_enumeration_find_mappings_by_signed_value(
814 field->type, value);
815 }
816
817 bt_put(container);
818 return iter;
819 }
820
821 int bt_field_signed_integer_get_value(struct bt_field *field, int64_t *value)
822 {
823 struct bt_field_integer *integer;
824 struct bt_field_type_integer *integer_type;
825
826 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
827 BT_ASSERT_PRE_NON_NULL(value, "Value");
828 BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
829 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
830 integer_type = container_of(field->type,
831 struct bt_field_type_integer, parent);
832 BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type),
833 "Field's type is unsigned: %!+f", field);
834 integer = container_of(field,
835 struct bt_field_integer, parent);
836 *value = integer->payload.signd;
837 return 0;
838 }
839
840 BT_ASSERT_PRE_FUNC
841 static inline bool value_is_in_range_signed(unsigned int size, int64_t value)
842 {
843 bool ret = true;
844 int64_t min_value, max_value;
845
846 min_value = -(1ULL << (size - 1));
847 max_value = (1ULL << (size - 1)) - 1;
848 if (value < min_value || value > max_value) {
849 BT_LOGF("Value is out of bounds: value=%" PRId64 ", "
850 "min-value=%" PRId64 ", max-value=%" PRId64,
851 value, min_value, max_value);
852 ret = false;
853 }
854
855 return ret;
856 }
857
858 int bt_field_signed_integer_set_value(struct bt_field *field, int64_t value)
859 {
860 int ret = 0;
861 struct bt_field_integer *integer;
862 struct bt_field_type_integer *integer_type;
863
864 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
865 BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
866 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
867 integer = container_of(field, struct bt_field_integer, parent);
868 integer_type = container_of(field->type,
869 struct bt_field_type_integer, parent);
870 BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type),
871 "Field's type is unsigned: %!+f", field);
872 BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value),
873 "Value is out of bounds: value=%" PRId64 ", %![field-]+f",
874 value, field);
875 integer->payload.signd = value;
876 bt_field_set(field, true);
877 return ret;
878 }
879
880 int bt_field_unsigned_integer_get_value(struct bt_field *field, uint64_t *value)
881 {
882 struct bt_field_integer *integer;
883 struct bt_field_type_integer *integer_type;
884
885 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
886 BT_ASSERT_PRE_NON_NULL(value, "Value");
887 BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
888 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
889 integer_type = container_of(field->type,
890 struct bt_field_type_integer, parent);
891 BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type),
892 "Field's type is signed: %!+f", field);
893 integer = container_of(field, struct bt_field_integer, parent);
894 *value = integer->payload.unsignd;
895 return 0;
896 }
897
898 BT_ASSERT_PRE_FUNC
899 static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value)
900 {
901 bool ret = true;
902 int64_t max_value;
903
904 max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1;
905 if (value > max_value) {
906 BT_LOGF("Value is out of bounds: value=%" PRIu64 ", "
907 "max-value=%" PRIu64,
908 value, max_value);
909 ret = false;
910 }
911
912 return ret;
913 }
914
915 int bt_field_unsigned_integer_set_value(struct bt_field *field, uint64_t value)
916 {
917 struct bt_field_integer *integer;
918 struct bt_field_type_integer *integer_type;
919
920 BT_ASSERT_PRE_NON_NULL(field, "Integer field");
921 BT_ASSERT_PRE_FIELD_HOT(field, "Integer field");
922 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field");
923 integer = container_of(field, struct bt_field_integer, parent);
924 integer_type = container_of(field->type,
925 struct bt_field_type_integer, parent);
926 BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type),
927 "Field's type is signed: %!+f", field);
928 BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value),
929 "Value is out of bounds: value=%" PRIu64 ", %![field-]+f",
930 value, field);
931 integer->payload.unsignd = value;
932 bt_field_set(field, true);
933 return 0;
934 }
935
936 int bt_field_floating_point_get_value(struct bt_field *field, double *value)
937 {
938 struct bt_field_floating_point *floating_point;
939
940 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
941 BT_ASSERT_PRE_NON_NULL(value, "Value");
942 BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field");
943 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field");
944 floating_point = container_of(field,
945 struct bt_field_floating_point, parent);
946 *value = floating_point->payload;
947 return 0;
948 }
949
950 int bt_field_floating_point_set_value(struct bt_field *field, double value)
951 {
952 struct bt_field_floating_point *floating_point;
953
954 BT_ASSERT_PRE_NON_NULL(field, "Floating point number field");
955 BT_ASSERT_PRE_FIELD_HOT(field, "Floating point number field");
956 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field");
957 floating_point = container_of(field, struct bt_field_floating_point,
958 parent);
959 floating_point->payload = value;
960 bt_field_set(field, true);
961 return 0;
962 }
963
964 const char *bt_field_string_get_value(struct bt_field *field)
965 {
966 struct bt_field_string *string;
967
968 BT_ASSERT_PRE_NON_NULL(field, "String field");
969 BT_ASSERT_PRE_FIELD_IS_SET(field, "String field");
970 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
971 string = container_of(field, struct bt_field_string, parent);
972 return string->payload->str;
973 }
974
975 int bt_field_string_set_value(struct bt_field *field, const char *value)
976 {
977 struct bt_field_string *string;
978
979 BT_ASSERT_PRE_NON_NULL(field, "String field");
980 BT_ASSERT_PRE_NON_NULL(value, "Value");
981 BT_ASSERT_PRE_FIELD_HOT(field, "String field");
982 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
983 string = container_of(field, struct bt_field_string, parent);
984 if (string->payload) {
985 g_string_assign(string->payload, value);
986 } else {
987 string->payload = g_string_new(value);
988 }
989
990 bt_field_set(field, true);
991 return 0;
992 }
993
994 int bt_field_string_append(struct bt_field *field, const char *value)
995 {
996 struct bt_field_string *string_field;
997
998 BT_ASSERT_PRE_NON_NULL(field, "String field");
999 BT_ASSERT_PRE_NON_NULL(value, "Value");
1000 BT_ASSERT_PRE_FIELD_HOT(field, "String field");
1001 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
1002 string_field = container_of(field, struct bt_field_string, parent);
1003 if (string_field->payload) {
1004 g_string_append(string_field->payload, value);
1005 } else {
1006 string_field->payload = g_string_new(value);
1007 }
1008
1009 bt_field_set(field, true);
1010 return 0;
1011 }
1012
1013 int bt_field_string_append_len(struct bt_field *field, const char *value,
1014 unsigned int length)
1015 {
1016 struct bt_field_string *string_field;
1017
1018 BT_ASSERT_PRE_NON_NULL(field, "String field");
1019 BT_ASSERT_PRE_NON_NULL(value, "Value");
1020 BT_ASSERT_PRE_FIELD_HOT(field, "String field");
1021 BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field");
1022 string_field = container_of(field, struct bt_field_string, parent);
1023
1024 /* make sure no null bytes are appended */
1025 BT_ASSERT_PRE(memchr(value, '\0', length) == NULL,
1026 "String value to append contains a null character: "
1027 "partial-value=\"%.32s\", length=%u", value, length);
1028
1029 if (string_field->payload) {
1030 g_string_append_len(string_field->payload, value, length);
1031 } else {
1032 string_field->payload = g_string_new_len(value, length);
1033 }
1034
1035 bt_field_set(field, true);
1036 return 0;
1037 }
1038
1039 BT_HIDDEN
1040 int _bt_field_validate_recursive(struct bt_field *field)
1041 {
1042 int ret = 0;
1043 enum bt_field_type_id type_id;
1044
1045 if (!field) {
1046 BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL.");
1047 ret = -1;
1048 goto end;
1049 }
1050
1051 BT_ASSERT(field_type_has_known_id(field->type));
1052 type_id = bt_field_type_get_type_id(field->type);
1053 ret = field_validate_funcs[type_id](field);
1054
1055 end:
1056 return ret;
1057 }
1058
1059 BT_HIDDEN
1060 void _bt_field_reset_recursive(struct bt_field *field)
1061 { BT_ASSERT(field);
1062 field_reset_funcs[field->type->id](field);
1063 }
1064
1065 BT_HIDDEN
1066 void _bt_field_set(struct bt_field *field, bool value)
1067 {
1068 BT_ASSERT(field);
1069 field->payload_set = value;
1070 }
1071
1072 BT_HIDDEN
1073 int bt_field_serialize_recursive(struct bt_field *field, struct bt_stream_pos *pos,
1074 enum bt_byte_order native_byte_order)
1075 {
1076 enum bt_field_type_id type_id;
1077
1078 BT_ASSERT(pos);
1079 BT_ASSERT_PRE_NON_NULL(field, "Field");
1080 BT_ASSERT(field_type_has_known_id(field->type));
1081 type_id = bt_field_type_get_type_id(field->type);
1082 return field_serialize_funcs[type_id](field, pos, native_byte_order);
1083 }
1084
1085 BT_HIDDEN
1086 bt_bool _bt_field_is_set_recursive(struct bt_field *field)
1087 {
1088 bt_bool is_set = BT_FALSE;
1089 enum bt_field_type_id type_id;
1090
1091 if (!field) {
1092 goto end;
1093 }
1094
1095 BT_ASSERT(field_type_has_known_id(field->type));
1096 type_id = bt_field_type_get_type_id(field->type);
1097 is_set = field_is_set_funcs[type_id](field);
1098
1099 end:
1100 return is_set;
1101 }
1102
1103 struct bt_field *bt_field_copy(struct bt_field *field)
1104 {
1105 int ret;
1106 struct bt_field *copy = NULL;
1107 enum bt_field_type_id type_id;
1108
1109 BT_ASSERT_PRE_NON_NULL(field, "Field");
1110 BT_ASSERT(field_type_has_known_id(field->type));
1111 copy = bt_field_create(field->type);
1112 if (!copy) {
1113 BT_LOGW("Cannot create field: ft-addr=%p", field->type);
1114 goto end;
1115 }
1116
1117 bt_field_set(copy, field->payload_set);
1118 type_id = bt_field_type_get_type_id(field->type);
1119 ret = field_copy_funcs[type_id](field, copy);
1120 if (ret) {
1121 BT_PUT(copy);
1122 }
1123
1124 end:
1125 return copy;
1126 }
1127
1128 static
1129 struct bt_field *bt_field_integer_create(struct bt_field_type *type)
1130 {
1131 struct bt_field_integer *integer = g_new0(
1132 struct bt_field_integer, 1);
1133
1134 BT_LOGD("Creating integer field object: ft-addr=%p", type);
1135
1136 if (integer) {
1137 BT_LOGD("Created integer field object: addr=%p, ft-addr=%p",
1138 &integer->parent, type);
1139 } else {
1140 BT_LOGE_STR("Failed to allocate one integer field.");
1141 }
1142
1143 return integer ? &integer->parent : NULL;
1144 }
1145
1146 static
1147 struct bt_field *bt_field_enumeration_create(
1148 struct bt_field_type *type)
1149 {
1150 struct bt_field_enumeration *enumeration = g_new0(
1151 struct bt_field_enumeration, 1);
1152
1153 BT_LOGD("Creating enumeration field object: ft-addr=%p", type);
1154
1155 if (enumeration) {
1156 BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p",
1157 &enumeration->parent, type);
1158 } else {
1159 BT_LOGE_STR("Failed to allocate one enumeration field.");
1160 }
1161
1162 return enumeration ? &enumeration->parent : NULL;
1163 }
1164
1165 static
1166 struct bt_field *bt_field_floating_point_create(
1167 struct bt_field_type *type)
1168 {
1169 struct bt_field_floating_point *floating_point;
1170
1171 BT_LOGD("Creating floating point number field object: ft-addr=%p", type);
1172 floating_point = g_new0(struct bt_field_floating_point, 1);
1173
1174 if (floating_point) {
1175 BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p",
1176 &floating_point->parent, type);
1177 } else {
1178 BT_LOGE_STR("Failed to allocate one floating point number field.");
1179 }
1180
1181 return floating_point ? &floating_point->parent : NULL;
1182 }
1183
1184 static
1185 struct bt_field *bt_field_structure_create(
1186 struct bt_field_type *type)
1187 {
1188 struct bt_field_type_structure *structure_type = container_of(type,
1189 struct bt_field_type_structure, parent);
1190 struct bt_field_structure *structure = g_new0(
1191 struct bt_field_structure, 1);
1192 struct bt_field *ret = NULL;
1193 size_t i;
1194
1195 BT_LOGD("Creating structure field object: ft-addr=%p", type);
1196
1197 if (!structure) {
1198 BT_LOGE_STR("Failed to allocate one structure field.");
1199 goto end;
1200 }
1201
1202 structure->fields = g_ptr_array_new_with_free_func(
1203 (GDestroyNotify) bt_put);
1204 g_ptr_array_set_size(structure->fields,
1205 structure_type->fields->len);
1206
1207 /* Create all fields contained by the structure field. */
1208 for (i = 0; i < structure_type->fields->len; i++) {
1209 struct bt_field *field;
1210 struct structure_field *field_type =
1211 g_ptr_array_index(structure_type->fields, i);
1212
1213 field = bt_field_create(field_type->type);
1214 if (!field) {
1215 BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu",
1216 g_quark_to_string(field_type->name), i);
1217 bt_field_structure_destroy_recursive(&structure->parent);
1218 goto end;
1219 }
1220
1221 g_ptr_array_index(structure->fields, i) = field;
1222 }
1223
1224 ret = &structure->parent;
1225 BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", ret,
1226 type);
1227 end:
1228 return ret;
1229 }
1230
1231 static
1232 struct bt_field *bt_field_variant_create(struct bt_field_type *type)
1233 {
1234 struct bt_field_variant *variant = g_new0(
1235 struct bt_field_variant, 1);
1236
1237 BT_LOGD("Creating variant field object: ft-addr=%p", type);
1238
1239 if (variant) {
1240 BT_LOGD("Created variant field object: addr=%p, ft-addr=%p",
1241 &variant->parent, type);
1242 } else {
1243 BT_LOGE_STR("Failed to allocate one variant field.");
1244 }
1245
1246 return variant ? &variant->parent : NULL;
1247 }
1248
1249 static
1250 struct bt_field *bt_field_array_create(struct bt_field_type *type)
1251 {
1252 struct bt_field_array *array = g_new0(struct bt_field_array, 1);
1253 struct bt_field_type_array *array_type;
1254 unsigned int array_length;
1255
1256 BT_LOGD("Creating array field object: ft-addr=%p", type);
1257 BT_ASSERT(type);
1258
1259 if (!array) {
1260 BT_LOGE_STR("Failed to allocate one array field.");
1261 goto error;
1262 }
1263
1264 array_type = container_of(type, struct bt_field_type_array, parent);
1265 array_length = array_type->length;
1266 array->elements = g_ptr_array_sized_new(array_length);
1267 if (!array->elements) {
1268 goto error;
1269 }
1270
1271 g_ptr_array_set_free_func(array->elements,
1272 (GDestroyNotify) bt_put);
1273 g_ptr_array_set_size(array->elements, array_length);
1274 BT_LOGD("Created array field object: addr=%p, ft-addr=%p",
1275 &array->parent, type);
1276 return &array->parent;
1277 error:
1278 g_free(array);
1279 return NULL;
1280 }
1281
1282 static
1283 struct bt_field *bt_field_sequence_create(
1284 struct bt_field_type *type)
1285 {
1286 struct bt_field_sequence *sequence = g_new0(
1287 struct bt_field_sequence, 1);
1288
1289 BT_LOGD("Creating sequence field object: ft-addr=%p", type);
1290
1291 if (sequence) {
1292 BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p",
1293 &sequence->parent, type);
1294 } else {
1295 BT_LOGE_STR("Failed to allocate one sequence field.");
1296 }
1297
1298 return sequence ? &sequence->parent : NULL;
1299 }
1300
1301 static
1302 struct bt_field *bt_field_string_create(struct bt_field_type *type)
1303 {
1304 struct bt_field_string *string = g_new0(
1305 struct bt_field_string, 1);
1306
1307 BT_LOGD("Creating string field object: ft-addr=%p", type);
1308
1309 if (string) {
1310 BT_LOGD("Created string field object: addr=%p, ft-addr=%p",
1311 &string->parent, type);
1312 } else {
1313 BT_LOGE_STR("Failed to allocate one string field.");
1314 }
1315
1316 return string ? &string->parent : NULL;
1317 }
1318
1319 static
1320 void bt_field_destroy(struct bt_object *obj)
1321 {
1322 struct bt_field *field;
1323 struct bt_field_type *type;
1324 enum bt_field_type_id type_id;
1325
1326 BT_ASSERT(obj);
1327 field = container_of(obj, struct bt_field, base);
1328 type = field->type;
1329 BT_ASSERT(field_type_has_known_id(type));
1330 type_id = bt_field_type_get_type_id(type);
1331 field_destroy_funcs[type_id](field);
1332 BT_LOGD_STR("Putting field's type.");
1333 bt_put(type);
1334 }
1335
1336 static
1337 void bt_field_integer_destroy(struct bt_field *field)
1338 {
1339 struct bt_field_integer *integer;
1340
1341 BT_ASSERT(field);
1342 BT_LOGD("Destroying integer field object: addr=%p", field);
1343 integer = container_of(field, struct bt_field_integer, parent);
1344 g_free(integer);
1345 }
1346
1347 static
1348 void bt_field_enumeration_destroy_recursive(struct bt_field *field)
1349 {
1350 struct bt_field_enumeration *enumeration;
1351
1352 BT_ASSERT(field);
1353 BT_LOGD("Destroying enumeration field object: addr=%p", field);
1354 enumeration = container_of(field, struct bt_field_enumeration,
1355 parent);
1356 BT_LOGD_STR("Putting payload field.");
1357 bt_put(enumeration->payload);
1358 g_free(enumeration);
1359 }
1360
1361 static
1362 void bt_field_floating_point_destroy(struct bt_field *field)
1363 {
1364 struct bt_field_floating_point *floating_point;
1365
1366 BT_ASSERT(field);
1367 BT_LOGD("Destroying floating point number field object: addr=%p", field);
1368 floating_point = container_of(field, struct bt_field_floating_point,
1369 parent);
1370 g_free(floating_point);
1371 }
1372
1373 static
1374 void bt_field_structure_destroy_recursive(struct bt_field *field)
1375 {
1376 struct bt_field_structure *structure;
1377
1378 BT_ASSERT(field);
1379 BT_LOGD("Destroying structure field object: addr=%p", field);
1380 structure = container_of(field, struct bt_field_structure, parent);
1381 g_ptr_array_free(structure->fields, TRUE);
1382 g_free(structure);
1383 }
1384
1385 static
1386 void bt_field_variant_destroy_recursive(struct bt_field *field)
1387 {
1388 struct bt_field_variant *variant;
1389
1390 BT_ASSERT(field);
1391 BT_LOGD("Destroying variant field object: addr=%p", field);
1392 variant = container_of(field, struct bt_field_variant, parent);
1393 BT_LOGD_STR("Putting tag field.");
1394 bt_put(variant->tag);
1395 BT_LOGD_STR("Putting payload field.");
1396 bt_put(variant->payload);
1397 g_free(variant);
1398 }
1399
1400 static
1401 void bt_field_array_destroy_recursive(struct bt_field *field)
1402 {
1403 struct bt_field_array *array;
1404
1405 BT_ASSERT(field);
1406 BT_LOGD("Destroying array field object: addr=%p", field);
1407 array = container_of(field, struct bt_field_array, parent);
1408 g_ptr_array_free(array->elements, TRUE);
1409 g_free(array);
1410 }
1411
1412 static
1413 void bt_field_sequence_destroy_recursive(struct bt_field *field)
1414 {
1415 struct bt_field_sequence *sequence;
1416
1417 BT_ASSERT(field);
1418 BT_LOGD("Destroying sequence field object: addr=%p", field);
1419 sequence = container_of(field, struct bt_field_sequence, parent);
1420 if (sequence->elements) {
1421 g_ptr_array_free(sequence->elements, TRUE);
1422 }
1423 BT_LOGD_STR("Putting length field.");
1424 bt_put(sequence->length);
1425 g_free(sequence);
1426 }
1427
1428 static
1429 void bt_field_string_destroy(struct bt_field *field)
1430 {
1431 struct bt_field_string *string;
1432
1433 BT_ASSERT(field);
1434 BT_LOGD("Destroying string field object: addr=%p", field);
1435 string = container_of(field, struct bt_field_string, parent);
1436 if (string->payload) {
1437 g_string_free(string->payload, TRUE);
1438 }
1439 g_free(string);
1440 }
1441
1442 static
1443 int bt_field_generic_validate(struct bt_field *field)
1444 {
1445 return (field && field->payload_set) ? 0 : -1;
1446 }
1447
1448 static
1449 int bt_field_enumeration_validate_recursive(struct bt_field *field)
1450 {
1451 int ret;
1452 struct bt_field_enumeration *enumeration;
1453
1454 BT_ASSERT(field);
1455 enumeration = container_of(field, struct bt_field_enumeration,
1456 parent);
1457 if (!enumeration->payload) {
1458 BT_ASSERT_PRE_MSG("Invalid enumeration field: payload is not set: "
1459 "%!+f", field);
1460 ret = -1;
1461 goto end;
1462 }
1463
1464 ret = bt_field_validate_recursive(enumeration->payload);
1465
1466 end:
1467 return ret;
1468 }
1469
1470 static
1471 int bt_field_structure_validate_recursive(struct bt_field *field)
1472 {
1473 int64_t i;
1474 int ret = 0;
1475 struct bt_field_structure *structure;
1476
1477 BT_ASSERT(field);
1478 structure = container_of(field, struct bt_field_structure, parent);
1479
1480 for (i = 0; i < structure->fields->len; i++) {
1481 ret = bt_field_validate_recursive(
1482 (void *) structure->fields->pdata[i]);
1483
1484 if (ret) {
1485 int this_ret;
1486 const char *name;
1487
1488 this_ret = bt_field_type_structure_get_field_by_index(
1489 field->type, &name, NULL, i);
1490 BT_ASSERT(this_ret == 0);
1491 BT_ASSERT_PRE_MSG("Invalid structure field's field: "
1492 "%![struct-field-]+f, field-name=\"%s\", "
1493 "index=%" PRId64 ", %![field-]+f",
1494 field, name, i, structure->fields->pdata[i]);
1495 goto end;
1496 }
1497 }
1498
1499 end:
1500 return ret;
1501 }
1502
1503 static
1504 int bt_field_variant_validate_recursive(struct bt_field *field)
1505 {
1506 int ret = 0;
1507 struct bt_field_variant *variant;
1508
1509 BT_ASSERT(field);
1510 variant = container_of(field, struct bt_field_variant, parent);
1511 ret = bt_field_validate_recursive(variant->payload);
1512 if (ret) {
1513 BT_ASSERT_PRE_MSG("Invalid variant field's payload field: "
1514 "%![variant-field-]+f, %![payload-field-]+f",
1515 field, variant->payload);
1516 }
1517
1518 return ret;
1519 }
1520
1521 static
1522 int bt_field_array_validate_recursive(struct bt_field *field)
1523 {
1524 int64_t i;
1525 int ret = 0;
1526 struct bt_field_array *array;
1527
1528 BT_ASSERT(field);
1529 array = container_of(field, struct bt_field_array, parent);
1530 for (i = 0; i < array->elements->len; i++) {
1531 ret = bt_field_validate_recursive((void *) array->elements->pdata[i]);
1532 if (ret) {
1533 BT_ASSERT_PRE_MSG("Invalid array field's element field: "
1534 "%![array-field-]+f, " PRId64 ", "
1535 "%![elem-field-]+f",
1536 field, i, array->elements->pdata[i]);
1537 goto end;
1538 }
1539 }
1540
1541 end:
1542 return ret;
1543 }
1544
1545 static
1546 int bt_field_sequence_validate_recursive(struct bt_field *field)
1547 {
1548 size_t i;
1549 int ret = 0;
1550 struct bt_field_sequence *sequence;
1551
1552 BT_ASSERT(field);
1553 sequence = container_of(field, struct bt_field_sequence, parent);
1554 for (i = 0; i < sequence->elements->len; i++) {
1555 ret = bt_field_validate_recursive(
1556 (void *) sequence->elements->pdata[i]);
1557 if (ret) {
1558 BT_ASSERT_PRE_MSG("Invalid sequence field's element field: "
1559 "%![seq-field-]+f, " PRId64 ", "
1560 "%![elem-field-]+f",
1561 field, i, sequence->elements->pdata[i]);
1562 goto end;
1563 }
1564 }
1565 end:
1566 return ret;
1567 }
1568
1569 static
1570 void bt_field_generic_reset(struct bt_field *field)
1571 {
1572 BT_ASSERT(field);
1573 field->payload_set = false;
1574 }
1575
1576 static
1577 void bt_field_enumeration_reset_recursive(struct bt_field *field)
1578 {
1579 struct bt_field_enumeration *enumeration;
1580
1581 BT_ASSERT(field);
1582 enumeration = container_of(field, struct bt_field_enumeration,
1583 parent);
1584 if (!enumeration->payload) {
1585 return;
1586 }
1587
1588 bt_field_reset_recursive(enumeration->payload);
1589 }
1590
1591 static
1592 void bt_field_structure_reset_recursive(struct bt_field *field)
1593 {
1594 int64_t i;
1595 struct bt_field_structure *structure;
1596
1597 BT_ASSERT(field);
1598 structure = container_of(field, struct bt_field_structure, parent);
1599
1600 for (i = 0; i < structure->fields->len; i++) {
1601 struct bt_field *member = structure->fields->pdata[i];
1602
1603 if (!member) {
1604 /*
1605 * Structure members are lazily initialized;
1606 * skip if this member has not been allocated
1607 * yet.
1608 */
1609 continue;
1610 }
1611
1612 bt_field_reset_recursive(member);
1613 }
1614 }
1615
1616 static
1617 void bt_field_variant_reset_recursive(struct bt_field *field)
1618 {
1619 struct bt_field_variant *variant;
1620
1621 BT_ASSERT(field);
1622 variant = container_of(field, struct bt_field_variant, parent);
1623 BT_PUT(variant->tag);
1624 BT_PUT(variant->payload);
1625 }
1626
1627 static
1628 void bt_field_array_reset_recursive(struct bt_field *field)
1629 {
1630 size_t i;
1631 struct bt_field_array *array;
1632
1633 BT_ASSERT(field);
1634 array = container_of(field, struct bt_field_array, parent);
1635
1636 for (i = 0; i < array->elements->len; i++) {
1637 struct bt_field *member = array->elements->pdata[i];
1638
1639 if (!member) {
1640 /*
1641 * Array elements are lazily initialized; skip
1642 * if this member has not been allocated yet.
1643 */
1644 continue;
1645 }
1646
1647 bt_field_reset_recursive(member);
1648 }
1649 }
1650
1651 static
1652 void bt_field_sequence_reset_recursive(struct bt_field *field)
1653 {
1654 struct bt_field_sequence *sequence;
1655
1656 BT_ASSERT(field);
1657 sequence = container_of(field, struct bt_field_sequence, parent);
1658
1659 if (sequence->elements) {
1660 g_ptr_array_free(sequence->elements, TRUE);
1661 sequence->elements = NULL;
1662 }
1663
1664 BT_PUT(sequence->length);
1665 }
1666
1667 static
1668 void bt_field_string_reset_recursive(struct bt_field *field)
1669 {
1670 struct bt_field_string *string;
1671
1672 BT_ASSERT(field);
1673 bt_field_generic_reset(field);
1674 string = container_of(field, struct bt_field_string, parent);
1675 if (string->payload) {
1676 g_string_truncate(string->payload, 0);
1677 }
1678 }
1679
1680 static
1681 int bt_field_integer_serialize(struct bt_field *field,
1682 struct bt_stream_pos *pos,
1683 enum bt_byte_order native_byte_order)
1684 {
1685 int ret = 0;
1686 struct bt_field_integer *integer = container_of(field,
1687 struct bt_field_integer, parent);
1688
1689 BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field");
1690 BT_LOGV("Serializing integer field: addr=%p, pos-offset=%" PRId64 ", "
1691 "native-bo=%s", field, pos->offset,
1692 bt_byte_order_string(native_byte_order));
1693
1694 retry:
1695 ret = bt_field_integer_write(integer, pos, native_byte_order);
1696 if (ret == -EFAULT) {
1697 /*
1698 * The field is too large to fit in the current packet's
1699 * remaining space. Bump the packet size and retry.
1700 */
1701 ret = increase_packet_size(pos);
1702 if (ret) {
1703 BT_LOGE("Cannot increase packet size: ret=%d", ret);
1704 goto end;
1705 }
1706 goto retry;
1707 }
1708
1709 end:
1710 return ret;
1711 }
1712
1713 static
1714 int bt_field_enumeration_serialize_recursive(struct bt_field *field,
1715 struct bt_stream_pos *pos,
1716 enum bt_byte_order native_byte_order)
1717 {
1718 struct bt_field_enumeration *enumeration = container_of(
1719 field, struct bt_field_enumeration, parent);
1720
1721 BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
1722 "native-bo=%s", field, pos->offset,
1723 bt_byte_order_string(native_byte_order));
1724 BT_LOGV_STR("Serializing enumeration field's payload field.");
1725 return bt_field_serialize_recursive(enumeration->payload, pos,
1726 native_byte_order);
1727 }
1728
1729 static
1730 int bt_field_floating_point_serialize(struct bt_field *field,
1731 struct bt_stream_pos *pos,
1732 enum bt_byte_order native_byte_order)
1733 {
1734 int ret = 0;
1735 struct bt_field_floating_point *floating_point = container_of(field,
1736 struct bt_field_floating_point, parent);
1737
1738 BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field");
1739 BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", "
1740 "native-bo=%s", field, pos->offset,
1741 bt_byte_order_string(native_byte_order));
1742
1743 retry:
1744 ret = bt_field_floating_point_write(floating_point, pos,
1745 native_byte_order);
1746 if (ret == -EFAULT) {
1747 /*
1748 * The field is too large to fit in the current packet's
1749 * remaining space. Bump the packet size and retry.
1750 */
1751 ret = increase_packet_size(pos);
1752 if (ret) {
1753 BT_LOGE("Cannot increase packet size: ret=%d", ret);
1754 goto end;
1755 }
1756 goto retry;
1757 }
1758
1759 end:
1760 return ret;
1761 }
1762
1763 static
1764 int bt_field_structure_serialize_recursive(struct bt_field *field,
1765 struct bt_stream_pos *pos,
1766 enum bt_byte_order native_byte_order)
1767 {
1768 int64_t i;
1769 int ret = 0;
1770 struct bt_field_structure *structure = container_of(
1771 field, struct bt_field_structure, parent);
1772
1773 BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", "
1774 "native-bo=%s", field, pos->offset,
1775 bt_byte_order_string(native_byte_order));
1776
1777 while (!bt_stream_pos_access_ok(pos,
1778 offset_align(pos->offset, field->type->alignment))) {
1779 ret = increase_packet_size(pos);
1780 if (ret) {
1781 BT_LOGE("Cannot increase packet size: ret=%d", ret);
1782 goto end;
1783 }
1784 }
1785
1786 if (!bt_stream_pos_align(pos, field->type->alignment)) {
1787 BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", "
1788 "align=%u", pos->offset, field->type->alignment);
1789 ret = -1;
1790 goto end;
1791 }
1792
1793 for (i = 0; i < structure->fields->len; i++) {
1794 struct bt_field *member = g_ptr_array_index(
1795 structure->fields, i);
1796 const char *field_name = NULL;
1797
1798 BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", "
1799 "field-addr=%p, index=%" PRId64,
1800 pos->offset, member, i);
1801
1802 if (!member) {
1803 ret = bt_field_type_structure_get_field_by_index(
1804 field->type, &field_name, NULL, i);
1805 BT_ASSERT(ret == 0);
1806 BT_LOGW("Cannot serialize structure field's field: field is not set: "
1807 "struct-field-addr=%p, "
1808 "field-name=\"%s\", index=%" PRId64,
1809 field, field_name, i);
1810 ret = -1;
1811 goto end;
1812 }
1813
1814 ret = bt_field_serialize_recursive(member, pos,
1815 native_byte_order);
1816 if (ret) {
1817 ret = bt_field_type_structure_get_field_by_index(
1818 field->type, &field_name, NULL, i);
1819 BT_ASSERT(ret == 0);
1820 BT_LOGW("Cannot serialize structure field's field: "
1821 "struct-field-addr=%p, field-addr=%p, "
1822 "field-name=\"%s\", index=%" PRId64,
1823 field->type, member, field_name, i);
1824 break;
1825 }
1826 }
1827
1828 end:
1829 return ret;
1830 }
1831
1832 static
1833 int bt_field_variant_serialize_recursive(struct bt_field *field,
1834 struct bt_stream_pos *pos,
1835 enum bt_byte_order native_byte_order)
1836 {
1837 struct bt_field_variant *variant = container_of(
1838 field, struct bt_field_variant, parent);
1839
1840 BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", "
1841 "native-bo=%s", field, pos->offset,
1842 bt_byte_order_string(native_byte_order));
1843 BT_LOGV_STR("Serializing variant field's payload field.");
1844 return bt_field_serialize_recursive(variant->payload, pos,
1845 native_byte_order);
1846 }
1847
1848 static
1849 int bt_field_array_serialize_recursive(struct bt_field *field,
1850 struct bt_stream_pos *pos,
1851 enum bt_byte_order native_byte_order)
1852 {
1853 int64_t i;
1854 int ret = 0;
1855 struct bt_field_array *array = container_of(
1856 field, struct bt_field_array, parent);
1857
1858 BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", "
1859 "native-bo=%s", field, pos->offset,
1860 bt_byte_order_string(native_byte_order));
1861
1862 for (i = 0; i < array->elements->len; i++) {
1863 struct bt_field *elem_field =
1864 g_ptr_array_index(array->elements, i);
1865
1866 BT_LOGV("Serializing array field's element field: "
1867 "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
1868 pos->offset, elem_field, i);
1869 ret = bt_field_serialize_recursive(elem_field, pos,
1870 native_byte_order);
1871 if (ret) {
1872 BT_LOGW("Cannot serialize array field's element field: "
1873 "array-field-addr=%p, field-addr=%p, "
1874 "index=%" PRId64, field, elem_field, i);
1875 goto end;
1876 }
1877 }
1878
1879 end:
1880 return ret;
1881 }
1882
1883 static
1884 int bt_field_sequence_serialize_recursive(struct bt_field *field,
1885 struct bt_stream_pos *pos,
1886 enum bt_byte_order native_byte_order)
1887 {
1888 int64_t i;
1889 int ret = 0;
1890 struct bt_field_sequence *sequence = container_of(
1891 field, struct bt_field_sequence, parent);
1892
1893 BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", "
1894 "native-bo=%s", field, pos->offset,
1895 bt_byte_order_string(native_byte_order));
1896
1897 for (i = 0; i < sequence->elements->len; i++) {
1898 struct bt_field *elem_field =
1899 g_ptr_array_index(sequence->elements, i);
1900
1901 BT_LOGV("Serializing sequence field's element field: "
1902 "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
1903 pos->offset, elem_field, i);
1904 ret = bt_field_serialize_recursive(elem_field, pos,
1905 native_byte_order);
1906 if (ret) {
1907 BT_LOGW("Cannot serialize sequence field's element field: "
1908 "sequence-field-addr=%p, field-addr=%p, "
1909 "index=%" PRId64, field, elem_field, i);
1910 goto end;
1911 }
1912 }
1913
1914 end:
1915 return ret;
1916 }
1917
1918 static
1919 int bt_field_string_serialize(struct bt_field *field, struct bt_stream_pos *pos,
1920 enum bt_byte_order native_byte_order)
1921 {
1922 int64_t i;
1923 int ret = 0;
1924 struct bt_field_string *string = container_of(field,
1925 struct bt_field_string, parent);
1926 struct bt_field_type *character_type =
1927 get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
1928 struct bt_field *character;
1929
1930 BT_ASSERT_PRE_FIELD_IS_SET(field, "String field");
1931 BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", "
1932 "native-bo=%s", field, pos->offset,
1933 bt_byte_order_string(native_byte_order));
1934
1935 BT_LOGV_STR("Creating character field from string field's character field type.");
1936 character = bt_field_create(character_type);
1937
1938 for (i = 0; i < string->payload->len + 1; i++) {
1939 const uint64_t chr = (uint64_t) string->payload->str[i];
1940
1941 ret = bt_field_unsigned_integer_set_value(character, chr);
1942 BT_ASSERT(ret == 0);
1943 BT_LOGV("Serializing string field's character field: "
1944 "pos-offset=%" PRId64 ", field-addr=%p, "
1945 "index=%" PRId64 ", char-int=%" PRIu64,
1946 pos->offset, character, i, chr);
1947 ret = bt_field_integer_serialize(character, pos,
1948 native_byte_order);
1949 if (ret) {
1950 BT_LOGW_STR("Cannot serialize character field.");
1951 goto end;
1952 }
1953 }
1954
1955 end:
1956 bt_put(character);
1957 bt_put(character_type);
1958 return ret;
1959 }
1960
1961 static
1962 int bt_field_integer_copy(struct bt_field *src, struct bt_field *dst)
1963 {
1964 struct bt_field_integer *integer_src, *integer_dst;
1965
1966 BT_LOGD("Copying integer field: src-field-addr=%p, dst-field-addr=%p",
1967 src, dst);
1968 integer_src = container_of(src, struct bt_field_integer, parent);
1969 integer_dst = container_of(dst, struct bt_field_integer, parent);
1970 integer_dst->payload = integer_src->payload;
1971 BT_LOGD_STR("Copied integer field.");
1972 return 0;
1973 }
1974
1975 static
1976 int bt_field_enumeration_copy_recursive(struct bt_field *src,
1977 struct bt_field *dst)
1978 {
1979 int ret = 0;
1980 struct bt_field_enumeration *enum_src, *enum_dst;
1981
1982 BT_LOGD("Copying enumeration field: src-field-addr=%p, dst-field-addr=%p",
1983 src, dst);
1984 enum_src = container_of(src, struct bt_field_enumeration, parent);
1985 enum_dst = container_of(dst, struct bt_field_enumeration, parent);
1986
1987 if (enum_src->payload) {
1988 BT_LOGD_STR("Copying enumeration field's payload field.");
1989 enum_dst->payload = bt_field_copy(enum_src->payload);
1990 if (!enum_dst->payload) {
1991 BT_LOGE_STR("Cannot copy enumeration field's payload field.");
1992 ret = -1;
1993 goto end;
1994 }
1995 }
1996
1997 BT_LOGD_STR("Copied enumeration field.");
1998 end:
1999 return ret;
2000 }
2001
2002 static
2003 int bt_field_floating_point_copy(struct bt_field *src, struct bt_field *dst)
2004 {
2005 struct bt_field_floating_point *float_src, *float_dst;
2006
2007 BT_LOGD("Copying floating point number field: src-field-addr=%p, dst-field-addr=%p",
2008 src, dst);
2009 float_src = container_of(src, struct bt_field_floating_point,
2010 parent);
2011 float_dst = container_of(dst, struct bt_field_floating_point,
2012 parent);
2013 float_dst->payload = float_src->payload;
2014 BT_LOGD_STR("Copied floating point number field.");
2015 return 0;
2016 }
2017
2018 static
2019 int bt_field_structure_copy_recursive(struct bt_field *src,
2020 struct bt_field *dst)
2021 {
2022 int ret = 0;
2023 int64_t i;
2024 struct bt_field_structure *struct_src, *struct_dst;
2025
2026 BT_LOGD("Copying structure field: src-field-addr=%p, dst-field-addr=%p",
2027 src, dst);
2028 struct_src = container_of(src, struct bt_field_structure, parent);
2029 struct_dst = container_of(dst, struct bt_field_structure, parent);
2030
2031 g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len);
2032
2033 for (i = 0; i < struct_src->fields->len; i++) {
2034 struct bt_field *field =
2035 g_ptr_array_index(struct_src->fields, i);
2036 struct bt_field *field_copy = NULL;
2037
2038 if (field) {
2039 BT_LOGD("Copying structure field's field: src-field-addr=%p"
2040 "index=%" PRId64, field, i);
2041 field_copy = bt_field_copy(field);
2042 if (!field_copy) {
2043 BT_LOGE("Cannot copy structure field's field: "
2044 "src-field-addr=%p, index=%" PRId64,
2045 field, i);
2046 ret = -1;
2047 goto end;
2048 }
2049 }
2050
2051 BT_MOVE(g_ptr_array_index(struct_dst->fields, i), field_copy);
2052 }
2053
2054 BT_LOGD_STR("Copied structure field.");
2055
2056 end:
2057 return ret;
2058 }
2059
2060 static
2061 int bt_field_variant_copy_recursive(struct bt_field *src,
2062 struct bt_field *dst)
2063 {
2064 int ret = 0;
2065 struct bt_field_variant *variant_src, *variant_dst;
2066
2067 BT_LOGD("Copying variant field: src-field-addr=%p, dst-field-addr=%p",
2068 src, dst);
2069 variant_src = container_of(src, struct bt_field_variant, parent);
2070 variant_dst = container_of(dst, struct bt_field_variant, parent);
2071
2072 if (variant_src->tag) {
2073 BT_LOGD_STR("Copying variant field's tag field.");
2074 variant_dst->tag = bt_field_copy(variant_src->tag);
2075 if (!variant_dst->tag) {
2076 BT_LOGE_STR("Cannot copy variant field's tag field.");
2077 ret = -1;
2078 goto end;
2079 }
2080 }
2081 if (variant_src->payload) {
2082 BT_LOGD_STR("Copying variant field's payload field.");
2083 variant_dst->payload = bt_field_copy(variant_src->payload);
2084 if (!variant_dst->payload) {
2085 BT_LOGE_STR("Cannot copy variant field's payload field.");
2086 ret = -1;
2087 goto end;
2088 }
2089 }
2090
2091 BT_LOGD_STR("Copied variant field.");
2092
2093 end:
2094 return ret;
2095 }
2096
2097 static
2098 int bt_field_array_copy_recursive(struct bt_field *src,
2099 struct bt_field *dst)
2100 {
2101 int ret = 0;
2102 int64_t i;
2103 struct bt_field_array *array_src, *array_dst;
2104
2105 BT_LOGD("Copying array field: src-field-addr=%p, dst-field-addr=%p",
2106 src, dst);
2107 array_src = container_of(src, struct bt_field_array, parent);
2108 array_dst = container_of(dst, struct bt_field_array, parent);
2109
2110 g_ptr_array_set_size(array_dst->elements, array_src->elements->len);
2111 for (i = 0; i < array_src->elements->len; i++) {
2112 struct bt_field *field =
2113 g_ptr_array_index(array_src->elements, i);
2114 struct bt_field *field_copy = NULL;
2115
2116 if (field) {
2117 BT_LOGD("Copying array field's element field: field-addr=%p, "
2118 "index=%" PRId64, field, i);
2119 field_copy = bt_field_copy(field);
2120 if (!field_copy) {
2121 BT_LOGE("Cannot copy array field's element field: "
2122 "src-field-addr=%p, index=%" PRId64,
2123 field, i);
2124 ret = -1;
2125 goto end;
2126 }
2127 }
2128
2129 g_ptr_array_index(array_dst->elements, i) = field_copy;
2130 }
2131
2132 BT_LOGD_STR("Copied array field.");
2133
2134 end:
2135 return ret;
2136 }
2137
2138 static
2139 int bt_field_sequence_copy_recursive(struct bt_field *src,
2140 struct bt_field *dst)
2141 {
2142 int ret = 0;
2143 int64_t i;
2144 struct bt_field_sequence *sequence_src, *sequence_dst;
2145 struct bt_field *src_length;
2146 struct bt_field *dst_length;
2147
2148 BT_LOGD("Copying sequence field: src-field-addr=%p, dst-field-addr=%p",
2149 src, dst);
2150 sequence_src = container_of(src, struct bt_field_sequence, parent);
2151 sequence_dst = container_of(dst, struct bt_field_sequence, parent);
2152
2153 src_length = bt_field_sequence_get_length(src);
2154 if (!src_length) {
2155 /* no length set yet: keep destination sequence empty */
2156 goto end;
2157 }
2158
2159 /* copy source length */
2160 BT_LOGD_STR("Copying sequence field's length field.");
2161 dst_length = bt_field_copy(src_length);
2162 BT_PUT(src_length);
2163 if (!dst_length) {
2164 BT_LOGE_STR("Cannot copy sequence field's length field.");
2165 ret = -1;
2166 goto end;
2167 }
2168
2169 /* this will initialize the destination sequence's internal array */
2170 ret = bt_field_sequence_set_length(dst, dst_length);
2171 bt_put(dst_length);
2172 if (ret) {
2173 BT_LOGE("Cannot set sequence field copy's length field: "
2174 "dst-length-field-addr=%p", dst_length);
2175 ret = -1;
2176 goto end;
2177 }
2178
2179 BT_ASSERT(sequence_dst->elements->len == sequence_src->elements->len);
2180
2181 for (i = 0; i < sequence_src->elements->len; i++) {
2182 struct bt_field *field =
2183 g_ptr_array_index(sequence_src->elements, i);
2184 struct bt_field *field_copy = NULL;
2185
2186 if (field) {
2187 BT_LOGD("Copying sequence field's element field: field-addr=%p, "
2188 "index=%" PRId64, field, i);
2189 field_copy = bt_field_copy(field);
2190 if (!field_copy) {
2191 BT_LOGE("Cannot copy sequence field's element field: "
2192 "src-field-addr=%p, index=%" PRId64,
2193 field, i);
2194 ret = -1;
2195 goto end;
2196 }
2197 }
2198
2199 g_ptr_array_index(sequence_dst->elements, i) = field_copy;
2200 }
2201
2202 BT_LOGD_STR("Copied sequence field.");
2203
2204 end:
2205 return ret;
2206 }
2207
2208 static
2209 int bt_field_string_copy_recursive(struct bt_field *src,
2210 struct bt_field *dst)
2211 {
2212 int ret = 0;
2213 struct bt_field_string *string_src, *string_dst;
2214
2215 BT_LOGD("Copying string field: src-field-addr=%p, dst-field-addr=%p",
2216 src, dst);
2217 string_src = container_of(src, struct bt_field_string, parent);
2218 string_dst = container_of(dst, struct bt_field_string, parent);
2219
2220 if (string_src->payload) {
2221 string_dst->payload = g_string_new(string_src->payload->str);
2222 if (!string_dst->payload) {
2223 BT_LOGE_STR("Failed to allocate a GString.");
2224 ret = -1;
2225 goto end;
2226 }
2227 }
2228
2229 BT_LOGD_STR("Copied string field.");
2230
2231 end:
2232 return ret;
2233 }
2234
2235 static
2236 int increase_packet_size(struct bt_stream_pos *pos)
2237 {
2238 int ret;
2239
2240 BT_ASSERT(pos);
2241 BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", "
2242 "cur-packet-size=%" PRIu64,
2243 pos->offset, pos->packet_size);
2244 ret = munmap_align(pos->base_mma);
2245 if (ret) {
2246 BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
2247 ": ret=%d", ret);
2248 goto end;
2249 }
2250
2251 pos->packet_size += PACKET_LEN_INCREMENT;
2252 do {
2253 ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
2254 pos->packet_size / CHAR_BIT);
2255 } while (ret == EINTR);
2256 if (ret) {
2257 BT_LOGE_ERRNO("Failed to preallocate memory space",
2258 ": ret=%d", ret);
2259 errno = EINTR;
2260 ret = -1;
2261 goto end;
2262 }
2263
2264 pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
2265 pos->flags, pos->fd, pos->mmap_offset);
2266 if (pos->base_mma == MAP_FAILED) {
2267 BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
2268 ": ret=%d", ret);
2269 ret = -1;
2270 }
2271
2272 BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", "
2273 "new-packet-size=%" PRIu64,
2274 pos->offset, pos->packet_size);
2275 BT_ASSERT(pos->packet_size % 8 == 0);
2276
2277 end:
2278 return ret;
2279 }
2280
2281 static
2282 void generic_field_freeze(struct bt_field *field)
2283 {
2284 field->frozen = true;
2285 }
2286
2287 static
2288 void bt_field_enumeration_freeze_recursive(struct bt_field *field)
2289 {
2290 struct bt_field_enumeration *enum_field =
2291 container_of(field, struct bt_field_enumeration, parent);
2292
2293 BT_LOGD("Freezing enumeration field object: addr=%p", field);
2294 BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload);
2295 bt_field_freeze_recursive(enum_field->payload);
2296 generic_field_freeze(field);
2297 }
2298
2299 static
2300 void bt_field_structure_freeze_recursive(struct bt_field *field)
2301 {
2302 int64_t i;
2303 struct bt_field_structure *structure_field =
2304 container_of(field, struct bt_field_structure, parent);
2305
2306 BT_LOGD("Freezing structure field object: addr=%p", field);
2307
2308 for (i = 0; i < structure_field->fields->len; i++) {
2309 struct bt_field *field =
2310 g_ptr_array_index(structure_field->fields, i);
2311
2312 BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64,
2313 field, i);
2314 bt_field_freeze_recursive(field);
2315 }
2316
2317 generic_field_freeze(field);
2318 }
2319
2320 static
2321 void bt_field_variant_freeze_recursive(struct bt_field *field)
2322 {
2323 struct bt_field_variant *variant_field =
2324 container_of(field, struct bt_field_variant, parent);
2325
2326 BT_LOGD("Freezing variant field object: addr=%p", field);
2327 BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag);
2328 bt_field_freeze_recursive(variant_field->tag);
2329 BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload);
2330 bt_field_freeze_recursive(variant_field->payload);
2331 generic_field_freeze(field);
2332 }
2333
2334 static
2335 void bt_field_array_freeze_recursive(struct bt_field *field)
2336 {
2337 int64_t i;
2338 struct bt_field_array *array_field =
2339 container_of(field, struct bt_field_array, parent);
2340
2341 BT_LOGD("Freezing array field object: addr=%p", field);
2342
2343 for (i = 0; i < array_field->elements->len; i++) {
2344 struct bt_field *elem_field =
2345 g_ptr_array_index(array_field->elements, i);
2346
2347 BT_LOGD("Freezing array field object's element field: "
2348 "element-field-addr=%p, index=%" PRId64,
2349 elem_field, i);
2350 bt_field_freeze_recursive(elem_field);
2351 }
2352
2353 generic_field_freeze(field);
2354 }
2355
2356 static
2357 void bt_field_sequence_freeze_recursive(struct bt_field *field)
2358 {
2359 int64_t i;
2360 struct bt_field_sequence *sequence_field =
2361 container_of(field, struct bt_field_sequence, parent);
2362
2363 BT_LOGD("Freezing sequence field object: addr=%p", field);
2364 BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p",
2365 sequence_field->length);
2366 bt_field_freeze_recursive(sequence_field->length);
2367
2368 for (i = 0; i < sequence_field->elements->len; i++) {
2369 struct bt_field *elem_field =
2370 g_ptr_array_index(sequence_field->elements, i);
2371
2372 BT_LOGD("Freezing sequence field object's element field: "
2373 "element-field-addr=%p, index=%" PRId64,
2374 elem_field, i);
2375 bt_field_freeze_recursive(elem_field);
2376 }
2377
2378 generic_field_freeze(field);
2379 }
2380
2381 BT_HIDDEN
2382 void _bt_field_freeze_recursive(struct bt_field *field)
2383 {
2384 enum bt_field_type_id type_id;
2385
2386 if (!field) {
2387 goto end;
2388 }
2389
2390 if (field->frozen) {
2391 goto end;
2392 }
2393
2394 BT_LOGD("Freezing field object: addr=%p", field);
2395 BT_ASSERT(field_type_has_known_id(field->type));
2396 type_id = bt_field_get_type_id(field);
2397 field_freeze_funcs[type_id](field);
2398 end:
2399 return;
2400 }
2401
2402 static
2403 bt_bool bt_field_generic_is_set(struct bt_field *field)
2404 {
2405 return field && field->payload_set;
2406 }
2407
2408 static
2409 bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *field)
2410 {
2411 bt_bool is_set = BT_FALSE;
2412 struct bt_field_enumeration *enumeration;
2413
2414 BT_ASSERT(field);
2415 enumeration = container_of(field, struct bt_field_enumeration,
2416 parent);
2417 if (!enumeration->payload) {
2418 goto end;
2419 }
2420
2421 is_set = bt_field_is_set_recursive(enumeration->payload);
2422 end:
2423 return is_set;
2424 }
2425
2426 static
2427 bt_bool bt_field_structure_is_set_recursive(struct bt_field *field)
2428 {
2429 bt_bool is_set = BT_FALSE;
2430 size_t i;
2431 struct bt_field_structure *structure;
2432
2433 BT_ASSERT(field);
2434 structure = container_of(field, struct bt_field_structure, parent);
2435 for (i = 0; i < structure->fields->len; i++) {
2436 is_set = bt_field_is_set_recursive(
2437 structure->fields->pdata[i]);
2438 if (!is_set) {
2439 goto end;
2440 }
2441 }
2442 end:
2443 return is_set;
2444 }
2445
2446 static
2447 bt_bool bt_field_variant_is_set_recursive(struct bt_field *field)
2448 {
2449 struct bt_field_variant *variant;
2450
2451 BT_ASSERT(field);
2452 variant = container_of(field, struct bt_field_variant, parent);
2453 return bt_field_is_set_recursive(variant->payload);
2454 }
2455
2456 static
2457 bt_bool bt_field_array_is_set_recursive(struct bt_field *field)
2458 {
2459 size_t i;
2460 bt_bool is_set = BT_FALSE;
2461 struct bt_field_array *array;
2462
2463 BT_ASSERT(field);
2464 array = container_of(field, struct bt_field_array, parent);
2465 for (i = 0; i < array->elements->len; i++) {
2466 is_set = bt_field_is_set_recursive(array->elements->pdata[i]);
2467 if (!is_set) {
2468 goto end;
2469 }
2470 }
2471 end:
2472 return is_set;
2473 }
2474
2475 static
2476 bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field)
2477 {
2478 size_t i;
2479 bt_bool is_set = BT_FALSE;
2480 struct bt_field_sequence *sequence;
2481
2482 BT_ASSERT(field);
2483 sequence = container_of(field, struct bt_field_sequence, parent);
2484 if (!sequence->elements) {
2485 goto end;
2486 }
2487
2488 for (i = 0; i < sequence->elements->len; i++) {
2489 is_set = bt_field_is_set_recursive(sequence->elements->pdata[i]);
2490 if (!is_set) {
2491 goto end;
2492 }
2493 }
2494 end:
2495 return is_set;
2496 }
This page took 0.117036 seconds and 5 git commands to generate.