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