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