Commit | Line | Data |
---|---|---|
3dca2276 PP |
1 | /* |
2 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
3 | * | |
4 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
5 | * | |
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | * of this software and associated documentation files (the "Software"), to deal | |
8 | * in the Software without restriction, including without limitation the rights | |
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | * copies of the Software, and to permit persons to whom the Software is | |
11 | * furnished to do so, subject to the following conditions: | |
12 | * | |
13 | * The above copyright notice and this permission notice shall be included in | |
14 | * all copies or substantial portions of the Software. | |
15 | * | |
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
22 | * SOFTWARE. | |
23 | */ | |
24 | ||
25 | #define BT_LOG_TAG "CTF-WRITER-FIELDS" | |
26 | #include <babeltrace/lib-logging-internal.h> | |
27 | ||
28 | #include <babeltrace/compat/fcntl-internal.h> | |
29 | #include <babeltrace/ctf-writer/fields-internal.h> | |
30 | #include <babeltrace/ctf-writer/field-types-internal.h> | |
31 | #include <babeltrace/ctf-writer/serialize-internal.h> | |
32 | #include <babeltrace/ctf-ir/fields-internal.h> | |
33 | #include <babeltrace/ctf-ir/field-types-internal.h> | |
34 | #include <babeltrace/assert-pre-internal.h> | |
35 | #include <babeltrace/object-internal.h> | |
36 | #include <babeltrace/ref.h> | |
37 | #include <babeltrace/compiler-internal.h> | |
38 | #include <babeltrace/endian-internal.h> | |
39 | #include <babeltrace/assert-internal.h> | |
40 | #include <float.h> | |
41 | #include <inttypes.h> | |
42 | #include <stdlib.h> | |
43 | ||
44 | static struct bt_field_common_methods bt_ctf_field_integer_methods = { | |
312c056a | 45 | .set_is_frozen = bt_field_common_generic_set_is_frozen, |
3dca2276 PP |
46 | .validate = bt_field_common_generic_validate, |
47 | .copy = NULL, | |
48 | .is_set = bt_field_common_generic_is_set, | |
49 | .reset = bt_field_common_generic_reset, | |
50 | }; | |
51 | ||
52 | static struct bt_field_common_methods bt_ctf_field_floating_point_methods = { | |
312c056a | 53 | .set_is_frozen = bt_field_common_generic_set_is_frozen, |
3dca2276 PP |
54 | .validate = bt_field_common_generic_validate, |
55 | .copy = NULL, | |
56 | .is_set = bt_field_common_generic_is_set, | |
57 | .reset = bt_field_common_generic_reset, | |
58 | }; | |
59 | ||
312c056a PP |
60 | static |
61 | void bt_ctf_field_enumeration_set_is_frozen_recursive( | |
62 | struct bt_field_common *field, bool is_frozen); | |
63 | ||
64 | static | |
65 | int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field); | |
66 | ||
67 | static | |
68 | bt_bool bt_ctf_field_enumeration_is_set_recursive( | |
69 | struct bt_field_common *field); | |
70 | ||
71 | static | |
72 | void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field); | |
73 | ||
3dca2276 | 74 | static struct bt_field_common_methods bt_ctf_field_enumeration_methods = { |
312c056a PP |
75 | .set_is_frozen = bt_ctf_field_enumeration_set_is_frozen_recursive, |
76 | .validate = bt_ctf_field_enumeration_validate_recursive, | |
3dca2276 | 77 | .copy = NULL, |
312c056a PP |
78 | .is_set = bt_ctf_field_enumeration_is_set_recursive, |
79 | .reset = bt_ctf_field_enumeration_reset_recursive, | |
3dca2276 PP |
80 | }; |
81 | ||
82 | static struct bt_field_common_methods bt_ctf_field_string_methods = { | |
312c056a | 83 | .set_is_frozen = bt_field_common_generic_set_is_frozen, |
3dca2276 PP |
84 | .validate = bt_field_common_generic_validate, |
85 | .copy = NULL, | |
86 | .is_set = bt_field_common_generic_is_set, | |
87 | .reset = bt_field_common_generic_reset, | |
88 | }; | |
89 | ||
90 | static struct bt_field_common_methods bt_ctf_field_structure_methods = { | |
312c056a | 91 | .set_is_frozen = bt_field_common_structure_set_is_frozen_recursive, |
3dca2276 PP |
92 | .validate = bt_field_common_structure_validate_recursive, |
93 | .copy = NULL, | |
94 | .is_set = bt_field_common_structure_is_set_recursive, | |
95 | .reset = bt_field_common_structure_reset_recursive, | |
96 | }; | |
97 | ||
98 | static struct bt_field_common_methods bt_ctf_field_sequence_methods = { | |
312c056a | 99 | .set_is_frozen = bt_field_common_sequence_set_is_frozen_recursive, |
3dca2276 PP |
100 | .validate = bt_field_common_sequence_validate_recursive, |
101 | .copy = NULL, | |
102 | .is_set = bt_field_common_sequence_is_set_recursive, | |
103 | .reset = bt_field_common_sequence_reset_recursive, | |
104 | }; | |
105 | ||
106 | static struct bt_field_common_methods bt_ctf_field_array_methods = { | |
312c056a | 107 | .set_is_frozen = bt_field_common_array_set_is_frozen_recursive, |
3dca2276 PP |
108 | .validate = bt_field_common_array_validate_recursive, |
109 | .copy = NULL, | |
110 | .is_set = bt_field_common_array_is_set_recursive, | |
111 | .reset = bt_field_common_array_reset_recursive, | |
112 | }; | |
113 | ||
312c056a PP |
114 | static |
115 | void bt_ctf_field_variant_set_is_frozen_recursive(struct bt_field_common *field, | |
116 | bool is_frozen); | |
117 | ||
118 | static | |
119 | int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field); | |
120 | ||
121 | static | |
122 | bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field); | |
123 | ||
124 | static | |
125 | void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field); | |
126 | ||
3dca2276 | 127 | static struct bt_field_common_methods bt_ctf_field_variant_methods = { |
312c056a PP |
128 | .set_is_frozen = bt_ctf_field_variant_set_is_frozen_recursive, |
129 | .validate = bt_ctf_field_variant_validate_recursive, | |
3dca2276 | 130 | .copy = NULL, |
312c056a PP |
131 | .is_set = bt_ctf_field_variant_is_set_recursive, |
132 | .reset = bt_ctf_field_variant_reset_recursive, | |
3dca2276 PP |
133 | }; |
134 | ||
135 | static | |
136 | struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *); | |
137 | ||
138 | static | |
139 | struct bt_ctf_field *bt_ctf_field_enumeration_create(struct bt_ctf_field_type *); | |
140 | ||
141 | static | |
142 | struct bt_ctf_field *bt_ctf_field_floating_point_create(struct bt_ctf_field_type *); | |
143 | ||
144 | static | |
145 | struct bt_ctf_field *bt_ctf_field_structure_create(struct bt_ctf_field_type *); | |
146 | ||
147 | static | |
148 | struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *); | |
149 | ||
150 | static | |
151 | struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *); | |
152 | ||
153 | static | |
154 | struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *); | |
155 | ||
156 | static | |
157 | struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *); | |
158 | ||
159 | static | |
160 | struct bt_ctf_field *(* const field_create_funcs[])(struct bt_ctf_field_type *) = { | |
161 | [BT_FIELD_TYPE_ID_INTEGER] = bt_ctf_field_integer_create, | |
162 | [BT_FIELD_TYPE_ID_ENUM] = bt_ctf_field_enumeration_create, | |
163 | [BT_FIELD_TYPE_ID_FLOAT] = bt_ctf_field_floating_point_create, | |
164 | [BT_FIELD_TYPE_ID_STRUCT] = bt_ctf_field_structure_create, | |
165 | [BT_FIELD_TYPE_ID_VARIANT] = bt_ctf_field_variant_create, | |
166 | [BT_FIELD_TYPE_ID_ARRAY] = bt_ctf_field_array_create, | |
167 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_ctf_field_sequence_create, | |
168 | [BT_FIELD_TYPE_ID_STRING] = bt_ctf_field_string_create, | |
169 | }; | |
170 | ||
171 | typedef int (*bt_ctf_field_serialize_recursive_func)( | |
172 | struct bt_field_common *, struct bt_ctf_stream_pos *, | |
173 | enum bt_ctf_byte_order); | |
174 | ||
312c056a PP |
175 | static |
176 | void bt_ctf_field_integer_destroy(struct bt_ctf_field *field) | |
177 | { | |
178 | BT_LOGD("Destroying CTF writer integer field object: addr=%p", field); | |
179 | bt_field_common_integer_finalize((void *) field); | |
180 | g_free(field); | |
181 | } | |
182 | ||
183 | static | |
184 | void bt_ctf_field_floating_point_destroy(struct bt_ctf_field *field) | |
185 | { | |
186 | BT_LOGD("Destroying CTF writer floating point field object: addr=%p", | |
187 | field); | |
188 | bt_field_common_floating_point_finalize((void *) field); | |
189 | g_free(field); | |
190 | } | |
191 | ||
192 | static | |
193 | void bt_ctf_field_enumeration_destroy_recursive(struct bt_ctf_field *field) | |
194 | { | |
195 | struct bt_ctf_field_enumeration *enumeration = BT_FROM_COMMON(field); | |
196 | ||
197 | BT_LOGD("Destroying CTF writer enumeration field object: addr=%p", | |
198 | field); | |
199 | BT_LOGD_STR("Putting container field."); | |
200 | bt_put(enumeration->container); | |
201 | bt_field_common_finalize((void *) field); | |
202 | g_free(field); | |
203 | } | |
204 | ||
205 | static | |
206 | void bt_ctf_field_structure_destroy_recursive(struct bt_ctf_field *field) | |
207 | { | |
208 | BT_LOGD("Destroying CTF writer structure field object: addr=%p", field); | |
209 | bt_field_common_structure_finalize_recursive((void *) field); | |
210 | g_free(field); | |
211 | } | |
212 | ||
213 | static | |
214 | void bt_ctf_field_variant_destroy_recursive(struct bt_ctf_field *field) | |
215 | { | |
216 | struct bt_ctf_field_variant *variant = BT_FROM_COMMON(field); | |
217 | ||
218 | BT_LOGD("Destroying CTF writer variant field object: addr=%p", field); | |
219 | BT_LOGD_STR("Putting tag field."); | |
220 | bt_put(variant->tag); | |
221 | bt_field_common_variant_finalize_recursive((void *) field); | |
222 | g_free(field); | |
223 | } | |
224 | ||
225 | static | |
226 | void bt_ctf_field_array_destroy_recursive(struct bt_ctf_field *field) | |
227 | { | |
228 | BT_LOGD("Destroying CTF writer array field object: addr=%p", field); | |
229 | bt_field_common_array_finalize_recursive((void *) field); | |
230 | g_free(field); | |
231 | } | |
232 | ||
233 | static | |
234 | void bt_ctf_field_sequence_destroy_recursive(struct bt_ctf_field *field) | |
235 | { | |
236 | BT_LOGD("Destroying CTF writer sequence field object: addr=%p", field); | |
237 | bt_field_common_sequence_finalize_recursive((void *) field); | |
238 | g_free(field); | |
239 | } | |
240 | ||
241 | static | |
242 | void bt_ctf_field_string_destroy(struct bt_ctf_field *field) | |
243 | { | |
244 | BT_LOGD("Destroying CTF writer string field object: addr=%p", field); | |
245 | bt_field_common_string_finalize((void *) field); | |
246 | g_free(field); | |
247 | } | |
248 | ||
3dca2276 PP |
249 | BT_HIDDEN |
250 | int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field, | |
251 | struct bt_ctf_stream_pos *pos, | |
252 | enum bt_ctf_byte_order native_byte_order) | |
253 | { | |
254 | struct bt_field_common *field_common = (void *) field; | |
255 | bt_ctf_field_serialize_recursive_func serialize_func; | |
256 | ||
257 | BT_ASSERT(pos); | |
258 | BT_ASSERT_PRE_NON_NULL(field, "Field"); | |
259 | BT_ASSERT(field_common->spec.writer.serialize_func); | |
260 | serialize_func = field_common->spec.writer.serialize_func; | |
261 | return serialize_func(field_common, pos, | |
262 | native_byte_order); | |
263 | } | |
264 | ||
265 | static | |
266 | int increase_packet_size(struct bt_ctf_stream_pos *pos) | |
267 | { | |
268 | int ret; | |
269 | ||
270 | BT_ASSERT(pos); | |
271 | BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", " | |
272 | "cur-packet-size=%" PRIu64, | |
273 | pos->offset, pos->packet_size); | |
274 | ret = munmap_align(pos->base_mma); | |
275 | if (ret) { | |
276 | BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping", | |
277 | ": ret=%d", ret); | |
278 | goto end; | |
279 | } | |
280 | ||
281 | pos->packet_size += PACKET_LEN_INCREMENT; | |
282 | do { | |
283 | ret = bt_posix_fallocate(pos->fd, pos->mmap_offset, | |
284 | pos->packet_size / CHAR_BIT); | |
285 | } while (ret == EINTR); | |
286 | if (ret) { | |
287 | BT_LOGE_ERRNO("Failed to preallocate memory space", | |
288 | ": ret=%d", ret); | |
289 | errno = EINTR; | |
290 | ret = -1; | |
291 | goto end; | |
292 | } | |
293 | ||
294 | pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot, | |
295 | pos->flags, pos->fd, pos->mmap_offset); | |
296 | if (pos->base_mma == MAP_FAILED) { | |
297 | BT_LOGE_ERRNO("Failed to perform an aligned memory mapping", | |
298 | ": ret=%d", ret); | |
299 | ret = -1; | |
300 | } | |
301 | ||
302 | BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", " | |
303 | "new-packet-size=%" PRIu64, | |
304 | pos->offset, pos->packet_size); | |
305 | BT_ASSERT(pos->packet_size % 8 == 0); | |
306 | ||
307 | end: | |
308 | return ret; | |
309 | } | |
310 | ||
311 | static | |
312 | int bt_ctf_field_integer_serialize(struct bt_field_common *field, | |
313 | struct bt_ctf_stream_pos *pos, | |
314 | enum bt_ctf_byte_order native_byte_order) | |
315 | { | |
316 | int ret = 0; | |
317 | ||
318 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Integer field"); | |
319 | BT_LOGV("Serializing CTF writer integer field: addr=%p, pos-offset=%" PRId64 ", " | |
320 | "native-bo=%s", field, pos->offset, | |
321 | bt_common_byte_order_string((int) native_byte_order)); | |
322 | ||
323 | retry: | |
324 | ret = bt_ctf_field_integer_write(field, pos, native_byte_order); | |
325 | if (ret == -EFAULT) { | |
326 | /* | |
327 | * The field is too large to fit in the current packet's | |
328 | * remaining space. Bump the packet size and retry. | |
329 | */ | |
330 | ret = increase_packet_size(pos); | |
331 | if (ret) { | |
332 | BT_LOGE("Cannot increase packet size: ret=%d", ret); | |
333 | goto end; | |
334 | } | |
335 | goto retry; | |
336 | } | |
337 | ||
338 | end: | |
339 | return ret; | |
340 | } | |
341 | ||
342 | static | |
343 | int bt_ctf_field_enumeration_serialize_recursive(struct bt_field_common *field, | |
344 | struct bt_ctf_stream_pos *pos, | |
345 | enum bt_ctf_byte_order native_byte_order) | |
346 | { | |
312c056a | 347 | struct bt_ctf_field_enumeration *enumeration = (void *) field; |
3dca2276 PP |
348 | |
349 | BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", " | |
350 | "native-bo=%s", field, pos->offset, | |
351 | bt_common_byte_order_string((int) native_byte_order)); | |
352 | BT_LOGV_STR("Serializing enumeration field's payload field."); | |
312c056a PP |
353 | return bt_ctf_field_serialize_recursive( |
354 | (void *) enumeration->container, pos, native_byte_order); | |
3dca2276 PP |
355 | } |
356 | ||
357 | static | |
358 | int bt_ctf_field_floating_point_serialize(struct bt_field_common *field, | |
359 | struct bt_ctf_stream_pos *pos, | |
360 | enum bt_ctf_byte_order native_byte_order) | |
361 | { | |
362 | int ret = 0; | |
363 | ||
364 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "Floating point number field"); | |
365 | BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", " | |
366 | "native-bo=%s", field, pos->offset, | |
367 | bt_common_byte_order_string((int) native_byte_order)); | |
368 | ||
369 | retry: | |
370 | ret = bt_ctf_field_floating_point_write(field, pos, | |
371 | native_byte_order); | |
372 | if (ret == -EFAULT) { | |
373 | /* | |
374 | * The field is too large to fit in the current packet's | |
375 | * remaining space. Bump the packet size and retry. | |
376 | */ | |
377 | ret = increase_packet_size(pos); | |
378 | if (ret) { | |
379 | BT_LOGE("Cannot increase packet size: ret=%d", ret); | |
380 | goto end; | |
381 | } | |
382 | goto retry; | |
383 | } | |
384 | ||
385 | end: | |
386 | return ret; | |
387 | } | |
388 | ||
389 | static | |
390 | int bt_ctf_field_structure_serialize_recursive(struct bt_field_common *field, | |
391 | struct bt_ctf_stream_pos *pos, | |
392 | enum bt_ctf_byte_order native_byte_order) | |
393 | { | |
394 | int64_t i; | |
395 | int ret = 0; | |
396 | struct bt_field_common_structure *structure = BT_FROM_COMMON(field); | |
397 | ||
398 | BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", " | |
399 | "native-bo=%s", field, pos->offset, | |
400 | bt_common_byte_order_string((int) native_byte_order)); | |
401 | ||
402 | while (!bt_ctf_stream_pos_access_ok(pos, | |
403 | offset_align(pos->offset, field->type->alignment))) { | |
404 | ret = increase_packet_size(pos); | |
405 | if (ret) { | |
406 | BT_LOGE("Cannot increase packet size: ret=%d", ret); | |
407 | goto end; | |
408 | } | |
409 | } | |
410 | ||
411 | if (!bt_ctf_stream_pos_align(pos, field->type->alignment)) { | |
412 | BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", " | |
413 | "align=%u", pos->offset, field->type->alignment); | |
414 | ret = -1; | |
415 | goto end; | |
416 | } | |
417 | ||
418 | for (i = 0; i < structure->fields->len; i++) { | |
419 | struct bt_field_common *member = g_ptr_array_index( | |
420 | structure->fields, i); | |
421 | const char *field_name = NULL; | |
422 | ||
423 | BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", " | |
424 | "field-addr=%p, index=%" PRId64, | |
425 | pos->offset, member, i); | |
426 | ||
427 | if (!member) { | |
094ff7c0 | 428 | ret = bt_field_type_common_structure_borrow_field_by_index( |
3dca2276 PP |
429 | field->type, &field_name, NULL, i); |
430 | BT_ASSERT(ret == 0); | |
431 | BT_LOGW("Cannot serialize structure field's field: field is not set: " | |
432 | "struct-field-addr=%p, " | |
433 | "field-name=\"%s\", index=%" PRId64, | |
434 | field, field_name, i); | |
435 | ret = -1; | |
436 | goto end; | |
437 | } | |
438 | ||
439 | ret = bt_ctf_field_serialize_recursive((void *) member, pos, | |
440 | native_byte_order); | |
441 | if (ret) { | |
094ff7c0 | 442 | ret = bt_field_type_common_structure_borrow_field_by_index( |
3dca2276 PP |
443 | field->type, &field_name, NULL, i); |
444 | BT_ASSERT(ret == 0); | |
445 | BT_LOGW("Cannot serialize structure field's field: " | |
446 | "struct-field-addr=%p, field-addr=%p, " | |
447 | "field-name=\"%s\", index=%" PRId64, | |
448 | field->type, member, field_name, i); | |
449 | break; | |
450 | } | |
451 | } | |
452 | ||
453 | end: | |
454 | return ret; | |
455 | } | |
456 | ||
457 | static | |
458 | int bt_ctf_field_variant_serialize_recursive(struct bt_field_common *field, | |
459 | struct bt_ctf_stream_pos *pos, | |
460 | enum bt_ctf_byte_order native_byte_order) | |
461 | { | |
462 | struct bt_field_common_variant *variant = BT_FROM_COMMON(field); | |
463 | ||
464 | BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", " | |
465 | "native-bo=%s", field, pos->offset, | |
466 | bt_common_byte_order_string((int) native_byte_order)); | |
467 | BT_LOGV_STR("Serializing variant field's payload field."); | |
468 | return bt_ctf_field_serialize_recursive( | |
312c056a | 469 | (void *) variant->current_field, pos, native_byte_order); |
3dca2276 PP |
470 | } |
471 | ||
472 | static | |
473 | int bt_ctf_field_array_serialize_recursive(struct bt_field_common *field, | |
474 | struct bt_ctf_stream_pos *pos, | |
475 | enum bt_ctf_byte_order native_byte_order) | |
476 | { | |
477 | int64_t i; | |
478 | int ret = 0; | |
479 | struct bt_field_common_array *array = BT_FROM_COMMON(field); | |
480 | ||
481 | BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", " | |
482 | "native-bo=%s", field, pos->offset, | |
483 | bt_common_byte_order_string((int) native_byte_order)); | |
484 | ||
485 | for (i = 0; i < array->elements->len; i++) { | |
486 | struct bt_field_common *elem_field = | |
487 | g_ptr_array_index(array->elements, i); | |
488 | ||
489 | BT_LOGV("Serializing array field's element field: " | |
490 | "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, | |
491 | pos->offset, elem_field, i); | |
492 | ret = bt_ctf_field_serialize_recursive( | |
493 | (void *) elem_field, pos, native_byte_order); | |
494 | if (ret) { | |
495 | BT_LOGW("Cannot serialize array field's element field: " | |
496 | "array-field-addr=%p, field-addr=%p, " | |
497 | "index=%" PRId64, field, elem_field, i); | |
498 | goto end; | |
499 | } | |
500 | } | |
501 | ||
502 | end: | |
503 | return ret; | |
504 | } | |
505 | ||
506 | static | |
507 | int bt_ctf_field_sequence_serialize_recursive(struct bt_field_common *field, | |
508 | struct bt_ctf_stream_pos *pos, | |
509 | enum bt_ctf_byte_order native_byte_order) | |
510 | { | |
511 | int64_t i; | |
512 | int ret = 0; | |
513 | struct bt_field_common_sequence *sequence = BT_FROM_COMMON(field); | |
514 | ||
515 | BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", " | |
516 | "native-bo=%s", field, pos->offset, | |
517 | bt_common_byte_order_string((int) native_byte_order)); | |
518 | ||
519 | for (i = 0; i < sequence->elements->len; i++) { | |
520 | struct bt_field_common *elem_field = | |
521 | g_ptr_array_index(sequence->elements, i); | |
522 | ||
523 | BT_LOGV("Serializing sequence field's element field: " | |
524 | "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, | |
525 | pos->offset, elem_field, i); | |
526 | ret = bt_ctf_field_serialize_recursive( | |
527 | (void *) elem_field, pos, native_byte_order); | |
528 | if (ret) { | |
529 | BT_LOGW("Cannot serialize sequence field's element field: " | |
530 | "sequence-field-addr=%p, field-addr=%p, " | |
531 | "index=%" PRId64, field, elem_field, i); | |
532 | goto end; | |
533 | } | |
534 | } | |
535 | ||
536 | end: | |
537 | return ret; | |
538 | } | |
539 | ||
540 | static | |
541 | int bt_ctf_field_string_serialize(struct bt_field_common *field, | |
542 | struct bt_ctf_stream_pos *pos, | |
543 | enum bt_ctf_byte_order native_byte_order) | |
544 | { | |
545 | int64_t i; | |
546 | int ret = 0; | |
547 | struct bt_field_common_string *string = BT_FROM_COMMON(field); | |
548 | struct bt_ctf_field_type *character_type = | |
549 | get_field_type(FIELD_TYPE_ALIAS_UINT8_T); | |
550 | struct bt_ctf_field *character; | |
551 | ||
552 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(field, "String field"); | |
553 | BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", " | |
554 | "native-bo=%s", field, pos->offset, | |
555 | bt_common_byte_order_string((int) native_byte_order)); | |
556 | ||
557 | BT_LOGV_STR("Creating character field from string field's character field type."); | |
558 | character = bt_ctf_field_create(character_type); | |
559 | ||
4d4b475d PP |
560 | for (i = 0; i < string->size + 1; i++) { |
561 | const uint64_t chr = (uint64_t) ((char *) string->buf->data)[i]; | |
3dca2276 PP |
562 | |
563 | ret = bt_ctf_field_integer_unsigned_set_value(character, chr); | |
564 | BT_ASSERT(ret == 0); | |
565 | BT_LOGV("Serializing string field's character field: " | |
566 | "pos-offset=%" PRId64 ", field-addr=%p, " | |
567 | "index=%" PRId64 ", char-int=%" PRIu64, | |
568 | pos->offset, character, i, chr); | |
569 | ret = bt_ctf_field_integer_serialize( | |
570 | (void *) character, pos, native_byte_order); | |
571 | if (ret) { | |
572 | BT_LOGW_STR("Cannot serialize character field."); | |
573 | goto end; | |
574 | } | |
575 | } | |
576 | ||
577 | end: | |
578 | bt_put(character); | |
579 | bt_put(character_type); | |
580 | return ret; | |
581 | } | |
582 | ||
583 | struct bt_ctf_field *bt_ctf_field_create(struct bt_ctf_field_type *type) | |
584 | { | |
585 | struct bt_ctf_field *field = NULL; | |
586 | enum bt_ctf_field_type_id type_id; | |
587 | ||
588 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); | |
589 | BT_ASSERT(field_type_common_has_known_id((void *) type)); | |
590 | BT_ASSERT_PRE(bt_field_type_common_validate((void *) type) == 0, | |
591 | "Field type is invalid: %!+wF", type); | |
592 | type_id = bt_ctf_field_type_get_type_id(type); | |
593 | field = field_create_funcs[type_id](type); | |
594 | if (!field) { | |
595 | goto end; | |
596 | } | |
597 | ||
598 | bt_field_type_common_freeze((void *) type); | |
599 | ||
600 | end: | |
601 | return field; | |
602 | } | |
603 | ||
604 | struct bt_ctf_field_type *bt_ctf_field_get_type(struct bt_ctf_field *field) | |
605 | { | |
094ff7c0 | 606 | return bt_get(bt_field_common_borrow_type((void *) field)); |
3dca2276 PP |
607 | } |
608 | ||
609 | enum bt_ctf_field_type_id bt_ctf_field_get_type_id(struct bt_ctf_field *field) | |
610 | { | |
611 | struct bt_field_common *field_common = (void *) field; | |
612 | ||
613 | BT_ASSERT_PRE_NON_NULL(field, "Field"); | |
614 | return (int) field_common->type->id; | |
615 | } | |
616 | ||
3dca2276 PP |
617 | int bt_ctf_field_sequence_set_length(struct bt_ctf_field *field, |
618 | struct bt_ctf_field *length_field) | |
619 | { | |
312c056a PP |
620 | int ret; |
621 | struct bt_field_common *common_length_field = (void *) length_field; | |
622 | uint64_t length; | |
623 | ||
624 | BT_ASSERT_PRE_NON_NULL(length_field, "Length field"); | |
625 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) length_field, "Length field"); | |
5a547eb3 PP |
626 | BT_ASSERT_PRE(common_length_field->type->id == BT_FIELD_TYPE_ID_INTEGER || |
627 | common_length_field->type->id == BT_FIELD_TYPE_ID_ENUM, | |
312c056a PP |
628 | "Length field must be an integer or enumeration field: %!+wf", |
629 | length_field); | |
630 | ||
5a547eb3 | 631 | if (common_length_field->type->id == BT_FIELD_TYPE_ID_ENUM) { |
312c056a PP |
632 | struct bt_ctf_field_enumeration *enumeration = (void *) |
633 | length_field; | |
634 | ||
635 | length_field = (void *) enumeration->container; | |
636 | } | |
637 | ||
638 | ret = bt_ctf_field_integer_unsigned_get_value(length_field, &length); | |
639 | BT_ASSERT(ret == 0); | |
3dca2276 | 640 | return bt_field_common_sequence_set_length((void *) field, |
312c056a | 641 | length, (bt_field_common_create_func) bt_ctf_field_create); |
3dca2276 PP |
642 | } |
643 | ||
644 | struct bt_ctf_field *bt_ctf_field_structure_get_field_by_index( | |
645 | struct bt_ctf_field *field, uint64_t index) | |
646 | { | |
094ff7c0 PP |
647 | return bt_get(bt_field_common_structure_borrow_field_by_index( |
648 | (void *) field, index)); | |
3dca2276 PP |
649 | } |
650 | ||
651 | struct bt_ctf_field *bt_ctf_field_structure_get_field_by_name( | |
652 | struct bt_ctf_field *field, const char *name) | |
653 | { | |
094ff7c0 PP |
654 | return bt_get(bt_field_common_structure_borrow_field_by_name( |
655 | (void *) field, name)); | |
3dca2276 PP |
656 | } |
657 | ||
3dca2276 PP |
658 | struct bt_ctf_field *bt_ctf_field_array_get_field( |
659 | struct bt_ctf_field *field, uint64_t index) | |
660 | { | |
312c056a PP |
661 | return bt_get( |
662 | bt_field_common_array_borrow_field((void *) field, index)); | |
3dca2276 PP |
663 | } |
664 | ||
665 | struct bt_ctf_field *bt_ctf_field_sequence_get_field( | |
666 | struct bt_ctf_field *field, uint64_t index) | |
667 | { | |
312c056a PP |
668 | return bt_get( |
669 | bt_field_common_sequence_borrow_field((void *) field, index)); | |
3dca2276 PP |
670 | } |
671 | ||
672 | struct bt_ctf_field *bt_ctf_field_variant_get_field(struct bt_ctf_field *field, | |
673 | struct bt_ctf_field *tag_field) | |
674 | { | |
312c056a PP |
675 | struct bt_ctf_field_variant *variant_field = (void *) field; |
676 | struct bt_ctf_field_enumeration *enum_field = (void *) tag_field; | |
677 | struct bt_field_type_common_variant *variant_ft; | |
678 | struct bt_field_type_common_enumeration *tag_ft; | |
679 | struct bt_ctf_field *current_field = NULL; | |
680 | bt_bool is_signed; | |
681 | uint64_t tag_uval; | |
682 | int ret; | |
683 | ||
684 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); | |
685 | BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field"); | |
686 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET((void *) tag_field, "Tag field"); | |
687 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID( | |
688 | (struct bt_field_common *) tag_field, | |
689 | BT_FIELD_TYPE_ID_ENUM, "Tag field"); | |
690 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID( | |
691 | (struct bt_field_common *) field, | |
692 | BT_FIELD_TYPE_ID_VARIANT, "Field"); | |
693 | BT_ASSERT_PRE( | |
694 | bt_field_common_validate_recursive((void *) tag_field) == 0, | |
695 | "Tag field is invalid: %!+wf", tag_field); | |
696 | variant_ft = BT_FROM_COMMON(variant_field->common.common.type); | |
697 | BT_ASSERT_PRE(bt_field_type_common_compare( | |
698 | BT_TO_COMMON(variant_ft->tag_ft), enum_field->common.type) == 0, | |
699 | "Unexpected tag field's type: %![expected-ft-]+wF, " | |
700 | "%![tag-ft-]+wF", variant_ft->tag_ft, | |
701 | enum_field->common.type); | |
702 | tag_ft = BT_FROM_COMMON(enum_field->common.type); | |
703 | is_signed = tag_ft->container_ft->is_signed; | |
704 | ||
705 | if (is_signed) { | |
706 | int64_t tag_ival; | |
707 | ||
708 | ret = bt_ctf_field_integer_signed_get_value( | |
709 | (void *) enum_field->container, &tag_ival); | |
710 | tag_uval = (uint64_t) tag_ival; | |
711 | } else { | |
712 | ret = bt_ctf_field_integer_unsigned_get_value( | |
713 | (void *) enum_field->container, &tag_uval); | |
714 | } | |
715 | ||
716 | BT_ASSERT(ret == 0); | |
717 | ret = bt_field_variant_common_set_tag((void *) field, tag_uval, | |
718 | is_signed); | |
719 | if (ret) { | |
720 | goto end; | |
721 | } | |
722 | ||
723 | bt_put(variant_field->tag); | |
724 | variant_field->tag = bt_get(tag_field); | |
725 | current_field = bt_ctf_field_variant_get_current_field(field); | |
726 | BT_ASSERT(current_field); | |
727 | ||
728 | end: | |
729 | return current_field; | |
3dca2276 PP |
730 | } |
731 | ||
732 | struct bt_ctf_field *bt_ctf_field_variant_get_current_field( | |
733 | struct bt_ctf_field *variant_field) | |
734 | { | |
094ff7c0 PP |
735 | return bt_get(bt_field_common_variant_borrow_current_field( |
736 | (void *) variant_field)); | |
3dca2276 PP |
737 | } |
738 | ||
312c056a PP |
739 | BT_HIDDEN |
740 | struct bt_ctf_field *bt_ctf_field_enumeration_borrow_container( | |
741 | struct bt_ctf_field *field) | |
3dca2276 | 742 | { |
312c056a PP |
743 | struct bt_ctf_field_enumeration *enumeration = (void *) field; |
744 | ||
745 | BT_ASSERT_PRE_NON_NULL(field, "Enumeration field"); | |
746 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID((struct bt_field_common *) field, | |
747 | BT_CTF_FIELD_TYPE_ID_ENUM, "Field"); | |
748 | BT_ASSERT(enumeration->container); | |
749 | return (void *) enumeration->container; | |
3dca2276 PP |
750 | } |
751 | ||
312c056a PP |
752 | struct bt_ctf_field *bt_ctf_field_enumeration_get_container( |
753 | struct bt_ctf_field *field) | |
3dca2276 | 754 | { |
312c056a | 755 | return bt_get(bt_ctf_field_enumeration_borrow_container(field)); |
3dca2276 PP |
756 | } |
757 | ||
312c056a PP |
758 | int bt_ctf_field_integer_signed_get_value(struct bt_ctf_field *field, |
759 | int64_t *value) | |
3dca2276 | 760 | { |
312c056a PP |
761 | struct bt_field_common_integer *integer = (void *) field; |
762 | ||
763 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
764 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
765 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field"); | |
766 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer), | |
767 | BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
768 | BT_ASSERT_PRE(bt_field_type_common_integer_is_signed( | |
769 | integer->common.type), | |
770 | "Field's type is unsigned: %!+_f", field); | |
771 | *value = integer->payload.signd; | |
772 | return 0; | |
3dca2276 PP |
773 | } |
774 | ||
775 | int bt_ctf_field_integer_signed_set_value(struct bt_ctf_field *field, | |
776 | int64_t value) | |
777 | { | |
312c056a PP |
778 | int ret = 0; |
779 | struct bt_field_common_integer *integer = (void *) field; | |
780 | struct bt_field_type_common_integer *integer_type; | |
781 | ||
782 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
783 | BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field"); | |
784 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer), | |
785 | BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
786 | integer_type = BT_FROM_COMMON(integer->common.type); | |
787 | BT_ASSERT_PRE( | |
788 | bt_field_type_common_integer_is_signed(integer->common.type), | |
789 | "Field's type is unsigned: %!+wf", field); | |
790 | BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value), | |
791 | "Value is out of bounds: value=%" PRId64 ", %![field-]+wf", | |
792 | value, field); | |
793 | integer->payload.signd = value; | |
794 | bt_field_common_set(BT_TO_COMMON(integer), true); | |
795 | return ret; | |
3dca2276 PP |
796 | } |
797 | ||
798 | int bt_ctf_field_integer_unsigned_get_value(struct bt_ctf_field *field, | |
799 | uint64_t *value) | |
800 | { | |
312c056a PP |
801 | struct bt_field_common_integer *integer = (void *) field; |
802 | ||
803 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
804 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
805 | BT_ASSERT_PRE_FIELD_COMMON_IS_SET(BT_TO_COMMON(integer), "Integer field"); | |
806 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer), | |
807 | BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
808 | BT_ASSERT_PRE( | |
809 | !bt_field_type_common_integer_is_signed(integer->common.type), | |
810 | "Field's type is signed: %!+wf", field); | |
811 | *value = integer->payload.unsignd; | |
812 | return 0; | |
3dca2276 PP |
813 | } |
814 | ||
312c056a PP |
815 | int bt_ctf_field_integer_unsigned_set_value(struct bt_ctf_field *field, |
816 | uint64_t value) | |
3dca2276 | 817 | { |
312c056a PP |
818 | struct bt_field_common_integer *integer = (void *) field; |
819 | struct bt_field_type_common_integer *integer_type; | |
820 | ||
821 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); | |
822 | BT_ASSERT_PRE_FIELD_COMMON_HOT(BT_TO_COMMON(integer), "Integer field"); | |
823 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(BT_TO_COMMON(integer), | |
824 | BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
825 | integer_type = BT_FROM_COMMON(integer->common.type); | |
826 | BT_ASSERT_PRE( | |
827 | !bt_field_type_common_integer_is_signed(integer->common.type), | |
828 | "Field's type is signed: %!+wf", field); | |
829 | BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value), | |
830 | "Value is out of bounds: value=%" PRIu64 ", %![field-]+wf", | |
831 | value, field); | |
832 | integer->payload.unsignd = value; | |
833 | bt_field_common_set(BT_TO_COMMON(integer), true); | |
834 | return 0; | |
3dca2276 PP |
835 | } |
836 | ||
837 | int bt_ctf_field_floating_point_get_value(struct bt_ctf_field *field, | |
838 | double *value) | |
839 | { | |
840 | return bt_field_common_floating_point_get_value((void *) field, value); | |
841 | } | |
842 | ||
843 | int bt_ctf_field_floating_point_set_value(struct bt_ctf_field *field, | |
844 | double value) | |
845 | { | |
846 | return bt_field_common_floating_point_set_value((void *) field, value); | |
847 | } | |
848 | ||
849 | const char *bt_ctf_field_string_get_value(struct bt_ctf_field *field) | |
850 | { | |
851 | return bt_field_common_string_get_value((void *) field); | |
852 | } | |
853 | ||
854 | int bt_ctf_field_string_set_value(struct bt_ctf_field *field, const char *value) | |
855 | { | |
856 | return bt_field_common_string_set_value((void *) field, value); | |
857 | } | |
858 | ||
859 | int bt_ctf_field_string_append(struct bt_ctf_field *field, const char *value) | |
860 | { | |
861 | return bt_field_common_string_append((void *) field, value); | |
862 | } | |
863 | ||
864 | int bt_ctf_field_string_append_len(struct bt_ctf_field *field, | |
865 | const char *value, unsigned int length) | |
866 | { | |
867 | return bt_field_common_string_append_len((void *) field, value, length); | |
868 | } | |
869 | ||
870 | struct bt_ctf_field *bt_ctf_field_copy(struct bt_ctf_field *field) | |
871 | { | |
872 | return (void *) bt_field_common_copy((void *) field); | |
873 | } | |
874 | ||
875 | static | |
876 | struct bt_ctf_field *bt_ctf_field_integer_create(struct bt_ctf_field_type *type) | |
877 | { | |
878 | struct bt_field_common_integer *integer = | |
879 | g_new0(struct bt_field_common_integer, 1); | |
880 | ||
881 | BT_LOGD("Creating CTF writer integer field object: ft-addr=%p", type); | |
882 | ||
883 | if (integer) { | |
884 | bt_field_common_initialize(BT_TO_COMMON(integer), (void *) type, | |
312c056a | 885 | (bt_object_release_func) bt_ctf_field_integer_destroy, |
3dca2276 PP |
886 | &bt_ctf_field_integer_methods); |
887 | integer->common.spec.writer.serialize_func = | |
888 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_integer_serialize; | |
889 | BT_LOGD("Created CTF writer integer field object: addr=%p, ft-addr=%p", | |
890 | integer, type); | |
891 | } else { | |
892 | BT_LOGE_STR("Failed to allocate one integer field."); | |
893 | } | |
894 | ||
895 | return (void *) integer; | |
896 | } | |
897 | ||
898 | static | |
899 | struct bt_ctf_field *bt_ctf_field_enumeration_create( | |
900 | struct bt_ctf_field_type *type) | |
901 | { | |
312c056a PP |
902 | struct bt_field_type_common_enumeration *enum_ft = (void *) type; |
903 | struct bt_ctf_field_enumeration *enumeration = g_new0( | |
904 | struct bt_ctf_field_enumeration, 1); | |
3dca2276 PP |
905 | |
906 | BT_LOGD("Creating CTF writer enumeration field object: ft-addr=%p", type); | |
907 | ||
312c056a | 908 | if (!enumeration) { |
3dca2276 | 909 | BT_LOGE_STR("Failed to allocate one enumeration field."); |
312c056a | 910 | goto end; |
3dca2276 PP |
911 | } |
912 | ||
312c056a PP |
913 | bt_field_common_initialize(BT_TO_COMMON(enumeration), |
914 | (void *) type, | |
915 | (bt_object_release_func) | |
916 | bt_ctf_field_enumeration_destroy_recursive, | |
917 | &bt_ctf_field_enumeration_methods); | |
918 | enumeration->container = (void *) bt_ctf_field_create( | |
919 | BT_FROM_COMMON(enum_ft->container_ft)); | |
920 | if (!enumeration->container) { | |
921 | BT_PUT(enumeration); | |
922 | goto end; | |
923 | } | |
924 | ||
925 | enumeration->common.spec.writer.serialize_func = | |
926 | (bt_ctf_field_serialize_recursive_func) | |
927 | bt_ctf_field_enumeration_serialize_recursive; | |
928 | BT_LOGD("Created CTF writer enumeration field object: addr=%p, ft-addr=%p", | |
929 | enumeration, type); | |
930 | ||
931 | end: | |
3dca2276 PP |
932 | return (void *) enumeration; |
933 | } | |
934 | ||
935 | static | |
936 | struct bt_ctf_field *bt_ctf_field_floating_point_create( | |
937 | struct bt_ctf_field_type *type) | |
938 | { | |
939 | struct bt_field_common_floating_point *floating_point; | |
940 | ||
941 | BT_LOGD("Creating CTF writer floating point number field object: ft-addr=%p", type); | |
942 | floating_point = g_new0(struct bt_field_common_floating_point, 1); | |
943 | ||
944 | if (floating_point) { | |
945 | bt_field_common_initialize(BT_TO_COMMON(floating_point), | |
946 | (void *) type, | |
312c056a PP |
947 | (bt_object_release_func) |
948 | bt_ctf_field_floating_point_destroy, | |
3dca2276 PP |
949 | &bt_ctf_field_floating_point_methods); |
950 | floating_point->common.spec.writer.serialize_func = | |
951 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_floating_point_serialize; | |
952 | BT_LOGD("Created CTF writer floating point number field object: addr=%p, ft-addr=%p", | |
953 | floating_point, type); | |
954 | } else { | |
955 | BT_LOGE_STR("Failed to allocate one floating point number field."); | |
956 | } | |
957 | ||
958 | return (void *) floating_point; | |
959 | } | |
960 | ||
961 | static | |
962 | struct bt_ctf_field *bt_ctf_field_structure_create( | |
963 | struct bt_ctf_field_type *type) | |
964 | { | |
965 | struct bt_field_common_structure *structure = g_new0( | |
966 | struct bt_field_common_structure, 1); | |
967 | int iret; | |
968 | ||
969 | BT_LOGD("Creating CTF writer structure field object: ft-addr=%p", type); | |
970 | ||
971 | if (!structure) { | |
972 | BT_LOGE_STR("Failed to allocate one structure field."); | |
973 | goto end; | |
974 | } | |
975 | ||
976 | iret = bt_field_common_structure_initialize(BT_TO_COMMON(structure), | |
312c056a PP |
977 | (void *) type, |
978 | (bt_object_release_func) | |
979 | bt_ctf_field_structure_destroy_recursive, | |
3dca2276 | 980 | &bt_ctf_field_structure_methods, |
312c056a PP |
981 | (bt_field_common_create_func) bt_ctf_field_create, |
982 | (GDestroyNotify) bt_put); | |
3dca2276 PP |
983 | structure->common.spec.writer.serialize_func = |
984 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_structure_serialize_recursive; | |
985 | if (iret) { | |
986 | BT_PUT(structure); | |
987 | goto end; | |
988 | } | |
989 | ||
990 | BT_LOGD("Created CTF writer structure field object: addr=%p, ft-addr=%p", | |
991 | structure, type); | |
992 | ||
993 | end: | |
994 | return (void *) structure; | |
995 | } | |
996 | ||
997 | static | |
998 | struct bt_ctf_field *bt_ctf_field_variant_create(struct bt_ctf_field_type *type) | |
999 | { | |
312c056a PP |
1000 | struct bt_field_type_common_variant *var_ft = (void *) type; |
1001 | struct bt_ctf_field_variant *variant = g_new0( | |
1002 | struct bt_ctf_field_variant, 1); | |
3dca2276 PP |
1003 | |
1004 | BT_LOGD("Creating CTF writer variant field object: ft-addr=%p", type); | |
1005 | ||
312c056a | 1006 | if (!variant) { |
3dca2276 | 1007 | BT_LOGE_STR("Failed to allocate one variant field."); |
312c056a | 1008 | goto end; |
3dca2276 PP |
1009 | } |
1010 | ||
312c056a PP |
1011 | bt_field_common_variant_initialize(BT_TO_COMMON(BT_TO_COMMON(variant)), |
1012 | (void *) type, | |
1013 | (bt_object_release_func) | |
1014 | bt_ctf_field_variant_destroy_recursive, | |
1015 | &bt_ctf_field_variant_methods, | |
1016 | (bt_field_common_create_func) bt_ctf_field_create, | |
1017 | (GDestroyNotify) bt_put); | |
1018 | variant->tag = (void *) bt_ctf_field_create( | |
1019 | BT_FROM_COMMON(var_ft->tag_ft)); | |
1020 | variant->common.common.spec.writer.serialize_func = | |
1021 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_variant_serialize_recursive; | |
1022 | BT_LOGD("Created CTF writer variant field object: addr=%p, ft-addr=%p", | |
1023 | variant, type); | |
1024 | ||
1025 | end: | |
3dca2276 PP |
1026 | return (void *) variant; |
1027 | } | |
1028 | ||
1029 | static | |
1030 | struct bt_ctf_field *bt_ctf_field_array_create(struct bt_ctf_field_type *type) | |
1031 | { | |
1032 | struct bt_field_common_array *array = | |
1033 | g_new0(struct bt_field_common_array, 1); | |
1034 | int ret; | |
1035 | ||
1036 | BT_LOGD("Creating CTF writer array field object: ft-addr=%p", type); | |
1037 | BT_ASSERT(type); | |
1038 | ||
1039 | if (!array) { | |
1040 | BT_LOGE_STR("Failed to allocate one array field."); | |
1041 | goto end; | |
1042 | } | |
1043 | ||
1044 | ret = bt_field_common_array_initialize(BT_TO_COMMON(array), | |
1045 | (void *) type, | |
312c056a PP |
1046 | (bt_object_release_func) |
1047 | bt_ctf_field_array_destroy_recursive, | |
1048 | &bt_ctf_field_array_methods, | |
1049 | (bt_field_common_create_func) bt_ctf_field_create, | |
1050 | (GDestroyNotify) bt_put); | |
3dca2276 PP |
1051 | array->common.spec.writer.serialize_func = |
1052 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_array_serialize_recursive; | |
1053 | if (ret) { | |
1054 | BT_PUT(array); | |
1055 | goto end; | |
1056 | } | |
1057 | ||
1058 | BT_LOGD("Created CTF writer array field object: addr=%p, ft-addr=%p", | |
1059 | array, type); | |
1060 | ||
1061 | end: | |
1062 | return (void *) array; | |
1063 | } | |
1064 | ||
1065 | static | |
1066 | struct bt_ctf_field *bt_ctf_field_sequence_create(struct bt_ctf_field_type *type) | |
1067 | { | |
1068 | struct bt_field_common_sequence *sequence = g_new0( | |
1069 | struct bt_field_common_sequence, 1); | |
1070 | ||
1071 | BT_LOGD("Creating CTF writer sequence field object: ft-addr=%p", type); | |
1072 | ||
1073 | if (sequence) { | |
312c056a | 1074 | bt_field_common_sequence_initialize(BT_TO_COMMON(sequence), |
3dca2276 | 1075 | (void *) type, |
312c056a PP |
1076 | (bt_object_release_func) |
1077 | bt_ctf_field_sequence_destroy_recursive, | |
1078 | &bt_ctf_field_sequence_methods, | |
1079 | (GDestroyNotify) bt_put); | |
3dca2276 PP |
1080 | sequence->common.spec.writer.serialize_func = |
1081 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_sequence_serialize_recursive; | |
1082 | BT_LOGD("Created CTF writer sequence field object: addr=%p, ft-addr=%p", | |
1083 | sequence, type); | |
1084 | } else { | |
1085 | BT_LOGE_STR("Failed to allocate one sequence field."); | |
1086 | } | |
1087 | ||
1088 | return (void *) sequence; | |
1089 | } | |
1090 | ||
1091 | static | |
1092 | struct bt_ctf_field *bt_ctf_field_string_create(struct bt_ctf_field_type *type) | |
1093 | { | |
1094 | struct bt_field_common_string *string = g_new0( | |
1095 | struct bt_field_common_string, 1); | |
1096 | ||
1097 | BT_LOGD("Creating CTF writer string field object: ft-addr=%p", type); | |
1098 | ||
1099 | if (string) { | |
4d4b475d | 1100 | bt_field_common_string_initialize(BT_TO_COMMON(string), |
3dca2276 | 1101 | (void *) type, |
312c056a PP |
1102 | (bt_object_release_func) |
1103 | bt_ctf_field_string_destroy, | |
3dca2276 PP |
1104 | &bt_ctf_field_string_methods); |
1105 | string->common.spec.writer.serialize_func = | |
1106 | (bt_ctf_field_serialize_recursive_func) bt_ctf_field_string_serialize; | |
1107 | BT_LOGD("Created CTF writer string field object: addr=%p, ft-addr=%p", | |
1108 | string, type); | |
1109 | } else { | |
1110 | BT_LOGE_STR("Failed to allocate one string field."); | |
1111 | } | |
1112 | ||
1113 | return (void *) string; | |
1114 | } | |
312c056a PP |
1115 | |
1116 | static | |
1117 | void bt_ctf_field_enumeration_set_is_frozen_recursive( | |
1118 | struct bt_field_common *field, bool is_frozen) | |
1119 | { | |
1120 | struct bt_ctf_field_enumeration *enumeration = (void *) field; | |
1121 | ||
1122 | if (enumeration->container) { | |
1123 | bt_field_common_set_is_frozen_recursive( | |
1124 | (void *) enumeration->container, is_frozen); | |
1125 | } | |
1126 | ||
1127 | bt_field_common_generic_set_is_frozen((void *) field, is_frozen); | |
1128 | } | |
1129 | ||
1130 | static | |
1131 | int bt_ctf_field_enumeration_validate_recursive(struct bt_field_common *field) | |
1132 | { | |
1133 | int ret = -1; | |
1134 | struct bt_ctf_field_enumeration *enumeration = (void *) field; | |
1135 | ||
1136 | if (enumeration->container) { | |
1137 | ret = bt_field_common_validate_recursive( | |
1138 | (void *) enumeration->container); | |
1139 | } | |
1140 | ||
1141 | return ret; | |
1142 | } | |
1143 | ||
1144 | static | |
1145 | bt_bool bt_ctf_field_enumeration_is_set_recursive(struct bt_field_common *field) | |
1146 | { | |
1147 | bt_bool is_set = BT_FALSE; | |
1148 | struct bt_ctf_field_enumeration *enumeration = (void *) field; | |
1149 | ||
1150 | if (enumeration->container) { | |
1151 | is_set = bt_field_common_is_set_recursive( | |
1152 | (void *) enumeration->container); | |
1153 | } | |
1154 | ||
1155 | return is_set; | |
1156 | } | |
1157 | ||
1158 | static | |
1159 | void bt_ctf_field_enumeration_reset_recursive(struct bt_field_common *field) | |
1160 | { | |
1161 | struct bt_ctf_field_enumeration *enumeration = (void *) field; | |
1162 | ||
1163 | if (enumeration->container) { | |
1164 | bt_field_common_reset_recursive( | |
1165 | (void *) enumeration->container); | |
1166 | } | |
1167 | ||
1168 | bt_field_common_generic_reset((void *) field); | |
1169 | } | |
1170 | ||
1171 | static | |
1172 | void bt_ctf_field_variant_set_is_frozen_recursive( | |
1173 | struct bt_field_common *field, bool is_frozen) | |
1174 | { | |
1175 | struct bt_ctf_field_variant *variant = (void *) field; | |
1176 | ||
1177 | if (variant->tag) { | |
1178 | bt_field_common_set_is_frozen_recursive( | |
1179 | (void *) variant->tag, is_frozen); | |
1180 | } | |
1181 | ||
1182 | bt_field_common_variant_set_is_frozen_recursive((void *) field, | |
1183 | is_frozen); | |
1184 | } | |
1185 | ||
1186 | static | |
1187 | int bt_ctf_field_variant_validate_recursive(struct bt_field_common *field) | |
1188 | { | |
1189 | int ret; | |
1190 | struct bt_ctf_field_variant *variant = (void *) field; | |
1191 | ||
1192 | if (variant->tag) { | |
1193 | ret = bt_field_common_validate_recursive( | |
1194 | (void *) variant->tag); | |
1195 | if (ret) { | |
1196 | goto end; | |
1197 | } | |
1198 | } | |
1199 | ||
1200 | ret = bt_field_common_variant_validate_recursive((void *) field); | |
1201 | ||
1202 | end: | |
1203 | return ret; | |
1204 | } | |
1205 | ||
1206 | static | |
1207 | bt_bool bt_ctf_field_variant_is_set_recursive(struct bt_field_common *field) | |
1208 | { | |
1209 | bt_bool is_set; | |
1210 | struct bt_ctf_field_variant *variant = (void *) field; | |
1211 | ||
1212 | if (variant->tag) { | |
1213 | is_set = bt_field_common_is_set_recursive( | |
1214 | (void *) variant->tag); | |
1215 | if (is_set) { | |
1216 | goto end; | |
1217 | } | |
1218 | } | |
1219 | ||
1220 | is_set = bt_field_common_variant_is_set_recursive((void *) field); | |
1221 | ||
1222 | end: | |
1223 | return is_set; | |
1224 | } | |
1225 | ||
1226 | static | |
1227 | void bt_ctf_field_variant_reset_recursive(struct bt_field_common *field) | |
1228 | { | |
1229 | struct bt_ctf_field_variant *variant = (void *) field; | |
1230 | ||
1231 | if (variant->tag) { | |
1232 | bt_field_common_reset_recursive( | |
1233 | (void *) variant->tag); | |
1234 | } | |
1235 | ||
1236 | bt_field_common_variant_reset_recursive((void *) field); | |
1237 | } | |
1238 | ||
1239 | BT_ASSERT_PRE_FUNC | |
1240 | static inline bool field_to_set_has_expected_type( | |
1241 | struct bt_field_common *struct_field, | |
1242 | const char *name, struct bt_field_common *value) | |
1243 | { | |
1244 | bool ret = true; | |
1245 | struct bt_field_type_common *expected_field_type = NULL; | |
1246 | ||
1247 | expected_field_type = | |
1248 | bt_field_type_common_structure_borrow_field_type_by_name( | |
1249 | struct_field->type, name); | |
1250 | ||
1251 | if (bt_field_type_common_compare(expected_field_type, value->type)) { | |
1252 | BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: " | |
1253 | "%![value-ft-]+_F, %![expected-ft-]+_F", value->type, | |
1254 | expected_field_type); | |
1255 | ret = false; | |
1256 | goto end; | |
1257 | } | |
1258 | ||
1259 | end: | |
1260 | return ret; | |
1261 | } | |
1262 | ||
1263 | BT_HIDDEN | |
1264 | int bt_ctf_field_structure_set_field_by_name(struct bt_ctf_field *field, | |
1265 | const char *name, struct bt_ctf_field *value) | |
1266 | { | |
1267 | int ret = 0; | |
1268 | GQuark field_quark; | |
1269 | struct bt_field_common *common_field = (void *) field; | |
1270 | struct bt_field_common_structure *structure = | |
1271 | BT_FROM_COMMON(common_field); | |
1272 | struct bt_field_common *common_value = (void *) value; | |
1273 | size_t index; | |
1274 | GHashTable *field_name_to_index; | |
1275 | struct bt_field_type_common_structure *structure_ft; | |
1276 | ||
1277 | BT_ASSERT_PRE_NON_NULL(field, "Parent field"); | |
1278 | BT_ASSERT_PRE_NON_NULL(name, "Field name"); | |
1279 | BT_ASSERT_PRE_NON_NULL(value, "Value field"); | |
1280 | BT_ASSERT_PRE_FIELD_COMMON_HAS_TYPE_ID(common_field, | |
1281 | BT_FIELD_TYPE_ID_STRUCT, "Parent field"); | |
1282 | BT_ASSERT_PRE(field_to_set_has_expected_type(common_field, | |
1283 | name, common_value), | |
1284 | "Value field's type is different from the expected field type."); | |
1285 | field_quark = g_quark_from_string(name); | |
1286 | structure_ft = BT_FROM_COMMON(common_field->type); | |
1287 | field_name_to_index = structure_ft->field_name_to_index; | |
1288 | if (!g_hash_table_lookup_extended(field_name_to_index, | |
1289 | GUINT_TO_POINTER(field_quark), NULL, | |
1290 | (gpointer *) &index)) { | |
1291 | BT_LOGV("Invalid parameter: no such field in structure field's type: " | |
1292 | "struct-field-addr=%p, struct-ft-addr=%p, " | |
1293 | "field-ft-addr=%p, name=\"%s\"", | |
1294 | field, common_field->type, common_value->type, name); | |
1295 | ret = -1; | |
1296 | goto end; | |
1297 | } | |
1298 | bt_get(value); | |
1299 | BT_MOVE(structure->fields->pdata[index], value); | |
1300 | ||
1301 | end: | |
1302 | return ret; | |
1303 | } |