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