docs: Add supported versions and fix-backport policy
[lttng-tools.git] / src / common / event-field-value.cpp
CommitLineData
d28fcdec
PP
1/*
2 * event-field-value.c
3 *
4 * Linux Trace Toolkit Control Library
5 *
6 * Copyright (C) 2020 Philippe Proulx <pproulx@efficios.com>
7 *
8 * SPDX-License-Identifier: LGPL-2.1-only
9 *
10 */
11
12#define _LGPL_SOURCE
c9e313bc
SM
13#include <common/error.hpp>
14#include <common/macros.hpp>
28ab034a 15
c9e313bc 16#include <lttng/event-field-value-internal.hpp>
d28fcdec 17
28ab034a
JG
18#include <stdbool.h>
19#include <stddef.h>
20
21static struct lttng_event_field_value *
22create_empty_field_val(enum lttng_event_field_value_type type, size_t size)
d28fcdec
PP
23{
24 struct lttng_event_field_value *field_val;
25
64803277 26 field_val = zmalloc<lttng_event_field_value>(size);
d28fcdec
PP
27 if (!field_val) {
28 goto end;
29 }
30
31 field_val->type = type;
32
33end:
34 return field_val;
35}
36
28ab034a 37struct lttng_event_field_value *lttng_event_field_value_uint_create(uint64_t val)
d28fcdec
PP
38{
39 struct lttng_event_field_value_uint *field_val;
40
28ab034a
JG
41 field_val = lttng::utils::container_of(
42 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT,
43 sizeof(*field_val)),
44 &lttng_event_field_value_uint::parent);
d28fcdec
PP
45 if (!field_val) {
46 goto error;
47 }
48
49 field_val->val = val;
50 goto end;
51
52error:
53 lttng_event_field_value_destroy(&field_val->parent);
54
55end:
56 return &field_val->parent;
57}
58
28ab034a 59struct lttng_event_field_value *lttng_event_field_value_int_create(int64_t val)
d28fcdec
PP
60{
61 struct lttng_event_field_value_int *field_val;
62
28ab034a
JG
63 field_val = lttng::utils::container_of(
64 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT, sizeof(*field_val)),
65 &lttng_event_field_value_int::parent);
d28fcdec
PP
66 if (!field_val) {
67 goto error;
68 }
69
70 field_val->val = val;
71 goto end;
72
73error:
74 lttng_event_field_value_destroy(&field_val->parent);
75
76end:
77 return &field_val->parent;
78}
79
28ab034a
JG
80static struct lttng_event_field_value_enum *
81create_enum_field_val(enum lttng_event_field_value_type type, size_t size)
d28fcdec
PP
82{
83 struct lttng_event_field_value_enum *field_val;
84
0114db0e 85 field_val = lttng::utils::container_of(create_empty_field_val(type, size),
28ab034a 86 &lttng_event_field_value_enum::parent);
d28fcdec
PP
87 if (!field_val) {
88 goto error;
89 }
90
91 lttng_dynamic_pointer_array_init(&field_val->labels, free);
92 goto end;
93
94error:
95 lttng_event_field_value_destroy(&field_val->parent);
96
97end:
98 return field_val;
99}
100
28ab034a 101struct lttng_event_field_value *lttng_event_field_value_enum_uint_create(uint64_t val)
d28fcdec
PP
102{
103 struct lttng_event_field_value_enum_uint *field_val;
104
28ab034a
JG
105 field_val = lttng::utils::container_of(
106 create_enum_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM,
107 sizeof(*field_val)),
108 &lttng_event_field_value_enum_uint::parent);
d28fcdec
PP
109 if (!field_val) {
110 goto error;
111 }
112
113 field_val->val = val;
114 goto end;
115
116error:
117 lttng_event_field_value_destroy(&field_val->parent.parent);
118
119end:
120 return &field_val->parent.parent;
121}
122
28ab034a 123struct lttng_event_field_value *lttng_event_field_value_enum_int_create(int64_t val)
d28fcdec
PP
124{
125 struct lttng_event_field_value_enum_int *field_val;
126
28ab034a
JG
127 field_val = lttng::utils::container_of(
128 create_enum_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM, sizeof(*field_val)),
129 &lttng_event_field_value_enum_int::parent);
d28fcdec
PP
130 if (!field_val) {
131 goto error;
132 }
133
134 field_val->val = val;
135 goto end;
136
137error:
138 lttng_event_field_value_destroy(&field_val->parent.parent);
139
140end:
141 return &field_val->parent.parent;
142}
143
d28fcdec
PP
144struct lttng_event_field_value *lttng_event_field_value_real_create(double val)
145{
0114db0e 146 struct lttng_event_field_value_real *field_val = lttng::utils::container_of(
28ab034a
JG
147 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_REAL, sizeof(*field_val)),
148 &lttng_event_field_value_real::parent);
d28fcdec
PP
149
150 if (!field_val) {
151 goto error;
152 }
153
154 field_val->val = val;
155 goto end;
156
157error:
158 lttng_event_field_value_destroy(&field_val->parent);
159
160end:
161 return &field_val->parent;
162}
163
28ab034a
JG
164struct lttng_event_field_value *lttng_event_field_value_string_create_with_size(const char *val,
165 size_t size)
d28fcdec 166{
0114db0e 167 struct lttng_event_field_value_string *field_val = lttng::utils::container_of(
28ab034a
JG
168 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_STRING, sizeof(*field_val)),
169 &lttng_event_field_value_string::parent);
d28fcdec
PP
170
171 if (!field_val) {
172 goto error;
173 }
174
ceaa850a
MD
175 if (size) {
176 LTTNG_ASSERT(val);
177 field_val->val = strndup(val, size);
178 } else {
179 /*
180 * User code do not expect a NULL string pointer. Populate with
181 * an empty string when length is 0.
182 */
183 field_val->val = strdup("");
184 }
d28fcdec
PP
185 if (!field_val->val) {
186 goto error;
187 }
188
189 goto end;
190
191error:
192 lttng_event_field_value_destroy(&field_val->parent);
193
194end:
195 return &field_val->parent;
196}
197
28ab034a 198struct lttng_event_field_value *lttng_event_field_value_string_create(const char *val)
d28fcdec 199{
a0377dfe 200 LTTNG_ASSERT(val);
28ab034a 201 return lttng_event_field_value_string_create_with_size(val, strlen(val));
d28fcdec
PP
202}
203
28ab034a 204static void destroy_field_val(void *field_val)
d28fcdec 205{
a6bc4ca9 206 lttng_event_field_value_destroy((lttng_event_field_value *) field_val);
d28fcdec
PP
207}
208
cd9adb8b 209struct lttng_event_field_value *lttng_event_field_value_array_create()
d28fcdec 210{
0114db0e 211 struct lttng_event_field_value_array *field_val = lttng::utils::container_of(
28ab034a
JG
212 create_empty_field_val(LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY, sizeof(*field_val)),
213 &lttng_event_field_value_array::parent);
d28fcdec
PP
214
215 if (!field_val) {
216 goto error;
217 }
218
219 lttng_dynamic_pointer_array_init(&field_val->elems, destroy_field_val);
220 goto end;
221
222error:
223 lttng_event_field_value_destroy(&field_val->parent);
224
225end:
226 return &field_val->parent;
227}
228
d28fcdec
PP
229void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val)
230{
231 if (!field_val) {
232 goto end;
233 }
234
235 switch (field_val->type) {
236 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
237 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
238 {
28ab034a
JG
239 struct lttng_event_field_value_enum *enum_field_val = lttng::utils::container_of(
240 field_val, &lttng_event_field_value_enum::parent);
d28fcdec
PP
241
242 lttng_dynamic_pointer_array_reset(&enum_field_val->labels);
243 break;
244 }
245 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
246 {
28ab034a
JG
247 struct lttng_event_field_value_string *str_field_val = lttng::utils::container_of(
248 field_val, &lttng_event_field_value_string::parent);
d28fcdec
PP
249
250 free(str_field_val->val);
251 break;
252 }
253 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
254 {
28ab034a
JG
255 struct lttng_event_field_value_array *array_field_expr = lttng::utils::container_of(
256 field_val, &lttng_event_field_value_array::parent);
d28fcdec
PP
257
258 lttng_dynamic_pointer_array_reset(&array_field_expr->elems);
259 break;
260 }
261 default:
262 break;
263 }
264
265 free(field_val);
266
267end:
268 return;
269}
270
28ab034a
JG
271int lttng_event_field_value_enum_append_label_with_size(struct lttng_event_field_value *field_val,
272 const char *label,
273 size_t size)
d28fcdec
PP
274{
275 int ret;
276 char *new_label;
277
a0377dfe
FD
278 LTTNG_ASSERT(field_val);
279 LTTNG_ASSERT(label);
d28fcdec
PP
280 new_label = strndup(label, size);
281 if (!new_label) {
282 ret = -1;
283 goto end;
284 }
285
286 ret = lttng_dynamic_pointer_array_add_pointer(
28ab034a
JG
287 &lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent)
288 ->labels,
289 new_label);
d28fcdec 290 if (ret == 0) {
cd9adb8b 291 new_label = nullptr;
d28fcdec
PP
292 }
293
294end:
295 free(new_label);
296 return ret;
297}
298
28ab034a
JG
299int lttng_event_field_value_enum_append_label(struct lttng_event_field_value *field_val,
300 const char *label)
d28fcdec 301{
a0377dfe 302 LTTNG_ASSERT(label);
28ab034a 303 return lttng_event_field_value_enum_append_label_with_size(field_val, label, strlen(label));
d28fcdec
PP
304}
305
28ab034a
JG
306int lttng_event_field_value_array_append(struct lttng_event_field_value *array_field_val,
307 struct lttng_event_field_value *field_val)
d28fcdec 308{
a0377dfe
FD
309 LTTNG_ASSERT(array_field_val);
310 LTTNG_ASSERT(field_val);
d28fcdec 311 return lttng_dynamic_pointer_array_add_pointer(
28ab034a
JG
312 &lttng::utils::container_of(array_field_val, &lttng_event_field_value_array::parent)
313 ->elems,
314 field_val);
d28fcdec
PP
315}
316
28ab034a 317int lttng_event_field_value_array_append_unavailable(struct lttng_event_field_value *array_field_val)
d28fcdec 318{
a0377dfe 319 LTTNG_ASSERT(array_field_val);
d28fcdec 320 return lttng_dynamic_pointer_array_add_pointer(
28ab034a
JG
321 &lttng::utils::container_of(array_field_val, &lttng_event_field_value_array::parent)
322 ->elems,
cd9adb8b 323 nullptr);
d28fcdec
PP
324}
325
28ab034a
JG
326enum lttng_event_field_value_type
327lttng_event_field_value_get_type(const struct lttng_event_field_value *field_val)
d28fcdec
PP
328{
329 enum lttng_event_field_value_type type;
330
331 if (!field_val) {
332 type = LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID;
333 goto end;
334 }
335
336 type = field_val->type;
337
338end:
339 return type;
340}
341
342enum lttng_event_field_value_status
28ab034a
JG
343lttng_event_field_value_unsigned_int_get_value(const struct lttng_event_field_value *field_val,
344 uint64_t *val)
d28fcdec
PP
345{
346 enum lttng_event_field_value_status status;
347
348 if (!field_val || !val) {
349 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
350 goto end;
351 }
352
353 switch (field_val->type) {
354 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_INT:
28ab034a
JG
355 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_uint::parent)
356 ->val;
d28fcdec
PP
357 break;
358 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
9918e00a 359 {
0114db0e 360 const struct lttng_event_field_value_enum *field_val_enum =
28ab034a
JG
361 lttng::utils::container_of(field_val,
362 &lttng_event_field_value_enum::parent);
0114db0e 363 const struct lttng_event_field_value_enum_uint *field_val_enum_uint =
28ab034a
JG
364 lttng::utils::container_of(field_val_enum,
365 &lttng_event_field_value_enum_uint::parent);
9918e00a 366 *val = field_val_enum_uint->val;
d28fcdec 367 break;
9918e00a 368 }
d28fcdec
PP
369 default:
370 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
371 goto end;
372 }
373
374 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
375
376end:
377 return status;
378}
379
380enum lttng_event_field_value_status
28ab034a
JG
381lttng_event_field_value_signed_int_get_value(const struct lttng_event_field_value *field_val,
382 int64_t *val)
d28fcdec
PP
383{
384 enum lttng_event_field_value_status status;
385
386 if (!field_val || !val) {
387 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
388 goto end;
389 }
390
391 switch (field_val->type) {
392 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
28ab034a
JG
393 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_int::parent)
394 ->val;
d28fcdec
PP
395 break;
396 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
9918e00a 397 {
28ab034a
JG
398 const struct lttng_event_field_value_enum *field_val_enum =
399 lttng::utils::container_of(field_val,
400 &lttng_event_field_value_enum::parent);
0114db0e 401 const struct lttng_event_field_value_enum_int *field_val_enum_uint =
28ab034a
JG
402 lttng::utils::container_of(field_val_enum,
403 &lttng_event_field_value_enum_int::parent);
9918e00a 404 *val = field_val_enum_uint->val;
d28fcdec 405 break;
9918e00a 406 }
d28fcdec
PP
407 default:
408 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
409 goto end;
410 }
411
412 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
413
414end:
415 return status;
416}
417
418enum lttng_event_field_value_status
28ab034a 419lttng_event_field_value_real_get_value(const struct lttng_event_field_value *field_val, double *val)
d28fcdec
PP
420{
421 enum lttng_event_field_value_status status;
422
28ab034a 423 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_REAL || !val) {
d28fcdec
PP
424 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
425 goto end;
426 }
427
28ab034a 428 *val = lttng::utils::container_of(field_val, &lttng_event_field_value_real::parent)->val;
d28fcdec
PP
429 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
430
431end:
432 return status;
433}
434
28ab034a 435static bool is_enum_field_val(const struct lttng_event_field_value *field_val)
d28fcdec
PP
436{
437 return field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM ||
438 field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM;
439}
440
441enum lttng_event_field_value_status
28ab034a
JG
442lttng_event_field_value_enum_get_label_count(const struct lttng_event_field_value *field_val,
443 unsigned int *count)
d28fcdec
PP
444{
445 enum lttng_event_field_value_status status;
446
447 if (!field_val || !is_enum_field_val(field_val) || !count) {
448 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
449 goto end;
450 }
451
452 *count = (unsigned int) lttng_dynamic_pointer_array_get_count(
28ab034a
JG
453 &lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent)
454 ->labels);
d28fcdec
PP
455 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
456
457end:
458 return status;
459}
460
28ab034a
JG
461const char *
462lttng_event_field_value_enum_get_label_at_index(const struct lttng_event_field_value *field_val,
463 unsigned int index)
d28fcdec
PP
464{
465 const char *ret;
466 const struct lttng_event_field_value_enum *enum_field_val;
467
468 if (!field_val || !is_enum_field_val(field_val)) {
cd9adb8b 469 ret = nullptr;
d28fcdec
PP
470 goto end;
471 }
472
28ab034a
JG
473 enum_field_val =
474 lttng::utils::container_of(field_val, &lttng_event_field_value_enum::parent);
d28fcdec
PP
475
476 if (index >= lttng_dynamic_pointer_array_get_count(&enum_field_val->labels)) {
cd9adb8b 477 ret = nullptr;
d28fcdec
PP
478 goto end;
479 }
480
a6bc4ca9 481 ret = (const char *) lttng_dynamic_pointer_array_get_pointer(&enum_field_val->labels,
28ab034a 482 index);
d28fcdec
PP
483
484end:
485 return ret;
486}
487
28ab034a
JG
488enum lttng_event_field_value_status
489lttng_event_field_value_string_get_value(const struct lttng_event_field_value *field_val,
490 const char **value)
d28fcdec 491{
7c920b63 492 enum lttng_event_field_value_status status;
d28fcdec
PP
493
494 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_STRING) {
7c920b63 495 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
d28fcdec
PP
496 goto end;
497 }
498
28ab034a
JG
499 *value =
500 lttng::utils::container_of(field_val, &lttng_event_field_value_string::parent)->val;
7c920b63 501 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
d28fcdec
PP
502
503end:
7c920b63 504 return status;
d28fcdec
PP
505}
506
28ab034a
JG
507enum lttng_event_field_value_status
508lttng_event_field_value_array_get_length(const struct lttng_event_field_value *field_val,
509 unsigned int *length)
d28fcdec
PP
510{
511 enum lttng_event_field_value_status status;
512
28ab034a 513 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY || !length) {
d28fcdec
PP
514 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
515 goto end;
516 }
517
518 *length = (unsigned int) lttng_dynamic_pointer_array_get_count(
28ab034a
JG
519 &lttng::utils::container_of(field_val, &lttng_event_field_value_array::parent)
520 ->elems);
d28fcdec
PP
521 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
522
523end:
524 return status;
525}
526
28ab034a
JG
527enum lttng_event_field_value_status lttng_event_field_value_array_get_element_at_index(
528 const struct lttng_event_field_value *field_val,
529 unsigned int index,
530 const struct lttng_event_field_value **elem_field_val)
d28fcdec
PP
531{
532 enum lttng_event_field_value_status status;
533 const struct lttng_event_field_value_array *array_field_val;
534
535 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
28ab034a 536 !elem_field_val) {
d28fcdec
PP
537 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
538 goto end;
539 }
540
28ab034a
JG
541 array_field_val =
542 lttng::utils::container_of(field_val, &lttng_event_field_value_array::parent);
d28fcdec
PP
543
544 if (index >= lttng_dynamic_pointer_array_get_count(&array_field_val->elems)) {
545 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
546 goto end;
547 }
548
a6bc4ca9 549 *elem_field_val = (lttng_event_field_value *) lttng_dynamic_pointer_array_get_pointer(
28ab034a 550 &array_field_val->elems, index);
d28fcdec
PP
551 if (*elem_field_val) {
552 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
553 } else {
554 status = LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE;
555 }
556
557end:
558 return status;
559}
This page took 0.077284 seconds and 4 git commands to generate.