MI: support double element
[lttng-tools.git] / src / lib / lttng-ctl / event-expr.c
CommitLineData
48c47564
PP
1/*
2 * event-expr.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
16#include <common/error.h>
17#include <common/macros.h>
18#include <lttng/event-expr-internal.h>
19
20enum lttng_event_expr_type lttng_event_expr_get_type(
21 const struct lttng_event_expr *expr)
22{
23 enum lttng_event_expr_type type;
24
25 if (!expr) {
26 type = LTTNG_EVENT_EXPR_TYPE_INVALID;
27 goto end;
28 }
29
30 type = expr->type;
31
32end:
33 return type;
34}
35
36static
37struct lttng_event_expr *create_empty_expr(enum lttng_event_expr_type type,
38 size_t size)
39{
40 struct lttng_event_expr *expr;
41
42 expr = zmalloc(size);
43 if (!expr) {
44 goto end;
45 }
46
47 expr->type = type;
48
49end:
50 return expr;
51}
52
53static
54struct lttng_event_expr_field *create_field_event_expr(
55 enum lttng_event_expr_type type,
56 const char *name)
57{
58 struct lttng_event_expr_field *expr =
59 container_of(
60 create_empty_expr(type, sizeof(*expr)),
61 struct lttng_event_expr_field, parent);
62
63 if (!expr) {
64 goto error;
65 }
66
67 assert(name);
68 expr->name = strdup(name);
69 if (!expr->name) {
70 goto error;
71 }
72
73 goto end;
74
75error:
5b5ad96e
FD
76 if (expr) {
77 lttng_event_expr_destroy(&expr->parent);
78 }
79 expr = NULL;
48c47564
PP
80
81end:
82 return expr;
83}
84
85struct lttng_event_expr *lttng_event_expr_event_payload_field_create(
86 const char *field_name)
87{
88 struct lttng_event_expr *expr = NULL;
89
90 if (!field_name) {
91 goto end;
92 }
93
94 expr = &create_field_event_expr(
95 LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD,
96 field_name)->parent;
97
98end:
99 return expr;
100}
101
102struct lttng_event_expr *lttng_event_expr_channel_context_field_create(
103 const char *field_name)
104{
105 struct lttng_event_expr *expr = NULL;
106
107 if (!field_name) {
108 goto end;
109 }
110
111 expr = &create_field_event_expr(
112 LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD,
113 field_name)->parent;
114
115end:
116 return expr;
117}
118
119struct lttng_event_expr *lttng_event_expr_app_specific_context_field_create(
120 const char *provider_name, const char *type_name)
121{
122 struct lttng_event_expr_app_specific_context_field *expr = NULL;
5b5ad96e 123 struct lttng_event_expr *ret_parent_expr;
48c47564
PP
124
125 if (!type_name || !provider_name) {
126 goto error;
127 }
128
129 expr = container_of(create_empty_expr(
130 LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD,
131 sizeof(*expr)),
132 struct lttng_event_expr_app_specific_context_field,
133 parent);
134 if (!expr) {
135 goto error;
136 }
137
138 expr->provider_name = strdup(provider_name);
139 if (!expr->provider_name) {
140 goto error;
141 }
142
143 expr->type_name = strdup(type_name);
144 if (!expr->type_name) {
145 goto error;
146 }
147
5b5ad96e 148 ret_parent_expr = &expr->parent;
48c47564
PP
149 goto end;
150
151error:
5b5ad96e
FD
152 if (expr) {
153 lttng_event_expr_destroy(&expr->parent);
154 }
155 ret_parent_expr = NULL;
48c47564
PP
156
157end:
5b5ad96e 158 return ret_parent_expr;
48c47564
PP
159}
160
161struct lttng_event_expr *lttng_event_expr_array_field_element_create(
162 struct lttng_event_expr *array_field_expr,
163 unsigned int index)
164{
165 struct lttng_event_expr_array_field_element *expr = NULL;
5b5ad96e 166 struct lttng_event_expr *ret_parent_expr;
48c47564
PP
167
168 /* The parent array field expression must be an l-value */
169 if (!array_field_expr ||
170 !lttng_event_expr_is_lvalue(array_field_expr)) {
171 goto error;
172 }
173
174 expr = container_of(create_empty_expr(
175 LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT,
176 sizeof(*expr)),
177 struct lttng_event_expr_array_field_element,
178 parent);
179 if (!expr) {
180 goto error;
181 }
182
183 expr->array_field_expr = array_field_expr;
184 expr->index = index;
5b5ad96e 185 ret_parent_expr = &expr->parent;
48c47564
PP
186 goto end;
187
188error:
5b5ad96e
FD
189 if (expr) {
190 lttng_event_expr_destroy(&expr->parent);
191 }
192 ret_parent_expr = NULL;
48c47564
PP
193
194end:
5b5ad96e 195 return ret_parent_expr;
48c47564
PP
196}
197
198const char *lttng_event_expr_event_payload_field_get_name(
199 const struct lttng_event_expr *expr)
200{
201 const char *ret = NULL;
202
203 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD) {
204 goto end;
205 }
206
207 ret = container_of(expr,
208 const struct lttng_event_expr_field, parent)->name;
209
210end:
211 return ret;
212}
213
214const char *lttng_event_expr_channel_context_field_get_name(
215 const struct lttng_event_expr *expr)
216{
217 const char *ret = NULL;
218
219 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD) {
220 goto end;
221 }
222
223 ret = container_of(expr,
224 const struct lttng_event_expr_field, parent)->name;
225
226end:
227 return ret;
228}
229
230const char *lttng_event_expr_app_specific_context_field_get_provider_name(
231 const struct lttng_event_expr *expr)
232{
233 const char *ret = NULL;
234
235 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
236 goto end;
237 }
238
239 ret = container_of(expr,
240 const struct lttng_event_expr_app_specific_context_field,
241 parent)->provider_name;
242
243end:
244 return ret;
245}
246
247const char *lttng_event_expr_app_specific_context_field_get_type_name(
248 const struct lttng_event_expr *expr)
249{
250 const char *ret = NULL;
251
252 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD) {
253 goto end;
254 }
255
256 ret = container_of(expr,
257 const struct lttng_event_expr_app_specific_context_field,
258 parent)->type_name;
259
260end:
261 return ret;
262}
263
264const struct lttng_event_expr *
265lttng_event_expr_array_field_element_get_parent_expr(
266 const struct lttng_event_expr *expr)
267{
268 const struct lttng_event_expr *ret = NULL;
269
270 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT) {
271 goto end;
272 }
273
274 ret = container_of(expr,
275 const struct lttng_event_expr_array_field_element,
276 parent)->array_field_expr;
277
278end:
279 return ret;
280}
281
282enum lttng_event_expr_status lttng_event_expr_array_field_element_get_index(
283 const struct lttng_event_expr *expr, unsigned int *index)
284{
285 enum lttng_event_expr_status ret = LTTNG_EVENT_EXPR_STATUS_OK;
286
287 if (!expr || expr->type != LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT ||
288 !index) {
289 ret = LTTNG_EVENT_EXPR_STATUS_INVALID;
290 goto end;
291 }
292
293 *index = container_of(expr,
294 const struct lttng_event_expr_array_field_element,
295 parent)->index;
296
297end:
298 return ret;
299}
300
301bool lttng_event_expr_is_equal(const struct lttng_event_expr *expr_a,
302 const struct lttng_event_expr *expr_b)
303{
304 bool is_equal = true;
305
306 if (!expr_a && !expr_b) {
307 /* Both `NULL`: equal */
308 goto end;
309 }
310
311 if (!expr_a || !expr_b) {
312 /* Only one `NULL`: not equal */
313 goto not_equal;
314 }
315
316 if (expr_a->type != expr_b->type) {
317 /* Different types: not equal */
318 goto not_equal;
319 }
320
321 switch (expr_a->type) {
322 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
323 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
324 {
325 const struct lttng_event_expr_field *field_expr_a =
326 container_of(expr_a,
327 const struct lttng_event_expr_field,
328 parent);
329 const struct lttng_event_expr_field *field_expr_b =
330 container_of(expr_b,
331 const struct lttng_event_expr_field,
332 parent);
333
334 if (strcmp(field_expr_a->name, field_expr_b->name) != 0) {
335 goto not_equal;
336 }
337
338 break;
339 }
340 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
341 {
342 const struct lttng_event_expr_app_specific_context_field *field_expr_a =
343 container_of(expr_a,
344 const struct lttng_event_expr_app_specific_context_field,
345 parent);
346 const struct lttng_event_expr_app_specific_context_field *field_expr_b =
347 container_of(expr_b,
348 const struct lttng_event_expr_app_specific_context_field,
349 parent);
350
351 if (strcmp(field_expr_a->provider_name,
352 field_expr_b->provider_name) != 0) {
353 goto not_equal;
354 }
355
356 if (strcmp(field_expr_a->type_name,
357 field_expr_b->type_name) != 0) {
358 goto not_equal;
359 }
360
361 break;
362 }
363 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
364 {
365 const struct lttng_event_expr_array_field_element *elem_expr_a =
366 container_of(expr_a,
367 const struct lttng_event_expr_array_field_element,
368 parent);
369 const struct lttng_event_expr_array_field_element *elem_expr_b =
370 container_of(expr_b,
371 const struct lttng_event_expr_array_field_element,
372 parent);
373
374 if (!lttng_event_expr_is_equal(elem_expr_a->array_field_expr,
375 elem_expr_b->array_field_expr)) {
376 goto not_equal;
377 }
378
379 if (elem_expr_a->index != elem_expr_b->index) {
380 goto not_equal;
381 }
382
383 break;
384 }
385 default:
386 break;
387 }
388
389 goto end;
390
391not_equal:
392 is_equal = false;
393
394end:
395 return is_equal;
396}
397
398void lttng_event_expr_destroy(struct lttng_event_expr *expr)
399{
400 if (!expr) {
401 goto end;
402 }
403
404 switch (expr->type) {
405 case LTTNG_EVENT_EXPR_TYPE_EVENT_PAYLOAD_FIELD:
406 case LTTNG_EVENT_EXPR_TYPE_CHANNEL_CONTEXT_FIELD:
407 {
408 struct lttng_event_expr_field *field_expr =
409 container_of(expr,
410 struct lttng_event_expr_field, parent);
411
412 free(field_expr->name);
413 break;
414 }
415 case LTTNG_EVENT_EXPR_TYPE_APP_SPECIFIC_CONTEXT_FIELD:
416 {
417 struct lttng_event_expr_app_specific_context_field *field_expr =
418 container_of(expr,
419 struct lttng_event_expr_app_specific_context_field,
420 parent);
421
422 free(field_expr->provider_name);
423 free(field_expr->type_name);
424 break;
425 }
426 case LTTNG_EVENT_EXPR_TYPE_ARRAY_FIELD_ELEMENT:
427 {
428 struct lttng_event_expr_array_field_element *elem_expr =
429 container_of(expr,
430 struct lttng_event_expr_array_field_element,
431 parent);
432
433 lttng_event_expr_destroy(elem_expr->array_field_expr);
434 break;
435 }
436 default:
437 break;
438 }
439
440 free(expr);
441
442end:
443 return;
444}
This page took 0.054504 seconds and 5 git commands to generate.