Commit | Line | Data |
---|---|---|
2e33ac5a PP |
1 | #ifndef BABELTRACE_CTF_IR_FIELDS_INTERNAL_H |
2 | #define BABELTRACE_CTF_IR_FIELDS_INTERNAL_H | |
273b65be JG |
3 | |
4 | /* | |
2e33ac5a | 5 | * Babeltrace - CTF IR: Event Fields internal |
273b65be | 6 | * |
de9dd397 | 7 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
273b65be JG |
8 | * |
9 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
10 | * | |
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
12 | * of this software and associated documentation files (the "Software"), to deal | |
13 | * in the Software without restriction, including without limitation the rights | |
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
15 | * copies of the Software, and to permit persons to whom the Software is | |
16 | * furnished to do so, subject to the following conditions: | |
17 | * | |
18 | * The above copyright notice and this permission notice shall be included in | |
19 | * all copies or substantial portions of the Software. | |
20 | * | |
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
27 | * SOFTWARE. | |
28 | */ | |
29 | ||
3dca2276 PP |
30 | #include <babeltrace/assert-pre-internal.h> |
31 | #include <babeltrace/common-internal.h> | |
32 | #include <babeltrace/ctf-ir/field-types-internal.h> | |
33 | #include <babeltrace/ctf-ir/utils-internal.h> | |
83509119 | 34 | #include <babeltrace/object-internal.h> |
273b65be | 35 | #include <babeltrace/babeltrace-internal.h> |
c55a9f58 | 36 | #include <babeltrace/types.h> |
dc3fffef | 37 | #include <stdint.h> |
4d4b475d | 38 | #include <string.h> |
3dca2276 | 39 | #include <inttypes.h> |
d990a4fb | 40 | #include <stdbool.h> |
273b65be JG |
41 | #include <glib.h> |
42 | ||
3dca2276 | 43 | #define BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(_field, _type_id, _name) \ |
312c056a | 44 | BT_ASSERT_PRE((_field)->type->id == ((int) (_type_id)), \ |
3dca2276 | 45 | _name " has the wrong type ID: expected-type-id=%s, " \ |
312c056a PP |
46 | "%![field-]+_f", \ |
47 | bt_common_field_type_id_string((int) (_type_id)), (_field)) | |
dc3fffef | 48 | |
3dca2276 PP |
49 | #define BT_ASSERT_PRE_FIELD_COMMON_IS_SET(_field, _name) \ |
50 | BT_ASSERT_PRE(bt_field_common_is_set_recursive(_field), \ | |
51 | _name " is not set: %!+_f", (_field)) | |
52 | ||
53 | #define BT_ASSERT_PRE_FIELD_COMMON_HOT(_field, _name) \ | |
54 | BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+_f", (_field)) | |
55 | ||
56 | struct bt_field; | |
57 | struct bt_field_common; | |
58 | ||
312c056a PP |
59 | typedef void (*bt_field_common_method_set_is_frozen)(struct bt_field_common *, |
60 | bool); | |
3dca2276 PP |
61 | typedef int (*bt_field_common_method_validate)(struct bt_field_common *); |
62 | typedef struct bt_field_common *(*bt_field_common_method_copy)( | |
63 | struct bt_field_common *); | |
64 | typedef bt_bool (*bt_field_common_method_is_set)(struct bt_field_common *); | |
65 | typedef void (*bt_field_common_method_reset)(struct bt_field_common *); | |
66 | ||
67 | struct bt_field_common_methods { | |
312c056a | 68 | bt_field_common_method_set_is_frozen set_is_frozen; |
3dca2276 PP |
69 | bt_field_common_method_validate validate; |
70 | bt_field_common_method_copy copy; | |
71 | bt_field_common_method_is_set is_set; | |
72 | bt_field_common_method_reset reset; | |
73 | }; | |
74 | ||
75 | struct bt_field_common { | |
83509119 | 76 | struct bt_object base; |
3dca2276 PP |
77 | struct bt_field_type_common *type; |
78 | struct bt_field_common_methods *methods; | |
d990a4fb JG |
79 | bool payload_set; |
80 | bool frozen; | |
3dca2276 PP |
81 | |
82 | /* | |
83 | * Specialized data for either CTF IR or CTF writer APIs. | |
84 | * See comment in `field-types-internal.h` for more details. | |
85 | */ | |
86 | union { | |
87 | struct { | |
88 | } ir; | |
89 | struct { | |
90 | void *serialize_func; | |
91 | } writer; | |
92 | } spec; | |
273b65be JG |
93 | }; |
94 | ||
3dca2276 PP |
95 | struct bt_field_common_integer { |
96 | struct bt_field_common common; | |
dc3fffef PP |
97 | union { |
98 | int64_t signd; | |
99 | uint64_t unsignd; | |
100 | } payload; | |
273b65be JG |
101 | }; |
102 | ||
3dca2276 PP |
103 | struct bt_field_common_floating_point { |
104 | struct bt_field_common common; | |
dc3fffef | 105 | double payload; |
273b65be JG |
106 | }; |
107 | ||
3dca2276 PP |
108 | struct bt_field_common_structure { |
109 | struct bt_field_common common; | |
312c056a PP |
110 | |
111 | /* Array of `struct bt_field_common *`, owned by this */ | |
112 | GPtrArray *fields; | |
273b65be JG |
113 | }; |
114 | ||
3dca2276 PP |
115 | struct bt_field_common_variant { |
116 | struct bt_field_common common; | |
312c056a PP |
117 | |
118 | union { | |
119 | uint64_t u; | |
120 | int64_t i; | |
121 | } tag_value; | |
122 | ||
123 | /* Weak: belongs to `choices` below */ | |
124 | struct bt_field_common *current_field; | |
125 | ||
126 | /* Array of `struct bt_field_common *`, owned by this */ | |
127 | GPtrArray *fields; | |
273b65be JG |
128 | }; |
129 | ||
3dca2276 PP |
130 | struct bt_field_common_array { |
131 | struct bt_field_common common; | |
312c056a PP |
132 | |
133 | /* Array of `struct bt_field_common *`, owned by this */ | |
134 | GPtrArray *elements; | |
273b65be JG |
135 | }; |
136 | ||
3dca2276 PP |
137 | struct bt_field_common_sequence { |
138 | struct bt_field_common common; | |
312c056a PP |
139 | |
140 | /* | |
141 | * This is the true sequence field's length: its value can be | |
142 | * less than `elements->len` below because we never shrink the | |
143 | * array of elements to avoid reallocation. | |
144 | */ | |
145 | uint64_t length; | |
146 | ||
147 | /* Array of `struct bt_field_common *`, owned by this */ | |
148 | GPtrArray *elements; | |
273b65be JG |
149 | }; |
150 | ||
3dca2276 PP |
151 | struct bt_field_common_string { |
152 | struct bt_field_common common; | |
4d4b475d PP |
153 | GArray *buf; |
154 | size_t size; | |
273b65be JG |
155 | }; |
156 | ||
312c056a PP |
157 | struct bt_field_enumeration { |
158 | struct bt_field_common_integer common; | |
159 | }; | |
3dca2276 PP |
160 | |
161 | BT_HIDDEN | |
162 | struct bt_field_common *bt_field_common_copy(struct bt_field_common *field); | |
163 | ||
164 | BT_HIDDEN | |
165 | int bt_field_common_structure_initialize(struct bt_field_common *field, | |
166 | struct bt_field_type_common *type, | |
3fea54f6 | 167 | bool is_shared, bt_object_release_func release_func, |
3dca2276 | 168 | struct bt_field_common_methods *methods, |
312c056a PP |
169 | bt_field_common_create_func field_create_func, |
170 | GDestroyNotify field_release_func); | |
3dca2276 PP |
171 | |
172 | BT_HIDDEN | |
173 | int bt_field_common_array_initialize(struct bt_field_common *field, | |
174 | struct bt_field_type_common *type, | |
3fea54f6 | 175 | bool is_shared, bt_object_release_func release_func, |
312c056a PP |
176 | struct bt_field_common_methods *methods, |
177 | bt_field_common_create_func field_create_func, | |
178 | GDestroyNotify field_destroy_func); | |
3dca2276 PP |
179 | |
180 | BT_HIDDEN | |
312c056a PP |
181 | int bt_field_common_sequence_initialize(struct bt_field_common *field, |
182 | struct bt_field_type_common *type, | |
3fea54f6 | 183 | bool is_shared, bt_object_release_func release_func, |
312c056a PP |
184 | struct bt_field_common_methods *methods, |
185 | GDestroyNotify field_destroy_func); | |
3dca2276 PP |
186 | |
187 | BT_HIDDEN | |
312c056a PP |
188 | int bt_field_common_variant_initialize(struct bt_field_common *field, |
189 | struct bt_field_type_common *type, | |
3fea54f6 | 190 | bool is_shared, bt_object_release_func release_func, |
312c056a PP |
191 | struct bt_field_common_methods *methods, |
192 | bt_field_common_create_func field_create_func, | |
193 | GDestroyNotify field_release_func); | |
194 | ||
4d4b475d PP |
195 | BT_HIDDEN |
196 | int bt_field_common_string_initialize(struct bt_field_common *field, | |
197 | struct bt_field_type_common *type, | |
3fea54f6 | 198 | bool is_shared, bt_object_release_func release_func, |
4d4b475d PP |
199 | struct bt_field_common_methods *methods); |
200 | ||
312c056a PP |
201 | BT_HIDDEN |
202 | int bt_field_common_generic_validate(struct bt_field_common *field); | |
3dca2276 PP |
203 | |
204 | BT_HIDDEN | |
205 | int bt_field_common_structure_validate_recursive(struct bt_field_common *field); | |
206 | ||
207 | BT_HIDDEN | |
208 | int bt_field_common_variant_validate_recursive(struct bt_field_common *field); | |
209 | ||
210 | BT_HIDDEN | |
211 | int bt_field_common_array_validate_recursive(struct bt_field_common *field); | |
212 | ||
213 | BT_HIDDEN | |
214 | int bt_field_common_sequence_validate_recursive(struct bt_field_common *field); | |
215 | ||
216 | BT_HIDDEN | |
217 | void bt_field_common_generic_reset(struct bt_field_common *field); | |
218 | ||
3dca2276 PP |
219 | BT_HIDDEN |
220 | void bt_field_common_structure_reset_recursive(struct bt_field_common *field); | |
221 | ||
222 | BT_HIDDEN | |
223 | void bt_field_common_variant_reset_recursive(struct bt_field_common *field); | |
224 | ||
225 | BT_HIDDEN | |
226 | void bt_field_common_array_reset_recursive(struct bt_field_common *field); | |
227 | ||
228 | BT_HIDDEN | |
229 | void bt_field_common_sequence_reset_recursive(struct bt_field_common *field); | |
230 | ||
3dca2276 | 231 | BT_HIDDEN |
312c056a PP |
232 | void bt_field_common_generic_set_is_frozen(struct bt_field_common *field, |
233 | bool is_frozen); | |
f6ccaed9 | 234 | |
273b65be | 235 | BT_HIDDEN |
312c056a PP |
236 | void bt_field_common_structure_set_is_frozen_recursive( |
237 | struct bt_field_common *field, bool is_frozen); | |
273b65be JG |
238 | |
239 | BT_HIDDEN | |
312c056a PP |
240 | void bt_field_common_variant_set_is_frozen_recursive( |
241 | struct bt_field_common *field, bool is_frozen); | |
f6ccaed9 PP |
242 | |
243 | BT_HIDDEN | |
312c056a PP |
244 | void bt_field_common_array_set_is_frozen_recursive( |
245 | struct bt_field_common *field, bool is_frozen); | |
f6ccaed9 PP |
246 | |
247 | BT_HIDDEN | |
312c056a PP |
248 | void bt_field_common_sequence_set_is_frozen_recursive( |
249 | struct bt_field_common *field, bool is_frozen); | |
273b65be | 250 | |
918be005 | 251 | BT_HIDDEN |
312c056a PP |
252 | void _bt_field_common_set_is_frozen_recursive(struct bt_field_common *field, |
253 | bool is_frozen); | |
3dca2276 PP |
254 | |
255 | BT_HIDDEN | |
256 | bt_bool bt_field_common_generic_is_set(struct bt_field_common *field); | |
257 | ||
3dca2276 PP |
258 | BT_HIDDEN |
259 | bt_bool bt_field_common_structure_is_set_recursive( | |
260 | struct bt_field_common *field); | |
261 | ||
262 | BT_HIDDEN | |
263 | bt_bool bt_field_common_variant_is_set_recursive(struct bt_field_common *field); | |
264 | ||
265 | BT_HIDDEN | |
266 | bt_bool bt_field_common_array_is_set_recursive(struct bt_field_common *field); | |
267 | ||
268 | BT_HIDDEN | |
269 | bt_bool bt_field_common_sequence_is_set_recursive(struct bt_field_common *field); | |
270 | ||
f6ccaed9 | 271 | #ifdef BT_DEV_MODE |
312c056a PP |
272 | # define bt_field_common_validate_recursive _bt_field_common_validate_recursive |
273 | # define bt_field_common_set_is_frozen_recursive _bt_field_common_set_is_frozen_recursive | |
274 | # define bt_field_common_is_set_recursive _bt_field_common_is_set_recursive | |
275 | # define bt_field_common_reset_recursive _bt_field_common_reset_recursive | |
276 | # define bt_field_common_set _bt_field_common_set | |
277 | # define bt_field_validate_recursive _bt_field_validate_recursive | |
278 | # define bt_field_set_is_frozen_recursive _bt_field_set_is_frozen_recursive | |
279 | # define bt_field_is_set_recursive _bt_field_is_set_recursive | |
280 | # define bt_field_reset_recursive _bt_field_reset_recursive | |
281 | # define bt_field_set _bt_field_set | |
f6ccaed9 | 282 | #else |
3dca2276 | 283 | # define bt_field_common_validate_recursive(_field) (-1) |
312c056a | 284 | # define bt_field_common_set_is_frozen_recursive(_field, _is_frozen) |
3dca2276 | 285 | # define bt_field_common_is_set_recursive(_field) (BT_FALSE) |
565b6706 | 286 | # define bt_field_common_reset_recursive(_field) |
3dca2276 PP |
287 | # define bt_field_common_set(_field, _val) |
288 | # define bt_field_validate_recursive(_field) (-1) | |
312c056a | 289 | # define bt_field_set_is_frozen_recursive(_field, _is_frozen) |
3dca2276 | 290 | # define bt_field_is_set_recursive(_field) (BT_FALSE) |
565b6706 | 291 | # define bt_field_reset_recursive(_field) |
f6ccaed9 PP |
292 | # define bt_field_set(_field, _val) |
293 | #endif | |
918be005 | 294 | |
3dca2276 PP |
295 | BT_ASSERT_FUNC |
296 | static inline bool field_type_common_has_known_id( | |
297 | struct bt_field_type_common *ft) | |
298 | { | |
312c056a PP |
299 | return (int) ft->id > BT_FIELD_TYPE_ID_UNKNOWN || |
300 | (int) ft->id < BT_FIELD_TYPE_ID_NR; | |
3dca2276 PP |
301 | } |
302 | ||
303 | static inline | |
304 | int _bt_field_common_validate_recursive(struct bt_field_common *field) | |
305 | { | |
306 | int ret = 0; | |
307 | ||
308 | if (!field) { | |
309 | BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL."); | |
310 | ret = -1; | |
311 | goto end; | |
312 | } | |
313 | ||
314 | BT_ASSERT(field_type_common_has_known_id(field->type)); | |
315 | ||
316 | if (field->methods->validate) { | |
317 | ret = field->methods->validate(field); | |
318 | } | |
319 | ||
320 | end: | |
321 | return ret; | |
322 | } | |
323 | ||
324 | static inline | |
325 | void _bt_field_common_reset_recursive(struct bt_field_common *field) | |
326 | { | |
327 | BT_ASSERT(field); | |
328 | BT_ASSERT(field->methods->reset); | |
329 | field->methods->reset(field); | |
330 | } | |
331 | ||
332 | static inline | |
333 | void _bt_field_common_set(struct bt_field_common *field, bool value) | |
334 | { | |
335 | BT_ASSERT(field); | |
336 | field->payload_set = value; | |
337 | } | |
338 | ||
339 | static inline | |
340 | bt_bool _bt_field_common_is_set_recursive(struct bt_field_common *field) | |
341 | { | |
342 | bt_bool is_set = BT_FALSE; | |
343 | ||
344 | if (!field) { | |
345 | goto end; | |
346 | } | |
347 | ||
348 | BT_ASSERT(field_type_common_has_known_id(field->type)); | |
349 | BT_ASSERT(field->methods->is_set); | |
350 | is_set = field->methods->is_set(field); | |
351 | ||
352 | end: | |
353 | return is_set; | |
354 | } | |
355 | ||
356 | static inline | |
357 | void bt_field_common_initialize(struct bt_field_common *field, | |
3fea54f6 | 358 | struct bt_field_type_common *ft, bool is_shared, |
3dca2276 PP |
359 | bt_object_release_func release_func, |
360 | struct bt_field_common_methods *methods) | |
361 | { | |
362 | BT_ASSERT(field); | |
363 | BT_ASSERT(ft); | |
3fea54f6 | 364 | bt_object_init(&field->base, is_shared, release_func); |
3dca2276 PP |
365 | field->methods = methods; |
366 | field->type = bt_get(ft); | |
367 | } | |
368 | ||
369 | static inline | |
094ff7c0 | 370 | struct bt_field_type_common *bt_field_common_borrow_type( |
3dca2276 PP |
371 | struct bt_field_common *field) |
372 | { | |
373 | struct bt_field_type_common *ret = NULL; | |
374 | ||
375 | BT_ASSERT_PRE_NON_NULL(field, "Field"); | |
094ff7c0 | 376 | ret = field->type; |
3dca2276 PP |
377 | return ret; |
378 | } | |
379 | ||
380 | static inline | |
312c056a | 381 | int64_t bt_field_common_sequence_get_length(struct bt_field_common *field) |
3dca2276 PP |
382 | { |
383 | struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); | |
384 | ||
385 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
386 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
387 | "Field"); | |
312c056a | 388 | return (int64_t) sequence->length; |
3dca2276 PP |
389 | } |
390 | ||
391 | static inline | |
392 | int bt_field_common_sequence_set_length(struct bt_field_common *field, | |
312c056a | 393 | uint64_t length, bt_field_common_create_func field_create_func) |
3dca2276 PP |
394 | { |
395 | int ret = 0; | |
3dca2276 | 396 | struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); |
3dca2276 PP |
397 | |
398 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
6c677fb5 PP |
399 | BT_ASSERT_PRE(((int64_t) length) >= 0, |
400 | "Invalid sequence length (too large): length=%" PRId64, | |
401 | length); | |
3dca2276 | 402 | BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Sequence field"); |
3dca2276 | 403 | |
6c677fb5 | 404 | if (unlikely(length > sequence->elements->len)) { |
312c056a PP |
405 | /* Make more room */ |
406 | struct bt_field_type_common_sequence *sequence_ft; | |
407 | uint64_t cur_len = sequence->elements->len; | |
408 | uint64_t i; | |
409 | ||
410 | g_ptr_array_set_size(sequence->elements, length); | |
411 | sequence_ft = BT_FROM_COMMON(sequence->common.type); | |
412 | ||
413 | for (i = cur_len; i < sequence->elements->len; i++) { | |
414 | struct bt_field_common *elem_field = | |
415 | field_create_func(sequence_ft->element_ft); | |
416 | ||
417 | if (!elem_field) { | |
418 | ret = -1; | |
419 | goto end; | |
420 | } | |
421 | ||
422 | BT_ASSERT(!sequence->elements->pdata[i]); | |
423 | sequence->elements->pdata[i] = elem_field; | |
424 | } | |
3dca2276 PP |
425 | } |
426 | ||
312c056a | 427 | sequence->length = length; |
3dca2276 PP |
428 | |
429 | end: | |
430 | return ret; | |
431 | } | |
432 | ||
433 | static inline | |
094ff7c0 | 434 | struct bt_field_common *bt_field_common_structure_borrow_field_by_name( |
3dca2276 PP |
435 | struct bt_field_common *field, const char *name) |
436 | { | |
437 | struct bt_field_common *ret = NULL; | |
438 | GQuark field_quark; | |
439 | struct bt_field_type_common_structure *structure_ft; | |
440 | struct bt_field_common_structure *structure = BT_FROM_COMMON(field); | |
441 | size_t index; | |
442 | GHashTable *field_name_to_index; | |
443 | ||
444 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); | |
445 | BT_ASSERT_PRE_NON_NULL(name, "Field name"); | |
446 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
447 | BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
448 | structure_ft = BT_FROM_COMMON(field->type); | |
449 | field_name_to_index = structure_ft->field_name_to_index; | |
450 | field_quark = g_quark_from_string(name); | |
451 | if (!g_hash_table_lookup_extended(field_name_to_index, | |
452 | GUINT_TO_POINTER(field_quark), | |
453 | NULL, (gpointer *) &index)) { | |
454 | BT_LOGV("Invalid parameter: no such field in structure field's type: " | |
455 | "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"", | |
456 | field, field->type, name); | |
457 | goto error; | |
458 | } | |
459 | ||
094ff7c0 | 460 | ret = structure->fields->pdata[index]; |
3dca2276 PP |
461 | BT_ASSERT(ret); |
462 | ||
463 | error: | |
464 | return ret; | |
465 | } | |
466 | ||
467 | static inline | |
094ff7c0 | 468 | struct bt_field_common *bt_field_common_structure_borrow_field_by_index( |
3dca2276 PP |
469 | struct bt_field_common *field, uint64_t index) |
470 | { | |
471 | struct bt_field_common_structure *structure = BT_FROM_COMMON(field); | |
472 | ||
473 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); | |
474 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
475 | BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
476 | BT_ASSERT_PRE(index < structure->fields->len, | |
477 | "Index is out of bound: %![struct-field-]+_f, " | |
478 | "index=%" PRIu64 ", count=%u", field, index, | |
479 | structure->fields->len); | |
094ff7c0 | 480 | return structure->fields->pdata[index]; |
3dca2276 PP |
481 | } |
482 | ||
3dca2276 | 483 | static inline |
094ff7c0 | 484 | struct bt_field_common *bt_field_common_array_borrow_field( |
312c056a | 485 | struct bt_field_common *field, uint64_t index) |
3dca2276 | 486 | { |
3dca2276 PP |
487 | struct bt_field_common_array *array = BT_FROM_COMMON(field); |
488 | ||
489 | BT_ASSERT_PRE_NON_NULL(field, "Array field"); | |
312c056a PP |
490 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, |
491 | "Field"); | |
3dca2276 PP |
492 | BT_ASSERT_PRE(index < array->elements->len, |
493 | "Index is out of bound: %![array-field-]+_f, " | |
494 | "index=%" PRIu64 ", count=%u", field, | |
495 | index, array->elements->len); | |
312c056a | 496 | return array->elements->pdata[(size_t) index]; |
3dca2276 PP |
497 | } |
498 | ||
499 | static inline | |
094ff7c0 | 500 | struct bt_field_common *bt_field_common_sequence_borrow_field( |
312c056a | 501 | struct bt_field_common *field, uint64_t index) |
3dca2276 | 502 | { |
3dca2276 PP |
503 | struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); |
504 | ||
505 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); | |
506 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
507 | "Field"); | |
312c056a | 508 | BT_ASSERT_PRE(index < sequence->length, |
3dca2276 PP |
509 | "Index is out of bound: %![seq-field-]+_f, " |
510 | "index=%" PRIu64 ", count=%u", field, index, | |
511 | sequence->elements->len); | |
312c056a | 512 | return sequence->elements->pdata[(size_t) index]; |
3dca2276 PP |
513 | } |
514 | ||
515 | static inline | |
312c056a PP |
516 | int bt_field_variant_common_set_tag(struct bt_field_common *variant_field, |
517 | uint64_t tag_uval, bool is_signed) | |
3dca2276 | 518 | { |
312c056a PP |
519 | int ret = 0; |
520 | int64_t choice_index; | |
521 | struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field); | |
3dca2276 | 522 | |
312c056a PP |
523 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
524 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
525 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
3dca2276 | 526 | |
312c056a PP |
527 | /* Find matching index in variant field's type */ |
528 | choice_index = bt_field_type_common_variant_find_choice_index( | |
529 | variant_field->type, tag_uval, is_signed); | |
530 | if (choice_index < 0) { | |
531 | ret = -1; | |
3dca2276 PP |
532 | goto end; |
533 | } | |
534 | ||
312c056a PP |
535 | /* Select corresponding field */ |
536 | BT_ASSERT(choice_index < variant->fields->len); | |
537 | variant->current_field = variant->fields->pdata[choice_index]; | |
538 | variant->tag_value.u = tag_uval; | |
3dca2276 PP |
539 | |
540 | end: | |
312c056a | 541 | return ret; |
3dca2276 PP |
542 | } |
543 | ||
544 | static inline | |
094ff7c0 | 545 | struct bt_field_common *bt_field_common_variant_borrow_current_field( |
3dca2276 PP |
546 | struct bt_field_common *variant_field) |
547 | { | |
548 | struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field); | |
549 | ||
550 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); | |
551 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
552 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
312c056a PP |
553 | BT_ASSERT_PRE(variant->current_field, |
554 | "Variant field has no current field: %!+_f", variant_field); | |
555 | return variant->current_field; | |
3dca2276 PP |
556 | } |
557 | ||
558 | static inline | |
312c056a PP |
559 | int bt_field_common_variant_get_tag_signed(struct bt_field_common *variant_field, |
560 | int64_t *tag) | |
3dca2276 PP |
561 | { |
562 | struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field); | |
563 | ||
564 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); | |
565 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
566 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
312c056a PP |
567 | BT_ASSERT_PRE(variant->current_field, |
568 | "Variant field has no current field: %!+_f", variant_field); | |
569 | *tag = variant->tag_value.i; | |
3dca2276 PP |
570 | return 0; |
571 | } | |
572 | ||
3dca2276 | 573 | static inline |
312c056a PP |
574 | int bt_field_common_variant_get_tag_unsigned(struct bt_field_common *variant_field, |
575 | uint64_t *tag) | |
3dca2276 | 576 | { |
312c056a | 577 | struct bt_field_common_variant *variant = BT_FROM_COMMON(variant_field); |
3dca2276 | 578 | |
312c056a PP |
579 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
580 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(variant_field, | |
581 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
582 | BT_ASSERT_PRE(variant->current_field, | |
583 | "Variant field has no current field: %!+_f", variant_field); | |
584 | *tag = variant->tag_value.u; | |
3dca2276 PP |
585 | return 0; |
586 | } | |
587 | ||
588 | static inline | |
589 | struct bt_field_type_enumeration_mapping_iterator * | |
590 | bt_field_common_enumeration_get_mappings(struct bt_field_common *field, | |
312c056a PP |
591 | bt_field_common_create_func field_create_func, |
592 | uint64_t uval) | |
3dca2276 | 593 | { |
312c056a | 594 | struct bt_field_type_common_enumeration *enum_type = NULL; |
3dca2276 PP |
595 | struct bt_field_type_common_integer *integer_type = NULL; |
596 | struct bt_field_type_enumeration_mapping_iterator *iter = NULL; | |
597 | ||
312c056a PP |
598 | BT_ASSERT(field); |
599 | BT_ASSERT(field->type->id == BT_FIELD_TYPE_ID_ENUM); | |
600 | BT_ASSERT(field->payload_set); | |
601 | enum_type = BT_FROM_COMMON(field->type); | |
602 | integer_type = enum_type->container_ft; | |
3dca2276 PP |
603 | |
604 | if (!integer_type->is_signed) { | |
3dca2276 | 605 | iter = bt_field_type_common_enumeration_unsigned_find_mappings_by_value( |
312c056a | 606 | field->type, uval); |
3dca2276 | 607 | } else { |
3dca2276 | 608 | iter = bt_field_type_common_enumeration_signed_find_mappings_by_value( |
312c056a | 609 | field->type, (int64_t) uval); |
3dca2276 PP |
610 | } |
611 | ||
3dca2276 PP |
612 | return iter; |
613 | } | |
614 | ||
615 | static inline | |
616 | int bt_field_common_floating_point_get_value(struct bt_field_common *field, | |
617 | double *value) | |
618 | { | |
619 | struct bt_field_common_floating_point *floating_point = | |
620 | BT_FROM_COMMON(field); | |
621 | ||
622 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); | |
623 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
624 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field"); | |
625 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
626 | BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
627 | *value = floating_point->payload; | |
628 | return 0; | |
629 | } | |
630 | ||
631 | static inline | |
632 | int bt_field_common_floating_point_set_value(struct bt_field_common *field, | |
633 | double value) | |
634 | { | |
635 | struct bt_field_common_floating_point *floating_point = | |
636 | BT_FROM_COMMON(field); | |
637 | ||
638 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); | |
639 | BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "Floating point number field"); | |
640 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
641 | BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
642 | floating_point->payload = value; | |
643 | bt_field_common_set(field, true); | |
644 | return 0; | |
645 | } | |
646 | ||
647 | static inline | |
648 | const char *bt_field_common_string_get_value(struct bt_field_common *field) | |
649 | { | |
650 | struct bt_field_common_string *string = BT_FROM_COMMON(field); | |
651 | ||
652 | BT_ASSERT_PRE_NON_NULL(field, "String field"); | |
653 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field"); | |
654 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
655 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
4d4b475d | 656 | return (const char *) string->buf->data; |
3dca2276 PP |
657 | } |
658 | ||
659 | static inline | |
6c677fb5 | 660 | int bt_field_common_string_clear(struct bt_field_common *field) |
3dca2276 | 661 | { |
6c677fb5 | 662 | struct bt_field_common_string *string_field = BT_FROM_COMMON(field); |
3dca2276 PP |
663 | |
664 | BT_ASSERT_PRE_NON_NULL(field, "String field"); | |
3dca2276 PP |
665 | BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field"); |
666 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
667 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
6c677fb5 | 668 | string_field->size = 0; |
3dca2276 PP |
669 | bt_field_common_set(field, true); |
670 | return 0; | |
671 | } | |
672 | ||
673 | static inline | |
674 | int bt_field_common_string_append_len(struct bt_field_common *field, | |
675 | const char *value, unsigned int length) | |
676 | { | |
677 | struct bt_field_common_string *string_field = BT_FROM_COMMON(field); | |
4d4b475d PP |
678 | char *data; |
679 | size_t new_size; | |
3dca2276 PP |
680 | |
681 | BT_ASSERT_PRE_NON_NULL(field, "String field"); | |
682 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
683 | BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field"); | |
684 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
685 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
686 | ||
4d4b475d | 687 | /* Make sure no null bytes are appended */ |
3dca2276 PP |
688 | BT_ASSERT_PRE(memchr(value, '\0', length) == NULL, |
689 | "String value to append contains a null character: " | |
690 | "partial-value=\"%.32s\", length=%u", value, length); | |
691 | ||
4d4b475d PP |
692 | new_size = string_field->size + length; |
693 | ||
6c677fb5 | 694 | if (unlikely(new_size + 1 > string_field->buf->len)) { |
4d4b475d | 695 | g_array_set_size(string_field->buf, new_size + 1); |
3dca2276 PP |
696 | } |
697 | ||
4d4b475d PP |
698 | data = string_field->buf->data; |
699 | memcpy(data + string_field->size, value, length); | |
700 | ((char *) string_field->buf->data)[new_size] = '\0'; | |
701 | string_field->size = new_size; | |
3dca2276 PP |
702 | bt_field_common_set(field, true); |
703 | return 0; | |
704 | } | |
705 | ||
4d4b475d PP |
706 | static inline |
707 | int bt_field_common_string_append(struct bt_field_common *field, | |
708 | const char *value) | |
709 | { | |
710 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
4d4b475d PP |
711 | return bt_field_common_string_append_len(field, value, |
712 | strlen(value)); | |
713 | } | |
714 | ||
312c056a | 715 | static inline |
6c677fb5 PP |
716 | int bt_field_common_string_set_value(struct bt_field_common *field, |
717 | const char *value) | |
312c056a | 718 | { |
312c056a | 719 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
6c677fb5 | 720 | BT_ASSERT_PRE_NON_NULL(value, "Value"); |
312c056a PP |
721 | BT_ASSERT_PRE_FIELD_COMMON_HOT(field, "String field"); |
722 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(field, | |
723 | BT_FIELD_TYPE_ID_STRING, "Field"); | |
6c677fb5 PP |
724 | bt_field_common_string_clear(field); |
725 | return bt_field_common_string_append_len(field, | |
726 | value, strlen(value)); | |
312c056a PP |
727 | } |
728 | ||
3dca2276 PP |
729 | static inline |
730 | int _bt_field_validate_recursive(struct bt_field *field) | |
731 | { | |
732 | return _bt_field_common_validate_recursive((void *) field); | |
733 | } | |
734 | ||
735 | static inline | |
312c056a | 736 | void _bt_field_set_is_frozen_recursive(struct bt_field *field, bool is_frozen) |
3dca2276 | 737 | { |
312c056a PP |
738 | return _bt_field_common_set_is_frozen_recursive((void *) field, |
739 | is_frozen); | |
3dca2276 PP |
740 | } |
741 | ||
742 | static inline | |
743 | bt_bool _bt_field_is_set_recursive(struct bt_field *field) | |
744 | { | |
745 | return _bt_field_common_is_set_recursive((void *) field); | |
746 | } | |
747 | ||
748 | static inline | |
749 | void _bt_field_reset_recursive(struct bt_field *field) | |
750 | { | |
751 | _bt_field_common_reset_recursive((void *) field); | |
752 | } | |
753 | ||
754 | static inline | |
755 | void _bt_field_set(struct bt_field *field, bool value) | |
756 | { | |
757 | _bt_field_common_set((void *) field, value); | |
758 | } | |
2e8876d3 | 759 | |
312c056a PP |
760 | static inline |
761 | void bt_field_common_finalize(struct bt_field_common *field) | |
762 | { | |
763 | BT_ASSERT(field); | |
764 | BT_LOGD_STR("Putting field's type."); | |
765 | bt_put(field->type); | |
766 | } | |
767 | ||
768 | static inline | |
769 | void bt_field_common_integer_finalize(struct bt_field_common *field) | |
770 | { | |
771 | BT_ASSERT(field); | |
772 | BT_LOGD("Finalizing common integer field object: addr=%p", field); | |
773 | bt_field_common_finalize(field); | |
774 | } | |
775 | ||
776 | static inline | |
777 | void bt_field_common_floating_point_finalize(struct bt_field_common *field) | |
778 | { | |
779 | BT_ASSERT(field); | |
780 | BT_LOGD("Finalizing common floating point number field object: addr=%p", field); | |
781 | bt_field_common_finalize(field); | |
782 | } | |
783 | ||
784 | static inline | |
785 | void bt_field_common_structure_finalize_recursive(struct bt_field_common *field) | |
786 | { | |
787 | struct bt_field_common_structure *structure = BT_FROM_COMMON(field); | |
788 | ||
789 | BT_ASSERT(field); | |
790 | BT_LOGD("Finalizing common structure field object: addr=%p", field); | |
791 | bt_field_common_finalize(field); | |
792 | ||
793 | if (structure->fields) { | |
794 | g_ptr_array_free(structure->fields, TRUE); | |
795 | } | |
796 | } | |
797 | ||
798 | static inline | |
799 | void bt_field_common_variant_finalize_recursive(struct bt_field_common *field) | |
800 | { | |
801 | struct bt_field_common_variant *variant = BT_FROM_COMMON(field); | |
802 | ||
803 | BT_ASSERT(field); | |
804 | BT_LOGD("Finalizing common variant field object: addr=%p", field); | |
805 | bt_field_common_finalize(field); | |
806 | ||
807 | if (variant->fields) { | |
808 | g_ptr_array_free(variant->fields, TRUE); | |
809 | } | |
810 | } | |
811 | ||
812 | static inline | |
813 | void bt_field_common_array_finalize_recursive(struct bt_field_common *field) | |
814 | { | |
815 | struct bt_field_common_array *array = BT_FROM_COMMON(field); | |
816 | ||
817 | BT_ASSERT(field); | |
818 | BT_LOGD("Finalizing common array field object: addr=%p", field); | |
819 | bt_field_common_finalize(field); | |
820 | ||
821 | if (array->elements) { | |
822 | g_ptr_array_free(array->elements, TRUE); | |
823 | } | |
824 | } | |
825 | ||
826 | static inline | |
827 | void bt_field_common_sequence_finalize_recursive(struct bt_field_common *field) | |
828 | { | |
829 | struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); | |
830 | ||
831 | BT_ASSERT(field); | |
832 | BT_LOGD("Finalizing common sequence field object: addr=%p", field); | |
833 | bt_field_common_finalize(field); | |
834 | ||
835 | if (sequence->elements) { | |
836 | g_ptr_array_free(sequence->elements, TRUE); | |
837 | } | |
838 | } | |
839 | ||
840 | static inline | |
841 | void bt_field_common_string_finalize(struct bt_field_common *field) | |
842 | { | |
843 | struct bt_field_common_string *string = BT_FROM_COMMON(field); | |
844 | ||
845 | BT_ASSERT(field); | |
846 | BT_LOGD("Finalizing common string field object: addr=%p", field); | |
847 | bt_field_common_finalize(field); | |
848 | ||
4d4b475d PP |
849 | if (string->buf) { |
850 | g_array_free(string->buf, TRUE); | |
312c056a PP |
851 | } |
852 | } | |
853 | ||
854 | BT_ASSERT_PRE_FUNC | |
855 | static inline bool value_is_in_range_signed(unsigned int size, int64_t value) | |
856 | { | |
857 | bool ret = true; | |
858 | int64_t min_value, max_value; | |
859 | ||
860 | min_value = -(1ULL << (size - 1)); | |
861 | max_value = (1ULL << (size - 1)) - 1; | |
862 | if (value < min_value || value > max_value) { | |
863 | BT_LOGF("Value is out of bounds: value=%" PRId64 ", " | |
864 | "min-value=%" PRId64 ", max-value=%" PRId64, | |
865 | value, min_value, max_value); | |
866 | ret = false; | |
867 | } | |
868 | ||
869 | return ret; | |
870 | } | |
871 | ||
872 | BT_ASSERT_PRE_FUNC | |
873 | static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value) | |
874 | { | |
875 | bool ret = true; | |
876 | int64_t max_value; | |
877 | ||
878 | max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; | |
879 | if (value > max_value) { | |
880 | BT_LOGF("Value is out of bounds: value=%" PRIu64 ", " | |
881 | "max-value=%" PRIu64, | |
882 | value, max_value); | |
883 | ret = false; | |
884 | } | |
885 | ||
886 | return ret; | |
887 | } | |
888 | ||
889 | BT_HIDDEN | |
890 | struct bt_field *bt_field_create_recursive(struct bt_field_type *type); | |
891 | ||
892 | BT_HIDDEN | |
893 | void bt_field_destroy_recursive(struct bt_field *field); | |
894 | ||
2e33ac5a | 895 | #endif /* BABELTRACE_CTF_IR_FIELDS_INTERNAL_H */ |