Commit | Line | Data |
---|---|---|
273b65be | 1 | /* |
2e33ac5a | 2 | * fields.c |
273b65be | 3 | * |
d2dc44b6 | 4 | * Babeltrace CTF IR - Event Fields |
273b65be | 5 | * |
de9dd397 | 6 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> |
273b65be JG |
7 | * |
8 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
9 | * | |
10 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
11 | * of this software and associated documentation files (the "Software"), to deal | |
12 | * in the Software without restriction, including without limitation the rights | |
13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
14 | * copies of the Software, and to permit persons to whom the Software is | |
15 | * furnished to do so, subject to the following conditions: | |
16 | * | |
17 | * The above copyright notice and this permission notice shall be included in | |
18 | * all copies or substantial portions of the Software. | |
19 | * | |
20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
26 | * SOFTWARE. | |
27 | */ | |
28 | ||
fc25abce PP |
29 | #define BT_LOG_TAG "FIELDS" |
30 | #include <babeltrace/lib-logging-internal.h> | |
31 | ||
2e33ac5a PP |
32 | #include <babeltrace/ctf-ir/fields-internal.h> |
33 | #include <babeltrace/ctf-ir/field-types-internal.h> | |
dc3fffef | 34 | #include <babeltrace/ctf-writer/serialize-internal.h> |
83509119 JG |
35 | #include <babeltrace/object-internal.h> |
36 | #include <babeltrace/ref.h> | |
3d9990ac PP |
37 | #include <babeltrace/compiler-internal.h> |
38 | #include <babeltrace/compat/fcntl-internal.h> | |
39 | #include <babeltrace/align-internal.h> | |
f6ccaed9 PP |
40 | #include <babeltrace/assert-internal.h> |
41 | #include <babeltrace/assert-pre-internal.h> | |
fc25abce | 42 | #include <inttypes.h> |
273b65be | 43 | |
273b65be | 44 | static |
50842bdc | 45 | struct bt_field *bt_field_integer_create(struct bt_field_type *); |
273b65be | 46 | static |
f6ccaed9 | 47 | struct bt_field *bt_field_enumeration_create(struct bt_field_type *); |
273b65be | 48 | static |
f6ccaed9 | 49 | struct bt_field *bt_field_floating_point_create(struct bt_field_type *); |
273b65be | 50 | static |
f6ccaed9 | 51 | struct bt_field *bt_field_structure_create(struct bt_field_type *); |
273b65be | 52 | static |
f6ccaed9 | 53 | struct bt_field *bt_field_variant_create(struct bt_field_type *); |
273b65be | 54 | static |
f6ccaed9 | 55 | struct bt_field *bt_field_array_create(struct bt_field_type *); |
273b65be | 56 | static |
f6ccaed9 | 57 | struct bt_field *bt_field_sequence_create(struct bt_field_type *); |
273b65be | 58 | static |
50842bdc | 59 | struct bt_field *bt_field_string_create(struct bt_field_type *); |
273b65be JG |
60 | |
61 | static | |
50842bdc | 62 | void bt_field_destroy(struct bt_object *); |
273b65be | 63 | static |
50842bdc | 64 | void bt_field_integer_destroy(struct bt_field *); |
273b65be | 65 | static |
f6ccaed9 | 66 | void bt_field_enumeration_destroy_recursive(struct bt_field *); |
273b65be | 67 | static |
50842bdc | 68 | void bt_field_floating_point_destroy(struct bt_field *); |
273b65be | 69 | static |
f6ccaed9 | 70 | void bt_field_structure_destroy_recursive(struct bt_field *); |
273b65be | 71 | static |
f6ccaed9 | 72 | void bt_field_variant_destroy_recursive(struct bt_field *); |
273b65be | 73 | static |
f6ccaed9 | 74 | void bt_field_array_destroy_recursive(struct bt_field *); |
273b65be | 75 | static |
f6ccaed9 | 76 | void bt_field_sequence_destroy_recursive(struct bt_field *); |
273b65be | 77 | static |
50842bdc | 78 | void bt_field_string_destroy(struct bt_field *); |
273b65be JG |
79 | |
80 | static | |
50842bdc | 81 | int bt_field_generic_validate(struct bt_field *); |
273b65be | 82 | static |
f6ccaed9 | 83 | int bt_field_structure_validate_recursive(struct bt_field *); |
273b65be | 84 | static |
f6ccaed9 | 85 | int bt_field_variant_validate_recursive(struct bt_field *); |
273b65be | 86 | static |
f6ccaed9 | 87 | int bt_field_enumeration_validate_recursive(struct bt_field *); |
273b65be | 88 | static |
f6ccaed9 | 89 | int bt_field_array_validate_recursive(struct bt_field *); |
273b65be | 90 | static |
f6ccaed9 | 91 | int bt_field_sequence_validate_recursive(struct bt_field *); |
273b65be | 92 | |
12c8a1a3 | 93 | static |
f6ccaed9 | 94 | void bt_field_generic_reset(struct bt_field *); |
12c8a1a3 | 95 | static |
f6ccaed9 | 96 | void bt_field_structure_reset_recursive(struct bt_field *); |
12c8a1a3 | 97 | static |
f6ccaed9 | 98 | void bt_field_variant_reset_recursive(struct bt_field *); |
12c8a1a3 | 99 | static |
f6ccaed9 | 100 | void bt_field_enumeration_reset_recursive(struct bt_field *); |
12c8a1a3 | 101 | static |
f6ccaed9 | 102 | void bt_field_array_reset_recursive(struct bt_field *); |
12c8a1a3 | 103 | static |
f6ccaed9 | 104 | void bt_field_sequence_reset_recursive(struct bt_field *); |
12c8a1a3 | 105 | static |
f6ccaed9 | 106 | void bt_field_string_reset_recursive(struct bt_field *); |
12c8a1a3 | 107 | |
273b65be | 108 | static |
50842bdc PP |
109 | int bt_field_integer_serialize(struct bt_field *, |
110 | struct bt_stream_pos *, enum bt_byte_order); | |
273b65be | 111 | static |
f6ccaed9 | 112 | int bt_field_enumeration_serialize_recursive(struct bt_field *, |
50842bdc | 113 | struct bt_stream_pos *, enum bt_byte_order); |
273b65be | 114 | static |
50842bdc PP |
115 | int bt_field_floating_point_serialize(struct bt_field *, |
116 | struct bt_stream_pos *, enum bt_byte_order); | |
273b65be | 117 | static |
f6ccaed9 | 118 | int bt_field_structure_serialize_recursive(struct bt_field *, |
50842bdc | 119 | struct bt_stream_pos *, enum bt_byte_order); |
273b65be | 120 | static |
f6ccaed9 | 121 | int bt_field_variant_serialize_recursive(struct bt_field *, |
50842bdc | 122 | struct bt_stream_pos *, enum bt_byte_order); |
273b65be | 123 | static |
f6ccaed9 | 124 | int bt_field_array_serialize_recursive(struct bt_field *, |
50842bdc | 125 | struct bt_stream_pos *, enum bt_byte_order); |
273b65be | 126 | static |
f6ccaed9 | 127 | int bt_field_sequence_serialize_recursive(struct bt_field *, |
50842bdc | 128 | struct bt_stream_pos *, enum bt_byte_order); |
273b65be | 129 | static |
50842bdc PP |
130 | int bt_field_string_serialize(struct bt_field *, |
131 | struct bt_stream_pos *, enum bt_byte_order); | |
273b65be | 132 | |
87d43dc1 | 133 | static |
50842bdc | 134 | int bt_field_integer_copy(struct bt_field *, struct bt_field *); |
87d43dc1 | 135 | static |
f6ccaed9 | 136 | int bt_field_enumeration_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 137 | static |
f6ccaed9 | 138 | int bt_field_floating_point_copy(struct bt_field *, struct bt_field *); |
87d43dc1 | 139 | static |
f6ccaed9 | 140 | int bt_field_structure_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 141 | static |
f6ccaed9 | 142 | int bt_field_variant_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 143 | static |
f6ccaed9 | 144 | int bt_field_array_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 145 | static |
f6ccaed9 | 146 | int bt_field_sequence_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 147 | static |
f6ccaed9 | 148 | int bt_field_string_copy_recursive(struct bt_field *, struct bt_field *); |
87d43dc1 | 149 | |
918be005 | 150 | static |
50842bdc | 151 | void generic_field_freeze(struct bt_field *); |
918be005 | 152 | static |
f6ccaed9 | 153 | void bt_field_enumeration_freeze_recursive(struct bt_field *); |
918be005 | 154 | static |
f6ccaed9 | 155 | void bt_field_structure_freeze_recursive(struct bt_field *); |
918be005 | 156 | static |
f6ccaed9 | 157 | void bt_field_variant_freeze_recursive(struct bt_field *); |
918be005 | 158 | static |
f6ccaed9 | 159 | void bt_field_array_freeze_recursive(struct bt_field *); |
918be005 | 160 | static |
f6ccaed9 | 161 | void bt_field_sequence_freeze_recursive(struct bt_field *); |
918be005 | 162 | |
76f869ab | 163 | static |
50842bdc | 164 | bt_bool bt_field_generic_is_set(struct bt_field *); |
76f869ab | 165 | static |
f6ccaed9 | 166 | bt_bool bt_field_structure_is_set_recursive(struct bt_field *); |
76f869ab | 167 | static |
f6ccaed9 | 168 | bt_bool bt_field_variant_is_set_recursive(struct bt_field *); |
76f869ab | 169 | static |
f6ccaed9 | 170 | bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *); |
76f869ab | 171 | static |
f6ccaed9 | 172 | bt_bool bt_field_array_is_set_recursive(struct bt_field *); |
76f869ab | 173 | static |
f6ccaed9 | 174 | bt_bool bt_field_sequence_is_set_recursive(struct bt_field *); |
76f869ab | 175 | |
273b65be | 176 | static |
50842bdc | 177 | int increase_packet_size(struct bt_stream_pos *pos); |
273b65be JG |
178 | |
179 | static | |
f6ccaed9 | 180 | struct bt_field *(* const field_create_funcs[])(struct bt_field_type *) = { |
50842bdc PP |
181 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_create, |
182 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_create, | |
f6ccaed9 | 183 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_create, |
50842bdc PP |
184 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_create, |
185 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_create, | |
186 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_create, | |
187 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_create, | |
188 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_create, | |
273b65be JG |
189 | }; |
190 | ||
191 | static | |
50842bdc PP |
192 | void (* const field_destroy_funcs[])(struct bt_field *) = { |
193 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_destroy, | |
f6ccaed9 PP |
194 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_destroy_recursive, |
195 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_destroy, | |
196 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_destroy_recursive, | |
197 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_destroy_recursive, | |
198 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_destroy_recursive, | |
199 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_destroy_recursive, | |
50842bdc | 200 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_destroy, |
273b65be JG |
201 | }; |
202 | ||
203 | static | |
50842bdc PP |
204 | int (* const field_validate_funcs[])(struct bt_field *) = { |
205 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_validate, | |
f6ccaed9 | 206 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_validate_recursive, |
50842bdc | 207 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_validate, |
f6ccaed9 PP |
208 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_validate_recursive, |
209 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_validate_recursive, | |
210 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_validate_recursive, | |
211 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_validate_recursive, | |
50842bdc | 212 | [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_validate, |
273b65be JG |
213 | }; |
214 | ||
12c8a1a3 | 215 | static |
f6ccaed9 | 216 | void (* const field_reset_funcs[])(struct bt_field *) = { |
50842bdc | 217 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_reset, |
f6ccaed9 | 218 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_reset_recursive, |
50842bdc | 219 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_reset, |
f6ccaed9 PP |
220 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_reset_recursive, |
221 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_reset_recursive, | |
222 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_reset_recursive, | |
223 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_reset_recursive, | |
224 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_reset_recursive, | |
12c8a1a3 JG |
225 | }; |
226 | ||
273b65be | 227 | static |
50842bdc PP |
228 | int (* const field_serialize_funcs[])(struct bt_field *, |
229 | struct bt_stream_pos *, enum bt_byte_order) = { | |
230 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_serialize, | |
f6ccaed9 PP |
231 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_serialize_recursive, |
232 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_serialize, | |
233 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_serialize_recursive, | |
234 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_serialize_recursive, | |
235 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_serialize_recursive, | |
236 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_serialize_recursive, | |
50842bdc | 237 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_serialize, |
273b65be JG |
238 | }; |
239 | ||
87d43dc1 | 240 | static |
50842bdc PP |
241 | int (* const field_copy_funcs[])(struct bt_field *, |
242 | struct bt_field *) = { | |
243 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_integer_copy, | |
f6ccaed9 | 244 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_copy_recursive, |
50842bdc | 245 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_floating_point_copy, |
f6ccaed9 PP |
246 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_copy_recursive, |
247 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_copy_recursive, | |
248 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_copy_recursive, | |
249 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_copy_recursive, | |
250 | [BT_FIELD_TYPE_ID_STRING] = bt_field_string_copy_recursive, | |
87d43dc1 JG |
251 | }; |
252 | ||
918be005 | 253 | static |
50842bdc PP |
254 | void (* const field_freeze_funcs[])(struct bt_field *) = { |
255 | [BT_FIELD_TYPE_ID_INTEGER] = generic_field_freeze, | |
256 | [BT_FIELD_TYPE_ID_FLOAT] = generic_field_freeze, | |
257 | [BT_FIELD_TYPE_ID_STRING] = generic_field_freeze, | |
f6ccaed9 PP |
258 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_freeze_recursive, |
259 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_freeze_recursive, | |
260 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_freeze_recursive, | |
261 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_freeze_recursive, | |
262 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_freeze_recursive, | |
918be005 PP |
263 | }; |
264 | ||
76f869ab | 265 | static |
50842bdc PP |
266 | bt_bool (* const field_is_set_funcs[])(struct bt_field *) = { |
267 | [BT_FIELD_TYPE_ID_INTEGER] = bt_field_generic_is_set, | |
f6ccaed9 | 268 | [BT_FIELD_TYPE_ID_ENUM] = bt_field_enumeration_is_set_recursive, |
50842bdc | 269 | [BT_FIELD_TYPE_ID_FLOAT] = bt_field_generic_is_set, |
f6ccaed9 PP |
270 | [BT_FIELD_TYPE_ID_STRUCT] = bt_field_structure_is_set_recursive, |
271 | [BT_FIELD_TYPE_ID_VARIANT] = bt_field_variant_is_set_recursive, | |
272 | [BT_FIELD_TYPE_ID_ARRAY] = bt_field_array_is_set_recursive, | |
273 | [BT_FIELD_TYPE_ID_SEQUENCE] = bt_field_sequence_is_set_recursive, | |
50842bdc | 274 | [BT_FIELD_TYPE_ID_STRING] = bt_field_generic_is_set, |
76f869ab JG |
275 | }; |
276 | ||
f6ccaed9 PP |
277 | BT_ASSERT_FUNC |
278 | static inline bool field_type_has_known_id(struct bt_field_type *ft) | |
279 | { | |
280 | return ft->id > BT_FIELD_TYPE_ID_UNKNOWN || | |
281 | ft->id < BT_FIELD_TYPE_ID_NR; | |
282 | } | |
283 | ||
284 | #define BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(_field, _type_id, _name) \ | |
285 | BT_ASSERT_PRE((_field)->type->id == (_type_id), \ | |
286 | _name " has the wrong type ID: expected-type-id=%s, " \ | |
287 | "%![field-]+f", bt_field_type_id_string(_type_id), \ | |
288 | (_field)) | |
289 | ||
290 | #define BT_ASSERT_PRE_FIELD_IS_SET(_field, _name) \ | |
291 | BT_ASSERT_PRE(bt_field_is_set_recursive(_field), \ | |
292 | _name " is not set: %!+f", (_field)) | |
293 | ||
294 | #define BT_ASSERT_PRE_FIELD_HOT(_field, _name) \ | |
295 | BT_ASSERT_PRE_HOT((_field), (_name), ": +%!+f", (_field)) | |
296 | ||
50842bdc | 297 | struct bt_field *bt_field_create(struct bt_field_type *type) |
273b65be | 298 | { |
50842bdc PP |
299 | struct bt_field *field = NULL; |
300 | enum bt_field_type_id type_id; | |
273b65be | 301 | |
f6ccaed9 PP |
302 | BT_ASSERT_PRE_NON_NULL(type, "Field type"); |
303 | BT_ASSERT(field_type_has_known_id(type)); | |
304 | BT_ASSERT_PRE(bt_field_type_validate(type) == 0, | |
305 | "Field type is invalid: %!+F", type); | |
273b65be | 306 | |
50842bdc | 307 | type_id = bt_field_type_get_type_id(type); |
273b65be JG |
308 | field = field_create_funcs[type_id](type); |
309 | if (!field) { | |
310 | goto error; | |
311 | } | |
312 | ||
313 | /* The type's declaration can't change after this point */ | |
50842bdc | 314 | bt_field_type_freeze(type); |
83509119 | 315 | bt_get(type); |
50842bdc | 316 | bt_object_init(field, bt_field_destroy); |
273b65be JG |
317 | field->type = type; |
318 | error: | |
319 | return field; | |
320 | } | |
321 | ||
fc25abce | 322 | /* Pre-2.0 CTF writer backward compatibility */ |
50842bdc | 323 | void bt_ctf_field_get(struct bt_field *field) |
273b65be | 324 | { |
83509119 | 325 | bt_get(field); |
273b65be JG |
326 | } |
327 | ||
fc25abce | 328 | /* Pre-2.0 CTF writer backward compatibility */ |
50842bdc | 329 | void bt_ctf_field_put(struct bt_field *field) |
273b65be | 330 | { |
83509119 | 331 | bt_put(field); |
273b65be JG |
332 | } |
333 | ||
50842bdc | 334 | struct bt_field_type *bt_field_get_type(struct bt_field *field) |
cd95e351 | 335 | { |
50842bdc | 336 | struct bt_field_type *ret = NULL; |
cd95e351 | 337 | |
f6ccaed9 | 338 | BT_ASSERT_PRE_NON_NULL(field, "Field"); |
cd95e351 | 339 | ret = field->type; |
83509119 | 340 | bt_get(ret); |
cd95e351 JG |
341 | return ret; |
342 | } | |
343 | ||
50842bdc | 344 | enum bt_field_type_id bt_field_get_type_id(struct bt_field *field) |
4ebcc695 | 345 | { |
f6ccaed9 PP |
346 | BT_ASSERT_PRE_NON_NULL(field, "Field"); |
347 | return bt_field_type_get_type_id(field->type); | |
4ebcc695 PP |
348 | } |
349 | ||
50842bdc | 350 | bt_bool bt_field_is_integer(struct bt_field *field) |
8f3553be | 351 | { |
50842bdc | 352 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_INTEGER; |
8f3553be PP |
353 | } |
354 | ||
50842bdc | 355 | bt_bool bt_field_is_floating_point(struct bt_field *field) |
8f3553be | 356 | { |
50842bdc | 357 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_FLOAT; |
8f3553be PP |
358 | } |
359 | ||
50842bdc | 360 | bt_bool bt_field_is_enumeration(struct bt_field *field) |
8f3553be | 361 | { |
50842bdc | 362 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ENUM; |
8f3553be PP |
363 | } |
364 | ||
50842bdc | 365 | bt_bool bt_field_is_string(struct bt_field *field) |
8f3553be | 366 | { |
50842bdc | 367 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRING; |
8f3553be PP |
368 | } |
369 | ||
50842bdc | 370 | bt_bool bt_field_is_structure(struct bt_field *field) |
8f3553be | 371 | { |
50842bdc | 372 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_STRUCT; |
8f3553be PP |
373 | } |
374 | ||
50842bdc | 375 | bt_bool bt_field_is_array(struct bt_field *field) |
8f3553be | 376 | { |
50842bdc | 377 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_ARRAY; |
8f3553be PP |
378 | } |
379 | ||
50842bdc | 380 | bt_bool bt_field_is_sequence(struct bt_field *field) |
8f3553be | 381 | { |
50842bdc | 382 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_SEQUENCE; |
8f3553be PP |
383 | } |
384 | ||
50842bdc | 385 | bt_bool bt_field_is_variant(struct bt_field *field) |
8f3553be | 386 | { |
50842bdc | 387 | return bt_field_get_type_id(field) == BT_FIELD_TYPE_ID_VARIANT; |
8f3553be PP |
388 | } |
389 | ||
2e8876d3 PP |
390 | BT_HIDDEN |
391 | int64_t bt_field_sequence_get_int_length(struct bt_field *field) | |
392 | { | |
393 | struct bt_field_sequence *sequence; | |
394 | int64_t ret; | |
395 | ||
f6ccaed9 PP |
396 | BT_ASSERT(field); |
397 | BT_ASSERT(bt_field_type_get_type_id(field->type) == | |
2e8876d3 PP |
398 | BT_FIELD_TYPE_ID_SEQUENCE); |
399 | sequence = container_of(field, struct bt_field_sequence, parent); | |
400 | if (!sequence->length) { | |
401 | ret = -1; | |
402 | goto end; | |
403 | } | |
404 | ||
405 | ret = (int64_t) sequence->elements->len; | |
406 | ||
407 | end: | |
408 | return ret; | |
409 | } | |
410 | ||
50842bdc PP |
411 | struct bt_field *bt_field_sequence_get_length( |
412 | struct bt_field *field) | |
cd95e351 | 413 | { |
50842bdc PP |
414 | struct bt_field *ret = NULL; |
415 | struct bt_field_sequence *sequence; | |
cd95e351 | 416 | |
f6ccaed9 PP |
417 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
418 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
419 | "Field"); | |
50842bdc | 420 | sequence = container_of(field, struct bt_field_sequence, parent); |
cd95e351 | 421 | ret = sequence->length; |
83509119 | 422 | bt_get(ret); |
cd95e351 JG |
423 | return ret; |
424 | } | |
425 | ||
50842bdc PP |
426 | int bt_field_sequence_set_length(struct bt_field *field, |
427 | struct bt_field *length_field) | |
273b65be JG |
428 | { |
429 | int ret = 0; | |
50842bdc PP |
430 | struct bt_field_integer *length; |
431 | struct bt_field_sequence *sequence; | |
273b65be JG |
432 | uint64_t sequence_length; |
433 | ||
f6ccaed9 PP |
434 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
435 | BT_ASSERT_PRE_NON_NULL(length_field, "Length field"); | |
436 | BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field"); | |
437 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(length_field, BT_FIELD_TYPE_ID_INTEGER, | |
438 | "Length field"); | |
439 | BT_ASSERT_PRE(!bt_field_type_integer_is_signed(length_field->type), | |
440 | "Length field's type is signed: %!+f", length_field); | |
441 | BT_ASSERT_PRE_FIELD_IS_SET(length_field, "Length field"); | |
a54f72f0 | 442 | |
50842bdc | 443 | length = container_of(length_field, struct bt_field_integer, |
273b65be | 444 | parent); |
dc3fffef | 445 | sequence_length = length->payload.unsignd; |
50842bdc | 446 | sequence = container_of(field, struct bt_field_sequence, parent); |
273b65be JG |
447 | if (sequence->elements) { |
448 | g_ptr_array_free(sequence->elements, TRUE); | |
83509119 | 449 | bt_put(sequence->length); |
273b65be JG |
450 | } |
451 | ||
f6fcfe74 | 452 | sequence->elements = g_ptr_array_sized_new((size_t) sequence_length); |
273b65be | 453 | if (!sequence->elements) { |
fc25abce | 454 | BT_LOGE_STR("Failed to allocate a GPtrArray."); |
273b65be JG |
455 | ret = -1; |
456 | goto end; | |
457 | } | |
458 | ||
fe0fe95c | 459 | g_ptr_array_set_free_func(sequence->elements, |
83509119 JG |
460 | (GDestroyNotify) bt_put); |
461 | g_ptr_array_set_size(sequence->elements, (size_t) sequence_length); | |
462 | bt_get(length_field); | |
273b65be | 463 | sequence->length = length_field; |
f6ccaed9 PP |
464 | bt_field_freeze_recursive(length_field); |
465 | ||
273b65be JG |
466 | end: |
467 | return ret; | |
468 | } | |
469 | ||
50842bdc PP |
470 | struct bt_field *bt_field_structure_get_field_by_name( |
471 | struct bt_field *field, const char *name) | |
273b65be | 472 | { |
50842bdc | 473 | struct bt_field *ret = NULL; |
273b65be | 474 | GQuark field_quark; |
50842bdc | 475 | struct bt_field_structure *structure; |
273b65be | 476 | size_t index; |
c58b9c62 | 477 | GHashTable *field_name_to_index; |
273b65be | 478 | |
f6ccaed9 PP |
479 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); |
480 | BT_ASSERT_PRE_NON_NULL(name, "Field name"); | |
481 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
c58b9c62 | 482 | field_name_to_index = |
50842bdc | 483 | container_of(field->type, struct bt_field_type_structure, |
c58b9c62 | 484 | parent)->field_name_to_index; |
273b65be | 485 | field_quark = g_quark_from_string(name); |
50842bdc | 486 | structure = container_of(field, struct bt_field_structure, parent); |
c58b9c62 | 487 | if (!g_hash_table_lookup_extended(field_name_to_index, |
fc25abce PP |
488 | GUINT_TO_POINTER(field_quark), |
489 | NULL, (gpointer *)&index)) { | |
6fa8d37b | 490 | BT_LOGV("Invalid parameter: no such field in structure field's type: " |
c58b9c62 JG |
491 | "struct-field-addr=%p, struct-ft-addr=%p, name=\"%s\"", |
492 | field, field->type, name); | |
273b65be JG |
493 | goto error; |
494 | } | |
495 | ||
c58b9c62 | 496 | ret = bt_get(structure->fields->pdata[index]); |
f6ccaed9 PP |
497 | BT_ASSERT(ret); |
498 | ||
273b65be | 499 | error: |
c58b9c62 | 500 | return ret; |
273b65be JG |
501 | } |
502 | ||
50842bdc PP |
503 | struct bt_field *bt_field_structure_get_field_by_index( |
504 | struct bt_field *field, uint64_t index) | |
cd95e351 | 505 | { |
50842bdc PP |
506 | struct bt_field_structure *structure; |
507 | struct bt_field *ret = NULL; | |
cd95e351 | 508 | |
f6ccaed9 PP |
509 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); |
510 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, "Field"); | |
511 | structure = container_of(field, struct bt_field_structure, parent); | |
512 | BT_ASSERT_PRE(index < structure->fields->len, | |
513 | "Index is out of bound: %![struct-field-]+f, " | |
514 | "index=%" PRIu64 ", count=%u", field, index, | |
515 | structure->fields->len); | |
516 | ret = bt_get(structure->fields->pdata[index]); | |
517 | return ret; | |
518 | } | |
fc25abce | 519 | |
f6ccaed9 PP |
520 | BT_ASSERT_PRE_FUNC |
521 | static inline bool field_to_set_has_expected_type(struct bt_field *struct_field, | |
522 | const char *name, struct bt_field *value) | |
523 | { | |
524 | bool ret = true; | |
525 | struct bt_field_type *expected_field_type = NULL; | |
cd95e351 | 526 | |
f6ccaed9 PP |
527 | expected_field_type = |
528 | bt_field_type_structure_get_field_type_by_name( | |
529 | struct_field->type, name); | |
530 | ||
531 | if (bt_field_type_compare(expected_field_type, value->type)) { | |
532 | BT_ASSERT_PRE_MSG("Value field's type is different from the expected field type: " | |
533 | "%![value-ft-]+F, %![expected-ft-]+F", value->type, | |
534 | expected_field_type); | |
535 | ret = false; | |
918be005 PP |
536 | goto end; |
537 | } | |
538 | ||
cd95e351 | 539 | end: |
f6ccaed9 | 540 | bt_put(expected_field_type); |
c58b9c62 | 541 | return ret; |
cd95e351 JG |
542 | } |
543 | ||
50842bdc PP |
544 | int bt_field_structure_set_field_by_name(struct bt_field *field, |
545 | const char *name, struct bt_field *value) | |
273b65be JG |
546 | { |
547 | int ret = 0; | |
548 | GQuark field_quark; | |
50842bdc | 549 | struct bt_field_structure *structure; |
273b65be | 550 | size_t index; |
c58b9c62 | 551 | GHashTable *field_name_to_index; |
273b65be | 552 | |
f6ccaed9 PP |
553 | BT_ASSERT_PRE_NON_NULL(field, "Structure field"); |
554 | BT_ASSERT_PRE_NON_NULL(name, "Field name"); | |
555 | BT_ASSERT_PRE_NON_NULL(value, "Value field"); | |
556 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRUCT, | |
557 | "Parent field"); | |
558 | BT_ASSERT_PRE(field_to_set_has_expected_type(field, name, value), | |
559 | "Value field's type is different from the expected field type."); | |
273b65be | 560 | field_quark = g_quark_from_string(name); |
50842bdc | 561 | structure = container_of(field, struct bt_field_structure, parent); |
c58b9c62 | 562 | field_name_to_index = |
50842bdc | 563 | container_of(field->type, struct bt_field_type_structure, |
c58b9c62 JG |
564 | parent)->field_name_to_index; |
565 | if (!g_hash_table_lookup_extended(field_name_to_index, | |
566 | GUINT_TO_POINTER(field_quark), NULL, | |
567 | (gpointer *) &index)) { | |
6fa8d37b | 568 | BT_LOGV("Invalid parameter: no such field in structure field's type: " |
fc25abce PP |
569 | "struct-field-addr=%p, struct-ft-addr=%p, " |
570 | "field-ft-addr=%p, name=\"%s\"", | |
571 | field, field->type, value->type, name); | |
572 | ret = -1; | |
273b65be JG |
573 | goto end; |
574 | } | |
83509119 | 575 | bt_get(value); |
c58b9c62 | 576 | BT_MOVE(structure->fields->pdata[index], value); |
f6ccaed9 | 577 | |
273b65be JG |
578 | end: |
579 | return ret; | |
580 | } | |
581 | ||
50842bdc | 582 | struct bt_field *bt_field_array_get_field(struct bt_field *field, |
273b65be JG |
583 | uint64_t index) |
584 | { | |
50842bdc PP |
585 | struct bt_field *new_field = NULL; |
586 | struct bt_field_type *field_type = NULL; | |
587 | struct bt_field_array *array; | |
273b65be | 588 | |
f6ccaed9 PP |
589 | BT_ASSERT_PRE_NON_NULL(field, "Array field"); |
590 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ARRAY, "Field"); | |
50842bdc | 591 | array = container_of(field, struct bt_field_array, parent); |
f6ccaed9 PP |
592 | BT_ASSERT_PRE(index < array->elements->len, |
593 | "Index is out of bound: %![array-field-]+f, " | |
594 | "index=%" PRIu64 ", count=%u", field, | |
595 | index, array->elements->len); | |
273b65be | 596 | |
50842bdc | 597 | field_type = bt_field_type_array_get_element_type(field->type); |
f6ccaed9 PP |
598 | if (array->elements->pdata[(size_t) index]) { |
599 | new_field = array->elements->pdata[(size_t) index]; | |
273b65be JG |
600 | goto end; |
601 | } | |
602 | ||
918be005 | 603 | /* We don't want to modify this field if it's frozen */ |
f6ccaed9 | 604 | BT_ASSERT_PRE_FIELD_HOT(field, "Array field"); |
50842bdc | 605 | new_field = bt_field_create(field_type); |
273b65be | 606 | array->elements->pdata[(size_t)index] = new_field; |
f6ccaed9 | 607 | |
273b65be | 608 | end: |
f6ccaed9 PP |
609 | bt_put(field_type); |
610 | bt_get(new_field); | |
273b65be JG |
611 | return new_field; |
612 | } | |
613 | ||
50842bdc | 614 | struct bt_field *bt_field_sequence_get_field(struct bt_field *field, |
273b65be JG |
615 | uint64_t index) |
616 | { | |
50842bdc PP |
617 | struct bt_field *new_field = NULL; |
618 | struct bt_field_type *field_type = NULL; | |
619 | struct bt_field_sequence *sequence; | |
273b65be | 620 | |
f6ccaed9 PP |
621 | BT_ASSERT_PRE_NON_NULL(field, "Sequence field"); |
622 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_SEQUENCE, | |
623 | "Field"); | |
50842bdc | 624 | sequence = container_of(field, struct bt_field_sequence, parent); |
f6ccaed9 PP |
625 | BT_ASSERT_PRE_NON_NULL(sequence->elements, "Sequence field's element array"); |
626 | BT_ASSERT_PRE(index < sequence->elements->len, | |
627 | "Index is out of bound: %![seq-field-]+f, " | |
628 | "index=%" PRIu64 ", count=%u", field, index, | |
629 | sequence->elements->len); | |
50842bdc | 630 | field_type = bt_field_type_sequence_get_element_type(field->type); |
83509119 JG |
631 | if (sequence->elements->pdata[(size_t) index]) { |
632 | new_field = sequence->elements->pdata[(size_t) index]; | |
273b65be JG |
633 | goto end; |
634 | } | |
635 | ||
918be005 | 636 | /* We don't want to modify this field if it's frozen */ |
f6ccaed9 | 637 | BT_ASSERT_PRE_FIELD_HOT(field, "Sequence field"); |
50842bdc | 638 | new_field = bt_field_create(field_type); |
83509119 | 639 | sequence->elements->pdata[(size_t) index] = new_field; |
f6ccaed9 | 640 | |
273b65be | 641 | end: |
f6ccaed9 PP |
642 | bt_put(field_type); |
643 | bt_get(new_field); | |
273b65be JG |
644 | return new_field; |
645 | } | |
646 | ||
50842bdc PP |
647 | struct bt_field *bt_field_variant_get_field(struct bt_field *field, |
648 | struct bt_field *tag_field) | |
273b65be | 649 | { |
50842bdc PP |
650 | struct bt_field *new_field = NULL; |
651 | struct bt_field_variant *variant; | |
652 | struct bt_field_type_variant *variant_type; | |
653 | struct bt_field_type *field_type; | |
654 | struct bt_field *tag_enum = NULL; | |
655 | struct bt_field_integer *tag_enum_integer; | |
273b65be JG |
656 | int64_t tag_enum_value; |
657 | ||
f6ccaed9 PP |
658 | BT_ASSERT_PRE_NON_NULL(field, "Variant field"); |
659 | BT_ASSERT_PRE_NON_NULL(tag_field, "Tag field"); | |
660 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_VARIANT, | |
661 | "Variant field"); | |
662 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(tag_field, BT_FIELD_TYPE_ID_ENUM, | |
663 | "Tag field"); | |
50842bdc | 664 | variant = container_of(field, struct bt_field_variant, parent); |
273b65be | 665 | variant_type = container_of(field->type, |
50842bdc PP |
666 | struct bt_field_type_variant, parent); |
667 | tag_enum = bt_field_enumeration_get_container(tag_field); | |
f6ccaed9 | 668 | BT_ASSERT_PRE_NON_NULL(tag_enum, "Tag field's container"); |
50842bdc | 669 | tag_enum_integer = container_of(tag_enum, struct bt_field_integer, |
273b65be | 670 | parent); |
f6ccaed9 PP |
671 | BT_ASSERT_PRE(bt_field_validate_recursive(tag_field) == 0, |
672 | "Tag field is invalid: %!+f", tag_field); | |
dc3fffef | 673 | tag_enum_value = tag_enum_integer->payload.signd; |
2829190c PP |
674 | |
675 | /* | |
676 | * If the variant currently has a tag and a payload, and if the | |
677 | * requested tag value is the same as the current one, return | |
678 | * the current payload instead of creating a fresh one. | |
679 | */ | |
680 | if (variant->tag && variant->payload) { | |
50842bdc PP |
681 | struct bt_field *cur_tag_container = NULL; |
682 | struct bt_field_integer *cur_tag_enum_integer; | |
2829190c PP |
683 | int64_t cur_tag_value; |
684 | ||
685 | cur_tag_container = | |
50842bdc | 686 | bt_field_enumeration_get_container(variant->tag); |
f6ccaed9 | 687 | BT_ASSERT(cur_tag_container); |
2829190c | 688 | cur_tag_enum_integer = container_of(cur_tag_container, |
50842bdc | 689 | struct bt_field_integer, parent); |
83509119 | 690 | bt_put(cur_tag_container); |
dc3fffef | 691 | cur_tag_value = cur_tag_enum_integer->payload.signd; |
2829190c PP |
692 | |
693 | if (cur_tag_value == tag_enum_value) { | |
694 | new_field = variant->payload; | |
83509119 | 695 | bt_get(new_field); |
2829190c PP |
696 | goto end; |
697 | } | |
698 | } | |
699 | ||
918be005 | 700 | /* We don't want to modify this field if it's frozen */ |
f6ccaed9 | 701 | BT_ASSERT_PRE_FIELD_HOT(field, "Variant field"); |
50842bdc | 702 | field_type = bt_field_type_variant_get_field_type_signed( |
b92ddaaa | 703 | variant_type, tag_enum_value); |
f6ccaed9 PP |
704 | |
705 | /* It's the caller's job to make sure the tag's value is valid */ | |
706 | BT_ASSERT_PRE(field_type, | |
707 | "Variant field's type does not contain a field type for " | |
708 | "this tag value: tag-value-signed=%" PRId64 ", " | |
709 | "%![var-ft-]+F, %![tag-field-]+f", tag_enum_value, | |
710 | variant_type, tag_field); | |
273b65be | 711 | |
50842bdc | 712 | new_field = bt_field_create(field_type); |
273b65be | 713 | if (!new_field) { |
fc25abce PP |
714 | BT_LOGW("Cannot create field: " |
715 | "variant-field-addr=%p, variant-ft-addr=%p, " | |
716 | "field-ft-addr=%p", field, field->type, field_type); | |
273b65be JG |
717 | goto end; |
718 | } | |
719 | ||
83509119 JG |
720 | bt_put(variant->tag); |
721 | bt_put(variant->payload); | |
722 | bt_get(new_field); | |
723 | bt_get(tag_field); | |
273b65be JG |
724 | variant->tag = tag_field; |
725 | variant->payload = new_field; | |
f6ccaed9 | 726 | |
273b65be | 727 | end: |
83509119 | 728 | bt_put(tag_enum); |
273b65be JG |
729 | return new_field; |
730 | } | |
731 | ||
50842bdc PP |
732 | struct bt_field *bt_field_variant_get_current_field( |
733 | struct bt_field *variant_field) | |
3f4a108d | 734 | { |
50842bdc | 735 | struct bt_field_variant *variant; |
3f4a108d | 736 | |
f6ccaed9 PP |
737 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
738 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT, | |
739 | "Field"); | |
50842bdc | 740 | variant = container_of(variant_field, struct bt_field_variant, |
3f4a108d | 741 | parent); |
f6ccaed9 | 742 | return bt_get(variant->payload); |
3f4a108d PP |
743 | } |
744 | ||
f6ccaed9 | 745 | struct bt_field *bt_field_variant_get_tag(struct bt_field *variant_field) |
f78d67fb | 746 | { |
50842bdc | 747 | struct bt_field_variant *variant; |
f78d67fb | 748 | |
f6ccaed9 PP |
749 | BT_ASSERT_PRE_NON_NULL(variant_field, "Variant field"); |
750 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(variant_field, BT_FIELD_TYPE_ID_VARIANT, | |
751 | "Field"); | |
50842bdc | 752 | variant = container_of(variant_field, struct bt_field_variant, |
f78d67fb | 753 | parent); |
f6ccaed9 | 754 | return bt_get(variant->tag); |
f78d67fb JG |
755 | } |
756 | ||
f6ccaed9 | 757 | struct bt_field *bt_field_enumeration_get_container(struct bt_field *field) |
273b65be | 758 | { |
50842bdc PP |
759 | struct bt_field *container = NULL; |
760 | struct bt_field_enumeration *enumeration; | |
273b65be | 761 | |
f6ccaed9 PP |
762 | BT_ASSERT_PRE_NON_NULL(field, "Enumeration field"); |
763 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field"); | |
50842bdc | 764 | enumeration = container_of(field, struct bt_field_enumeration, |
273b65be JG |
765 | parent); |
766 | if (!enumeration->payload) { | |
f6ccaed9 PP |
767 | struct bt_field_type_enumeration *enumeration_type; |
768 | ||
918be005 | 769 | /* We don't want to modify this field if it's frozen */ |
f6ccaed9 | 770 | BT_ASSERT_PRE_FIELD_HOT(field, "Enumeration field"); |
918be005 | 771 | |
f6ccaed9 | 772 | enumeration_type = container_of(field->type, |
50842bdc | 773 | struct bt_field_type_enumeration, parent); |
273b65be | 774 | enumeration->payload = |
50842bdc | 775 | bt_field_create(enumeration_type->container); |
273b65be JG |
776 | } |
777 | ||
778 | container = enumeration->payload; | |
f6ccaed9 | 779 | return bt_get(container); |
273b65be JG |
780 | } |
781 | ||
50842bdc PP |
782 | struct bt_field_type_enumeration_mapping_iterator * |
783 | bt_field_enumeration_get_mappings(struct bt_field *field) | |
cd95e351 JG |
784 | { |
785 | int ret; | |
50842bdc | 786 | struct bt_field *container = NULL; |
50842bdc PP |
787 | struct bt_field_type_integer *integer_type = NULL; |
788 | struct bt_field_type_enumeration_mapping_iterator *iter = NULL; | |
cd95e351 | 789 | |
f6ccaed9 PP |
790 | BT_ASSERT_PRE_NON_NULL(field, "Enumeration field"); |
791 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_ENUM, "Field"); | |
50842bdc | 792 | container = bt_field_enumeration_get_container(field); |
f6ccaed9 PP |
793 | BT_ASSERT_PRE(container, |
794 | "Enumeration field has no container field: %!+f", field); | |
795 | BT_ASSERT(container->type); | |
796 | integer_type = container_of(container->type, | |
50842bdc | 797 | struct bt_field_type_integer, parent); |
f6ccaed9 PP |
798 | BT_ASSERT_PRE_FIELD_IS_SET(container, |
799 | "Enumeration field's payload field"); | |
cd95e351 | 800 | |
dc3fffef | 801 | if (!integer_type->is_signed) { |
cd95e351 | 802 | uint64_t value; |
96e8f959 | 803 | |
f6ccaed9 PP |
804 | ret = bt_field_unsigned_integer_get_value(container, &value); |
805 | BT_ASSERT(ret == 0); | |
50842bdc | 806 | iter = bt_field_type_enumeration_find_mappings_by_unsigned_value( |
96e8f959 | 807 | field->type, value); |
cd95e351 JG |
808 | } else { |
809 | int64_t value; | |
96e8f959 | 810 | |
f6ccaed9 PP |
811 | ret = bt_field_signed_integer_get_value(container, &value); |
812 | BT_ASSERT(ret == 0); | |
50842bdc | 813 | iter = bt_field_type_enumeration_find_mappings_by_signed_value( |
96e8f959 | 814 | field->type, value); |
cd95e351 JG |
815 | } |
816 | ||
83509119 | 817 | bt_put(container); |
e0f15669 | 818 | return iter; |
cd95e351 JG |
819 | } |
820 | ||
f6ccaed9 | 821 | int bt_field_signed_integer_get_value(struct bt_field *field, int64_t *value) |
cd95e351 | 822 | { |
50842bdc PP |
823 | struct bt_field_integer *integer; |
824 | struct bt_field_type_integer *integer_type; | |
cd95e351 | 825 | |
f6ccaed9 PP |
826 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); |
827 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
828 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field"); | |
829 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
cd95e351 | 830 | integer_type = container_of(field->type, |
50842bdc | 831 | struct bt_field_type_integer, parent); |
f6ccaed9 PP |
832 | BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type), |
833 | "Field's type is unsigned: %!+f", field); | |
cd95e351 | 834 | integer = container_of(field, |
50842bdc | 835 | struct bt_field_integer, parent); |
dc3fffef | 836 | *value = integer->payload.signd; |
f6ccaed9 | 837 | return 0; |
cd95e351 JG |
838 | } |
839 | ||
f6ccaed9 PP |
840 | BT_ASSERT_PRE_FUNC |
841 | static inline bool value_is_in_range_signed(unsigned int size, int64_t value) | |
273b65be | 842 | { |
f6ccaed9 | 843 | bool ret = true; |
273b65be JG |
844 | int64_t min_value, max_value; |
845 | ||
9dc0d640 JG |
846 | min_value = -(1ULL << (size - 1)); |
847 | max_value = (1ULL << (size - 1)) - 1; | |
273b65be | 848 | if (value < min_value || value > max_value) { |
f6ccaed9 | 849 | BT_LOGF("Value is out of bounds: value=%" PRId64 ", " |
fc25abce | 850 | "min-value=%" PRId64 ", max-value=%" PRId64, |
f6ccaed9 PP |
851 | value, min_value, max_value); |
852 | ret = false; | |
273b65be JG |
853 | } |
854 | ||
273b65be JG |
855 | return ret; |
856 | } | |
857 | ||
f6ccaed9 | 858 | int bt_field_signed_integer_set_value(struct bt_field *field, int64_t value) |
cd95e351 JG |
859 | { |
860 | int ret = 0; | |
50842bdc PP |
861 | struct bt_field_integer *integer; |
862 | struct bt_field_type_integer *integer_type; | |
cd95e351 | 863 | |
f6ccaed9 PP |
864 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); |
865 | BT_ASSERT_PRE_FIELD_HOT(field, "Integer field"); | |
866 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
867 | integer = container_of(field, struct bt_field_integer, parent); | |
cd95e351 | 868 | integer_type = container_of(field->type, |
50842bdc | 869 | struct bt_field_type_integer, parent); |
f6ccaed9 PP |
870 | BT_ASSERT_PRE(bt_field_type_integer_is_signed(field->type), |
871 | "Field's type is unsigned: %!+f", field); | |
872 | BT_ASSERT_PRE(value_is_in_range_signed(integer_type->size, value), | |
873 | "Value is out of bounds: value=%" PRId64 ", %![field-]+f", | |
874 | value, field); | |
875 | integer->payload.signd = value; | |
876 | bt_field_set(field, true); | |
cd95e351 JG |
877 | return ret; |
878 | } | |
879 | ||
f6ccaed9 | 880 | int bt_field_unsigned_integer_get_value(struct bt_field *field, uint64_t *value) |
273b65be | 881 | { |
50842bdc PP |
882 | struct bt_field_integer *integer; |
883 | struct bt_field_type_integer *integer_type; | |
fc25abce | 884 | |
f6ccaed9 PP |
885 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); |
886 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
887 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field"); | |
888 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
273b65be | 889 | integer_type = container_of(field->type, |
50842bdc | 890 | struct bt_field_type_integer, parent); |
f6ccaed9 PP |
891 | BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type), |
892 | "Field's type is signed: %!+f", field); | |
893 | integer = container_of(field, struct bt_field_integer, parent); | |
894 | *value = integer->payload.unsignd; | |
895 | return 0; | |
896 | } | |
897 | ||
898 | BT_ASSERT_PRE_FUNC | |
899 | static inline bool value_is_in_range_unsigned(unsigned int size, uint64_t value) | |
900 | { | |
901 | bool ret = true; | |
902 | int64_t max_value; | |
273b65be | 903 | |
8684abc8 | 904 | max_value = (size == 64) ? UINT64_MAX : ((uint64_t) 1 << size) - 1; |
273b65be | 905 | if (value > max_value) { |
f6ccaed9 PP |
906 | BT_LOGF("Value is out of bounds: value=%" PRIu64 ", " |
907 | "max-value=%" PRIu64, | |
908 | value, max_value); | |
909 | ret = false; | |
273b65be JG |
910 | } |
911 | ||
273b65be JG |
912 | return ret; |
913 | } | |
914 | ||
f6ccaed9 | 915 | int bt_field_unsigned_integer_set_value(struct bt_field *field, uint64_t value) |
cd95e351 | 916 | { |
f6ccaed9 PP |
917 | struct bt_field_integer *integer; |
918 | struct bt_field_type_integer *integer_type; | |
fc25abce | 919 | |
f6ccaed9 PP |
920 | BT_ASSERT_PRE_NON_NULL(field, "Integer field"); |
921 | BT_ASSERT_PRE_FIELD_HOT(field, "Integer field"); | |
922 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_INTEGER, "Field"); | |
923 | integer = container_of(field, struct bt_field_integer, parent); | |
924 | integer_type = container_of(field->type, | |
925 | struct bt_field_type_integer, parent); | |
926 | BT_ASSERT_PRE(!bt_field_type_integer_is_signed(field->type), | |
927 | "Field's type is signed: %!+f", field); | |
928 | BT_ASSERT_PRE(value_is_in_range_unsigned(integer_type->size, value), | |
929 | "Value is out of bounds: value=%" PRIu64 ", %![field-]+f", | |
930 | value, field); | |
931 | integer->payload.unsignd = value; | |
932 | bt_field_set(field, true); | |
933 | return 0; | |
934 | } | |
fc25abce | 935 | |
f6ccaed9 PP |
936 | int bt_field_floating_point_get_value(struct bt_field *field, double *value) |
937 | { | |
938 | struct bt_field_floating_point *floating_point; | |
cd95e351 | 939 | |
f6ccaed9 PP |
940 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); |
941 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
942 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field"); | |
943 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
cd95e351 | 944 | floating_point = container_of(field, |
50842bdc | 945 | struct bt_field_floating_point, parent); |
dc3fffef | 946 | *value = floating_point->payload; |
f6ccaed9 | 947 | return 0; |
cd95e351 JG |
948 | } |
949 | ||
f6ccaed9 | 950 | int bt_field_floating_point_set_value(struct bt_field *field, double value) |
273b65be | 951 | { |
50842bdc | 952 | struct bt_field_floating_point *floating_point; |
273b65be | 953 | |
f6ccaed9 PP |
954 | BT_ASSERT_PRE_NON_NULL(field, "Floating point number field"); |
955 | BT_ASSERT_PRE_FIELD_HOT(field, "Floating point number field"); | |
956 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_FLOAT, "Field"); | |
50842bdc | 957 | floating_point = container_of(field, struct bt_field_floating_point, |
273b65be | 958 | parent); |
dc3fffef | 959 | floating_point->payload = value; |
f6ccaed9 PP |
960 | bt_field_set(field, true); |
961 | return 0; | |
273b65be JG |
962 | } |
963 | ||
50842bdc | 964 | const char *bt_field_string_get_value(struct bt_field *field) |
cd95e351 | 965 | { |
50842bdc | 966 | struct bt_field_string *string; |
cd95e351 | 967 | |
f6ccaed9 PP |
968 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
969 | BT_ASSERT_PRE_FIELD_IS_SET(field, "String field"); | |
970 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field"); | |
971 | string = container_of(field, struct bt_field_string, parent); | |
972 | return string->payload->str; | |
cd95e351 JG |
973 | } |
974 | ||
f6ccaed9 | 975 | int bt_field_string_set_value(struct bt_field *field, const char *value) |
273b65be | 976 | { |
50842bdc | 977 | struct bt_field_string *string; |
273b65be | 978 | |
f6ccaed9 PP |
979 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
980 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
981 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
982 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field"); | |
50842bdc | 983 | string = container_of(field, struct bt_field_string, parent); |
273b65be | 984 | if (string->payload) { |
97736814 JG |
985 | g_string_assign(string->payload, value); |
986 | } else { | |
987 | string->payload = g_string_new(value); | |
273b65be JG |
988 | } |
989 | ||
f6ccaed9 PP |
990 | bt_field_set(field, true); |
991 | return 0; | |
273b65be JG |
992 | } |
993 | ||
f6ccaed9 | 994 | int bt_field_string_append(struct bt_field *field, const char *value) |
c6f9c5a3 | 995 | { |
50842bdc | 996 | struct bt_field_string *string_field; |
c6f9c5a3 | 997 | |
f6ccaed9 PP |
998 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
999 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
1000 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
1001 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field"); | |
50842bdc | 1002 | string_field = container_of(field, struct bt_field_string, parent); |
c6f9c5a3 PP |
1003 | if (string_field->payload) { |
1004 | g_string_append(string_field->payload, value); | |
1005 | } else { | |
1006 | string_field->payload = g_string_new(value); | |
1007 | } | |
1008 | ||
f6ccaed9 PP |
1009 | bt_field_set(field, true); |
1010 | return 0; | |
c6f9c5a3 PP |
1011 | } |
1012 | ||
f6ccaed9 PP |
1013 | int bt_field_string_append_len(struct bt_field *field, const char *value, |
1014 | unsigned int length) | |
f98c6554 | 1015 | { |
50842bdc | 1016 | struct bt_field_string *string_field; |
f98c6554 | 1017 | |
f6ccaed9 PP |
1018 | BT_ASSERT_PRE_NON_NULL(field, "String field"); |
1019 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
1020 | BT_ASSERT_PRE_FIELD_HOT(field, "String field"); | |
1021 | BT_ASSERT_PRE_FIELD_HAS_TYPE_ID(field, BT_FIELD_TYPE_ID_STRING, "Field"); | |
50842bdc | 1022 | string_field = container_of(field, struct bt_field_string, parent); |
f98c6554 PP |
1023 | |
1024 | /* make sure no null bytes are appended */ | |
f6ccaed9 PP |
1025 | BT_ASSERT_PRE(memchr(value, '\0', length) == NULL, |
1026 | "String value to append contains a null character: " | |
1027 | "partial-value=\"%.32s\", length=%u", value, length); | |
f98c6554 PP |
1028 | |
1029 | if (string_field->payload) { | |
f6ccaed9 | 1030 | g_string_append_len(string_field->payload, value, length); |
f98c6554 | 1031 | } else { |
f6ccaed9 | 1032 | string_field->payload = g_string_new_len(value, length); |
f98c6554 PP |
1033 | } |
1034 | ||
f6ccaed9 PP |
1035 | bt_field_set(field, true); |
1036 | return 0; | |
f98c6554 PP |
1037 | } |
1038 | ||
273b65be | 1039 | BT_HIDDEN |
f6ccaed9 | 1040 | int _bt_field_validate_recursive(struct bt_field *field) |
273b65be JG |
1041 | { |
1042 | int ret = 0; | |
50842bdc | 1043 | enum bt_field_type_id type_id; |
273b65be JG |
1044 | |
1045 | if (!field) { | |
f6ccaed9 | 1046 | BT_ASSERT_PRE_MSG("%s", "Invalid field: field is NULL."); |
273b65be JG |
1047 | ret = -1; |
1048 | goto end; | |
1049 | } | |
1050 | ||
f6ccaed9 | 1051 | BT_ASSERT(field_type_has_known_id(field->type)); |
50842bdc | 1052 | type_id = bt_field_type_get_type_id(field->type); |
273b65be | 1053 | ret = field_validate_funcs[type_id](field); |
f6ccaed9 | 1054 | |
273b65be JG |
1055 | end: |
1056 | return ret; | |
1057 | } | |
1058 | ||
f6ccaed9 PP |
1059 | BT_HIDDEN |
1060 | void _bt_field_reset_recursive(struct bt_field *field) | |
1061 | { BT_ASSERT(field); | |
1062 | field_reset_funcs[field->type->id](field); | |
1063 | } | |
12c8a1a3 | 1064 | |
f6ccaed9 PP |
1065 | BT_HIDDEN |
1066 | void _bt_field_set(struct bt_field *field, bool value) | |
1067 | { | |
1068 | BT_ASSERT(field); | |
1069 | field->payload_set = value; | |
12c8a1a3 JG |
1070 | } |
1071 | ||
273b65be | 1072 | BT_HIDDEN |
f6ccaed9 | 1073 | int bt_field_serialize_recursive(struct bt_field *field, struct bt_stream_pos *pos, |
50842bdc | 1074 | enum bt_byte_order native_byte_order) |
273b65be | 1075 | { |
50842bdc | 1076 | enum bt_field_type_id type_id; |
273b65be | 1077 | |
f6ccaed9 PP |
1078 | BT_ASSERT(pos); |
1079 | BT_ASSERT_PRE_NON_NULL(field, "Field"); | |
1080 | BT_ASSERT(field_type_has_known_id(field->type)); | |
50842bdc | 1081 | type_id = bt_field_type_get_type_id(field->type); |
f6ccaed9 | 1082 | return field_serialize_funcs[type_id](field, pos, native_byte_order); |
273b65be JG |
1083 | } |
1084 | ||
f6ccaed9 PP |
1085 | BT_HIDDEN |
1086 | bt_bool _bt_field_is_set_recursive(struct bt_field *field) | |
76f869ab | 1087 | { |
d4bf905a | 1088 | bt_bool is_set = BT_FALSE; |
50842bdc | 1089 | enum bt_field_type_id type_id; |
76f869ab JG |
1090 | |
1091 | if (!field) { | |
1092 | goto end; | |
1093 | } | |
1094 | ||
f6ccaed9 | 1095 | BT_ASSERT(field_type_has_known_id(field->type)); |
50842bdc | 1096 | type_id = bt_field_type_get_type_id(field->type); |
d4bf905a | 1097 | is_set = field_is_set_funcs[type_id](field); |
f6ccaed9 | 1098 | |
76f869ab | 1099 | end: |
d4bf905a | 1100 | return is_set; |
76f869ab JG |
1101 | } |
1102 | ||
50842bdc | 1103 | struct bt_field *bt_field_copy(struct bt_field *field) |
87d43dc1 JG |
1104 | { |
1105 | int ret; | |
50842bdc PP |
1106 | struct bt_field *copy = NULL; |
1107 | enum bt_field_type_id type_id; | |
87d43dc1 | 1108 | |
f6ccaed9 PP |
1109 | BT_ASSERT_PRE_NON_NULL(field, "Field"); |
1110 | BT_ASSERT(field_type_has_known_id(field->type)); | |
50842bdc | 1111 | copy = bt_field_create(field->type); |
87d43dc1 | 1112 | if (!copy) { |
fc25abce | 1113 | BT_LOGW("Cannot create field: ft-addr=%p", field->type); |
87d43dc1 JG |
1114 | goto end; |
1115 | } | |
1116 | ||
f6ccaed9 PP |
1117 | bt_field_set(copy, field->payload_set); |
1118 | type_id = bt_field_type_get_type_id(field->type); | |
87d43dc1 JG |
1119 | ret = field_copy_funcs[type_id](field, copy); |
1120 | if (ret) { | |
f6ccaed9 | 1121 | BT_PUT(copy); |
87d43dc1 | 1122 | } |
f6ccaed9 | 1123 | |
87d43dc1 JG |
1124 | end: |
1125 | return copy; | |
1126 | } | |
1127 | ||
273b65be | 1128 | static |
50842bdc | 1129 | struct bt_field *bt_field_integer_create(struct bt_field_type *type) |
273b65be | 1130 | { |
50842bdc PP |
1131 | struct bt_field_integer *integer = g_new0( |
1132 | struct bt_field_integer, 1); | |
273b65be | 1133 | |
fc25abce PP |
1134 | BT_LOGD("Creating integer field object: ft-addr=%p", type); |
1135 | ||
1136 | if (integer) { | |
1137 | BT_LOGD("Created integer field object: addr=%p, ft-addr=%p", | |
1138 | &integer->parent, type); | |
1139 | } else { | |
1140 | BT_LOGE_STR("Failed to allocate one integer field."); | |
1141 | } | |
1142 | ||
273b65be JG |
1143 | return integer ? &integer->parent : NULL; |
1144 | } | |
1145 | ||
1146 | static | |
50842bdc PP |
1147 | struct bt_field *bt_field_enumeration_create( |
1148 | struct bt_field_type *type) | |
273b65be | 1149 | { |
50842bdc PP |
1150 | struct bt_field_enumeration *enumeration = g_new0( |
1151 | struct bt_field_enumeration, 1); | |
273b65be | 1152 | |
fc25abce PP |
1153 | BT_LOGD("Creating enumeration field object: ft-addr=%p", type); |
1154 | ||
1155 | if (enumeration) { | |
1156 | BT_LOGD("Created enumeration field object: addr=%p, ft-addr=%p", | |
1157 | &enumeration->parent, type); | |
1158 | } else { | |
1159 | BT_LOGE_STR("Failed to allocate one enumeration field."); | |
1160 | } | |
1161 | ||
273b65be JG |
1162 | return enumeration ? &enumeration->parent : NULL; |
1163 | } | |
1164 | ||
1165 | static | |
50842bdc PP |
1166 | struct bt_field *bt_field_floating_point_create( |
1167 | struct bt_field_type *type) | |
273b65be | 1168 | { |
50842bdc | 1169 | struct bt_field_floating_point *floating_point; |
273b65be | 1170 | |
fc25abce | 1171 | BT_LOGD("Creating floating point number field object: ft-addr=%p", type); |
50842bdc | 1172 | floating_point = g_new0(struct bt_field_floating_point, 1); |
fc25abce PP |
1173 | |
1174 | if (floating_point) { | |
1175 | BT_LOGD("Created floating point number field object: addr=%p, ft-addr=%p", | |
1176 | &floating_point->parent, type); | |
1177 | } else { | |
1178 | BT_LOGE_STR("Failed to allocate one floating point number field."); | |
1179 | } | |
1180 | ||
273b65be JG |
1181 | return floating_point ? &floating_point->parent : NULL; |
1182 | } | |
1183 | ||
1184 | static | |
50842bdc PP |
1185 | struct bt_field *bt_field_structure_create( |
1186 | struct bt_field_type *type) | |
273b65be | 1187 | { |
50842bdc PP |
1188 | struct bt_field_type_structure *structure_type = container_of(type, |
1189 | struct bt_field_type_structure, parent); | |
1190 | struct bt_field_structure *structure = g_new0( | |
1191 | struct bt_field_structure, 1); | |
1192 | struct bt_field *ret = NULL; | |
c58b9c62 | 1193 | size_t i; |
273b65be | 1194 | |
fc25abce PP |
1195 | BT_LOGD("Creating structure field object: ft-addr=%p", type); |
1196 | ||
8c1aa858 | 1197 | if (!structure) { |
fc25abce | 1198 | BT_LOGE_STR("Failed to allocate one structure field."); |
273b65be JG |
1199 | goto end; |
1200 | } | |
1201 | ||
273b65be | 1202 | structure->fields = g_ptr_array_new_with_free_func( |
50842bdc | 1203 | (GDestroyNotify) bt_put); |
273b65be | 1204 | g_ptr_array_set_size(structure->fields, |
c58b9c62 JG |
1205 | structure_type->fields->len); |
1206 | ||
1207 | /* Create all fields contained by the structure field. */ | |
1208 | for (i = 0; i < structure_type->fields->len; i++) { | |
50842bdc | 1209 | struct bt_field *field; |
c58b9c62 JG |
1210 | struct structure_field *field_type = |
1211 | g_ptr_array_index(structure_type->fields, i); | |
1212 | ||
50842bdc | 1213 | field = bt_field_create(field_type->type); |
c58b9c62 JG |
1214 | if (!field) { |
1215 | BT_LOGE("Failed to create structure field's member: name=\"%s\", index=%zu", | |
1216 | g_quark_to_string(field_type->name), i); | |
f6ccaed9 | 1217 | bt_field_structure_destroy_recursive(&structure->parent); |
c58b9c62 JG |
1218 | goto end; |
1219 | } | |
1220 | ||
1221 | g_ptr_array_index(structure->fields, i) = field; | |
1222 | } | |
1223 | ||
1224 | ret = &structure->parent; | |
1225 | BT_LOGD("Created structure field object: addr=%p, ft-addr=%p", ret, | |
1226 | type); | |
273b65be | 1227 | end: |
c58b9c62 | 1228 | return ret; |
273b65be JG |
1229 | } |
1230 | ||
1231 | static | |
50842bdc | 1232 | struct bt_field *bt_field_variant_create(struct bt_field_type *type) |
273b65be | 1233 | { |
50842bdc PP |
1234 | struct bt_field_variant *variant = g_new0( |
1235 | struct bt_field_variant, 1); | |
fc25abce PP |
1236 | |
1237 | BT_LOGD("Creating variant field object: ft-addr=%p", type); | |
1238 | ||
1239 | if (variant) { | |
1240 | BT_LOGD("Created variant field object: addr=%p, ft-addr=%p", | |
1241 | &variant->parent, type); | |
1242 | } else { | |
1243 | BT_LOGE_STR("Failed to allocate one variant field."); | |
1244 | } | |
1245 | ||
273b65be JG |
1246 | return variant ? &variant->parent : NULL; |
1247 | } | |
1248 | ||
1249 | static | |
50842bdc | 1250 | struct bt_field *bt_field_array_create(struct bt_field_type *type) |
273b65be | 1251 | { |
50842bdc PP |
1252 | struct bt_field_array *array = g_new0(struct bt_field_array, 1); |
1253 | struct bt_field_type_array *array_type; | |
273b65be JG |
1254 | unsigned int array_length; |
1255 | ||
fc25abce | 1256 | BT_LOGD("Creating array field object: ft-addr=%p", type); |
f6ccaed9 | 1257 | BT_ASSERT(type); |
fc25abce PP |
1258 | |
1259 | if (!array) { | |
1260 | BT_LOGE_STR("Failed to allocate one array field."); | |
273b65be JG |
1261 | goto error; |
1262 | } | |
1263 | ||
50842bdc | 1264 | array_type = container_of(type, struct bt_field_type_array, parent); |
273b65be | 1265 | array_length = array_type->length; |
fe0fe95c | 1266 | array->elements = g_ptr_array_sized_new(array_length); |
273b65be JG |
1267 | if (!array->elements) { |
1268 | goto error; | |
1269 | } | |
1270 | ||
fe0fe95c | 1271 | g_ptr_array_set_free_func(array->elements, |
50842bdc | 1272 | (GDestroyNotify) bt_put); |
273b65be | 1273 | g_ptr_array_set_size(array->elements, array_length); |
fc25abce PP |
1274 | BT_LOGD("Created array field object: addr=%p, ft-addr=%p", |
1275 | &array->parent, type); | |
273b65be JG |
1276 | return &array->parent; |
1277 | error: | |
1278 | g_free(array); | |
1279 | return NULL; | |
1280 | } | |
1281 | ||
1282 | static | |
50842bdc PP |
1283 | struct bt_field *bt_field_sequence_create( |
1284 | struct bt_field_type *type) | |
273b65be | 1285 | { |
50842bdc PP |
1286 | struct bt_field_sequence *sequence = g_new0( |
1287 | struct bt_field_sequence, 1); | |
fc25abce PP |
1288 | |
1289 | BT_LOGD("Creating sequence field object: ft-addr=%p", type); | |
1290 | ||
1291 | if (sequence) { | |
1292 | BT_LOGD("Created sequence field object: addr=%p, ft-addr=%p", | |
1293 | &sequence->parent, type); | |
1294 | } else { | |
1295 | BT_LOGE_STR("Failed to allocate one sequence field."); | |
1296 | } | |
1297 | ||
273b65be JG |
1298 | return sequence ? &sequence->parent : NULL; |
1299 | } | |
1300 | ||
1301 | static | |
50842bdc | 1302 | struct bt_field *bt_field_string_create(struct bt_field_type *type) |
273b65be | 1303 | { |
50842bdc PP |
1304 | struct bt_field_string *string = g_new0( |
1305 | struct bt_field_string, 1); | |
fc25abce PP |
1306 | |
1307 | BT_LOGD("Creating string field object: ft-addr=%p", type); | |
1308 | ||
1309 | if (string) { | |
1310 | BT_LOGD("Created string field object: addr=%p, ft-addr=%p", | |
1311 | &string->parent, type); | |
1312 | } else { | |
1313 | BT_LOGE_STR("Failed to allocate one string field."); | |
1314 | } | |
1315 | ||
273b65be JG |
1316 | return string ? &string->parent : NULL; |
1317 | } | |
1318 | ||
1319 | static | |
50842bdc | 1320 | void bt_field_destroy(struct bt_object *obj) |
273b65be | 1321 | { |
50842bdc PP |
1322 | struct bt_field *field; |
1323 | struct bt_field_type *type; | |
1324 | enum bt_field_type_id type_id; | |
273b65be | 1325 | |
f6ccaed9 | 1326 | BT_ASSERT(obj); |
50842bdc | 1327 | field = container_of(obj, struct bt_field, base); |
273b65be | 1328 | type = field->type; |
f6ccaed9 | 1329 | BT_ASSERT(field_type_has_known_id(type)); |
50842bdc | 1330 | type_id = bt_field_type_get_type_id(type); |
273b65be | 1331 | field_destroy_funcs[type_id](field); |
fc25abce | 1332 | BT_LOGD_STR("Putting field's type."); |
83509119 | 1333 | bt_put(type); |
273b65be JG |
1334 | } |
1335 | ||
1336 | static | |
50842bdc | 1337 | void bt_field_integer_destroy(struct bt_field *field) |
273b65be | 1338 | { |
50842bdc | 1339 | struct bt_field_integer *integer; |
273b65be | 1340 | |
f6ccaed9 | 1341 | BT_ASSERT(field); |
fc25abce | 1342 | BT_LOGD("Destroying integer field object: addr=%p", field); |
50842bdc | 1343 | integer = container_of(field, struct bt_field_integer, parent); |
273b65be JG |
1344 | g_free(integer); |
1345 | } | |
1346 | ||
1347 | static | |
f6ccaed9 | 1348 | void bt_field_enumeration_destroy_recursive(struct bt_field *field) |
273b65be | 1349 | { |
50842bdc | 1350 | struct bt_field_enumeration *enumeration; |
273b65be | 1351 | |
f6ccaed9 | 1352 | BT_ASSERT(field); |
fc25abce | 1353 | BT_LOGD("Destroying enumeration field object: addr=%p", field); |
50842bdc | 1354 | enumeration = container_of(field, struct bt_field_enumeration, |
273b65be | 1355 | parent); |
fc25abce | 1356 | BT_LOGD_STR("Putting payload field."); |
83509119 | 1357 | bt_put(enumeration->payload); |
273b65be JG |
1358 | g_free(enumeration); |
1359 | } | |
1360 | ||
1361 | static | |
50842bdc | 1362 | void bt_field_floating_point_destroy(struct bt_field *field) |
273b65be | 1363 | { |
50842bdc | 1364 | struct bt_field_floating_point *floating_point; |
273b65be | 1365 | |
f6ccaed9 | 1366 | BT_ASSERT(field); |
fc25abce | 1367 | BT_LOGD("Destroying floating point number field object: addr=%p", field); |
50842bdc | 1368 | floating_point = container_of(field, struct bt_field_floating_point, |
273b65be JG |
1369 | parent); |
1370 | g_free(floating_point); | |
1371 | } | |
1372 | ||
1373 | static | |
f6ccaed9 | 1374 | void bt_field_structure_destroy_recursive(struct bt_field *field) |
273b65be | 1375 | { |
50842bdc | 1376 | struct bt_field_structure *structure; |
273b65be | 1377 | |
f6ccaed9 | 1378 | BT_ASSERT(field); |
fc25abce | 1379 | BT_LOGD("Destroying structure field object: addr=%p", field); |
50842bdc | 1380 | structure = container_of(field, struct bt_field_structure, parent); |
273b65be JG |
1381 | g_ptr_array_free(structure->fields, TRUE); |
1382 | g_free(structure); | |
1383 | } | |
1384 | ||
1385 | static | |
f6ccaed9 | 1386 | void bt_field_variant_destroy_recursive(struct bt_field *field) |
273b65be | 1387 | { |
50842bdc | 1388 | struct bt_field_variant *variant; |
273b65be | 1389 | |
f6ccaed9 | 1390 | BT_ASSERT(field); |
fc25abce | 1391 | BT_LOGD("Destroying variant field object: addr=%p", field); |
50842bdc | 1392 | variant = container_of(field, struct bt_field_variant, parent); |
fc25abce | 1393 | BT_LOGD_STR("Putting tag field."); |
83509119 | 1394 | bt_put(variant->tag); |
fc25abce | 1395 | BT_LOGD_STR("Putting payload field."); |
83509119 | 1396 | bt_put(variant->payload); |
273b65be JG |
1397 | g_free(variant); |
1398 | } | |
1399 | ||
1400 | static | |
f6ccaed9 | 1401 | void bt_field_array_destroy_recursive(struct bt_field *field) |
273b65be | 1402 | { |
50842bdc | 1403 | struct bt_field_array *array; |
273b65be | 1404 | |
f6ccaed9 | 1405 | BT_ASSERT(field); |
fc25abce | 1406 | BT_LOGD("Destroying array field object: addr=%p", field); |
50842bdc | 1407 | array = container_of(field, struct bt_field_array, parent); |
273b65be JG |
1408 | g_ptr_array_free(array->elements, TRUE); |
1409 | g_free(array); | |
1410 | } | |
1411 | ||
1412 | static | |
f6ccaed9 | 1413 | void bt_field_sequence_destroy_recursive(struct bt_field *field) |
273b65be | 1414 | { |
50842bdc | 1415 | struct bt_field_sequence *sequence; |
273b65be | 1416 | |
f6ccaed9 | 1417 | BT_ASSERT(field); |
fc25abce | 1418 | BT_LOGD("Destroying sequence field object: addr=%p", field); |
50842bdc | 1419 | sequence = container_of(field, struct bt_field_sequence, parent); |
4fef87ab JG |
1420 | if (sequence->elements) { |
1421 | g_ptr_array_free(sequence->elements, TRUE); | |
1422 | } | |
fc25abce | 1423 | BT_LOGD_STR("Putting length field."); |
83509119 | 1424 | bt_put(sequence->length); |
273b65be JG |
1425 | g_free(sequence); |
1426 | } | |
1427 | ||
1428 | static | |
50842bdc | 1429 | void bt_field_string_destroy(struct bt_field *field) |
273b65be | 1430 | { |
50842bdc | 1431 | struct bt_field_string *string; |
fc25abce | 1432 | |
f6ccaed9 | 1433 | BT_ASSERT(field); |
fc25abce | 1434 | BT_LOGD("Destroying string field object: addr=%p", field); |
50842bdc | 1435 | string = container_of(field, struct bt_field_string, parent); |
9b2b7163 JG |
1436 | if (string->payload) { |
1437 | g_string_free(string->payload, TRUE); | |
1438 | } | |
273b65be JG |
1439 | g_free(string); |
1440 | } | |
1441 | ||
1442 | static | |
50842bdc | 1443 | int bt_field_generic_validate(struct bt_field *field) |
273b65be | 1444 | { |
da2f6971 | 1445 | return (field && field->payload_set) ? 0 : -1; |
273b65be JG |
1446 | } |
1447 | ||
1448 | static | |
f6ccaed9 | 1449 | int bt_field_enumeration_validate_recursive(struct bt_field *field) |
273b65be JG |
1450 | { |
1451 | int ret; | |
50842bdc | 1452 | struct bt_field_enumeration *enumeration; |
273b65be | 1453 | |
f6ccaed9 | 1454 | BT_ASSERT(field); |
50842bdc | 1455 | enumeration = container_of(field, struct bt_field_enumeration, |
273b65be JG |
1456 | parent); |
1457 | if (!enumeration->payload) { | |
f6ccaed9 PP |
1458 | BT_ASSERT_PRE_MSG("Invalid enumeration field: payload is not set: " |
1459 | "%!+f", field); | |
273b65be JG |
1460 | ret = -1; |
1461 | goto end; | |
1462 | } | |
1463 | ||
f6ccaed9 PP |
1464 | ret = bt_field_validate_recursive(enumeration->payload); |
1465 | ||
273b65be JG |
1466 | end: |
1467 | return ret; | |
1468 | } | |
1469 | ||
1470 | static | |
f6ccaed9 | 1471 | int bt_field_structure_validate_recursive(struct bt_field *field) |
273b65be | 1472 | { |
fc25abce | 1473 | int64_t i; |
273b65be | 1474 | int ret = 0; |
50842bdc | 1475 | struct bt_field_structure *structure; |
273b65be | 1476 | |
f6ccaed9 | 1477 | BT_ASSERT(field); |
50842bdc | 1478 | structure = container_of(field, struct bt_field_structure, parent); |
f6ccaed9 | 1479 | |
273b65be | 1480 | for (i = 0; i < structure->fields->len; i++) { |
f6ccaed9 PP |
1481 | ret = bt_field_validate_recursive( |
1482 | (void *) structure->fields->pdata[i]); | |
fc25abce | 1483 | |
273b65be | 1484 | if (ret) { |
fc25abce | 1485 | int this_ret; |
6ce12048 | 1486 | const char *name; |
6ce12048 | 1487 | |
50842bdc | 1488 | this_ret = bt_field_type_structure_get_field_by_index( |
f6ccaed9 PP |
1489 | field->type, &name, NULL, i); |
1490 | BT_ASSERT(this_ret == 0); | |
1491 | BT_ASSERT_PRE_MSG("Invalid structure field's field: " | |
1492 | "%![struct-field-]+f, field-name=\"%s\", " | |
1493 | "index=%" PRId64 ", %![field-]+f", | |
1494 | field, name, i, structure->fields->pdata[i]); | |
273b65be JG |
1495 | goto end; |
1496 | } | |
1497 | } | |
f6ccaed9 | 1498 | |
273b65be JG |
1499 | end: |
1500 | return ret; | |
1501 | } | |
1502 | ||
1503 | static | |
f6ccaed9 | 1504 | int bt_field_variant_validate_recursive(struct bt_field *field) |
273b65be JG |
1505 | { |
1506 | int ret = 0; | |
50842bdc | 1507 | struct bt_field_variant *variant; |
273b65be | 1508 | |
f6ccaed9 | 1509 | BT_ASSERT(field); |
50842bdc | 1510 | variant = container_of(field, struct bt_field_variant, parent); |
f6ccaed9 | 1511 | ret = bt_field_validate_recursive(variant->payload); |
fc25abce | 1512 | if (ret) { |
f6ccaed9 PP |
1513 | BT_ASSERT_PRE_MSG("Invalid variant field's payload field: " |
1514 | "%![variant-field-]+f, %![payload-field-]+f", | |
fc25abce PP |
1515 | field, variant->payload); |
1516 | } | |
f6ccaed9 | 1517 | |
273b65be JG |
1518 | return ret; |
1519 | } | |
1520 | ||
1521 | static | |
f6ccaed9 | 1522 | int bt_field_array_validate_recursive(struct bt_field *field) |
273b65be | 1523 | { |
fc25abce | 1524 | int64_t i; |
273b65be | 1525 | int ret = 0; |
50842bdc | 1526 | struct bt_field_array *array; |
273b65be | 1527 | |
f6ccaed9 | 1528 | BT_ASSERT(field); |
50842bdc | 1529 | array = container_of(field, struct bt_field_array, parent); |
273b65be | 1530 | for (i = 0; i < array->elements->len; i++) { |
f6ccaed9 | 1531 | ret = bt_field_validate_recursive((void *) array->elements->pdata[i]); |
273b65be | 1532 | if (ret) { |
f6ccaed9 PP |
1533 | BT_ASSERT_PRE_MSG("Invalid array field's element field: " |
1534 | "%![array-field-]+f, " PRId64 ", " | |
1535 | "%![elem-field-]+f", | |
1536 | field, i, array->elements->pdata[i]); | |
273b65be JG |
1537 | goto end; |
1538 | } | |
1539 | } | |
f6ccaed9 | 1540 | |
273b65be JG |
1541 | end: |
1542 | return ret; | |
1543 | } | |
1544 | ||
1545 | static | |
f6ccaed9 | 1546 | int bt_field_sequence_validate_recursive(struct bt_field *field) |
273b65be JG |
1547 | { |
1548 | size_t i; | |
1549 | int ret = 0; | |
50842bdc | 1550 | struct bt_field_sequence *sequence; |
273b65be | 1551 | |
f6ccaed9 | 1552 | BT_ASSERT(field); |
50842bdc | 1553 | sequence = container_of(field, struct bt_field_sequence, parent); |
273b65be | 1554 | for (i = 0; i < sequence->elements->len; i++) { |
f6ccaed9 PP |
1555 | ret = bt_field_validate_recursive( |
1556 | (void *) sequence->elements->pdata[i]); | |
273b65be | 1557 | if (ret) { |
f6ccaed9 PP |
1558 | BT_ASSERT_PRE_MSG("Invalid sequence field's element field: " |
1559 | "%![seq-field-]+f, " PRId64 ", " | |
1560 | "%![elem-field-]+f", | |
1561 | field, i, sequence->elements->pdata[i]); | |
273b65be JG |
1562 | goto end; |
1563 | } | |
1564 | } | |
1565 | end: | |
1566 | return ret; | |
1567 | } | |
1568 | ||
12c8a1a3 | 1569 | static |
f6ccaed9 | 1570 | void bt_field_generic_reset(struct bt_field *field) |
12c8a1a3 | 1571 | { |
f6ccaed9 | 1572 | BT_ASSERT(field); |
d990a4fb | 1573 | field->payload_set = false; |
12c8a1a3 JG |
1574 | } |
1575 | ||
1576 | static | |
f6ccaed9 | 1577 | void bt_field_enumeration_reset_recursive(struct bt_field *field) |
12c8a1a3 | 1578 | { |
50842bdc | 1579 | struct bt_field_enumeration *enumeration; |
12c8a1a3 | 1580 | |
f6ccaed9 | 1581 | BT_ASSERT(field); |
50842bdc | 1582 | enumeration = container_of(field, struct bt_field_enumeration, |
12c8a1a3 JG |
1583 | parent); |
1584 | if (!enumeration->payload) { | |
f6ccaed9 | 1585 | return; |
12c8a1a3 JG |
1586 | } |
1587 | ||
f6ccaed9 | 1588 | bt_field_reset_recursive(enumeration->payload); |
12c8a1a3 JG |
1589 | } |
1590 | ||
1591 | static | |
f6ccaed9 | 1592 | void bt_field_structure_reset_recursive(struct bt_field *field) |
12c8a1a3 | 1593 | { |
fc25abce | 1594 | int64_t i; |
50842bdc | 1595 | struct bt_field_structure *structure; |
12c8a1a3 | 1596 | |
f6ccaed9 | 1597 | BT_ASSERT(field); |
50842bdc | 1598 | structure = container_of(field, struct bt_field_structure, parent); |
f6ccaed9 | 1599 | |
12c8a1a3 | 1600 | for (i = 0; i < structure->fields->len; i++) { |
50842bdc | 1601 | struct bt_field *member = structure->fields->pdata[i]; |
12c8a1a3 JG |
1602 | |
1603 | if (!member) { | |
1604 | /* | |
f6ccaed9 PP |
1605 | * Structure members are lazily initialized; |
1606 | * skip if this member has not been allocated | |
1607 | * yet. | |
12c8a1a3 JG |
1608 | */ |
1609 | continue; | |
1610 | } | |
1611 | ||
f6ccaed9 | 1612 | bt_field_reset_recursive(member); |
12c8a1a3 | 1613 | } |
12c8a1a3 JG |
1614 | } |
1615 | ||
1616 | static | |
f6ccaed9 | 1617 | void bt_field_variant_reset_recursive(struct bt_field *field) |
12c8a1a3 | 1618 | { |
50842bdc | 1619 | struct bt_field_variant *variant; |
12c8a1a3 | 1620 | |
f6ccaed9 | 1621 | BT_ASSERT(field); |
50842bdc | 1622 | variant = container_of(field, struct bt_field_variant, parent); |
6ead1648 JG |
1623 | BT_PUT(variant->tag); |
1624 | BT_PUT(variant->payload); | |
12c8a1a3 JG |
1625 | } |
1626 | ||
1627 | static | |
f6ccaed9 | 1628 | void bt_field_array_reset_recursive(struct bt_field *field) |
12c8a1a3 JG |
1629 | { |
1630 | size_t i; | |
50842bdc | 1631 | struct bt_field_array *array; |
12c8a1a3 | 1632 | |
f6ccaed9 | 1633 | BT_ASSERT(field); |
50842bdc | 1634 | array = container_of(field, struct bt_field_array, parent); |
f6ccaed9 | 1635 | |
12c8a1a3 | 1636 | for (i = 0; i < array->elements->len; i++) { |
50842bdc | 1637 | struct bt_field *member = array->elements->pdata[i]; |
12c8a1a3 JG |
1638 | |
1639 | if (!member) { | |
1640 | /* | |
f6ccaed9 PP |
1641 | * Array elements are lazily initialized; skip |
1642 | * if this member has not been allocated yet. | |
12c8a1a3 JG |
1643 | */ |
1644 | continue; | |
1645 | } | |
1646 | ||
f6ccaed9 | 1647 | bt_field_reset_recursive(member); |
12c8a1a3 | 1648 | } |
12c8a1a3 JG |
1649 | } |
1650 | ||
1651 | static | |
f6ccaed9 | 1652 | void bt_field_sequence_reset_recursive(struct bt_field *field) |
12c8a1a3 | 1653 | { |
50842bdc | 1654 | struct bt_field_sequence *sequence; |
12c8a1a3 | 1655 | |
f6ccaed9 | 1656 | BT_ASSERT(field); |
50842bdc | 1657 | sequence = container_of(field, struct bt_field_sequence, parent); |
f6ccaed9 | 1658 | |
6ead1648 JG |
1659 | if (sequence->elements) { |
1660 | g_ptr_array_free(sequence->elements, TRUE); | |
1661 | sequence->elements = NULL; | |
12c8a1a3 | 1662 | } |
f6ccaed9 | 1663 | |
6ead1648 | 1664 | BT_PUT(sequence->length); |
12c8a1a3 JG |
1665 | } |
1666 | ||
1667 | static | |
f6ccaed9 | 1668 | void bt_field_string_reset_recursive(struct bt_field *field) |
12c8a1a3 | 1669 | { |
50842bdc | 1670 | struct bt_field_string *string; |
12c8a1a3 | 1671 | |
f6ccaed9 PP |
1672 | BT_ASSERT(field); |
1673 | bt_field_generic_reset(field); | |
50842bdc | 1674 | string = container_of(field, struct bt_field_string, parent); |
12c8a1a3 JG |
1675 | if (string->payload) { |
1676 | g_string_truncate(string->payload, 0); | |
1677 | } | |
12c8a1a3 JG |
1678 | } |
1679 | ||
273b65be | 1680 | static |
50842bdc PP |
1681 | int bt_field_integer_serialize(struct bt_field *field, |
1682 | struct bt_stream_pos *pos, | |
1683 | enum bt_byte_order native_byte_order) | |
273b65be JG |
1684 | { |
1685 | int ret = 0; | |
50842bdc PP |
1686 | struct bt_field_integer *integer = container_of(field, |
1687 | struct bt_field_integer, parent); | |
273b65be | 1688 | |
f6ccaed9 | 1689 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Integer field"); |
fc25abce PP |
1690 | BT_LOGV("Serializing integer field: addr=%p, pos-offset=%" PRId64 ", " |
1691 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1692 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1693 | |
273b65be | 1694 | retry: |
50842bdc | 1695 | ret = bt_field_integer_write(integer, pos, native_byte_order); |
273b65be JG |
1696 | if (ret == -EFAULT) { |
1697 | /* | |
1698 | * The field is too large to fit in the current packet's | |
1699 | * remaining space. Bump the packet size and retry. | |
1700 | */ | |
1701 | ret = increase_packet_size(pos); | |
1702 | if (ret) { | |
fc25abce | 1703 | BT_LOGE("Cannot increase packet size: ret=%d", ret); |
273b65be JG |
1704 | goto end; |
1705 | } | |
1706 | goto retry; | |
1707 | } | |
f6ccaed9 | 1708 | |
273b65be JG |
1709 | end: |
1710 | return ret; | |
1711 | } | |
1712 | ||
1713 | static | |
f6ccaed9 | 1714 | int bt_field_enumeration_serialize_recursive(struct bt_field *field, |
50842bdc PP |
1715 | struct bt_stream_pos *pos, |
1716 | enum bt_byte_order native_byte_order) | |
273b65be | 1717 | { |
50842bdc PP |
1718 | struct bt_field_enumeration *enumeration = container_of( |
1719 | field, struct bt_field_enumeration, parent); | |
273b65be | 1720 | |
fc25abce PP |
1721 | BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", " |
1722 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1723 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1724 | BT_LOGV_STR("Serializing enumeration field's payload field."); |
f6ccaed9 | 1725 | return bt_field_serialize_recursive(enumeration->payload, pos, |
dc3fffef | 1726 | native_byte_order); |
273b65be JG |
1727 | } |
1728 | ||
1729 | static | |
50842bdc PP |
1730 | int bt_field_floating_point_serialize(struct bt_field *field, |
1731 | struct bt_stream_pos *pos, | |
1732 | enum bt_byte_order native_byte_order) | |
273b65be JG |
1733 | { |
1734 | int ret = 0; | |
50842bdc PP |
1735 | struct bt_field_floating_point *floating_point = container_of(field, |
1736 | struct bt_field_floating_point, parent); | |
273b65be | 1737 | |
f6ccaed9 | 1738 | BT_ASSERT_PRE_FIELD_IS_SET(field, "Floating point number field"); |
fc25abce PP |
1739 | BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", " |
1740 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1741 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1742 | |
273b65be | 1743 | retry: |
50842bdc | 1744 | ret = bt_field_floating_point_write(floating_point, pos, |
dc3fffef | 1745 | native_byte_order); |
273b65be JG |
1746 | if (ret == -EFAULT) { |
1747 | /* | |
1748 | * The field is too large to fit in the current packet's | |
1749 | * remaining space. Bump the packet size and retry. | |
1750 | */ | |
1751 | ret = increase_packet_size(pos); | |
1752 | if (ret) { | |
fc25abce | 1753 | BT_LOGE("Cannot increase packet size: ret=%d", ret); |
273b65be JG |
1754 | goto end; |
1755 | } | |
1756 | goto retry; | |
1757 | } | |
f6ccaed9 | 1758 | |
273b65be JG |
1759 | end: |
1760 | return ret; | |
1761 | } | |
1762 | ||
1763 | static | |
f6ccaed9 | 1764 | int bt_field_structure_serialize_recursive(struct bt_field *field, |
50842bdc PP |
1765 | struct bt_stream_pos *pos, |
1766 | enum bt_byte_order native_byte_order) | |
273b65be | 1767 | { |
fc25abce | 1768 | int64_t i; |
273b65be | 1769 | int ret = 0; |
50842bdc PP |
1770 | struct bt_field_structure *structure = container_of( |
1771 | field, struct bt_field_structure, parent); | |
273b65be | 1772 | |
fc25abce PP |
1773 | BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", " |
1774 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1775 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1776 | |
50842bdc | 1777 | while (!bt_stream_pos_access_ok(pos, |
dc3fffef | 1778 | offset_align(pos->offset, field->type->alignment))) { |
9f56e450 JG |
1779 | ret = increase_packet_size(pos); |
1780 | if (ret) { | |
fc25abce | 1781 | BT_LOGE("Cannot increase packet size: ret=%d", ret); |
9f56e450 JG |
1782 | goto end; |
1783 | } | |
273b65be JG |
1784 | } |
1785 | ||
50842bdc | 1786 | if (!bt_stream_pos_align(pos, field->type->alignment)) { |
fc25abce PP |
1787 | BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", " |
1788 | "align=%u", pos->offset, field->type->alignment); | |
70fd5a51 MD |
1789 | ret = -1; |
1790 | goto end; | |
1791 | } | |
273b65be JG |
1792 | |
1793 | for (i = 0; i < structure->fields->len; i++) { | |
50842bdc | 1794 | struct bt_field *member = g_ptr_array_index( |
273b65be | 1795 | structure->fields, i); |
b3376dd9 PP |
1796 | const char *field_name = NULL; |
1797 | ||
fc25abce PP |
1798 | BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", " |
1799 | "field-addr=%p, index=%" PRId64, | |
1800 | pos->offset, member, i); | |
b3376dd9 PP |
1801 | |
1802 | if (!member) { | |
f6ccaed9 PP |
1803 | ret = bt_field_type_structure_get_field_by_index( |
1804 | field->type, &field_name, NULL, i); | |
1805 | BT_ASSERT(ret == 0); | |
b3376dd9 PP |
1806 | BT_LOGW("Cannot serialize structure field's field: field is not set: " |
1807 | "struct-field-addr=%p, " | |
1808 | "field-name=\"%s\", index=%" PRId64, | |
1809 | field, field_name, i); | |
1810 | ret = -1; | |
1811 | goto end; | |
1812 | } | |
1813 | ||
f6ccaed9 PP |
1814 | ret = bt_field_serialize_recursive(member, pos, |
1815 | native_byte_order); | |
273b65be | 1816 | if (ret) { |
f6ccaed9 PP |
1817 | ret = bt_field_type_structure_get_field_by_index( |
1818 | field->type, &field_name, NULL, i); | |
1819 | BT_ASSERT(ret == 0); | |
fc25abce PP |
1820 | BT_LOGW("Cannot serialize structure field's field: " |
1821 | "struct-field-addr=%p, field-addr=%p, " | |
1822 | "field-name=\"%s\", index=%" PRId64, | |
b3376dd9 | 1823 | field->type, member, field_name, i); |
273b65be JG |
1824 | break; |
1825 | } | |
1826 | } | |
f6ccaed9 | 1827 | |
9f56e450 | 1828 | end: |
273b65be JG |
1829 | return ret; |
1830 | } | |
1831 | ||
1832 | static | |
f6ccaed9 | 1833 | int bt_field_variant_serialize_recursive(struct bt_field *field, |
50842bdc PP |
1834 | struct bt_stream_pos *pos, |
1835 | enum bt_byte_order native_byte_order) | |
273b65be | 1836 | { |
50842bdc PP |
1837 | struct bt_field_variant *variant = container_of( |
1838 | field, struct bt_field_variant, parent); | |
273b65be | 1839 | |
fc25abce PP |
1840 | BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", " |
1841 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1842 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1843 | BT_LOGV_STR("Serializing variant field's payload field."); |
f6ccaed9 | 1844 | return bt_field_serialize_recursive(variant->payload, pos, |
dc3fffef | 1845 | native_byte_order); |
273b65be JG |
1846 | } |
1847 | ||
1848 | static | |
f6ccaed9 | 1849 | int bt_field_array_serialize_recursive(struct bt_field *field, |
50842bdc PP |
1850 | struct bt_stream_pos *pos, |
1851 | enum bt_byte_order native_byte_order) | |
273b65be | 1852 | { |
fc25abce | 1853 | int64_t i; |
273b65be | 1854 | int ret = 0; |
50842bdc PP |
1855 | struct bt_field_array *array = container_of( |
1856 | field, struct bt_field_array, parent); | |
273b65be | 1857 | |
fc25abce PP |
1858 | BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", " |
1859 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1860 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1861 | |
273b65be | 1862 | for (i = 0; i < array->elements->len; i++) { |
50842bdc | 1863 | struct bt_field *elem_field = |
fc25abce PP |
1864 | g_ptr_array_index(array->elements, i); |
1865 | ||
1866 | BT_LOGV("Serializing array field's element field: " | |
1867 | "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, | |
1868 | pos->offset, elem_field, i); | |
f6ccaed9 | 1869 | ret = bt_field_serialize_recursive(elem_field, pos, |
dc3fffef | 1870 | native_byte_order); |
273b65be | 1871 | if (ret) { |
fc25abce PP |
1872 | BT_LOGW("Cannot serialize array field's element field: " |
1873 | "array-field-addr=%p, field-addr=%p, " | |
1874 | "index=%" PRId64, field, elem_field, i); | |
273b65be JG |
1875 | goto end; |
1876 | } | |
1877 | } | |
f6ccaed9 | 1878 | |
273b65be JG |
1879 | end: |
1880 | return ret; | |
1881 | } | |
1882 | ||
1883 | static | |
f6ccaed9 | 1884 | int bt_field_sequence_serialize_recursive(struct bt_field *field, |
50842bdc PP |
1885 | struct bt_stream_pos *pos, |
1886 | enum bt_byte_order native_byte_order) | |
273b65be | 1887 | { |
fc25abce | 1888 | int64_t i; |
273b65be | 1889 | int ret = 0; |
50842bdc PP |
1890 | struct bt_field_sequence *sequence = container_of( |
1891 | field, struct bt_field_sequence, parent); | |
273b65be | 1892 | |
fc25abce PP |
1893 | BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", " |
1894 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1895 | bt_byte_order_string(native_byte_order)); |
fc25abce | 1896 | |
273b65be | 1897 | for (i = 0; i < sequence->elements->len; i++) { |
50842bdc | 1898 | struct bt_field *elem_field = |
fc25abce PP |
1899 | g_ptr_array_index(sequence->elements, i); |
1900 | ||
1901 | BT_LOGV("Serializing sequence field's element field: " | |
1902 | "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64, | |
1903 | pos->offset, elem_field, i); | |
f6ccaed9 | 1904 | ret = bt_field_serialize_recursive(elem_field, pos, |
dc3fffef | 1905 | native_byte_order); |
273b65be | 1906 | if (ret) { |
fc25abce PP |
1907 | BT_LOGW("Cannot serialize sequence field's element field: " |
1908 | "sequence-field-addr=%p, field-addr=%p, " | |
1909 | "index=%" PRId64, field, elem_field, i); | |
273b65be JG |
1910 | goto end; |
1911 | } | |
1912 | } | |
f6ccaed9 | 1913 | |
273b65be JG |
1914 | end: |
1915 | return ret; | |
1916 | } | |
1917 | ||
1918 | static | |
f6ccaed9 | 1919 | int bt_field_string_serialize(struct bt_field *field, struct bt_stream_pos *pos, |
50842bdc | 1920 | enum bt_byte_order native_byte_order) |
273b65be | 1921 | { |
fc25abce | 1922 | int64_t i; |
273b65be | 1923 | int ret = 0; |
50842bdc PP |
1924 | struct bt_field_string *string = container_of(field, |
1925 | struct bt_field_string, parent); | |
1926 | struct bt_field_type *character_type = | |
273b65be | 1927 | get_field_type(FIELD_TYPE_ALIAS_UINT8_T); |
50842bdc | 1928 | struct bt_field *character; |
fc25abce | 1929 | |
f6ccaed9 | 1930 | BT_ASSERT_PRE_FIELD_IS_SET(field, "String field"); |
fc25abce PP |
1931 | BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", " |
1932 | "native-bo=%s", field, pos->offset, | |
50842bdc | 1933 | bt_byte_order_string(native_byte_order)); |
fc25abce PP |
1934 | |
1935 | BT_LOGV_STR("Creating character field from string field's character field type."); | |
50842bdc | 1936 | character = bt_field_create(character_type); |
273b65be JG |
1937 | |
1938 | for (i = 0; i < string->payload->len + 1; i++) { | |
fc25abce PP |
1939 | const uint64_t chr = (uint64_t) string->payload->str[i]; |
1940 | ||
50842bdc | 1941 | ret = bt_field_unsigned_integer_set_value(character, chr); |
f6ccaed9 | 1942 | BT_ASSERT(ret == 0); |
fc25abce PP |
1943 | BT_LOGV("Serializing string field's character field: " |
1944 | "pos-offset=%" PRId64 ", field-addr=%p, " | |
1945 | "index=%" PRId64 ", char-int=%" PRIu64, | |
1946 | pos->offset, character, i, chr); | |
50842bdc | 1947 | ret = bt_field_integer_serialize(character, pos, |
dc3fffef | 1948 | native_byte_order); |
273b65be | 1949 | if (ret) { |
b3376dd9 | 1950 | BT_LOGW_STR("Cannot serialize character field."); |
273b65be JG |
1951 | goto end; |
1952 | } | |
1953 | } | |
f6ccaed9 | 1954 | |
273b65be | 1955 | end: |
83509119 JG |
1956 | bt_put(character); |
1957 | bt_put(character_type); | |
273b65be JG |
1958 | return ret; |
1959 | } | |
1960 | ||
87d43dc1 | 1961 | static |
f6ccaed9 | 1962 | int bt_field_integer_copy(struct bt_field *src, struct bt_field *dst) |
87d43dc1 | 1963 | { |
50842bdc | 1964 | struct bt_field_integer *integer_src, *integer_dst; |
87d43dc1 | 1965 | |
fc25abce PP |
1966 | BT_LOGD("Copying integer field: src-field-addr=%p, dst-field-addr=%p", |
1967 | src, dst); | |
50842bdc PP |
1968 | integer_src = container_of(src, struct bt_field_integer, parent); |
1969 | integer_dst = container_of(dst, struct bt_field_integer, parent); | |
dc3fffef | 1970 | integer_dst->payload = integer_src->payload; |
fc25abce | 1971 | BT_LOGD_STR("Copied integer field."); |
87d43dc1 JG |
1972 | return 0; |
1973 | } | |
1974 | ||
1975 | static | |
f6ccaed9 | 1976 | int bt_field_enumeration_copy_recursive(struct bt_field *src, |
50842bdc | 1977 | struct bt_field *dst) |
87d43dc1 JG |
1978 | { |
1979 | int ret = 0; | |
50842bdc | 1980 | struct bt_field_enumeration *enum_src, *enum_dst; |
87d43dc1 | 1981 | |
fc25abce PP |
1982 | BT_LOGD("Copying enumeration field: src-field-addr=%p, dst-field-addr=%p", |
1983 | src, dst); | |
50842bdc PP |
1984 | enum_src = container_of(src, struct bt_field_enumeration, parent); |
1985 | enum_dst = container_of(dst, struct bt_field_enumeration, parent); | |
87d43dc1 JG |
1986 | |
1987 | if (enum_src->payload) { | |
fc25abce | 1988 | BT_LOGD_STR("Copying enumeration field's payload field."); |
50842bdc | 1989 | enum_dst->payload = bt_field_copy(enum_src->payload); |
87d43dc1 | 1990 | if (!enum_dst->payload) { |
fc25abce | 1991 | BT_LOGE_STR("Cannot copy enumeration field's payload field."); |
87d43dc1 JG |
1992 | ret = -1; |
1993 | goto end; | |
1994 | } | |
1995 | } | |
fc25abce PP |
1996 | |
1997 | BT_LOGD_STR("Copied enumeration field."); | |
87d43dc1 JG |
1998 | end: |
1999 | return ret; | |
2000 | } | |
2001 | ||
2002 | static | |
f6ccaed9 | 2003 | int bt_field_floating_point_copy(struct bt_field *src, struct bt_field *dst) |
87d43dc1 | 2004 | { |
50842bdc | 2005 | struct bt_field_floating_point *float_src, *float_dst; |
87d43dc1 | 2006 | |
fc25abce PP |
2007 | BT_LOGD("Copying floating point number field: src-field-addr=%p, dst-field-addr=%p", |
2008 | src, dst); | |
50842bdc | 2009 | float_src = container_of(src, struct bt_field_floating_point, |
87d43dc1 | 2010 | parent); |
50842bdc | 2011 | float_dst = container_of(dst, struct bt_field_floating_point, |
87d43dc1 | 2012 | parent); |
dc3fffef | 2013 | float_dst->payload = float_src->payload; |
fc25abce | 2014 | BT_LOGD_STR("Copied floating point number field."); |
87d43dc1 JG |
2015 | return 0; |
2016 | } | |
2017 | ||
2018 | static | |
f6ccaed9 | 2019 | int bt_field_structure_copy_recursive(struct bt_field *src, |
50842bdc | 2020 | struct bt_field *dst) |
87d43dc1 | 2021 | { |
fc25abce PP |
2022 | int ret = 0; |
2023 | int64_t i; | |
50842bdc | 2024 | struct bt_field_structure *struct_src, *struct_dst; |
87d43dc1 | 2025 | |
fc25abce PP |
2026 | BT_LOGD("Copying structure field: src-field-addr=%p, dst-field-addr=%p", |
2027 | src, dst); | |
50842bdc PP |
2028 | struct_src = container_of(src, struct bt_field_structure, parent); |
2029 | struct_dst = container_of(dst, struct bt_field_structure, parent); | |
87d43dc1 | 2030 | |
8bfa3f9c | 2031 | g_ptr_array_set_size(struct_dst->fields, struct_src->fields->len); |
87d43dc1 JG |
2032 | |
2033 | for (i = 0; i < struct_src->fields->len; i++) { | |
50842bdc | 2034 | struct bt_field *field = |
50fd95bf | 2035 | g_ptr_array_index(struct_src->fields, i); |
50842bdc | 2036 | struct bt_field *field_copy = NULL; |
87d43dc1 | 2037 | |
50fd95bf | 2038 | if (field) { |
32e87ceb | 2039 | BT_LOGD("Copying structure field's field: src-field-addr=%p" |
fc25abce | 2040 | "index=%" PRId64, field, i); |
50842bdc | 2041 | field_copy = bt_field_copy(field); |
50fd95bf | 2042 | if (!field_copy) { |
fc25abce PP |
2043 | BT_LOGE("Cannot copy structure field's field: " |
2044 | "src-field-addr=%p, index=%" PRId64, | |
2045 | field, i); | |
50fd95bf PP |
2046 | ret = -1; |
2047 | goto end; | |
2048 | } | |
87d43dc1 | 2049 | } |
50fd95bf | 2050 | |
c58b9c62 | 2051 | BT_MOVE(g_ptr_array_index(struct_dst->fields, i), field_copy); |
87d43dc1 | 2052 | } |
fc25abce PP |
2053 | |
2054 | BT_LOGD_STR("Copied structure field."); | |
2055 | ||
87d43dc1 JG |
2056 | end: |
2057 | return ret; | |
2058 | } | |
2059 | ||
2060 | static | |
f6ccaed9 | 2061 | int bt_field_variant_copy_recursive(struct bt_field *src, |
50842bdc | 2062 | struct bt_field *dst) |
87d43dc1 JG |
2063 | { |
2064 | int ret = 0; | |
50842bdc | 2065 | struct bt_field_variant *variant_src, *variant_dst; |
87d43dc1 | 2066 | |
fc25abce PP |
2067 | BT_LOGD("Copying variant field: src-field-addr=%p, dst-field-addr=%p", |
2068 | src, dst); | |
50842bdc PP |
2069 | variant_src = container_of(src, struct bt_field_variant, parent); |
2070 | variant_dst = container_of(dst, struct bt_field_variant, parent); | |
87d43dc1 JG |
2071 | |
2072 | if (variant_src->tag) { | |
fc25abce | 2073 | BT_LOGD_STR("Copying variant field's tag field."); |
50842bdc | 2074 | variant_dst->tag = bt_field_copy(variant_src->tag); |
87d43dc1 | 2075 | if (!variant_dst->tag) { |
fc25abce | 2076 | BT_LOGE_STR("Cannot copy variant field's tag field."); |
87d43dc1 JG |
2077 | ret = -1; |
2078 | goto end; | |
2079 | } | |
2080 | } | |
2081 | if (variant_src->payload) { | |
fc25abce | 2082 | BT_LOGD_STR("Copying variant field's payload field."); |
50842bdc | 2083 | variant_dst->payload = bt_field_copy(variant_src->payload); |
87d43dc1 | 2084 | if (!variant_dst->payload) { |
fc25abce | 2085 | BT_LOGE_STR("Cannot copy variant field's payload field."); |
87d43dc1 JG |
2086 | ret = -1; |
2087 | goto end; | |
2088 | } | |
2089 | } | |
fc25abce PP |
2090 | |
2091 | BT_LOGD_STR("Copied variant field."); | |
2092 | ||
87d43dc1 JG |
2093 | end: |
2094 | return ret; | |
2095 | } | |
2096 | ||
2097 | static | |
f6ccaed9 | 2098 | int bt_field_array_copy_recursive(struct bt_field *src, |
50842bdc | 2099 | struct bt_field *dst) |
87d43dc1 | 2100 | { |
fc25abce PP |
2101 | int ret = 0; |
2102 | int64_t i; | |
50842bdc | 2103 | struct bt_field_array *array_src, *array_dst; |
87d43dc1 | 2104 | |
fc25abce PP |
2105 | BT_LOGD("Copying array field: src-field-addr=%p, dst-field-addr=%p", |
2106 | src, dst); | |
50842bdc PP |
2107 | array_src = container_of(src, struct bt_field_array, parent); |
2108 | array_dst = container_of(dst, struct bt_field_array, parent); | |
87d43dc1 | 2109 | |
8bfa3f9c | 2110 | g_ptr_array_set_size(array_dst->elements, array_src->elements->len); |
87d43dc1 | 2111 | for (i = 0; i < array_src->elements->len; i++) { |
50842bdc | 2112 | struct bt_field *field = |
50fd95bf | 2113 | g_ptr_array_index(array_src->elements, i); |
50842bdc | 2114 | struct bt_field *field_copy = NULL; |
87d43dc1 | 2115 | |
50fd95bf | 2116 | if (field) { |
fc25abce PP |
2117 | BT_LOGD("Copying array field's element field: field-addr=%p, " |
2118 | "index=%" PRId64, field, i); | |
50842bdc | 2119 | field_copy = bt_field_copy(field); |
50fd95bf | 2120 | if (!field_copy) { |
fc25abce PP |
2121 | BT_LOGE("Cannot copy array field's element field: " |
2122 | "src-field-addr=%p, index=%" PRId64, | |
2123 | field, i); | |
50fd95bf PP |
2124 | ret = -1; |
2125 | goto end; | |
2126 | } | |
87d43dc1 | 2127 | } |
50fd95bf | 2128 | |
8bfa3f9c | 2129 | g_ptr_array_index(array_dst->elements, i) = field_copy; |
87d43dc1 | 2130 | } |
fc25abce PP |
2131 | |
2132 | BT_LOGD_STR("Copied array field."); | |
2133 | ||
87d43dc1 JG |
2134 | end: |
2135 | return ret; | |
2136 | } | |
2137 | ||
2138 | static | |
f6ccaed9 | 2139 | int bt_field_sequence_copy_recursive(struct bt_field *src, |
50842bdc | 2140 | struct bt_field *dst) |
87d43dc1 | 2141 | { |
fc25abce PP |
2142 | int ret = 0; |
2143 | int64_t i; | |
50842bdc PP |
2144 | struct bt_field_sequence *sequence_src, *sequence_dst; |
2145 | struct bt_field *src_length; | |
2146 | struct bt_field *dst_length; | |
87d43dc1 | 2147 | |
fc25abce PP |
2148 | BT_LOGD("Copying sequence field: src-field-addr=%p, dst-field-addr=%p", |
2149 | src, dst); | |
50842bdc PP |
2150 | sequence_src = container_of(src, struct bt_field_sequence, parent); |
2151 | sequence_dst = container_of(dst, struct bt_field_sequence, parent); | |
87d43dc1 | 2152 | |
50842bdc | 2153 | src_length = bt_field_sequence_get_length(src); |
59ab494d PP |
2154 | if (!src_length) { |
2155 | /* no length set yet: keep destination sequence empty */ | |
2156 | goto end; | |
2157 | } | |
2158 | ||
2159 | /* copy source length */ | |
fc25abce | 2160 | BT_LOGD_STR("Copying sequence field's length field."); |
50842bdc | 2161 | dst_length = bt_field_copy(src_length); |
fc25abce | 2162 | BT_PUT(src_length); |
59ab494d | 2163 | if (!dst_length) { |
fc25abce | 2164 | BT_LOGE_STR("Cannot copy sequence field's length field."); |
59ab494d PP |
2165 | ret = -1; |
2166 | goto end; | |
2167 | } | |
2168 | ||
2169 | /* this will initialize the destination sequence's internal array */ | |
50842bdc | 2170 | ret = bt_field_sequence_set_length(dst, dst_length); |
83509119 | 2171 | bt_put(dst_length); |
59ab494d | 2172 | if (ret) { |
fc25abce PP |
2173 | BT_LOGE("Cannot set sequence field copy's length field: " |
2174 | "dst-length-field-addr=%p", dst_length); | |
2175 | ret = -1; | |
59ab494d PP |
2176 | goto end; |
2177 | } | |
2178 | ||
f6ccaed9 | 2179 | BT_ASSERT(sequence_dst->elements->len == sequence_src->elements->len); |
59ab494d | 2180 | |
87d43dc1 | 2181 | for (i = 0; i < sequence_src->elements->len; i++) { |
50842bdc | 2182 | struct bt_field *field = |
50fd95bf | 2183 | g_ptr_array_index(sequence_src->elements, i); |
50842bdc | 2184 | struct bt_field *field_copy = NULL; |
87d43dc1 | 2185 | |
50fd95bf | 2186 | if (field) { |
fc25abce PP |
2187 | BT_LOGD("Copying sequence field's element field: field-addr=%p, " |
2188 | "index=%" PRId64, field, i); | |
50842bdc | 2189 | field_copy = bt_field_copy(field); |
50fd95bf | 2190 | if (!field_copy) { |
fc25abce PP |
2191 | BT_LOGE("Cannot copy sequence field's element field: " |
2192 | "src-field-addr=%p, index=%" PRId64, | |
2193 | field, i); | |
50fd95bf PP |
2194 | ret = -1; |
2195 | goto end; | |
2196 | } | |
87d43dc1 | 2197 | } |
59ab494d | 2198 | |
8bfa3f9c | 2199 | g_ptr_array_index(sequence_dst->elements, i) = field_copy; |
87d43dc1 | 2200 | } |
fc25abce PP |
2201 | |
2202 | BT_LOGD_STR("Copied sequence field."); | |
2203 | ||
87d43dc1 JG |
2204 | end: |
2205 | return ret; | |
2206 | } | |
2207 | ||
2208 | static | |
f6ccaed9 | 2209 | int bt_field_string_copy_recursive(struct bt_field *src, |
50842bdc | 2210 | struct bt_field *dst) |
87d43dc1 JG |
2211 | { |
2212 | int ret = 0; | |
50842bdc | 2213 | struct bt_field_string *string_src, *string_dst; |
87d43dc1 | 2214 | |
fc25abce PP |
2215 | BT_LOGD("Copying string field: src-field-addr=%p, dst-field-addr=%p", |
2216 | src, dst); | |
50842bdc PP |
2217 | string_src = container_of(src, struct bt_field_string, parent); |
2218 | string_dst = container_of(dst, struct bt_field_string, parent); | |
87d43dc1 JG |
2219 | |
2220 | if (string_src->payload) { | |
2221 | string_dst->payload = g_string_new(string_src->payload->str); | |
2222 | if (!string_dst->payload) { | |
fc25abce | 2223 | BT_LOGE_STR("Failed to allocate a GString."); |
87d43dc1 JG |
2224 | ret = -1; |
2225 | goto end; | |
2226 | } | |
2227 | } | |
fc25abce PP |
2228 | |
2229 | BT_LOGD_STR("Copied string field."); | |
2230 | ||
87d43dc1 JG |
2231 | end: |
2232 | return ret; | |
2233 | } | |
2234 | ||
273b65be | 2235 | static |
50842bdc | 2236 | int increase_packet_size(struct bt_stream_pos *pos) |
273b65be JG |
2237 | { |
2238 | int ret; | |
2239 | ||
f6ccaed9 | 2240 | BT_ASSERT(pos); |
fc25abce PP |
2241 | BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", " |
2242 | "cur-packet-size=%" PRIu64, | |
2243 | pos->offset, pos->packet_size); | |
273b65be JG |
2244 | ret = munmap_align(pos->base_mma); |
2245 | if (ret) { | |
c606e638 PP |
2246 | BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping", |
2247 | ": ret=%d", ret); | |
273b65be JG |
2248 | goto end; |
2249 | } | |
2250 | ||
2251 | pos->packet_size += PACKET_LEN_INCREMENT; | |
d9548894 MD |
2252 | do { |
2253 | ret = bt_posix_fallocate(pos->fd, pos->mmap_offset, | |
2254 | pos->packet_size / CHAR_BIT); | |
2255 | } while (ret == EINTR); | |
273b65be | 2256 | if (ret) { |
c606e638 PP |
2257 | BT_LOGE_ERRNO("Failed to preallocate memory space", |
2258 | ": ret=%d", ret); | |
d9548894 MD |
2259 | errno = EINTR; |
2260 | ret = -1; | |
273b65be JG |
2261 | goto end; |
2262 | } | |
2263 | ||
2264 | pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot, | |
2265 | pos->flags, pos->fd, pos->mmap_offset); | |
2266 | if (pos->base_mma == MAP_FAILED) { | |
c606e638 PP |
2267 | BT_LOGE_ERRNO("Failed to perform an aligned memory mapping", |
2268 | ": ret=%d", ret); | |
273b65be JG |
2269 | ret = -1; |
2270 | } | |
fc25abce PP |
2271 | |
2272 | BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", " | |
2273 | "new-packet-size=%" PRIu64, | |
2274 | pos->offset, pos->packet_size); | |
f6ccaed9 | 2275 | BT_ASSERT(pos->packet_size % 8 == 0); |
b3376dd9 | 2276 | |
273b65be JG |
2277 | end: |
2278 | return ret; | |
2279 | } | |
918be005 PP |
2280 | |
2281 | static | |
50842bdc | 2282 | void generic_field_freeze(struct bt_field *field) |
918be005 | 2283 | { |
d990a4fb | 2284 | field->frozen = true; |
918be005 PP |
2285 | } |
2286 | ||
2287 | static | |
f6ccaed9 | 2288 | void bt_field_enumeration_freeze_recursive(struct bt_field *field) |
918be005 | 2289 | { |
50842bdc PP |
2290 | struct bt_field_enumeration *enum_field = |
2291 | container_of(field, struct bt_field_enumeration, parent); | |
918be005 | 2292 | |
fc25abce PP |
2293 | BT_LOGD("Freezing enumeration field object: addr=%p", field); |
2294 | BT_LOGD("Freezing enumeration field object's contained payload field: payload-field-addr=%p", enum_field->payload); | |
f6ccaed9 | 2295 | bt_field_freeze_recursive(enum_field->payload); |
918be005 PP |
2296 | generic_field_freeze(field); |
2297 | } | |
2298 | ||
2299 | static | |
f6ccaed9 | 2300 | void bt_field_structure_freeze_recursive(struct bt_field *field) |
918be005 | 2301 | { |
fc25abce | 2302 | int64_t i; |
50842bdc PP |
2303 | struct bt_field_structure *structure_field = |
2304 | container_of(field, struct bt_field_structure, parent); | |
918be005 | 2305 | |
fc25abce PP |
2306 | BT_LOGD("Freezing structure field object: addr=%p", field); |
2307 | ||
918be005 | 2308 | for (i = 0; i < structure_field->fields->len; i++) { |
50842bdc | 2309 | struct bt_field *field = |
918be005 PP |
2310 | g_ptr_array_index(structure_field->fields, i); |
2311 | ||
fc25abce PP |
2312 | BT_LOGD("Freezing structure field's field: field-addr=%p, index=%" PRId64, |
2313 | field, i); | |
f6ccaed9 | 2314 | bt_field_freeze_recursive(field); |
918be005 PP |
2315 | } |
2316 | ||
2317 | generic_field_freeze(field); | |
2318 | } | |
2319 | ||
2320 | static | |
f6ccaed9 | 2321 | void bt_field_variant_freeze_recursive(struct bt_field *field) |
918be005 | 2322 | { |
50842bdc PP |
2323 | struct bt_field_variant *variant_field = |
2324 | container_of(field, struct bt_field_variant, parent); | |
918be005 | 2325 | |
fc25abce PP |
2326 | BT_LOGD("Freezing variant field object: addr=%p", field); |
2327 | BT_LOGD("Freezing variant field object's tag field: tag-field-addr=%p", variant_field->tag); | |
f6ccaed9 | 2328 | bt_field_freeze_recursive(variant_field->tag); |
fc25abce | 2329 | BT_LOGD("Freezing variant field object's payload field: payload-field-addr=%p", variant_field->payload); |
f6ccaed9 | 2330 | bt_field_freeze_recursive(variant_field->payload); |
918be005 PP |
2331 | generic_field_freeze(field); |
2332 | } | |
2333 | ||
2334 | static | |
f6ccaed9 | 2335 | void bt_field_array_freeze_recursive(struct bt_field *field) |
918be005 | 2336 | { |
fc25abce | 2337 | int64_t i; |
50842bdc PP |
2338 | struct bt_field_array *array_field = |
2339 | container_of(field, struct bt_field_array, parent); | |
918be005 | 2340 | |
fc25abce PP |
2341 | BT_LOGD("Freezing array field object: addr=%p", field); |
2342 | ||
918be005 | 2343 | for (i = 0; i < array_field->elements->len; i++) { |
50842bdc | 2344 | struct bt_field *elem_field = |
918be005 PP |
2345 | g_ptr_array_index(array_field->elements, i); |
2346 | ||
fc25abce PP |
2347 | BT_LOGD("Freezing array field object's element field: " |
2348 | "element-field-addr=%p, index=%" PRId64, | |
2349 | elem_field, i); | |
f6ccaed9 | 2350 | bt_field_freeze_recursive(elem_field); |
918be005 PP |
2351 | } |
2352 | ||
2353 | generic_field_freeze(field); | |
2354 | } | |
2355 | ||
2356 | static | |
f6ccaed9 | 2357 | void bt_field_sequence_freeze_recursive(struct bt_field *field) |
918be005 | 2358 | { |
fc25abce | 2359 | int64_t i; |
50842bdc PP |
2360 | struct bt_field_sequence *sequence_field = |
2361 | container_of(field, struct bt_field_sequence, parent); | |
918be005 | 2362 | |
fc25abce PP |
2363 | BT_LOGD("Freezing sequence field object: addr=%p", field); |
2364 | BT_LOGD("Freezing sequence field object's length field: length-field-addr=%p", | |
2365 | sequence_field->length); | |
f6ccaed9 | 2366 | bt_field_freeze_recursive(sequence_field->length); |
918be005 PP |
2367 | |
2368 | for (i = 0; i < sequence_field->elements->len; i++) { | |
50842bdc | 2369 | struct bt_field *elem_field = |
918be005 PP |
2370 | g_ptr_array_index(sequence_field->elements, i); |
2371 | ||
fc25abce PP |
2372 | BT_LOGD("Freezing sequence field object's element field: " |
2373 | "element-field-addr=%p, index=%" PRId64, | |
2374 | elem_field, i); | |
f6ccaed9 | 2375 | bt_field_freeze_recursive(elem_field); |
918be005 PP |
2376 | } |
2377 | ||
2378 | generic_field_freeze(field); | |
2379 | } | |
2380 | ||
2381 | BT_HIDDEN | |
f6ccaed9 | 2382 | void _bt_field_freeze_recursive(struct bt_field *field) |
918be005 | 2383 | { |
50842bdc | 2384 | enum bt_field_type_id type_id; |
35f77de4 | 2385 | |
918be005 PP |
2386 | if (!field) { |
2387 | goto end; | |
2388 | } | |
2389 | ||
fc25abce | 2390 | if (field->frozen) { |
35f77de4 JG |
2391 | goto end; |
2392 | } | |
918be005 | 2393 | |
fc25abce | 2394 | BT_LOGD("Freezing field object: addr=%p", field); |
f6ccaed9 | 2395 | BT_ASSERT(field_type_has_known_id(field->type)); |
50842bdc | 2396 | type_id = bt_field_get_type_id(field); |
35f77de4 | 2397 | field_freeze_funcs[type_id](field); |
918be005 PP |
2398 | end: |
2399 | return; | |
2400 | } | |
76f869ab JG |
2401 | |
2402 | static | |
50842bdc | 2403 | bt_bool bt_field_generic_is_set(struct bt_field *field) |
76f869ab JG |
2404 | { |
2405 | return field && field->payload_set; | |
2406 | } | |
2407 | ||
2408 | static | |
f6ccaed9 | 2409 | bt_bool bt_field_enumeration_is_set_recursive(struct bt_field *field) |
76f869ab | 2410 | { |
d4bf905a | 2411 | bt_bool is_set = BT_FALSE; |
50842bdc | 2412 | struct bt_field_enumeration *enumeration; |
76f869ab | 2413 | |
f6ccaed9 | 2414 | BT_ASSERT(field); |
50842bdc | 2415 | enumeration = container_of(field, struct bt_field_enumeration, |
76f869ab JG |
2416 | parent); |
2417 | if (!enumeration->payload) { | |
2418 | goto end; | |
2419 | } | |
2420 | ||
f6ccaed9 | 2421 | is_set = bt_field_is_set_recursive(enumeration->payload); |
76f869ab | 2422 | end: |
d4bf905a | 2423 | return is_set; |
76f869ab JG |
2424 | } |
2425 | ||
2426 | static | |
f6ccaed9 | 2427 | bt_bool bt_field_structure_is_set_recursive(struct bt_field *field) |
76f869ab | 2428 | { |
d4bf905a | 2429 | bt_bool is_set = BT_FALSE; |
76f869ab | 2430 | size_t i; |
50842bdc | 2431 | struct bt_field_structure *structure; |
76f869ab | 2432 | |
f6ccaed9 | 2433 | BT_ASSERT(field); |
50842bdc | 2434 | structure = container_of(field, struct bt_field_structure, parent); |
76f869ab | 2435 | for (i = 0; i < structure->fields->len; i++) { |
f6ccaed9 | 2436 | is_set = bt_field_is_set_recursive( |
f1367c62 | 2437 | structure->fields->pdata[i]); |
d4bf905a | 2438 | if (!is_set) { |
76f869ab JG |
2439 | goto end; |
2440 | } | |
2441 | } | |
2442 | end: | |
d4bf905a | 2443 | return is_set; |
76f869ab JG |
2444 | } |
2445 | ||
2446 | static | |
f6ccaed9 | 2447 | bt_bool bt_field_variant_is_set_recursive(struct bt_field *field) |
76f869ab | 2448 | { |
50842bdc | 2449 | struct bt_field_variant *variant; |
76f869ab | 2450 | |
f6ccaed9 | 2451 | BT_ASSERT(field); |
50842bdc | 2452 | variant = container_of(field, struct bt_field_variant, parent); |
f6ccaed9 | 2453 | return bt_field_is_set_recursive(variant->payload); |
76f869ab JG |
2454 | } |
2455 | ||
2456 | static | |
f6ccaed9 | 2457 | bt_bool bt_field_array_is_set_recursive(struct bt_field *field) |
76f869ab JG |
2458 | { |
2459 | size_t i; | |
d4bf905a | 2460 | bt_bool is_set = BT_FALSE; |
50842bdc | 2461 | struct bt_field_array *array; |
76f869ab | 2462 | |
f6ccaed9 | 2463 | BT_ASSERT(field); |
50842bdc | 2464 | array = container_of(field, struct bt_field_array, parent); |
76f869ab | 2465 | for (i = 0; i < array->elements->len; i++) { |
f6ccaed9 | 2466 | is_set = bt_field_is_set_recursive(array->elements->pdata[i]); |
d4bf905a | 2467 | if (!is_set) { |
76f869ab JG |
2468 | goto end; |
2469 | } | |
2470 | } | |
2471 | end: | |
d4bf905a | 2472 | return is_set; |
76f869ab JG |
2473 | } |
2474 | ||
2475 | static | |
f6ccaed9 | 2476 | bt_bool bt_field_sequence_is_set_recursive(struct bt_field *field) |
76f869ab JG |
2477 | { |
2478 | size_t i; | |
d4bf905a | 2479 | bt_bool is_set = BT_FALSE; |
50842bdc | 2480 | struct bt_field_sequence *sequence; |
76f869ab | 2481 | |
f6ccaed9 | 2482 | BT_ASSERT(field); |
50842bdc | 2483 | sequence = container_of(field, struct bt_field_sequence, parent); |
6ead1648 JG |
2484 | if (!sequence->elements) { |
2485 | goto end; | |
2486 | } | |
2487 | ||
76f869ab | 2488 | for (i = 0; i < sequence->elements->len; i++) { |
f6ccaed9 | 2489 | is_set = bt_field_is_set_recursive(sequence->elements->pdata[i]); |
d4bf905a | 2490 | if (!is_set) { |
76f869ab JG |
2491 | goto end; |
2492 | } | |
2493 | } | |
2494 | end: | |
d4bf905a | 2495 | return is_set; |
76f869ab | 2496 | } |