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