Fix: event field value: assertion fails on empty string
[lttng-tools.git] / src / common / event-field-value.c
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
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
21static
22struct 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
34end:
35 return field_val;
36}
37
38LTTNG_HIDDEN
39struct 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
55error:
56 lttng_event_field_value_destroy(&field_val->parent);
57
58end:
59 return &field_val->parent;
60}
61
62LTTNG_HIDDEN
63struct 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
79error:
80 lttng_event_field_value_destroy(&field_val->parent);
81
82end:
83 return &field_val->parent;
84}
85
86static
87struct 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
101error:
102 lttng_event_field_value_destroy(&field_val->parent);
103
104end:
105 return field_val;
106}
107
108LTTNG_HIDDEN
109struct 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
125error:
126 lttng_event_field_value_destroy(&field_val->parent.parent);
127
128end:
129 return &field_val->parent.parent;
130}
131
132LTTNG_HIDDEN
133struct 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
149error:
150 lttng_event_field_value_destroy(&field_val->parent.parent);
151
152end:
153 return &field_val->parent.parent;
154}
155
156LTTNG_HIDDEN
157struct 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
172error:
173 lttng_event_field_value_destroy(&field_val->parent);
174
175end:
176 return &field_val->parent;
177}
178
179LTTNG_HIDDEN
180struct 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
f6181513
MD
193 if (size) {
194 assert(val);
195 field_val->val = strndup(val, size);
196 } else {
197 /*
198 * User code do not expect a NULL string pointer. Populate with
199 * an empty string when length is 0.
200 */
201 field_val->val = strdup("");
202 }
d28fcdec
PP
203 if (!field_val->val) {
204 goto error;
205 }
206
207 goto end;
208
209error:
210 lttng_event_field_value_destroy(&field_val->parent);
211
212end:
213 return &field_val->parent;
214}
215
216LTTNG_HIDDEN
217struct lttng_event_field_value *lttng_event_field_value_string_create(
218 const char *val)
219{
220 assert(val);
221 return lttng_event_field_value_string_create_with_size(val,
222 strlen(val));
223}
224
225static
226void destroy_field_val(void *field_val)
227{
228 lttng_event_field_value_destroy(field_val);
229}
230
231LTTNG_HIDDEN
232struct lttng_event_field_value *lttng_event_field_value_array_create(void)
233{
234 struct lttng_event_field_value_array *field_val = container_of(
235 create_empty_field_val(
236 LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY,
237 sizeof(*field_val)),
238 struct lttng_event_field_value_array, parent);
239
240 if (!field_val) {
241 goto error;
242 }
243
244 lttng_dynamic_pointer_array_init(&field_val->elems, destroy_field_val);
245 goto end;
246
247error:
248 lttng_event_field_value_destroy(&field_val->parent);
249
250end:
251 return &field_val->parent;
252}
253
254LTTNG_HIDDEN
255void lttng_event_field_value_destroy(struct lttng_event_field_value *field_val)
256{
257 if (!field_val) {
258 goto end;
259 }
260
261 switch (field_val->type) {
262 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
263 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
264 {
265 struct lttng_event_field_value_enum *enum_field_val =
266 container_of(field_val,
267 struct lttng_event_field_value_enum, parent);
268
269 lttng_dynamic_pointer_array_reset(&enum_field_val->labels);
270 break;
271 }
272 case LTTNG_EVENT_FIELD_VALUE_TYPE_STRING:
273 {
274 struct lttng_event_field_value_string *str_field_val =
275 container_of(field_val,
276 struct lttng_event_field_value_string, parent);
277
278 free(str_field_val->val);
279 break;
280 }
281 case LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY:
282 {
283 struct lttng_event_field_value_array *array_field_expr =
284 container_of(field_val,
285 struct lttng_event_field_value_array,
286 parent);
287
288 lttng_dynamic_pointer_array_reset(&array_field_expr->elems);
289 break;
290 }
291 default:
292 break;
293 }
294
295 free(field_val);
296
297end:
298 return;
299}
300
301LTTNG_HIDDEN
302int lttng_event_field_value_enum_append_label_with_size(
303 struct lttng_event_field_value *field_val,
304 const char *label, size_t size)
305{
306 int ret;
307 char *new_label;
308
309 assert(field_val);
310 assert(label);
311 new_label = strndup(label, size);
312 if (!new_label) {
313 ret = -1;
314 goto end;
315 }
316
317 ret = lttng_dynamic_pointer_array_add_pointer(
318 &container_of(field_val,
319 struct lttng_event_field_value_enum, parent)->labels,
320 new_label);
321 if (ret == 0) {
322 new_label = NULL;
323 }
324
325end:
326 free(new_label);
327 return ret;
328}
329
330LTTNG_HIDDEN
331int lttng_event_field_value_enum_append_label(
332 struct lttng_event_field_value *field_val,
333 const char *label)
334{
335 assert(label);
336 return lttng_event_field_value_enum_append_label_with_size(field_val,
337 label, strlen(label));
338}
339
340LTTNG_HIDDEN
341int lttng_event_field_value_array_append(
342 struct lttng_event_field_value *array_field_val,
343 struct lttng_event_field_value *field_val)
344{
345 assert(array_field_val);
346 assert(field_val);
347 return lttng_dynamic_pointer_array_add_pointer(
348 &container_of(array_field_val,
349 struct lttng_event_field_value_array, parent)->elems,
350 field_val);
351}
352
353LTTNG_HIDDEN
354int lttng_event_field_value_array_append_unavailable(
355 struct lttng_event_field_value *array_field_val)
356{
357 assert(array_field_val);
358 return lttng_dynamic_pointer_array_add_pointer(
359 &container_of(array_field_val,
360 struct lttng_event_field_value_array, parent)->elems,
361 NULL);
362}
363
364enum lttng_event_field_value_type lttng_event_field_value_get_type(
365 const struct lttng_event_field_value *field_val)
366{
367 enum lttng_event_field_value_type type;
368
369 if (!field_val) {
370 type = LTTNG_EVENT_FIELD_VALUE_TYPE_INVALID;
371 goto end;
372 }
373
374 type = field_val->type;
375
376end:
377 return type;
378}
379
380enum lttng_event_field_value_status
381lttng_event_field_value_unsigned_int_get_value(
382 const struct lttng_event_field_value *field_val, uint64_t *val)
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_UNSIGNED_INT:
393 *val = container_of(field_val,
394 const struct lttng_event_field_value_uint,
395 parent)->val;
396 break;
397 case LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM:
9918e00a
SM
398 {
399 const struct lttng_event_field_value_enum *field_val_enum = container_of(
400 field_val,
401 const struct lttng_event_field_value_enum,
402 parent);
403 const struct lttng_event_field_value_enum_uint
404 *field_val_enum_uint = container_of(
405 field_val_enum,
406 const struct lttng_event_field_value_enum_uint,
407 parent);
408 *val = field_val_enum_uint->val;
d28fcdec 409 break;
9918e00a 410 }
d28fcdec
PP
411 default:
412 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
413 goto end;
414 }
415
416 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
417
418end:
419 return status;
420}
421
422enum lttng_event_field_value_status
423lttng_event_field_value_signed_int_get_value(
424 const struct lttng_event_field_value *field_val, int64_t *val)
425{
426 enum lttng_event_field_value_status status;
427
428 if (!field_val || !val) {
429 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
430 goto end;
431 }
432
433 switch (field_val->type) {
434 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_INT:
435 *val = container_of(field_val,
436 const struct lttng_event_field_value_int,
437 parent)->val;
438 break;
439 case LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM:
9918e00a
SM
440 {
441 const struct lttng_event_field_value_enum *field_val_enum = container_of(
442 field_val,
443 const struct lttng_event_field_value_enum,
444 parent);
445 const struct lttng_event_field_value_enum_int
446 *field_val_enum_uint = container_of(
447 field_val_enum,
448 const struct lttng_event_field_value_enum_int,
449 parent);
450 *val = field_val_enum_uint->val;
d28fcdec 451 break;
9918e00a 452 }
d28fcdec
PP
453 default:
454 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
455 goto end;
456 }
457
458 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
459
460end:
461 return status;
462}
463
464enum lttng_event_field_value_status
465lttng_event_field_value_real_get_value(
466 const struct lttng_event_field_value *field_val, double *val)
467{
468 enum lttng_event_field_value_status status;
469
470 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_REAL ||
471 !val) {
472 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
473 goto end;
474 }
475
476 *val = container_of(field_val,
477 const struct lttng_event_field_value_real, parent)->val;
478 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
479
480end:
481 return status;
482}
483
484static
485bool is_enum_field_val(const struct lttng_event_field_value *field_val)
486{
487 return field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_UNSIGNED_ENUM ||
488 field_val->type == LTTNG_EVENT_FIELD_VALUE_TYPE_SIGNED_ENUM;
489}
490
491enum lttng_event_field_value_status
492lttng_event_field_value_enum_get_label_count(
493 const struct lttng_event_field_value *field_val,
494 unsigned int *count)
495{
496 enum lttng_event_field_value_status status;
497
498 if (!field_val || !is_enum_field_val(field_val) || !count) {
499 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
500 goto end;
501 }
502
503 *count = (unsigned int) lttng_dynamic_pointer_array_get_count(
504 &container_of(field_val,
505 const struct lttng_event_field_value_enum,
506 parent)->labels);
507 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
508
509end:
510 return status;
511}
512
513const char *lttng_event_field_value_enum_get_label_at_index(
514 const struct lttng_event_field_value *field_val,
515 unsigned int index)
516{
517 const char *ret;
518 const struct lttng_event_field_value_enum *enum_field_val;
519
520 if (!field_val || !is_enum_field_val(field_val)) {
521 ret = NULL;
522 goto end;
523 }
524
525 enum_field_val = container_of(field_val,
526 const struct lttng_event_field_value_enum, parent);
527
528 if (index >= lttng_dynamic_pointer_array_get_count(&enum_field_val->labels)) {
529 ret = NULL;
530 goto end;
531 }
532
533 ret = lttng_dynamic_pointer_array_get_pointer(&enum_field_val->labels,
534 index);
535
536end:
537 return ret;
538}
539
7c920b63
PP
540enum lttng_event_field_value_status lttng_event_field_value_string_get_value(
541 const struct lttng_event_field_value *field_val,
542 const char **value)
d28fcdec 543{
7c920b63 544 enum lttng_event_field_value_status status;
d28fcdec
PP
545
546 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_STRING) {
7c920b63 547 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
d28fcdec
PP
548 goto end;
549 }
550
7c920b63 551 *value = container_of(field_val,
d28fcdec 552 const struct lttng_event_field_value_string, parent)->val;
7c920b63 553 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
d28fcdec
PP
554
555end:
7c920b63 556 return status;
d28fcdec
PP
557}
558
559enum lttng_event_field_value_status lttng_event_field_value_array_get_length(
560 const struct lttng_event_field_value *field_val,
561 unsigned int *length)
562{
563 enum lttng_event_field_value_status status;
564
565 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
566 !length) {
567 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
568 goto end;
569 }
570
571 *length = (unsigned int) lttng_dynamic_pointer_array_get_count(
572 &container_of(field_val,
573 const struct lttng_event_field_value_array,
574 parent)->elems);
575 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
576
577end:
578 return status;
579}
580
581enum lttng_event_field_value_status
582lttng_event_field_value_array_get_element_at_index(
583 const struct lttng_event_field_value *field_val,
584 unsigned int index,
585 const struct lttng_event_field_value **elem_field_val)
586{
587 enum lttng_event_field_value_status status;
588 const struct lttng_event_field_value_array *array_field_val;
589
590 if (!field_val || field_val->type != LTTNG_EVENT_FIELD_VALUE_TYPE_ARRAY ||
591 !elem_field_val) {
592 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
593 goto end;
594 }
595
596 array_field_val = container_of(field_val,
597 const struct lttng_event_field_value_array, parent);
598
599 if (index >= lttng_dynamic_pointer_array_get_count(&array_field_val->elems)) {
600 status = LTTNG_EVENT_FIELD_VALUE_STATUS_INVALID;
601 goto end;
602 }
603
604 *elem_field_val = lttng_dynamic_pointer_array_get_pointer(
605 &array_field_val->elems, index);
606 if (*elem_field_val) {
607 status = LTTNG_EVENT_FIELD_VALUE_STATUS_OK;
608 } else {
609 status = LTTNG_EVENT_FIELD_VALUE_STATUS_UNAVAILABLE;
610 }
611
612end:
613 return status;
614}
This page took 0.053144 seconds and 4 git commands to generate.