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