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