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