Commit | Line | Data |
---|---|---|
3dca2276 PP |
1 | #ifndef BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H |
2 | #define BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H | |
3 | ||
4 | /* | |
3dca2276 PP |
5 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
6 | * | |
7 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
10 | * of this software and associated documentation files (the "Software"), to deal | |
11 | * in the Software without restriction, including without limitation the rights | |
12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
13 | * copies of the Software, and to permit persons to whom the Software is | |
14 | * furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
25 | * SOFTWARE. | |
26 | * | |
27 | * The Common Trace Format (CTF) Specification is available at | |
28 | * http://www.efficios.com/ctf | |
29 | */ | |
30 | ||
31 | #include <stdint.h> | |
32 | #include <stddef.h> | |
33 | ||
67d2ce02 | 34 | #include <babeltrace2/ctf-writer/assert-pre-internal.h> |
3fadfbc0 MJ |
35 | #include <babeltrace2/babeltrace-internal.h> |
36 | #include <babeltrace2/common-internal.h> | |
37 | #include <babeltrace2/ctf-writer/field-types-internal.h> | |
38 | #include <babeltrace2/ctf-writer/fields.h> | |
39 | #include <babeltrace2/ctf-writer/utils-internal.h> | |
40 | #include <babeltrace2/ctf-writer/object-internal.h> | |
41 | #include <babeltrace2/ctfser-internal.h> | |
42 | #include <babeltrace2/types.h> | |
16ca5ff0 PP |
43 | #include <glib.h> |
44 | #include <inttypes.h> | |
45 | #include <stdbool.h> | |
46 | #include <stdint.h> | |
47 | #include <string.h> | |
48 | ||
67d2ce02 MJ |
49 | #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \ |
50 | BT_CTF_ASSERT_PRE((_field)->type->id == ((int) (_type_id)), \ | |
16ca5ff0 PP |
51 | _name " has the wrong type ID: expected-type-id=%s, " \ |
52 | "field-addr=%p", \ | |
53 | bt_ctf_field_type_id_string((int) (_type_id)), (_field)) | |
54 | ||
67d2ce02 MJ |
55 | #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(_field, _name) \ |
56 | BT_CTF_ASSERT_PRE(bt_ctf_field_common_is_set_recursive(_field), \ | |
16ca5ff0 PP |
57 | _name " is not set: field-addr=%p", (_field)) |
58 | ||
67d2ce02 MJ |
59 | #define BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(_field, _name) \ |
60 | BT_CTF_ASSERT_PRE_HOT((_field), (_name), ": field-addr=%p", (_field)) | |
16ca5ff0 PP |
61 | |
62 | struct bt_ctf_field_common; | |
63 | ||
64 | typedef void (*bt_ctf_field_common_method_set_is_frozen)(struct bt_ctf_field_common *, | |
65 | bool); | |
66 | typedef int (*bt_ctf_field_common_method_validate)(struct bt_ctf_field_common *); | |
67 | typedef struct bt_ctf_field_common *(*bt_ctf_field_common_method_copy)( | |
68 | struct bt_ctf_field_common *); | |
69 | typedef bt_bool (*bt_ctf_field_common_method_is_set)(struct bt_ctf_field_common *); | |
70 | typedef void (*bt_ctf_field_common_method_reset)(struct bt_ctf_field_common *); | |
71 | ||
72 | struct bt_ctf_field_common_methods { | |
73 | bt_ctf_field_common_method_set_is_frozen set_is_frozen; | |
74 | bt_ctf_field_common_method_validate validate; | |
75 | bt_ctf_field_common_method_copy copy; | |
76 | bt_ctf_field_common_method_is_set is_set; | |
77 | bt_ctf_field_common_method_reset reset; | |
78 | }; | |
79 | ||
80 | struct bt_ctf_field_common { | |
e1e02a22 | 81 | struct bt_ctf_object base; |
16ca5ff0 PP |
82 | struct bt_ctf_field_type_common *type; |
83 | struct bt_ctf_field_common_methods *methods; | |
84 | bool payload_set; | |
85 | bool frozen; | |
86 | ||
87 | /* | |
88 | * Specialized data for either CTF IR or CTF writer APIs. | |
89 | * See comment in `field-types-internal.h` for more details. | |
90 | */ | |
91 | union { | |
92 | struct { | |
93 | } ir; | |
94 | struct { | |
95 | void *serialize_func; | |
96 | } writer; | |
97 | } spec; | |
98 | }; | |
99 | ||
100 | struct bt_ctf_field_common_integer { | |
101 | struct bt_ctf_field_common common; | |
102 | union { | |
103 | int64_t signd; | |
104 | uint64_t unsignd; | |
105 | } payload; | |
106 | }; | |
107 | ||
108 | struct bt_ctf_field_common_floating_point { | |
109 | struct bt_ctf_field_common common; | |
110 | double payload; | |
111 | }; | |
112 | ||
113 | struct bt_ctf_field_common_structure { | |
114 | struct bt_ctf_field_common common; | |
115 | ||
116 | /* Array of `struct bt_ctf_field_common *`, owned by this */ | |
117 | GPtrArray *fields; | |
118 | }; | |
119 | ||
120 | struct bt_ctf_field_common_variant { | |
121 | struct bt_ctf_field_common common; | |
122 | ||
123 | union { | |
124 | uint64_t u; | |
125 | int64_t i; | |
126 | } tag_value; | |
127 | ||
128 | /* Weak: belongs to `choices` below */ | |
129 | struct bt_ctf_field_common *current_field; | |
130 | ||
131 | /* Array of `struct bt_ctf_field_common *`, owned by this */ | |
132 | GPtrArray *fields; | |
133 | }; | |
134 | ||
135 | struct bt_ctf_field_common_array { | |
136 | struct bt_ctf_field_common common; | |
137 | ||
138 | /* Array of `struct bt_ctf_field_common *`, owned by this */ | |
139 | GPtrArray *elements; | |
140 | }; | |
141 | ||
142 | struct bt_ctf_field_common_sequence { | |
143 | struct bt_ctf_field_common common; | |
144 | ||
145 | /* | |
146 | * This is the true sequence field's length: its value can be | |
147 | * less than `elements->len` below because we never shrink the | |
148 | * array of elements to avoid reallocation. | |
149 | */ | |
150 | uint64_t length; | |
151 | ||
152 | /* Array of `struct bt_ctf_field_common *`, owned by this */ | |
153 | GPtrArray *elements; | |
154 | }; | |
155 | ||
156 | struct bt_ctf_field_common_string { | |
157 | struct bt_ctf_field_common common; | |
158 | GArray *buf; | |
159 | size_t size; | |
160 | }; | |
161 | ||
162 | BT_HIDDEN | |
163 | struct bt_ctf_field_common *bt_ctf_field_common_copy(struct bt_ctf_field_common *field); | |
164 | ||
165 | BT_HIDDEN | |
166 | int bt_ctf_field_common_structure_initialize(struct bt_ctf_field_common *field, | |
167 | struct bt_ctf_field_type_common *type, | |
e1e02a22 | 168 | bool is_shared, bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
169 | struct bt_ctf_field_common_methods *methods, |
170 | bt_ctf_field_common_create_func field_create_func, | |
171 | GDestroyNotify field_release_func); | |
172 | ||
173 | BT_HIDDEN | |
174 | int bt_ctf_field_common_array_initialize(struct bt_ctf_field_common *field, | |
175 | struct bt_ctf_field_type_common *type, | |
e1e02a22 | 176 | bool is_shared, bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
177 | struct bt_ctf_field_common_methods *methods, |
178 | bt_ctf_field_common_create_func field_create_func, | |
179 | GDestroyNotify field_destroy_func); | |
180 | ||
181 | BT_HIDDEN | |
182 | int bt_ctf_field_common_sequence_initialize(struct bt_ctf_field_common *field, | |
183 | struct bt_ctf_field_type_common *type, | |
e1e02a22 | 184 | bool is_shared, bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
185 | struct bt_ctf_field_common_methods *methods, |
186 | GDestroyNotify field_destroy_func); | |
187 | ||
188 | BT_HIDDEN | |
189 | int bt_ctf_field_common_variant_initialize(struct bt_ctf_field_common *field, | |
190 | struct bt_ctf_field_type_common *type, | |
e1e02a22 | 191 | bool is_shared, bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
192 | struct bt_ctf_field_common_methods *methods, |
193 | bt_ctf_field_common_create_func field_create_func, | |
194 | GDestroyNotify field_release_func); | |
195 | ||
196 | BT_HIDDEN | |
197 | int bt_ctf_field_common_string_initialize(struct bt_ctf_field_common *field, | |
198 | struct bt_ctf_field_type_common *type, | |
e1e02a22 | 199 | bool is_shared, bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
200 | struct bt_ctf_field_common_methods *methods); |
201 | ||
202 | BT_HIDDEN | |
203 | int bt_ctf_field_common_generic_validate(struct bt_ctf_field_common *field); | |
204 | ||
205 | BT_HIDDEN | |
206 | int bt_ctf_field_common_structure_validate_recursive(struct bt_ctf_field_common *field); | |
207 | ||
208 | BT_HIDDEN | |
209 | int bt_ctf_field_common_variant_validate_recursive(struct bt_ctf_field_common *field); | |
210 | ||
211 | BT_HIDDEN | |
212 | int bt_ctf_field_common_array_validate_recursive(struct bt_ctf_field_common *field); | |
213 | ||
214 | BT_HIDDEN | |
215 | int bt_ctf_field_common_sequence_validate_recursive(struct bt_ctf_field_common *field); | |
216 | ||
217 | BT_HIDDEN | |
218 | void bt_ctf_field_common_generic_reset(struct bt_ctf_field_common *field); | |
219 | ||
220 | BT_HIDDEN | |
221 | void bt_ctf_field_common_structure_reset_recursive(struct bt_ctf_field_common *field); | |
222 | ||
223 | BT_HIDDEN | |
224 | void bt_ctf_field_common_variant_reset_recursive(struct bt_ctf_field_common *field); | |
225 | ||
226 | BT_HIDDEN | |
227 | void bt_ctf_field_common_array_reset_recursive(struct bt_ctf_field_common *field); | |
228 | ||
229 | BT_HIDDEN | |
230 | void bt_ctf_field_common_sequence_reset_recursive(struct bt_ctf_field_common *field); | |
231 | ||
232 | BT_HIDDEN | |
233 | void bt_ctf_field_common_generic_set_is_frozen(struct bt_ctf_field_common *field, | |
234 | bool is_frozen); | |
235 | ||
236 | BT_HIDDEN | |
237 | void bt_ctf_field_common_structure_set_is_frozen_recursive( | |
238 | struct bt_ctf_field_common *field, bool is_frozen); | |
239 | ||
240 | BT_HIDDEN | |
241 | void bt_ctf_field_common_variant_set_is_frozen_recursive( | |
242 | struct bt_ctf_field_common *field, bool is_frozen); | |
243 | ||
244 | BT_HIDDEN | |
245 | void bt_ctf_field_common_array_set_is_frozen_recursive( | |
246 | struct bt_ctf_field_common *field, bool is_frozen); | |
247 | ||
248 | BT_HIDDEN | |
249 | void bt_ctf_field_common_sequence_set_is_frozen_recursive( | |
250 | struct bt_ctf_field_common *field, bool is_frozen); | |
251 | ||
252 | BT_HIDDEN | |
253 | void _bt_ctf_field_common_set_is_frozen_recursive(struct bt_ctf_field_common *field, | |
254 | bool is_frozen); | |
255 | ||
256 | BT_HIDDEN | |
257 | bt_bool bt_ctf_field_common_generic_is_set(struct bt_ctf_field_common *field); | |
258 | ||
259 | BT_HIDDEN | |
260 | bt_bool bt_ctf_field_common_structure_is_set_recursive( | |
261 | struct bt_ctf_field_common *field); | |
262 | ||
263 | BT_HIDDEN | |
264 | bt_bool bt_ctf_field_common_variant_is_set_recursive(struct bt_ctf_field_common *field); | |
265 | ||
266 | BT_HIDDEN | |
267 | bt_bool bt_ctf_field_common_array_is_set_recursive(struct bt_ctf_field_common *field); | |
268 | ||
269 | BT_HIDDEN | |
270 | bt_bool bt_ctf_field_common_sequence_is_set_recursive(struct bt_ctf_field_common *field); | |
271 | ||
272 | #ifdef BT_DEV_MODE | |
273 | # define bt_ctf_field_common_validate_recursive _bt_ctf_field_common_validate_recursive | |
274 | # define bt_ctf_field_common_set_is_frozen_recursive _bt_ctf_field_common_set_is_frozen_recursive | |
275 | # define bt_ctf_field_common_is_set_recursive _bt_ctf_field_common_is_set_recursive | |
276 | # define bt_ctf_field_common_reset_recursive _bt_ctf_field_common_reset_recursive | |
277 | # define bt_ctf_field_common_set _bt_ctf_field_common_set | |
278 | #else | |
279 | # define bt_ctf_field_common_validate_recursive(_field) (-1) | |
280 | # define bt_ctf_field_common_set_is_frozen_recursive(_field, _is_frozen) | |
281 | # define bt_ctf_field_common_is_set_recursive(_field) (BT_FALSE) | |
282 | # define bt_ctf_field_common_reset_recursive(_field) | |
283 | # define bt_ctf_field_common_set(_field, _val) | |
284 | #endif | |
285 | ||
286 | BT_ASSERT_FUNC | |
287 | static inline bool field_type_common_has_known_id( | |
288 | struct bt_ctf_field_type_common *ft) | |
289 | { | |
290 | return (int) ft->id > BT_CTF_FIELD_TYPE_ID_UNKNOWN || | |
291 | (int) ft->id < BT_CTF_FIELD_TYPE_ID_NR; | |
292 | } | |
293 | ||
294 | static inline | |
295 | int _bt_ctf_field_common_validate_recursive(struct bt_ctf_field_common *field) | |
296 | { | |
297 | int ret = 0; | |
298 | ||
299 | if (!field) { | |
67d2ce02 | 300 | BT_CTF_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL."); |
16ca5ff0 PP |
301 | ret = -1; |
302 | goto end; | |
303 | } | |
304 | ||
305 | BT_ASSERT(field_type_common_has_known_id(field->type)); | |
306 | ||
307 | if (field->methods->validate) { | |
308 | ret = field->methods->validate(field); | |
309 | } | |
310 | ||
311 | end: | |
312 | return ret; | |
313 | } | |
314 | ||
315 | static inline | |
316 | void _bt_ctf_field_common_reset_recursive(struct bt_ctf_field_common *field) | |
317 | { | |
318 | BT_ASSERT(field); | |
319 | BT_ASSERT(field->methods->reset); | |
320 | field->methods->reset(field); | |
321 | } | |
322 | ||
323 | static inline | |
324 | void _bt_ctf_field_common_set(struct bt_ctf_field_common *field, bool value) | |
325 | { | |
326 | BT_ASSERT(field); | |
327 | field->payload_set = value; | |
328 | } | |
329 | ||
330 | static inline | |
331 | bt_bool _bt_ctf_field_common_is_set_recursive(struct bt_ctf_field_common *field) | |
332 | { | |
333 | bt_bool is_set = BT_FALSE; | |
334 | ||
335 | if (!field) { | |
336 | goto end; | |
337 | } | |
338 | ||
339 | BT_ASSERT(field_type_common_has_known_id(field->type)); | |
340 | BT_ASSERT(field->methods->is_set); | |
341 | is_set = field->methods->is_set(field); | |
342 | ||
343 | end: | |
344 | return is_set; | |
345 | } | |
346 | ||
347 | static inline | |
348 | void bt_ctf_field_common_initialize(struct bt_ctf_field_common *field, | |
349 | struct bt_ctf_field_type_common *ft, bool is_shared, | |
e1e02a22 | 350 | bt_ctf_object_release_func release_func, |
16ca5ff0 PP |
351 | struct bt_ctf_field_common_methods *methods) |
352 | { | |
353 | BT_ASSERT(field); | |
354 | BT_ASSERT(ft); | |
e1e02a22 | 355 | bt_ctf_object_init(&field->base, is_shared, release_func); |
16ca5ff0 | 356 | field->methods = methods; |
e1e02a22 | 357 | field->type = (void *) bt_ctf_object_get_ref(ft); |
16ca5ff0 PP |
358 | } |
359 | ||
360 | static inline | |
361 | struct bt_ctf_field_type_common *bt_ctf_field_common_borrow_type( | |
362 | struct bt_ctf_field_common *field) | |
363 | { | |
364 | struct bt_ctf_field_type_common *ret = NULL; | |
365 | ||
67d2ce02 | 366 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Field"); |
16ca5ff0 PP |
367 | ret = field->type; |
368 | return ret; | |
369 | } | |
370 | ||
371 | static inline | |
372 | int64_t bt_ctf_field_common_sequence_get_length(struct bt_ctf_field_common *field) | |
373 | { | |
374 | struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); | |
375 | ||
67d2ce02 MJ |
376 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
377 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE, | |
16ca5ff0 PP |
378 | "Field"); |
379 | return (int64_t) sequence->length; | |
380 | } | |
381 | ||
382 | static inline | |
383 | int bt_ctf_field_common_sequence_set_length(struct bt_ctf_field_common *field, | |
384 | uint64_t length, bt_ctf_field_common_create_func field_create_func) | |
385 | { | |
386 | int ret = 0; | |
387 | struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); | |
388 | ||
67d2ce02 MJ |
389 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
390 | BT_CTF_ASSERT_PRE(((int64_t) length) >= 0, | |
16ca5ff0 PP |
391 | "Invalid sequence length (too large): length=%" PRId64, |
392 | length); | |
67d2ce02 | 393 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Sequence field"); |
16ca5ff0 PP |
394 | |
395 | if (unlikely(length > sequence->elements->len)) { | |
396 | /* Make more room */ | |
397 | struct bt_ctf_field_type_common_sequence *sequence_ft; | |
398 | uint64_t cur_len = sequence->elements->len; | |
399 | uint64_t i; | |
400 | ||
401 | g_ptr_array_set_size(sequence->elements, length); | |
402 | sequence_ft = BT_CTF_FROM_COMMON(sequence->common.type); | |
403 | ||
404 | for (i = cur_len; i < sequence->elements->len; i++) { | |
405 | struct bt_ctf_field_common *elem_field = | |
406 | field_create_func(sequence_ft->element_ft); | |
407 | ||
408 | if (!elem_field) { | |
409 | ret = -1; | |
410 | goto end; | |
411 | } | |
412 | ||
413 | BT_ASSERT(!sequence->elements->pdata[i]); | |
414 | sequence->elements->pdata[i] = elem_field; | |
415 | } | |
416 | } | |
417 | ||
418 | sequence->length = length; | |
419 | ||
420 | end: | |
421 | return ret; | |
422 | } | |
423 | ||
424 | static inline | |
425 | struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_name( | |
426 | struct bt_ctf_field_common *field, const char *name) | |
427 | { | |
428 | struct bt_ctf_field_common *ret = NULL; | |
429 | GQuark field_quark; | |
430 | struct bt_ctf_field_type_common_structure *structure_ft; | |
431 | struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); | |
432 | size_t index; | |
433 | GHashTable *field_name_to_index; | |
434 | ||
67d2ce02 MJ |
435 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Structure field"); |
436 | BT_CTF_ASSERT_PRE_NON_NULL(name, "Field name"); | |
437 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
438 | BT_CTF_FIELD_TYPE_ID_STRUCT, "Field"); |
439 | structure_ft = BT_CTF_FROM_COMMON(field->type); | |
440 | field_name_to_index = structure_ft->field_name_to_index; | |
441 | field_quark = g_quark_from_string(name); | |
442 | if (!g_hash_table_lookup_extended(field_name_to_index, | |
443 | GUINT_TO_POINTER(field_quark), | |
444 | NULL, (gpointer *) &index)) { | |
445 | BT_LOGV("Invalid parameter: no such field in structure field's type: " | |
446 | "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"", | |
447 | field, field->type, name); | |
448 | goto error; | |
449 | } | |
450 | ||
451 | ret = structure->fields->pdata[index]; | |
452 | BT_ASSERT(ret); | |
453 | ||
454 | error: | |
455 | return ret; | |
456 | } | |
457 | ||
458 | static inline | |
459 | struct bt_ctf_field_common *bt_ctf_field_common_structure_borrow_field_by_index( | |
460 | struct bt_ctf_field_common *field, uint64_t index) | |
461 | { | |
462 | struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); | |
463 | ||
67d2ce02 MJ |
464 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Structure field"); |
465 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 | 466 | BT_CTF_FIELD_TYPE_ID_STRUCT, "Field"); |
67d2ce02 | 467 | BT_CTF_ASSERT_PRE(index < structure->fields->len, |
16ca5ff0 PP |
468 | "Index is out of bound: struct-field-addr=%p, " |
469 | "index=%" PRIu64 ", count=%u", field, index, | |
470 | structure->fields->len); | |
471 | return structure->fields->pdata[index]; | |
472 | } | |
473 | ||
474 | static inline | |
475 | struct bt_ctf_field_common *bt_ctf_field_common_array_borrow_field( | |
476 | struct bt_ctf_field_common *field, uint64_t index) | |
477 | { | |
478 | struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field); | |
479 | ||
67d2ce02 MJ |
480 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Array field"); |
481 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_ARRAY, | |
16ca5ff0 | 482 | "Field"); |
67d2ce02 | 483 | BT_CTF_ASSERT_PRE(index < array->elements->len, |
16ca5ff0 PP |
484 | "Index is out of bound: array-field-addr=%p, " |
485 | "index=%" PRIu64 ", count=%u", field, | |
486 | index, array->elements->len); | |
487 | return array->elements->pdata[(size_t) index]; | |
488 | } | |
489 | ||
490 | static inline | |
491 | struct bt_ctf_field_common *bt_ctf_field_common_sequence_borrow_field( | |
492 | struct bt_ctf_field_common *field, uint64_t index) | |
493 | { | |
494 | struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); | |
495 | ||
67d2ce02 MJ |
496 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
497 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, BT_CTF_FIELD_TYPE_ID_SEQUENCE, | |
16ca5ff0 | 498 | "Field"); |
67d2ce02 | 499 | BT_CTF_ASSERT_PRE(index < sequence->length, |
16ca5ff0 PP |
500 | "Index is out of bound: seq-field-addr=%p, " |
501 | "index=%" PRIu64 ", count=%u", field, index, | |
502 | sequence->elements->len); | |
503 | return sequence->elements->pdata[(size_t) index]; | |
504 | } | |
505 | ||
506 | static inline | |
507 | int bt_ctf_field_common_variant_set_tag(struct bt_ctf_field_common *variant_field, | |
508 | uint64_t tag_uval, bool is_signed) | |
509 | { | |
510 | int ret = 0; | |
511 | int64_t choice_index; | |
512 | struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); | |
513 | ||
67d2ce02 MJ |
514 | BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
515 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
16ca5ff0 PP |
516 | BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); |
517 | ||
518 | /* Find matching index in variant field's type */ | |
519 | choice_index = bt_ctf_field_type_common_variant_find_choice_index( | |
520 | variant_field->type, tag_uval, is_signed); | |
521 | if (choice_index < 0) { | |
522 | ret = -1; | |
523 | goto end; | |
524 | } | |
525 | ||
526 | /* Select corresponding field */ | |
527 | BT_ASSERT(choice_index < variant->fields->len); | |
528 | variant->current_field = variant->fields->pdata[choice_index]; | |
529 | variant->tag_value.u = tag_uval; | |
530 | ||
531 | end: | |
532 | return ret; | |
533 | } | |
534 | ||
535 | static inline | |
536 | struct bt_ctf_field_common *bt_ctf_field_common_variant_borrow_current_field( | |
537 | struct bt_ctf_field_common *variant_field) | |
538 | { | |
539 | struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); | |
540 | ||
67d2ce02 MJ |
541 | BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
542 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
16ca5ff0 | 543 | BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); |
67d2ce02 | 544 | BT_CTF_ASSERT_PRE(variant->current_field, |
16ca5ff0 PP |
545 | "Variant field has no current field: field-addr=%p", variant_field); |
546 | return variant->current_field; | |
547 | } | |
548 | ||
549 | static inline | |
550 | int bt_ctf_field_common_variant_get_tag_signed(struct bt_ctf_field_common *variant_field, | |
551 | int64_t *tag) | |
552 | { | |
553 | struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); | |
554 | ||
67d2ce02 MJ |
555 | BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
556 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
16ca5ff0 | 557 | BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); |
67d2ce02 | 558 | BT_CTF_ASSERT_PRE(variant->current_field, |
16ca5ff0 PP |
559 | "Variant field has no current field: field-addr=%p", variant_field); |
560 | *tag = variant->tag_value.i; | |
561 | return 0; | |
562 | } | |
563 | ||
564 | static inline | |
565 | int bt_ctf_field_common_variant_get_tag_unsigned(struct bt_ctf_field_common *variant_field, | |
566 | uint64_t *tag) | |
567 | { | |
568 | struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(variant_field); | |
569 | ||
67d2ce02 MJ |
570 | BT_CTF_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
571 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
16ca5ff0 | 572 | BT_CTF_FIELD_TYPE_ID_VARIANT, "Field"); |
67d2ce02 | 573 | BT_CTF_ASSERT_PRE(variant->current_field, |
16ca5ff0 PP |
574 | "Variant field has no current field: field-addr=%p", variant_field); |
575 | *tag = variant->tag_value.u; | |
576 | return 0; | |
577 | } | |
578 | ||
579 | static inline | |
580 | int bt_ctf_field_common_floating_point_get_value(struct bt_ctf_field_common *field, | |
581 | double *value) | |
582 | { | |
583 | struct bt_ctf_field_common_floating_point *floating_point = | |
584 | BT_CTF_FROM_COMMON(field); | |
585 | ||
67d2ce02 MJ |
586 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Floating point number field"); |
587 | BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); | |
588 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field"); | |
589 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
590 | BT_CTF_FIELD_TYPE_ID_FLOAT, "Field"); |
591 | *value = floating_point->payload; | |
592 | return 0; | |
593 | } | |
594 | ||
595 | static inline | |
596 | int bt_ctf_field_common_floating_point_set_value(struct bt_ctf_field_common *field, | |
597 | double value) | |
598 | { | |
599 | struct bt_ctf_field_common_floating_point *floating_point = | |
600 | BT_CTF_FROM_COMMON(field); | |
601 | ||
67d2ce02 MJ |
602 | BT_CTF_ASSERT_PRE_NON_NULL(field, "Floating point number field"); |
603 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "Floating point number field"); | |
604 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
605 | BT_CTF_FIELD_TYPE_ID_FLOAT, "Field"); |
606 | floating_point->payload = value; | |
607 | bt_ctf_field_common_set(field, true); | |
608 | return 0; | |
609 | } | |
610 | ||
611 | static inline | |
612 | const char *bt_ctf_field_common_string_get_value(struct bt_ctf_field_common *field) | |
613 | { | |
614 | struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field); | |
615 | ||
67d2ce02 MJ |
616 | BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); |
617 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field"); | |
618 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
619 | BT_CTF_FIELD_TYPE_ID_STRING, "Field"); |
620 | return (const char *) string->buf->data; | |
621 | } | |
622 | ||
623 | static inline | |
624 | int bt_ctf_field_common_string_clear(struct bt_ctf_field_common *field) | |
625 | { | |
626 | struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field); | |
627 | ||
67d2ce02 MJ |
628 | BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); |
629 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); | |
630 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
631 | BT_CTF_FIELD_TYPE_ID_STRING, "Field"); |
632 | string_field->size = 0; | |
633 | bt_ctf_field_common_set(field, true); | |
634 | return 0; | |
635 | } | |
636 | ||
637 | static inline | |
638 | int bt_ctf_field_common_string_append_len(struct bt_ctf_field_common *field, | |
639 | const char *value, unsigned int length) | |
640 | { | |
641 | struct bt_ctf_field_common_string *string_field = BT_CTF_FROM_COMMON(field); | |
642 | char *data; | |
643 | size_t new_size; | |
644 | ||
67d2ce02 MJ |
645 | BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); |
646 | BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); | |
647 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); | |
648 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
649 | BT_CTF_FIELD_TYPE_ID_STRING, "Field"); |
650 | ||
651 | /* Make sure no null bytes are appended */ | |
67d2ce02 | 652 | BT_CTF_ASSERT_PRE(memchr(value, '\0', length) == NULL, |
16ca5ff0 PP |
653 | "String value to append contains a null character: " |
654 | "partial-value=\"%.32s\", length=%u", value, length); | |
655 | ||
656 | new_size = string_field->size + length; | |
657 | ||
658 | if (unlikely(new_size + 1 > string_field->buf->len)) { | |
659 | g_array_set_size(string_field->buf, new_size + 1); | |
660 | } | |
661 | ||
662 | data = string_field->buf->data; | |
663 | memcpy(data + string_field->size, value, length); | |
664 | ((char *) string_field->buf->data)[new_size] = '\0'; | |
665 | string_field->size = new_size; | |
666 | bt_ctf_field_common_set(field, true); | |
667 | return 0; | |
668 | } | |
669 | ||
670 | static inline | |
671 | int bt_ctf_field_common_string_append(struct bt_ctf_field_common *field, | |
672 | const char *value) | |
673 | { | |
67d2ce02 | 674 | BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); |
16ca5ff0 PP |
675 | return bt_ctf_field_common_string_append_len(field, value, |
676 | strlen(value)); | |
677 | } | |
678 | ||
679 | static inline | |
680 | int bt_ctf_field_common_string_set_value(struct bt_ctf_field_common *field, | |
681 | const char *value) | |
682 | { | |
67d2ce02 MJ |
683 | BT_CTF_ASSERT_PRE_NON_NULL(field, "String field"); |
684 | BT_CTF_ASSERT_PRE_NON_NULL(value, "Value"); | |
685 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HOT(field, "String field"); | |
686 | BT_CTF_ASSERT_PRE_CTF_FIELD_COMMON_HAS_TYPE_ID(field, | |
16ca5ff0 PP |
687 | BT_CTF_FIELD_TYPE_ID_STRING, "Field"); |
688 | bt_ctf_field_common_string_clear(field); | |
689 | return bt_ctf_field_common_string_append_len(field, | |
690 | value, strlen(value)); | |
691 | } | |
692 | ||
693 | static inline | |
694 | void bt_ctf_field_common_finalize(struct bt_ctf_field_common *field) | |
695 | { | |
696 | BT_ASSERT(field); | |
697 | BT_LOGD_STR("Putting field's type."); | |
e1e02a22 | 698 | bt_ctf_object_put_ref(field->type); |
16ca5ff0 PP |
699 | } |
700 | ||
701 | static inline | |
702 | void bt_ctf_field_common_integer_finalize(struct bt_ctf_field_common *field) | |
703 | { | |
704 | BT_ASSERT(field); | |
705 | BT_LOGD("Finalizing common integer field object: addr=%p", field); | |
706 | bt_ctf_field_common_finalize(field); | |
707 | } | |
708 | ||
709 | static inline | |
710 | void bt_ctf_field_common_floating_point_finalize(struct bt_ctf_field_common *field) | |
711 | { | |
712 | BT_ASSERT(field); | |
713 | BT_LOGD("Finalizing common floating point number field object: addr=%p", field); | |
714 | bt_ctf_field_common_finalize(field); | |
715 | } | |
716 | ||
717 | static inline | |
718 | void bt_ctf_field_common_structure_finalize_recursive(struct bt_ctf_field_common *field) | |
719 | { | |
720 | struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field); | |
721 | ||
722 | BT_ASSERT(field); | |
723 | BT_LOGD("Finalizing common structure field object: addr=%p", field); | |
724 | bt_ctf_field_common_finalize(field); | |
725 | ||
726 | if (structure->fields) { | |
727 | g_ptr_array_free(structure->fields, TRUE); | |
728 | } | |
729 | } | |
730 | ||
731 | static inline | |
732 | void bt_ctf_field_common_variant_finalize_recursive(struct bt_ctf_field_common *field) | |
733 | { | |
734 | struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field); | |
735 | ||
736 | BT_ASSERT(field); | |
737 | BT_LOGD("Finalizing common variant field object: addr=%p", field); | |
738 | bt_ctf_field_common_finalize(field); | |
739 | ||
740 | if (variant->fields) { | |
741 | g_ptr_array_free(variant->fields, TRUE); | |
742 | } | |
743 | } | |
744 | ||
745 | static inline | |
746 | void bt_ctf_field_common_array_finalize_recursive(struct bt_ctf_field_common *field) | |
747 | { | |
748 | struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field); | |
749 | ||
750 | BT_ASSERT(field); | |
751 | BT_LOGD("Finalizing common array field object: addr=%p", field); | |
752 | bt_ctf_field_common_finalize(field); | |
753 | ||
754 | if (array->elements) { | |
755 | g_ptr_array_free(array->elements, TRUE); | |
756 | } | |
757 | } | |
758 | ||
759 | static inline | |
760 | void bt_ctf_field_common_sequence_finalize_recursive(struct bt_ctf_field_common *field) | |
761 | { | |
762 | struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field); | |
763 | ||
764 | BT_ASSERT(field); | |
765 | BT_LOGD("Finalizing common sequence field object: addr=%p", field); | |
766 | bt_ctf_field_common_finalize(field); | |
767 | ||
768 | if (sequence->elements) { | |
769 | g_ptr_array_free(sequence->elements, TRUE); | |
770 | } | |
771 | } | |
772 | ||
773 | static inline | |
774 | void bt_ctf_field_common_string_finalize(struct bt_ctf_field_common *field) | |
775 | { | |
776 | struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field); | |
777 | ||
778 | BT_ASSERT(field); | |
779 | BT_LOGD("Finalizing common string field object: addr=%p", field); | |
780 | bt_ctf_field_common_finalize(field); | |
781 | ||
782 | if (string->buf) { | |
783 | g_array_free(string->buf, TRUE); | |
784 | } | |
785 | } | |
786 | ||
67d2ce02 | 787 | BT_CTF_ASSERT_PRE_FUNC |
16ca5ff0 PP |
788 | static inline bool value_is_in_range_signed(unsigned int size, int64_t value) |
789 | { | |
790 | bool ret = true; | |
791 | int64_t min_value, max_value; | |
792 | ||
793 | min_value = -(1ULL << (size - 1)); | |
794 | max_value = (1ULL << (size - 1)) - 1; | |
795 | if (value < min_value || value > max_value) { | |
796 | BT_LOGF("Value is out of bounds: value=%" PRId64 ", " | |
797 | "min-value=%" PRId64 ", max-value=%" PRId64, | |
798 | value, min_value, max_value); | |
799 | ret = false; | |
800 | } | |
801 | ||
802 | return ret; | |
803 | } | |
804 | ||
67d2ce02 | 805 | BT_CTF_ASSERT_PRE_FUNC |
16ca5ff0 PP |
806 | static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value) |
807 | { | |
808 | bool ret = true; | |
809 | int64_t max_value; | |
810 | ||
811 | max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; | |
812 | if (value > max_value) { | |
813 | BT_LOGF("Value is out of bounds: value=%" PRIu64 ", " | |
814 | "max-value=%" PRIu64, | |
815 | value, max_value); | |
816 | ret = false; | |
817 | } | |
818 | ||
819 | return ret; | |
820 | } | |
3dca2276 | 821 | |
312c056a | 822 | struct bt_ctf_field_enumeration { |
16ca5ff0 PP |
823 | struct bt_ctf_field_common common; |
824 | struct bt_ctf_field_common_integer *container; | |
312c056a PP |
825 | }; |
826 | ||
827 | struct bt_ctf_field_variant { | |
16ca5ff0 | 828 | struct bt_ctf_field_common_variant common; |
312c056a PP |
829 | struct bt_ctf_field_enumeration *tag; |
830 | }; | |
831 | ||
3dca2276 PP |
832 | BT_HIDDEN |
833 | int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field, | |
013f35c6 | 834 | struct bt_ctfser *ctfser, |
3dca2276 PP |
835 | enum bt_ctf_byte_order native_byte_order); |
836 | ||
312c056a PP |
837 | BT_HIDDEN |
838 | int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field, | |
839 | const char *name, struct bt_ctf_field *value); | |
840 | ||
841 | BT_HIDDEN | |
842 | struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container( | |
843 | struct bt_ctf_field *field); | |
844 | ||
3dca2276 PP |
845 | static inline |
846 | bt_bool bt_ctf_field_is_set_recursive(struct bt_ctf_field *field) | |
847 | { | |
16ca5ff0 | 848 | return bt_ctf_field_common_is_set_recursive((void *) field); |
3dca2276 PP |
849 | } |
850 | ||
851 | #endif /* BABELTRACE_CTF_WRITER_FIELDS_INTERNAL_H */ |