Commit | Line | Data |
---|---|---|
9c312311 | 1 | /* This file is part of the Linux Trace Toolkit viewer |
852f16bb | 2 | * Copyright (C) 2003-2005 Michel Dagenais and Simon Bouvier-Zappa |
9c312311 | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License Version 2 as | |
6 | * published by the Free Software Foundation; | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
11 | * GNU General Public License for more details. | |
12 | * | |
13 | * You should have received a copy of the GNU General Public License | |
14 | * along with this program; if not, write to the Free Software | |
15 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, | |
16 | * MA 02111-1307, USA. | |
17 | */ | |
18 | ||
7e7af7f2 | 19 | /*! \file lttv/lttv/filter.c |
20 | * \brief Defines the core filter of application | |
21 | * | |
22 | * consist in AND, OR and NOT nested expressions, forming a tree with | |
23 | * simple relations as leaves. The simple relations test if a field | |
24 | * in an event is equal, not equal, smaller, smaller or equal, larger, or | |
25 | * larger or equal to a specified value. | |
26 | * | |
27 | * Fields specified in a simple expression can take following | |
28 | * values | |
29 | * | |
da2e1bfb | 30 | * \verbatim |
31 | * LttvTracefileContext{} | |
7e7af7f2 | 32 | * |->event\ |
6471e71f | 33 | * | |->name (String, converted to GQuark) (channel.event) |
34 | * | |->subname (String, converted to GQuark) | |
7e7af7f2 | 35 | * | |->category (String, not yet implemented) |
36 | * | |->time (LttTime) | |
bbd9d557 | 37 | * | |->tsc (LttCycleCount --> uint64) |
33bdc8dd | 38 | * | |->target_pid (target PID of the event) |
7e7af7f2 | 39 | * | |->fields |
6471e71f | 40 | * | |->"channel name" |
c56a714e | 41 | * | |->"event name" |
42 | * | |->"field name" | |
43 | * | |->"sub-field name" | |
44 | * | |->... | |
45 | * | |->"leaf-field name" (field type) | |
6471e71f | 46 | * |->channel (or tracefile) |
7e7af7f2 | 47 | * | |->name (String, converted to GQuark) |
48 | * |->trace | |
49 | * | |->name (String, converted to GQuark) | |
50 | * |->state | |
2ec11087 | 51 | * |->pid (guint) |
52 | * |->ppid (guint) | |
7e7af7f2 | 53 | * |->creation_time (LttTime) |
54 | * |->insertion_time (LttTime) | |
55 | * |->process_name (String, converted to GQuark) | |
7b5f6cf1 | 56 | * |->thread_brand (String, converted to GQuark) |
7e7af7f2 | 57 | * |->execution_mode (LttvExecutionMode) |
58 | * |->execution_submode (LttvExecutionSubmode) | |
59 | * |->process_status (LttvProcessStatus) | |
6e0d58d6 | 60 | * |->cpu (guint) |
da2e1bfb | 61 | * \endverbatim |
150f0d33 | 62 | */ |
63 | ||
64 | /* | |
bbd9d557 | 65 | * \todo |
150f0d33 | 66 | * - refine switch of expression in multiple uses functions |
be66ef34 | 67 | * - remove the idle expressions in the tree |
150f0d33 | 68 | */ |
69 | ||
4e4d11b3 | 70 | #ifdef HAVE_CONFIG_H |
71 | #include <config.h> | |
72 | #endif | |
73 | ||
72911c5d | 74 | //#define TEST |
be66ef34 | 75 | #ifdef TEST |
76 | #include <time.h> | |
77 | #include <sys/time.h> | |
78 | #endif | |
79 | ||
87834cd1 | 80 | #include <lttv/lttv.h> |
150f0d33 | 81 | #include <lttv/filter.h> |
327a4314 | 82 | #include <ltt/trace.h> |
83 | #include <stdlib.h> | |
84 | #include <string.h> | |
80f9611a | 85 | |
86 | /** | |
56e29124 | 87 | * @fn LttvSimpleExpression* lttv_simple_expression_new() |
88 | * | |
80f9611a | 89 | * Constructor for LttvSimpleExpression |
90 | * @return pointer to new LttvSimpleExpression | |
91 | */ | |
92 | LttvSimpleExpression* | |
93 | lttv_simple_expression_new() { | |
94 | ||
95 | LttvSimpleExpression* se = g_new(LttvSimpleExpression,1); | |
96 | ||
97 | se->field = LTTV_FILTER_UNDEFINED; | |
98 | se->op = NULL; | |
99 | se->offset = 0; | |
80f9611a | 100 | |
101 | return se; | |
102 | } | |
103 | ||
9354c7da | 104 | /* |
105 | * Keeps the array order. | |
106 | */ | |
107 | static inline gpointer ltt_g_ptr_array_remove_index_slow(GPtrArray *fp, | |
108 | int index) | |
109 | { | |
110 | gpointer ptr; | |
111 | int i; | |
112 | ||
113 | if (fp->len == 0) | |
114 | return NULL; | |
115 | ||
116 | ptr = g_ptr_array_index(fp, index); | |
117 | for (i = index; i < fp->len - 1; i++) { | |
118 | g_ptr_array_index(fp, i) = g_ptr_array_index(fp, i + 1); | |
119 | } | |
120 | g_ptr_array_remove_index(fp, fp->len - 1); | |
121 | return ptr; | |
122 | } | |
123 | ||
0769c82f | 124 | /** |
7e7af7f2 | 125 | * @fn gboolean lttv_simple_expression_assign_field(GPtrArray*,LttvSimpleExpression*) |
56e29124 | 126 | * |
0769c82f | 127 | * Parse through filtering field hierarchy as specified |
128 | * by user. This function compares each value to | |
129 | * predetermined quarks | |
130 | * @param fp The field path list | |
bb87caa7 | 131 | * @param se current simple expression |
0769c82f | 132 | * @return success/failure of operation |
133 | */ | |
134 | gboolean | |
9ab5ebd7 | 135 | lttv_simple_expression_assign_field(GPtrArray* fp, LttvSimpleExpression* se) { |
0769c82f | 136 | |
f4e9dd16 | 137 | GString* f = NULL; |
6668c31b | 138 | |
2b99ec10 | 139 | if(fp->len < 2) return FALSE; |
8f318283 BP |
140 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
141 | g_assert(f); | |
9354c7da | 142 | |
143 | ||
47aa6e58 | 144 | /* |
145 | * Parse through the specified | |
146 | * hardcoded fields. | |
147 | * | |
148 | * Take note however that the | |
149 | * 'event' subfields might change | |
150 | * depending on values specified | |
151 | * in core.xml file. Hence, if | |
152 | * none of the subfields in the | |
153 | * array match the hardcoded | |
154 | * subfields, it will be considered | |
155 | * as a dynamic field | |
156 | */ | |
6668c31b | 157 | |
80f9611a | 158 | if(!g_strcasecmp(f->str,"trace") ) { |
47aa6e58 | 159 | /* |
160 | * Possible values: | |
161 | * trace.name | |
162 | */ | |
73050a5f | 163 | g_string_free(f,TRUE); |
9354c7da | 164 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
80f9611a | 165 | if(!g_strcasecmp(f->str,"name")) { |
389ba50e | 166 | se->field = LTTV_FILTER_TRACE_NAME; |
167 | } | |
80f9611a | 168 | } else if(!g_strcasecmp(f->str,"traceset") ) { |
47aa6e58 | 169 | /* |
170 | * FIXME: not yet implemented ! | |
171 | */ | |
6471e71f | 172 | } else if(!g_strcasecmp(f->str,"tracefile") |
173 | || !g_strcasecmp(f->str,"channel") ) { | |
47aa6e58 | 174 | /* |
175 | * Possible values: | |
176 | * tracefile.name | |
6471e71f | 177 | * channel.name |
47aa6e58 | 178 | */ |
73050a5f | 179 | g_string_free(f,TRUE); |
9354c7da | 180 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
80f9611a | 181 | if(!g_strcasecmp(f->str,"name")) { |
389ba50e | 182 | se->field = LTTV_FILTER_TRACEFILE_NAME; |
183 | } | |
80f9611a | 184 | } else if(!g_strcasecmp(f->str,"state") ) { |
47aa6e58 | 185 | /* |
186 | * Possible values: | |
187 | * state.pid | |
188 | * state.ppid | |
189 | * state.creation_time | |
190 | * state.insertion_time | |
191 | * state.process_name | |
7b5f6cf1 | 192 | * state.thread_brand |
47aa6e58 | 193 | * state.execution_mode |
194 | * state.execution_submode | |
195 | * state.process_status | |
196 | * state.cpu | |
197 | */ | |
73050a5f | 198 | g_string_free(f,TRUE); |
9354c7da | 199 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
80f9611a | 200 | if(!g_strcasecmp(f->str,"pid") ) { |
389ba50e | 201 | se->field = LTTV_FILTER_STATE_PID; |
202 | } | |
80f9611a | 203 | else if(!g_strcasecmp(f->str,"ppid") ) { |
389ba50e | 204 | se->field = LTTV_FILTER_STATE_PPID; |
205 | } | |
80f9611a | 206 | else if(!g_strcasecmp(f->str,"creation_time") ) { |
389ba50e | 207 | se->field = LTTV_FILTER_STATE_CT; |
208 | } | |
80f9611a | 209 | else if(!g_strcasecmp(f->str,"insertion_time") ) { |
389ba50e | 210 | se->field = LTTV_FILTER_STATE_IT; |
211 | } | |
80f9611a | 212 | else if(!g_strcasecmp(f->str,"process_name") ) { |
389ba50e | 213 | se->field = LTTV_FILTER_STATE_P_NAME; |
214 | } | |
7b5f6cf1 | 215 | else if(!g_strcasecmp(f->str,"thread_brand") ) { |
216 | se->field = LTTV_FILTER_STATE_T_BRAND; | |
217 | } | |
80f9611a | 218 | else if(!g_strcasecmp(f->str,"execution_mode") ) { |
389ba50e | 219 | se->field = LTTV_FILTER_STATE_EX_MODE; |
220 | } | |
80f9611a | 221 | else if(!g_strcasecmp(f->str,"execution_submode") ) { |
389ba50e | 222 | se->field = LTTV_FILTER_STATE_EX_SUBMODE; |
223 | } | |
80f9611a | 224 | else if(!g_strcasecmp(f->str,"process_status") ) { |
389ba50e | 225 | se->field = LTTV_FILTER_STATE_P_STATUS; |
226 | } | |
80f9611a | 227 | else if(!g_strcasecmp(f->str,"cpu") ) { |
389ba50e | 228 | se->field = LTTV_FILTER_STATE_CPU; |
229 | } | |
80f9611a | 230 | } else if(!g_strcasecmp(f->str,"event") ) { |
389ba50e | 231 | /* |
232 | * Possible values: | |
233 | * event.name | |
6471e71f | 234 | * event.channel |
389ba50e | 235 | * event.category |
236 | * event.time | |
237 | * event.tsc | |
33bdc8dd | 238 | * event.target_pid |
c56a714e | 239 | * event.field |
389ba50e | 240 | */ |
73050a5f | 241 | g_string_free(f,TRUE); |
9354c7da | 242 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
6668c31b | 243 | |
80f9611a | 244 | if(!g_strcasecmp(f->str,"name") ) { |
389ba50e | 245 | se->field = LTTV_FILTER_EVENT_NAME; |
246 | } | |
6471e71f | 247 | else if(!g_strcasecmp(f->str,"subname") ) { |
248 | se->field = LTTV_FILTER_EVENT_SUBNAME; | |
249 | } | |
80f9611a | 250 | else if(!g_strcasecmp(f->str,"category") ) { |
389ba50e | 251 | /* |
252 | * FIXME: Category not yet functional in lttv | |
253 | */ | |
254 | se->field = LTTV_FILTER_EVENT_CATEGORY; | |
255 | } | |
80f9611a | 256 | else if(!g_strcasecmp(f->str,"time") ) { |
389ba50e | 257 | se->field = LTTV_FILTER_EVENT_TIME; |
2b99ec10 | 258 | } |
80f9611a | 259 | else if(!g_strcasecmp(f->str,"tsc") ) { |
389ba50e | 260 | se->field = LTTV_FILTER_EVENT_TSC; |
2b99ec10 | 261 | } |
33bdc8dd | 262 | else if(!g_strcasecmp(f->str,"target_pid") ) { |
263 | se->field = LTTV_FILTER_EVENT_TARGET_PID; | |
264 | } | |
c56a714e | 265 | else if(!g_strcasecmp(f->str,"field") ) { |
389ba50e | 266 | se->field = LTTV_FILTER_EVENT_FIELD; |
c8f08e26 | 267 | g_string_free(f,TRUE); |
9354c7da | 268 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
c56a714e | 269 | |
270 | } else { | |
9354c7da | 271 | //g_string_free(f,TRUE); |
272 | //f=ltt_g_ptr_array_remove_index_slow(fp,0); | |
c56a714e | 273 | g_warning("Unknown event filter subtype %s", f->str); |
2b99ec10 | 274 | } |
91ad3f0a | 275 | } else { |
fb04197e | 276 | g_string_free(f,TRUE); |
9354c7da | 277 | f=ltt_g_ptr_array_remove_index_slow(fp,0); |
fb04197e | 278 | |
91ad3f0a | 279 | g_warning("Unrecognized field in filter string"); |
0769c82f | 280 | } |
47aa6e58 | 281 | |
56e29124 | 282 | /* free memory for last string */ |
73050a5f | 283 | g_string_free(f,TRUE); |
56e29124 | 284 | |
285 | /* array should be empty */ | |
73050a5f | 286 | g_assert(fp->len == 0); |
56e29124 | 287 | |
56e29124 | 288 | if(se->field == LTTV_FILTER_UNDEFINED) { |
289 | g_warning("The specified field was not recognized !"); | |
290 | return FALSE; | |
291 | } | |
91ad3f0a | 292 | return TRUE; |
0769c82f | 293 | } |
294 | ||
bb87caa7 | 295 | /** |
56e29124 | 296 | * @fn gboolean lttv_simple_expression_assign_operator(LttvSimpleExpression*,LttvExpressionOp) |
297 | * | |
bb87caa7 | 298 | * Sets the function pointer for the current |
299 | * Simple Expression | |
300 | * @param se current simple expression | |
7e7af7f2 | 301 | * @param op current operator |
bb87caa7 | 302 | * @return success/failure of operation |
303 | */ | |
be66ef34 | 304 | gboolean |
305 | lttv_simple_expression_assign_operator(LttvSimpleExpression* se, LttvExpressionOp op) { | |
aa4600f3 | 306 | |
bb87caa7 | 307 | switch(se->field) { |
56e29124 | 308 | /* |
309 | * string | |
310 | */ | |
bb87caa7 | 311 | case LTTV_FILTER_TRACE_NAME: |
312 | case LTTV_FILTER_TRACEFILE_NAME: | |
313 | case LTTV_FILTER_STATE_P_NAME: | |
7b5f6cf1 | 314 | case LTTV_FILTER_STATE_T_BRAND: |
6471e71f | 315 | case LTTV_FILTER_EVENT_SUBNAME: |
be66ef34 | 316 | case LTTV_FILTER_STATE_EX_MODE: |
317 | case LTTV_FILTER_STATE_EX_SUBMODE: | |
318 | case LTTV_FILTER_STATE_P_STATUS: | |
bb87caa7 | 319 | switch(op) { |
320 | case LTTV_FIELD_EQ: | |
c6832b57 | 321 | se->op = lttv_apply_op_eq_quark; |
bb87caa7 | 322 | break; |
323 | case LTTV_FIELD_NE: | |
c6832b57 | 324 | se->op = lttv_apply_op_ne_quark; |
bb87caa7 | 325 | break; |
326 | default: | |
73050a5f | 327 | g_warning("Error encountered in operator assignment = or != expected"); |
bb87caa7 | 328 | return FALSE; |
329 | } | |
330 | break; | |
6471e71f | 331 | /* |
332 | * two strings. | |
333 | */ | |
334 | case LTTV_FILTER_EVENT_NAME: | |
335 | switch(op) { | |
336 | case LTTV_FIELD_EQ: | |
337 | se->op = lttv_apply_op_eq_quarks; | |
338 | break; | |
339 | case LTTV_FIELD_NE: | |
340 | se->op = lttv_apply_op_ne_quarks; | |
341 | break; | |
342 | default: | |
343 | g_warning("Error encountered in operator assignment = or != expected"); | |
344 | return FALSE; | |
345 | } | |
56e29124 | 346 | /* |
347 | * integer | |
348 | */ | |
bbd9d557 | 349 | case LTTV_FILTER_EVENT_TSC: |
bb87caa7 | 350 | switch(op) { |
351 | case LTTV_FIELD_EQ: | |
352 | se->op = lttv_apply_op_eq_uint64; | |
353 | break; | |
354 | case LTTV_FIELD_NE: | |
355 | se->op = lttv_apply_op_ne_uint64; | |
356 | break; | |
357 | case LTTV_FIELD_LT: | |
358 | se->op = lttv_apply_op_lt_uint64; | |
359 | break; | |
360 | case LTTV_FIELD_LE: | |
361 | se->op = lttv_apply_op_le_uint64; | |
362 | break; | |
363 | case LTTV_FIELD_GT: | |
364 | se->op = lttv_apply_op_gt_uint64; | |
365 | break; | |
366 | case LTTV_FIELD_GE: | |
367 | se->op = lttv_apply_op_ge_uint64; | |
368 | break; | |
369 | default: | |
370 | g_warning("Error encountered in operator assignment"); | |
371 | return FALSE; | |
372 | } | |
373 | break; | |
6e0d58d6 | 374 | /* |
2ec11087 | 375 | * unsigned integers |
6e0d58d6 | 376 | */ |
377 | case LTTV_FILTER_STATE_CPU: | |
378 | case LTTV_FILTER_STATE_PID: | |
379 | case LTTV_FILTER_STATE_PPID: | |
33bdc8dd | 380 | case LTTV_FILTER_EVENT_TARGET_PID: |
6e0d58d6 | 381 | switch(op) { |
382 | case LTTV_FIELD_EQ: | |
2ec11087 | 383 | se->op = lttv_apply_op_eq_uint; |
6e0d58d6 | 384 | break; |
385 | case LTTV_FIELD_NE: | |
2ec11087 | 386 | se->op = lttv_apply_op_ne_uint; |
6e0d58d6 | 387 | break; |
388 | case LTTV_FIELD_LT: | |
2ec11087 | 389 | se->op = lttv_apply_op_lt_uint; |
6e0d58d6 | 390 | break; |
391 | case LTTV_FIELD_LE: | |
2ec11087 | 392 | se->op = lttv_apply_op_le_uint; |
6e0d58d6 | 393 | break; |
394 | case LTTV_FIELD_GT: | |
2ec11087 | 395 | se->op = lttv_apply_op_gt_uint; |
6e0d58d6 | 396 | break; |
397 | case LTTV_FIELD_GE: | |
2ec11087 | 398 | se->op = lttv_apply_op_ge_uint; |
6e0d58d6 | 399 | break; |
400 | default: | |
401 | g_warning("Error encountered in operator assignment"); | |
402 | return FALSE; | |
403 | } | |
404 | break; | |
405 | ||
f017db44 | 406 | /* |
407 | * Enums | |
be66ef34 | 408 | * Entered as string, converted to enum |
409 | * | |
f017db44 | 410 | * can only be compared with 'equal' or 'not equal' operators |
411 | * | |
412 | * unsigned int of 16 bits are used here since enums | |
be66ef34 | 413 | * should not go over 2^16-1 values |
f017db44 | 414 | */ |
be66ef34 | 415 | // case /*NOTHING*/: |
416 | // switch(op) { | |
417 | // case LTTV_FIELD_EQ: | |
418 | // se->op = lttv_apply_op_eq_uint16; | |
419 | // break; | |
420 | // case LTTV_FIELD_NE: | |
421 | // se->op = lttv_apply_op_ne_uint16; | |
422 | // break; | |
423 | // default: | |
424 | // g_warning("Error encountered in operator assignment = or != expected"); | |
425 | // return FALSE; | |
426 | // } | |
427 | // break; | |
56e29124 | 428 | /* |
7145a073 | 429 | * Ltttime |
56e29124 | 430 | */ |
bb87caa7 | 431 | case LTTV_FILTER_STATE_CT: |
432 | case LTTV_FILTER_STATE_IT: | |
433 | case LTTV_FILTER_EVENT_TIME: | |
bb87caa7 | 434 | switch(op) { |
435 | case LTTV_FIELD_EQ: | |
7145a073 | 436 | se->op = lttv_apply_op_eq_ltttime; |
bb87caa7 | 437 | break; |
438 | case LTTV_FIELD_NE: | |
7145a073 | 439 | se->op = lttv_apply_op_ne_ltttime; |
bb87caa7 | 440 | break; |
441 | case LTTV_FIELD_LT: | |
7145a073 | 442 | se->op = lttv_apply_op_lt_ltttime; |
bb87caa7 | 443 | break; |
444 | case LTTV_FIELD_LE: | |
7145a073 | 445 | se->op = lttv_apply_op_le_ltttime; |
bb87caa7 | 446 | break; |
447 | case LTTV_FIELD_GT: | |
7145a073 | 448 | se->op = lttv_apply_op_gt_ltttime; |
bb87caa7 | 449 | break; |
450 | case LTTV_FIELD_GE: | |
7145a073 | 451 | se->op = lttv_apply_op_ge_ltttime; |
bb87caa7 | 452 | break; |
453 | default: | |
454 | g_warning("Error encountered in operator assignment"); | |
455 | return FALSE; | |
456 | } | |
457 | break; | |
458 | default: | |
9ab5ebd7 | 459 | g_warning("Error encountered in operator assignation ! Field type:%i",se->field); |
bb87caa7 | 460 | return FALSE; |
461 | } | |
aa4600f3 | 462 | |
463 | return TRUE; | |
bb87caa7 | 464 | |
465 | } | |
466 | ||
9ab5ebd7 | 467 | /** |
7e7af7f2 | 468 | * @fn gboolean lttv_simple_expression_assign_value(LttvSimpleExpression*,char*) |
9ab5ebd7 | 469 | * |
470 | * Assign the value field to the current LttvSimpleExpression | |
471 | * @param se pointer to the current LttvSimpleExpression | |
472 | * @param value string value for simple expression | |
473 | */ | |
be66ef34 | 474 | gboolean |
475 | lttv_simple_expression_assign_value(LttvSimpleExpression* se, char* value) { | |
9ab5ebd7 | 476 | |
46c40a93 | 477 | unsigned i; |
478 | gboolean is_double = FALSE; | |
c6832b57 | 479 | LttTime t = ltt_time_zero; |
480 | GString* v; | |
571ef1ed | 481 | guint string_len; |
9ab5ebd7 | 482 | |
483 | switch(se->field) { | |
484 | /* | |
be66ef34 | 485 | * Strings |
486 | * entered as strings, converted to Quarks | |
9ab5ebd7 | 487 | */ |
488 | case LTTV_FILTER_TRACE_NAME: | |
489 | case LTTV_FILTER_TRACEFILE_NAME: | |
490 | case LTTV_FILTER_STATE_P_NAME: | |
7b5f6cf1 | 491 | case LTTV_FILTER_STATE_T_BRAND: |
6471e71f | 492 | case LTTV_FILTER_EVENT_SUBNAME: |
be66ef34 | 493 | case LTTV_FILTER_STATE_EX_MODE: |
494 | case LTTV_FILTER_STATE_EX_SUBMODE: | |
495 | case LTTV_FILTER_STATE_P_STATUS: | |
496 | // se->value.v_string = value; | |
c56a714e | 497 | se->value.v_quark = g_quark_from_string(value); |
c6832b57 | 498 | g_free(value); |
9ab5ebd7 | 499 | break; |
6471e71f | 500 | /* |
501 | * Two strings. | |
502 | */ | |
503 | case LTTV_FILTER_EVENT_NAME: | |
504 | { | |
505 | /* channel.event */ | |
506 | char *end = strchr(value, '.'); | |
507 | if (end) { | |
508 | *end = '\0'; | |
509 | end++; | |
510 | se->value.v_quarks.q[0] = g_quark_from_string(value); | |
511 | se->value.v_quarks.q[1] = g_quark_from_string(end); | |
512 | } else { | |
513 | se->value.v_quarks.q[0] = (GQuark)0; | |
514 | se->value.v_quarks.q[1] = g_quark_from_string(value); | |
515 | } | |
516 | g_free(value); | |
517 | } | |
518 | break; | |
9ab5ebd7 | 519 | /* |
be66ef34 | 520 | * integer -- supposed to be uint64 |
9ab5ebd7 | 521 | */ |
bbd9d557 | 522 | case LTTV_FILTER_EVENT_TSC: |
9ab5ebd7 | 523 | se->value.v_uint64 = atoi(value); |
524 | g_free(value); | |
525 | break; | |
6e0d58d6 | 526 | /* |
2ec11087 | 527 | * unsigned integers |
6e0d58d6 | 528 | */ |
529 | case LTTV_FILTER_STATE_PID: | |
530 | case LTTV_FILTER_STATE_PPID: | |
531 | case LTTV_FILTER_STATE_CPU: | |
33bdc8dd | 532 | case LTTV_FILTER_EVENT_TARGET_PID: |
2ec11087 | 533 | se->value.v_uint = atoi(value); |
6e0d58d6 | 534 | g_free(value); |
535 | break; | |
9ab5ebd7 | 536 | /* |
7145a073 | 537 | * LttTime |
9ab5ebd7 | 538 | */ |
539 | case LTTV_FILTER_STATE_CT: | |
540 | case LTTV_FILTER_STATE_IT: | |
541 | case LTTV_FILTER_EVENT_TIME: | |
7145a073 | 542 | //se->value.v_double = atof(value); |
46c40a93 | 543 | /* |
544 | * parsing logic could be optimised, | |
545 | * but as for now, simpler this way | |
546 | */ | |
547 | v = g_string_new(""); | |
571ef1ed | 548 | string_len = strlen(value); |
549 | for(i=0;i<string_len;i++) { | |
46c40a93 | 550 | if(value[i] == '.') { |
551 | /* cannot specify number with more than one '.' */ | |
552 | if(is_double) return FALSE; | |
553 | else is_double = TRUE; | |
826f1ab2 | 554 | t.tv_sec = atoi(v->str); |
46c40a93 | 555 | g_string_free(v,TRUE); |
556 | v = g_string_new(""); | |
4ec0c904 | 557 | } else v = g_string_append_c(v,value[i]); |
46c40a93 | 558 | } |
559 | /* number can be integer or double */ | |
826f1ab2 | 560 | if(is_double) t.tv_nsec = atoi(v->str); |
571ef1ed | 561 | else { |
562 | t.tv_sec = atoi(v->str); | |
563 | t.tv_nsec = 0; | |
564 | } | |
c6832b57 | 565 | |
46c40a93 | 566 | g_string_free(v,TRUE); |
567 | ||
568 | se->value.v_ltttime = t; | |
9ab5ebd7 | 569 | g_free(value); |
570 | break; | |
571 | default: | |
572 | g_warning("Error encountered in value assignation ! Field type = %i",se->field); | |
c6832b57 | 573 | g_free(value); |
9ab5ebd7 | 574 | return FALSE; |
575 | } | |
576 | ||
577 | return TRUE; | |
578 | ||
579 | } | |
580 | ||
31452f49 | 581 | /** |
56e29124 | 582 | * @fn void lttv_simple_expression_destroy(LttvSimpleExpression*) |
583 | * | |
9ab5ebd7 | 584 | * Disallocate memory for the current |
56e29124 | 585 | * simple expression |
586 | * @param se pointer to the current LttvSimpleExpression | |
587 | */ | |
588 | void | |
589 | lttv_simple_expression_destroy(LttvSimpleExpression* se) { | |
590 | ||
9ab5ebd7 | 591 | // g_free(se->value); |
786c5c3b | 592 | // switch(se->field) { |
593 | // case LTTV_FILTER_TRACE_NAME: | |
594 | // case LTTV_FILTER_TRACEFILE_NAME: | |
595 | // case LTTV_FILTER_STATE_P_NAME: | |
596 | // case LTTV_FILTER_EVENT_NAME: | |
597 | // g_free(se->value.v_string); | |
598 | // break; | |
599 | // } | |
56e29124 | 600 | g_free(se); |
601 | ||
602 | } | |
603 | ||
604 | /** | |
605 | * @fn gint lttv_struct_type(gint) | |
606 | * | |
80f9611a | 607 | * Finds the structure type depending |
608 | * on the fields in parameters | |
609 | * @params ft Field of the current structure | |
610 | * @return LttvStructType enum or -1 for error | |
84a333d6 | 611 | */ |
80f9611a | 612 | gint |
613 | lttv_struct_type(gint ft) { | |
5f185a2b | 614 | |
80f9611a | 615 | switch(ft) { |
616 | case LTTV_FILTER_TRACE_NAME: | |
617 | return LTTV_FILTER_TRACE; | |
618 | break; | |
619 | case LTTV_FILTER_TRACEFILE_NAME: | |
620 | return LTTV_FILTER_TRACEFILE; | |
621 | break; | |
622 | case LTTV_FILTER_STATE_PID: | |
623 | case LTTV_FILTER_STATE_PPID: | |
624 | case LTTV_FILTER_STATE_CT: | |
625 | case LTTV_FILTER_STATE_IT: | |
626 | case LTTV_FILTER_STATE_P_NAME: | |
6471e71f | 627 | case LTTV_FILTER_STATE_T_BRAND: |
80f9611a | 628 | case LTTV_FILTER_STATE_EX_MODE: |
629 | case LTTV_FILTER_STATE_EX_SUBMODE: | |
630 | case LTTV_FILTER_STATE_P_STATUS: | |
631 | case LTTV_FILTER_STATE_CPU: | |
632 | return LTTV_FILTER_STATE; | |
633 | break; | |
634 | case LTTV_FILTER_EVENT_NAME: | |
6471e71f | 635 | case LTTV_FILTER_EVENT_SUBNAME: |
80f9611a | 636 | case LTTV_FILTER_EVENT_CATEGORY: |
637 | case LTTV_FILTER_EVENT_TIME: | |
638 | case LTTV_FILTER_EVENT_TSC: | |
33bdc8dd | 639 | case LTTV_FILTER_EVENT_TARGET_PID: |
80f9611a | 640 | case LTTV_FILTER_EVENT_FIELD: |
641 | return LTTV_FILTER_EVENT; | |
642 | break; | |
643 | default: | |
644 | return -1; | |
645 | } | |
84a333d6 | 646 | } |
647 | ||
2ec11087 | 648 | /** |
649 | * @fn gboolean lttv_apply_op_eq_uint(gpointer,LttvFieldValue) | |
650 | * | |
651 | * Applies the 'equal' operator to the | |
652 | * specified structure and value | |
653 | * @param v1 left member of comparison | |
654 | * @param v2 right member of comparison | |
655 | * @return success/failure of operation | |
656 | */ | |
657 | gboolean lttv_apply_op_eq_uint(const gpointer v1, LttvFieldValue v2) { | |
658 | ||
659 | guint* r = (guint*) v1; | |
660 | return (*r == v2.v_uint); | |
661 | ||
662 | } | |
663 | ||
150f0d33 | 664 | /** |
7e7af7f2 | 665 | * @fn gboolean lttv_apply_op_eq_uint64(gpointer,LttvFieldValue) |
56e29124 | 666 | * |
150f0d33 | 667 | * Applies the 'equal' operator to the |
47aa6e58 | 668 | * specified structure and value |
669 | * @param v1 left member of comparison | |
670 | * @param v2 right member of comparison | |
150f0d33 | 671 | * @return success/failure of operation |
672 | */ | |
4d9ff942 | 673 | gboolean lttv_apply_op_eq_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 674 | |
675 | guint64* r = (guint64*) v1; | |
9ab5ebd7 | 676 | return (*r == v2.v_uint64); |
83aa92fc | 677 | |
678 | } | |
150f0d33 | 679 | |
5b729fcf | 680 | /** |
7e7af7f2 | 681 | * @fn gboolean lttv_apply_op_eq_uint32(gpointer,LttvFieldValue) |
56e29124 | 682 | * |
5b729fcf | 683 | * Applies the 'equal' operator to the |
47aa6e58 | 684 | * specified structure and value |
685 | * @param v1 left member of comparison | |
686 | * @param v2 right member of comparison | |
5b729fcf | 687 | * @return success/failure of operation |
688 | */ | |
4d9ff942 | 689 | gboolean lttv_apply_op_eq_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 690 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 691 | return (*r == v2.v_uint32); |
83aa92fc | 692 | } |
5b729fcf | 693 | |
694 | /** | |
7e7af7f2 | 695 | * @fn gboolean lttv_apply_op_eq_uint16(gpointer,LttvFieldValue) |
56e29124 | 696 | * |
5b729fcf | 697 | * Applies the 'equal' operator to the |
47aa6e58 | 698 | * specified structure and value |
699 | * @param v1 left member of comparison | |
700 | * @param v2 right member of comparison | |
5b729fcf | 701 | * @return success/failure of operation |
702 | */ | |
4d9ff942 | 703 | gboolean lttv_apply_op_eq_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 704 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 705 | return (*r == v2.v_uint16); |
83aa92fc | 706 | } |
5b729fcf | 707 | |
708 | /** | |
7e7af7f2 | 709 | * @fn gboolean lttv_apply_op_eq_double(gpointer,LttvFieldValue) |
56e29124 | 710 | * |
5b729fcf | 711 | * Applies the 'equal' operator to the |
47aa6e58 | 712 | * specified structure and value |
713 | * @param v1 left member of comparison | |
714 | * @param v2 right member of comparison | |
5b729fcf | 715 | * @return success/failure of operation |
716 | */ | |
4d9ff942 | 717 | gboolean lttv_apply_op_eq_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 718 | double* r = (double*) v1; |
9ab5ebd7 | 719 | return (*r == v2.v_double); |
83aa92fc | 720 | } |
5b729fcf | 721 | |
722 | /** | |
7e7af7f2 | 723 | * @fn gboolean lttv_apply_op_eq_string(gpointer,LttvFieldValue) |
56e29124 | 724 | * |
5b729fcf | 725 | * Applies the 'equal' operator to the |
47aa6e58 | 726 | * specified structure and value |
727 | * @param v1 left member of comparison | |
728 | * @param v2 right member of comparison | |
5b729fcf | 729 | * @return success/failure of operation |
730 | */ | |
4d9ff942 | 731 | gboolean lttv_apply_op_eq_string(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 732 | char* r = (char*) v1; |
9ab5ebd7 | 733 | return (!g_strcasecmp(r,v2.v_string)); |
83aa92fc | 734 | } |
150f0d33 | 735 | |
c6832b57 | 736 | /** |
7e7af7f2 | 737 | * @fn gboolean lttv_apply_op_eq_quark(gpointer,LttvFieldValue) |
c6832b57 | 738 | * |
739 | * Applies the 'equal' operator to the | |
740 | * specified structure and value | |
741 | * @param v1 left member of comparison | |
742 | * @param v2 right member of comparison | |
743 | * @return success/failure of operation | |
744 | */ | |
745 | gboolean lttv_apply_op_eq_quark(const gpointer v1, LttvFieldValue v2) { | |
746 | GQuark* r = (GQuark*) v1; | |
c56a714e | 747 | return (*r == v2.v_quark); |
c6832b57 | 748 | } |
749 | ||
6471e71f | 750 | /** |
751 | * @fn gboolean lttv_apply_op_eq_quarks(gpointer,LttvFieldValue) | |
752 | * | |
753 | * Applies the 'equal' operator to the | |
754 | * specified structure and value | |
755 | * @param v1 left member of comparison | |
756 | * @param v2 right member of comparison | |
757 | * @return success/failure of operation | |
758 | */ | |
759 | gboolean lttv_apply_op_eq_quarks(const gpointer v1, LttvFieldValue v2) { | |
760 | GQuark *r1 = (GQuark *) v1; | |
761 | GQuark *r2 = r1 + 1; | |
762 | if (likely(*r1 != (GQuark)0) && *r1 != v2.v_quarks.q[0]) | |
763 | return 0; | |
764 | if (*r2 != v2.v_quarks.q[1]) | |
765 | return 0; | |
766 | return 1; | |
767 | } | |
768 | ||
7145a073 | 769 | /** |
7e7af7f2 | 770 | * @fn gboolean lttv_apply_op_eq_ltttime(gpointer,LttvFieldValue) |
7145a073 | 771 | * |
772 | * Applies the 'equal' operator to the | |
773 | * specified structure and value | |
774 | * @param v1 left member of comparison | |
775 | * @param v2 right member of comparison | |
776 | * @return success/failure of operation | |
777 | */ | |
4d9ff942 | 778 | gboolean lttv_apply_op_eq_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 779 | LttTime* r = (LttTime*) v1; |
c6832b57 | 780 | return ltt_time_compare(*r, v2.v_ltttime)==0?1:0; |
7145a073 | 781 | } |
782 | ||
2ec11087 | 783 | /** |
784 | * @fn gboolean lttv_apply_op_ne_uint(gpointer,LttvFieldValue) | |
785 | * | |
786 | * Applies the 'not equal' operator to the | |
787 | * specified structure and value | |
788 | * @param v1 left member of comparison | |
789 | * @param v2 right member of comparison | |
790 | * @return success/failure of operation | |
791 | */ | |
792 | gboolean lttv_apply_op_ne_uint(const gpointer v1, LttvFieldValue v2) { | |
793 | guint* r = (guint*) v1; | |
794 | return (*r != v2.v_uint); | |
795 | } | |
7145a073 | 796 | |
150f0d33 | 797 | /** |
7e7af7f2 | 798 | * @fn gboolean lttv_apply_op_ne_uint64(gpointer,LttvFieldValue) |
56e29124 | 799 | * |
150f0d33 | 800 | * Applies the 'not equal' operator to the |
47aa6e58 | 801 | * specified structure and value |
802 | * @param v1 left member of comparison | |
803 | * @param v2 right member of comparison | |
150f0d33 | 804 | * @return success/failure of operation |
805 | */ | |
4d9ff942 | 806 | gboolean lttv_apply_op_ne_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 807 | guint64* r = (guint64*) v1; |
9ab5ebd7 | 808 | return (*r != v2.v_uint64); |
83aa92fc | 809 | } |
150f0d33 | 810 | |
5b729fcf | 811 | /** |
7e7af7f2 | 812 | * @fn gboolean lttv_apply_op_ne_uint32(gpointer,LttvFieldValue) |
56e29124 | 813 | * |
5b729fcf | 814 | * Applies the 'not equal' operator to the |
47aa6e58 | 815 | * specified structure and value |
816 | * @param v1 left member of comparison | |
817 | * @param v2 right member of comparison | |
5b729fcf | 818 | * @return success/failure of operation |
819 | */ | |
4d9ff942 | 820 | gboolean lttv_apply_op_ne_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 821 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 822 | return (*r != v2.v_uint32); |
83aa92fc | 823 | } |
5b729fcf | 824 | |
825 | /** | |
7e7af7f2 | 826 | * @fn gboolean lttv_apply_op_ne_uint16(gpointer,LttvFieldValue) |
56e29124 | 827 | * |
5b729fcf | 828 | * Applies the 'not equal' operator to the |
47aa6e58 | 829 | * specified structure and value |
830 | * @param v1 left member of comparison | |
831 | * @param v2 right member of comparison | |
5b729fcf | 832 | * @return success/failure of operation |
833 | */ | |
4d9ff942 | 834 | gboolean lttv_apply_op_ne_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 835 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 836 | return (*r != v2.v_uint16); |
83aa92fc | 837 | } |
5b729fcf | 838 | |
839 | /** | |
7e7af7f2 | 840 | * @fn gboolean lttv_apply_op_ne_double(gpointer,LttvFieldValue) |
56e29124 | 841 | * |
5b729fcf | 842 | * Applies the 'not equal' operator to the |
47aa6e58 | 843 | * specified structure and value |
844 | * @param v1 left member of comparison | |
845 | * @param v2 right member of comparison | |
5b729fcf | 846 | * @return success/failure of operation |
847 | */ | |
4d9ff942 | 848 | gboolean lttv_apply_op_ne_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 849 | double* r = (double*) v1; |
9ab5ebd7 | 850 | return (*r != v2.v_double); |
83aa92fc | 851 | } |
5b729fcf | 852 | |
853 | /** | |
7e7af7f2 | 854 | * @fn gboolean lttv_apply_op_ne_string(gpointer,LttvFieldValue) |
56e29124 | 855 | * |
5b729fcf | 856 | * Applies the 'not equal' operator to the |
47aa6e58 | 857 | * specified structure and value |
858 | * @param v1 left member of comparison | |
859 | * @param v2 right member of comparison | |
5b729fcf | 860 | * @return success/failure of operation |
861 | */ | |
4d9ff942 | 862 | gboolean lttv_apply_op_ne_string(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 863 | char* r = (char*) v1; |
9ab5ebd7 | 864 | return (g_strcasecmp(r,v2.v_string)); |
83aa92fc | 865 | } |
150f0d33 | 866 | |
c6832b57 | 867 | /** |
7e7af7f2 | 868 | * @fn gboolean lttv_apply_op_ne_quark(gpointer,LttvFieldValue) |
c6832b57 | 869 | * |
870 | * Applies the 'not equal' operator to the | |
871 | * specified structure and value | |
872 | * @param v1 left member of comparison | |
873 | * @param v2 right member of comparison | |
874 | * @return success/failure of operation | |
875 | */ | |
876 | gboolean lttv_apply_op_ne_quark(const gpointer v1, LttvFieldValue v2) { | |
877 | GQuark* r = (GQuark*) v1; | |
c56a714e | 878 | return (*r != v2.v_quark); |
c6832b57 | 879 | } |
880 | ||
6471e71f | 881 | /** |
882 | * @fn gboolean lttv_apply_op_ne_quarks(gpointer,LttvFieldValue) | |
883 | * | |
884 | * Applies the 'equal' operator to the | |
885 | * specified structure and value | |
886 | * @param v1 left member of comparison | |
887 | * @param v2 right member of comparison | |
888 | * @return success/failure of operation | |
889 | */ | |
890 | gboolean lttv_apply_op_ne_quarks(const gpointer v1, LttvFieldValue v2) { | |
891 | GQuark *r1 = (GQuark *) v1; | |
892 | GQuark *r2 = r1 + 1; | |
893 | if ((*r1 == (GQuark)0 || *r1 == v2.v_quarks.q[0]) && *r2 == v2.v_quarks.q[1]) | |
894 | return 0; | |
895 | else | |
896 | return 1; | |
897 | } | |
c6832b57 | 898 | |
7145a073 | 899 | /** |
7e7af7f2 | 900 | * @fn gboolean lttv_apply_op_ne_ltttime(gpointer,LttvFieldValue) |
7145a073 | 901 | * |
902 | * Applies the 'not equal' operator to the | |
903 | * specified structure and value | |
904 | * @param v1 left member of comparison | |
905 | * @param v2 right member of comparison | |
906 | * @return success/failure of operation | |
907 | */ | |
4d9ff942 | 908 | gboolean lttv_apply_op_ne_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 909 | LttTime* r = (LttTime*) v1; |
46c40a93 | 910 | return ltt_time_compare(*r, v2.v_ltttime)!=0?1:0; |
7145a073 | 911 | } |
912 | ||
2ec11087 | 913 | /** |
914 | * @fn gboolean lttv_apply_op_lt_uint(gpointer,LttvFieldValue) | |
915 | * | |
916 | * Applies the 'lower than' operator to the | |
917 | * specified structure and value | |
918 | * @param v1 left member of comparison | |
919 | * @param v2 right member of comparison | |
920 | * @return success/failure of operation | |
921 | */ | |
922 | gboolean lttv_apply_op_lt_uint(const gpointer v1, LttvFieldValue v2) { | |
923 | guint* r = (guint*) v1; | |
924 | return (*r < v2.v_uint); | |
925 | } | |
7145a073 | 926 | |
150f0d33 | 927 | /** |
7e7af7f2 | 928 | * @fn gboolean lttv_apply_op_lt_uint64(gpointer,LttvFieldValue) |
56e29124 | 929 | * |
150f0d33 | 930 | * Applies the 'lower than' operator to the |
47aa6e58 | 931 | * specified structure and value |
932 | * @param v1 left member of comparison | |
933 | * @param v2 right member of comparison | |
150f0d33 | 934 | * @return success/failure of operation |
935 | */ | |
4d9ff942 | 936 | gboolean lttv_apply_op_lt_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 937 | guint64* r = (guint64*) v1; |
9ab5ebd7 | 938 | return (*r < v2.v_uint64); |
83aa92fc | 939 | } |
150f0d33 | 940 | |
5b729fcf | 941 | /** |
7e7af7f2 | 942 | * @fn gboolean lttv_apply_op_lt_uint32(gpointer,LttvFieldValue) |
56e29124 | 943 | * |
5b729fcf | 944 | * Applies the 'lower than' operator to the |
47aa6e58 | 945 | * specified structure and value |
946 | * @param v1 left member of comparison | |
947 | * @param v2 right member of comparison | |
5b729fcf | 948 | * @return success/failure of operation |
949 | */ | |
4d9ff942 | 950 | gboolean lttv_apply_op_lt_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 951 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 952 | return (*r < v2.v_uint32); |
83aa92fc | 953 | } |
5b729fcf | 954 | |
955 | /** | |
7e7af7f2 | 956 | * @fn gboolean lttv_apply_op_lt_uint16(gpointer,LttvFieldValue) |
56e29124 | 957 | * |
5b729fcf | 958 | * Applies the 'lower than' operator to the |
47aa6e58 | 959 | * specified structure and value |
960 | * @param v1 left member of comparison | |
961 | * @param v2 right member of comparison | |
5b729fcf | 962 | * @return success/failure of operation |
963 | */ | |
4d9ff942 | 964 | gboolean lttv_apply_op_lt_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 965 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 966 | return (*r < v2.v_uint16); |
83aa92fc | 967 | } |
5b729fcf | 968 | |
969 | /** | |
7e7af7f2 | 970 | * @fn gboolean lttv_apply_op_lt_double(gpointer,LttvFieldValue) |
56e29124 | 971 | * |
5b729fcf | 972 | * Applies the 'lower than' operator to the |
47aa6e58 | 973 | * specified structure and value |
974 | * @param v1 left member of comparison | |
975 | * @param v2 right member of comparison | |
5b729fcf | 976 | * @return success/failure of operation |
977 | */ | |
4d9ff942 | 978 | gboolean lttv_apply_op_lt_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 979 | double* r = (double*) v1; |
9ab5ebd7 | 980 | return (*r < v2.v_double); |
83aa92fc | 981 | } |
5b729fcf | 982 | |
7145a073 | 983 | /** |
7e7af7f2 | 984 | * @fn gboolean lttv_apply_op_lt_ltttime(gpointer,LttvFieldValue) |
7145a073 | 985 | * |
986 | * Applies the 'lower than' operator to the | |
987 | * specified structure and value | |
988 | * @param v1 left member of comparison | |
989 | * @param v2 right member of comparison | |
990 | * @return success/failure of operation | |
991 | */ | |
4d9ff942 | 992 | gboolean lttv_apply_op_lt_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 993 | LttTime* r = (LttTime*) v1; |
c6832b57 | 994 | // return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec < v2.v_ltttime.tv_nsec))); |
995 | return ltt_time_compare(*r, v2.v_ltttime)==-1?1:0; | |
7145a073 | 996 | } |
997 | ||
2ec11087 | 998 | /** |
999 | * @fn gboolean lttv_apply_op_le_uint(gpointer,LttvFieldValue) | |
1000 | * | |
1001 | * Applies the 'lower or equal' operator to the | |
1002 | * specified structure and value | |
1003 | * @param v1 left member of comparison | |
1004 | * @param v2 right member of comparison | |
1005 | * @return success/failure of operation | |
1006 | */ | |
1007 | gboolean lttv_apply_op_le_uint(const gpointer v1, LttvFieldValue v2) { | |
1008 | guint* r = (guint*) v1; | |
1009 | return (*r <= v2.v_uint); | |
1010 | } | |
7145a073 | 1011 | |
5b729fcf | 1012 | /** |
7e7af7f2 | 1013 | * @fn gboolean lttv_apply_op_le_uint64(gpointer,LttvFieldValue) |
56e29124 | 1014 | * |
1015 | * Applies the 'lower or equal' operator to the | |
47aa6e58 | 1016 | * specified structure and value |
1017 | * @param v1 left member of comparison | |
1018 | * @param v2 right member of comparison | |
5b729fcf | 1019 | * @return success/failure of operation |
1020 | */ | |
4d9ff942 | 1021 | gboolean lttv_apply_op_le_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1022 | guint64* r = (guint64*) v1; |
9ab5ebd7 | 1023 | return (*r <= v2.v_uint64); |
83aa92fc | 1024 | } |
150f0d33 | 1025 | |
1026 | /** | |
7e7af7f2 | 1027 | * @fn gboolean lttv_apply_op_le_uint32(gpointer,LttvFieldValue) |
56e29124 | 1028 | * |
150f0d33 | 1029 | * Applies the 'lower or equal' operator to the |
47aa6e58 | 1030 | * specified structure and value |
1031 | * @param v1 left member of comparison | |
1032 | * @param v2 right member of comparison | |
150f0d33 | 1033 | * @return success/failure of operation |
1034 | */ | |
4d9ff942 | 1035 | gboolean lttv_apply_op_le_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1036 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 1037 | return (*r <= v2.v_uint32); |
83aa92fc | 1038 | } |
150f0d33 | 1039 | |
5b729fcf | 1040 | /** |
7e7af7f2 | 1041 | * @fn gboolean lttv_apply_op_le_uint16(gpointer,LttvFieldValue) |
56e29124 | 1042 | * |
5b729fcf | 1043 | * Applies the 'lower or equal' operator to the |
47aa6e58 | 1044 | * specified structure and value |
1045 | * @param v1 left member of comparison | |
1046 | * @param v2 right member of comparison | |
5b729fcf | 1047 | * @return success/failure of operation |
1048 | */ | |
4d9ff942 | 1049 | gboolean lttv_apply_op_le_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1050 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 1051 | return (*r <= v2.v_uint16); |
83aa92fc | 1052 | } |
5b729fcf | 1053 | |
1054 | /** | |
7e7af7f2 | 1055 | * @fn gboolean lttv_apply_op_le_double(gpointer,LttvFieldValue) |
56e29124 | 1056 | * |
5b729fcf | 1057 | * Applies the 'lower or equal' operator to the |
47aa6e58 | 1058 | * specified structure and value |
1059 | * @param v1 left member of comparison | |
1060 | * @param v2 right member of comparison | |
5b729fcf | 1061 | * @return success/failure of operation |
1062 | */ | |
4d9ff942 | 1063 | gboolean lttv_apply_op_le_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1064 | double* r = (double*) v1; |
9ab5ebd7 | 1065 | return (*r <= v2.v_double); |
83aa92fc | 1066 | } |
5b729fcf | 1067 | |
7145a073 | 1068 | /** |
7e7af7f2 | 1069 | * @fn gboolean lttv_apply_op_le_ltttime(gpointer,LttvFieldValue) |
7145a073 | 1070 | * |
1071 | * Applies the 'lower or equal' operator to the | |
1072 | * specified structure and value | |
1073 | * @param v1 left member of comparison | |
1074 | * @param v2 right member of comparison | |
1075 | * @return success/failure of operation | |
1076 | */ | |
4d9ff942 | 1077 | gboolean lttv_apply_op_le_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 1078 | LttTime* r = (LttTime*) v1; |
c6832b57 | 1079 | // return ((r->tv_sec < v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec <= v2.v_ltttime.tv_nsec))); |
1080 | return ltt_time_compare(*r, v2.v_ltttime)<1?1:0; | |
7145a073 | 1081 | } |
1082 | ||
1083 | ||
2ec11087 | 1084 | /** |
1085 | * @fn gboolean lttv_apply_op_gt_uint(gpointer,LttvFieldValue) | |
1086 | * | |
1087 | * Applies the 'greater than' operator to the | |
1088 | * specified structure and value | |
1089 | * @param v1 left member of comparison | |
1090 | * @param v2 right member of comparison | |
1091 | * @return success/failure of operation | |
1092 | */ | |
1093 | gboolean lttv_apply_op_gt_uint(const gpointer v1, LttvFieldValue v2) { | |
1094 | guint* r = (guint*) v1; | |
1095 | return (*r > v2.v_uint); | |
1096 | } | |
1097 | ||
5b729fcf | 1098 | /** |
7e7af7f2 | 1099 | * @fn gboolean lttv_apply_op_gt_uint64(gpointer,LttvFieldValue) |
56e29124 | 1100 | * |
83aa92fc | 1101 | * Applies the 'greater than' operator to the |
47aa6e58 | 1102 | * specified structure and value |
1103 | * @param v1 left member of comparison | |
1104 | * @param v2 right member of comparison | |
5b729fcf | 1105 | * @return success/failure of operation |
1106 | */ | |
4d9ff942 | 1107 | gboolean lttv_apply_op_gt_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1108 | guint64* r = (guint64*) v1; |
9ab5ebd7 | 1109 | return (*r > v2.v_uint64); |
83aa92fc | 1110 | } |
150f0d33 | 1111 | |
1112 | /** | |
7e7af7f2 | 1113 | * @fn gboolean lttv_apply_op_gt_uint32(gpointer,LttvFieldValue) |
56e29124 | 1114 | * |
150f0d33 | 1115 | * Applies the 'greater than' operator to the |
47aa6e58 | 1116 | * specified structure and value |
1117 | * @param v1 left member of comparison | |
1118 | * @param v2 right member of comparison | |
150f0d33 | 1119 | * @return success/failure of operation |
1120 | */ | |
4d9ff942 | 1121 | gboolean lttv_apply_op_gt_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1122 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 1123 | return (*r > v2.v_uint32); |
83aa92fc | 1124 | } |
150f0d33 | 1125 | |
5b729fcf | 1126 | /** |
7e7af7f2 | 1127 | * @fn gboolean lttv_apply_op_gt_uint16(gpointer,LttvFieldValue) |
56e29124 | 1128 | * |
5b729fcf | 1129 | * Applies the 'greater than' operator to the |
47aa6e58 | 1130 | * specified structure and value |
1131 | * @param v1 left member of comparison | |
1132 | * @param v2 right member of comparison | |
5b729fcf | 1133 | * @return success/failure of operation |
1134 | */ | |
4d9ff942 | 1135 | gboolean lttv_apply_op_gt_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1136 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 1137 | return (*r > v2.v_uint16); |
83aa92fc | 1138 | } |
5b729fcf | 1139 | |
1140 | /** | |
7e7af7f2 | 1141 | * @fn gboolean lttv_apply_op_gt_double(gpointer,LttvFieldValue) |
56e29124 | 1142 | * |
5b729fcf | 1143 | * Applies the 'greater than' operator to the |
47aa6e58 | 1144 | * specified structure and value |
1145 | * @param v1 left member of comparison | |
1146 | * @param v2 right member of comparison | |
5b729fcf | 1147 | * @return success/failure of operation |
1148 | */ | |
4d9ff942 | 1149 | gboolean lttv_apply_op_gt_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1150 | double* r = (double*) v1; |
9ab5ebd7 | 1151 | return (*r > v2.v_double); |
83aa92fc | 1152 | } |
5b729fcf | 1153 | |
7145a073 | 1154 | /** |
7e7af7f2 | 1155 | * @fn gboolean lttv_apply_op_gt_ltttime(gpointer,LttvFieldValue) |
7145a073 | 1156 | * |
1157 | * Applies the 'greater than' operator to the | |
1158 | * specified structure and value | |
1159 | * @param v1 left member of comparison | |
1160 | * @param v2 right member of comparison | |
1161 | * @return success/failure of operation | |
1162 | */ | |
4d9ff942 | 1163 | gboolean lttv_apply_op_gt_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 1164 | LttTime* r = (LttTime*) v1; |
c6832b57 | 1165 | // return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec > v2.v_ltttime.tv_nsec))); |
1166 | return ltt_time_compare(*r, v2.v_ltttime)==1?1:0; | |
7145a073 | 1167 | } |
1168 | ||
2ec11087 | 1169 | /** |
1170 | * @fn gboolean lttv_apply_op_ge_uint(gpointer,LttvFieldValue) | |
1171 | * | |
1172 | * Applies the 'greater or equal' operator to the | |
1173 | * specified structure and value | |
1174 | * @param v1 left member of comparison | |
1175 | * @param v2 right member of comparison | |
1176 | * @return success/failure of operation | |
1177 | */ | |
1178 | gboolean lttv_apply_op_ge_uint(const gpointer v1, LttvFieldValue v2) { | |
1179 | guint* r = (guint*) v1; | |
1180 | return (*r >= v2.v_uint); | |
1181 | } | |
7145a073 | 1182 | |
5b729fcf | 1183 | /** |
7e7af7f2 | 1184 | * @fn gboolean lttv_apply_op_ge_uint64(gpointer,LttvFieldValue) |
56e29124 | 1185 | * |
83aa92fc | 1186 | * Applies the 'greater or equal' operator to the |
47aa6e58 | 1187 | * specified structure and value |
1188 | * @param v1 left member of comparison | |
1189 | * @param v2 right member of comparison | |
5b729fcf | 1190 | * @return success/failure of operation |
1191 | */ | |
4d9ff942 | 1192 | gboolean lttv_apply_op_ge_uint64(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1193 | guint64* r = (guint64*) v1; |
9ab5ebd7 | 1194 | return (*r >= v2.v_uint64); |
83aa92fc | 1195 | } |
150f0d33 | 1196 | |
1197 | /** | |
7e7af7f2 | 1198 | * @fn gboolean lttv_apply_op_ge_uint32(gpointer,LttvFieldValue) |
56e29124 | 1199 | * |
150f0d33 | 1200 | * Applies the 'greater or equal' operator to the |
47aa6e58 | 1201 | * specified structure and value |
1202 | * @param v1 left member of comparison | |
1203 | * @param v2 right member of comparison | |
150f0d33 | 1204 | * @return success/failure of operation |
1205 | */ | |
4d9ff942 | 1206 | gboolean lttv_apply_op_ge_uint32(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1207 | guint32* r = (guint32*) v1; |
9ab5ebd7 | 1208 | return (*r >= v2.v_uint32); |
83aa92fc | 1209 | } |
150f0d33 | 1210 | |
5b729fcf | 1211 | /** |
7e7af7f2 | 1212 | * @fn gboolean lttv_apply_op_ge_uint16(gpointer,LttvFieldValue) |
56e29124 | 1213 | * |
5b729fcf | 1214 | * Applies the 'greater or equal' operator to the |
47aa6e58 | 1215 | * specified structure and value |
1216 | * @param v1 left member of comparison | |
1217 | * @param v2 right member of comparison | |
5b729fcf | 1218 | * @return success/failure of operation |
1219 | */ | |
4d9ff942 | 1220 | gboolean lttv_apply_op_ge_uint16(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1221 | guint16* r = (guint16*) v1; |
9ab5ebd7 | 1222 | return (*r >= v2.v_uint16); |
83aa92fc | 1223 | } |
150f0d33 | 1224 | |
5b729fcf | 1225 | /** |
7e7af7f2 | 1226 | * @fn gboolean lttv_apply_op_ge_double(gpointer,LttvFieldValue) |
56e29124 | 1227 | * |
5b729fcf | 1228 | * Applies the 'greater or equal' operator to the |
47aa6e58 | 1229 | * specified structure and value |
1230 | * @param v1 left member of comparison | |
1231 | * @param v2 right member of comparison | |
5b729fcf | 1232 | * @return success/failure of operation |
1233 | */ | |
4d9ff942 | 1234 | gboolean lttv_apply_op_ge_double(const gpointer v1, LttvFieldValue v2) { |
83aa92fc | 1235 | double* r = (double*) v1; |
9ab5ebd7 | 1236 | return (*r >= v2.v_double); |
83aa92fc | 1237 | } |
150f0d33 | 1238 | |
7145a073 | 1239 | /** |
7e7af7f2 | 1240 | * @fn gboolean lttv_apply_op_ge_ltttime(gpointer,LttvFieldValue) |
7145a073 | 1241 | * |
1242 | * Applies the 'greater or equal' operator to the | |
1243 | * specified structure and value | |
1244 | * @param v1 left member of comparison | |
1245 | * @param v2 right member of comparison | |
1246 | * @return success/failure of operation | |
1247 | */ | |
4d9ff942 | 1248 | gboolean lttv_apply_op_ge_ltttime(const gpointer v1, LttvFieldValue v2) { |
7145a073 | 1249 | LttTime* r = (LttTime*) v1; |
c6832b57 | 1250 | // return ((r->tv_sec > v2.v_ltttime.tv_sec) || ((r->tv_sec == v2.v_ltttime.tv_sec) && (r->tv_nsec >= v2.v_ltttime.tv_nsec))); |
1251 | return ltt_time_compare(*r, v2.v_ltttime)>-1?1:0; | |
7145a073 | 1252 | } |
1253 | ||
1254 | ||
150f0d33 | 1255 | |
1256 | /** | |
56e29124 | 1257 | * Makes a copy of the current filter tree |
1258 | * @param tree pointer to the current tree | |
1259 | * @return new copy of the filter tree | |
150f0d33 | 1260 | */ |
1261 | LttvFilterTree* | |
4d9ff942 | 1262 | lttv_filter_tree_clone(const LttvFilterTree* tree) { |
150f0d33 | 1263 | |
8c89f5a8 | 1264 | LttvFilterTree* newtree = lttv_filter_tree_new(); |
150f0d33 | 1265 | |
8c89f5a8 | 1266 | newtree->node = tree->node; |
1267 | ||
1268 | newtree->left = tree->left; | |
1269 | if(newtree->left == LTTV_TREE_NODE) { | |
1270 | newtree->l_child.t = lttv_filter_tree_clone(tree->l_child.t); | |
1271 | } else if(newtree->left == LTTV_TREE_LEAF) { | |
1272 | newtree->l_child.leaf = lttv_simple_expression_new(); | |
1273 | newtree->l_child.leaf->field = tree->l_child.leaf->field; | |
1274 | newtree->l_child.leaf->offset = tree->l_child.leaf->offset; | |
1275 | newtree->l_child.leaf->op = tree->l_child.leaf->op; | |
9ab5ebd7 | 1276 | /* FIXME: special case for string copy ! */ |
1277 | newtree->l_child.leaf->value = tree->l_child.leaf->value; | |
8c89f5a8 | 1278 | } |
1279 | ||
1280 | newtree->right = tree->right; | |
1281 | if(newtree->right == LTTV_TREE_NODE) { | |
1282 | newtree->r_child.t = lttv_filter_tree_clone(tree->r_child.t); | |
1283 | } else if(newtree->right == LTTV_TREE_LEAF) { | |
1284 | newtree->r_child.leaf = lttv_simple_expression_new(); | |
1285 | newtree->r_child.leaf->field = tree->r_child.leaf->field; | |
1286 | newtree->r_child.leaf->offset = tree->r_child.leaf->offset; | |
1287 | newtree->r_child.leaf->op = tree->r_child.leaf->op; | |
9ab5ebd7 | 1288 | newtree->r_child.leaf->value = tree->r_child.leaf->value; |
8c89f5a8 | 1289 | } |
1290 | ||
1291 | return newtree; | |
1292 | ||
150f0d33 | 1293 | } |
1294 | ||
1295 | /** | |
56e29124 | 1296 | * Makes a copy of the current filter |
1297 | * @param filter pointer to the current filter | |
1298 | * @return new copy of the filter | |
150f0d33 | 1299 | */ |
1300 | LttvFilter* | |
4d9ff942 | 1301 | lttv_filter_clone(const LttvFilter* filter) { |
ebcead4a | 1302 | |
571ef1ed | 1303 | if(!filter) return NULL; |
ebcead4a | 1304 | |
150f0d33 | 1305 | LttvFilter* newfilter = g_new(LttvFilter,1); |
1306 | ||
150f0d33 | 1307 | strcpy(newfilter->expression,filter->expression); |
1308 | ||
1309 | newfilter->head = lttv_filter_tree_clone(filter->head); | |
1310 | ||
1311 | return newfilter; | |
1312 | ||
1313 | } | |
1314 | ||
1315 | ||
84a333d6 | 1316 | /** |
56e29124 | 1317 | * @fn LttvFilter* lttv_filter_new() |
1318 | * | |
571ef1ed | 1319 | * Creates a new LttvFilter |
1320 | * @return the current LttvFilter or NULL if error | |
31452f49 | 1321 | */ |
2ea36caf | 1322 | LttvFilter* |
5f185a2b | 1323 | lttv_filter_new() { |
a4c292d4 | 1324 | |
5f185a2b | 1325 | LttvFilter* filter = g_new(LttvFilter,1); |
1326 | filter->expression = NULL; | |
1327 | filter->head = NULL; | |
7e7af7f2 | 1328 | |
1329 | return filter; | |
5f185a2b | 1330 | |
1331 | } | |
a4c292d4 | 1332 | |
8c89f5a8 | 1333 | /** |
56e29124 | 1334 | * @fn gboolean lttv_filter_update(LttvFilter*) |
1335 | * | |
8c89f5a8 | 1336 | * Updates the current LttvFilter by building |
1337 | * its tree based upon the expression string | |
1338 | * @param filter pointer to the current LttvFilter | |
1339 | * @return Failure/Success of operation | |
1340 | */ | |
5f185a2b | 1341 | gboolean |
1342 | lttv_filter_update(LttvFilter* filter) { | |
1343 | ||
571ef1ed | 1344 | // g_print("filter::lttv_filter_new()\n"); /* debug */ |
5f185a2b | 1345 | |
1346 | if(filter->expression == NULL) return FALSE; | |
1347 | ||
571ef1ed | 1348 | int |
a4c292d4 | 1349 | i, |
571ef1ed | 1350 | p_nesting=0, /* parenthesis nesting value */ |
72911c5d | 1351 | not=0; |
571ef1ed | 1352 | guint expression_len; |
72911c5d | 1353 | |
1601b365 | 1354 | /* trees */ |
5b729fcf | 1355 | LttvFilterTree |
1601b365 | 1356 | *tree = lttv_filter_tree_new(), /* main tree */ |
1357 | *subtree = NULL, /* buffer for subtrees */ | |
1358 | *t1, /* buffer #1 */ | |
72911c5d | 1359 | *t2, /* buffer #2 */ |
1360 | *t3; /* buffer #3 */ | |
1601b365 | 1361 | |
5f185a2b | 1362 | /* |
1363 | * the filter | |
1364 | * If the tree already exists, | |
1365 | * destroy it and build a new one | |
1366 | */ | |
1367 | if(filter->head != NULL) lttv_filter_tree_destroy(filter->head); | |
f3020899 | 1368 | filter->head = NULL; /* will be assigned at the end */ |
5f185a2b | 1369 | |
1601b365 | 1370 | /* |
1371 | * Tree Stack | |
f4e9dd16 | 1372 | * each element of the list |
1373 | * is a sub tree created | |
1374 | * by the use of parenthesis in the | |
1375 | * global expression. The final tree | |
1601b365 | 1376 | * will be the one left at the root of |
f4e9dd16 | 1377 | * the list |
1378 | */ | |
18d1226f | 1379 | GPtrArray *tree_stack = g_ptr_array_new(); |
1380 | g_ptr_array_add( tree_stack,(gpointer) tree ); | |
f4e9dd16 | 1381 | |
a4c292d4 | 1382 | /* temporary values */ |
0769c82f | 1383 | GString *a_field_component = g_string_new(""); |
ef2b07c1 | 1384 | GString *a_string_spaces = g_string_new(""); |
56e29124 | 1385 | GPtrArray *a_field_path = g_ptr_array_new(); |
1386 | ||
1387 | /* simple expression buffer */ | |
389ba50e | 1388 | LttvSimpleExpression* a_simple_expression = lttv_simple_expression_new(); |
d564d2ad | 1389 | |
1390 | gint nest_quotes = 0; | |
0769c82f | 1391 | |
a4c292d4 | 1392 | /* |
571ef1ed | 1393 | * Parse entire expression and construct |
1394 | * the binary tree. There are two steps | |
1395 | * in browsing that string | |
1396 | * 1. finding boolean ops " &,|,^,! " and parenthesis " {,(,[,],),} " | |
1397 | * 2. finding simple expressions | |
1398 | * - field path ( separated by dots ) | |
1399 | * - op ( >, <, =, >=, <=, !=) | |
1400 | * - value ( integer, string ... ) | |
1401 | * To spare computing time, the whole | |
1402 | * string is parsed in this loop for a | |
1403 | * O(n) complexity order. | |
1601b365 | 1404 | * |
18d1226f | 1405 | * When encountering logical op &,|,^ |
1406 | * 1. parse the last value if any | |
1407 | * 2. create a new tree | |
1408 | * 3. add the expression (simple exp, or exp (subtree)) to the tree | |
1409 | * 4. concatenate this tree with the current tree on top of the stack | |
1410 | * When encountering math ops >,>=,<,<=,=,!= | |
1411 | * 1. add to op to the simple expression | |
1412 | * 2. concatenate last field component to field path | |
1413 | * When encountering concatening ops . | |
1414 | * 1. concatenate last field component to field path | |
1415 | * When encountering opening parenthesis (,{,[ | |
1416 | * 1. create a new subtree on top of tree stack | |
1417 | * When encountering closing parenthesis ),},] | |
1418 | * 1. add the expression on right child of the current tree | |
1419 | * 2. the subtree is completed, allocate a new subtree | |
1420 | * 3. pop the tree value from the tree stack | |
1421 | */ | |
be66ef34 | 1422 | |
1423 | #ifdef TEST | |
1424 | struct timeval starttime; | |
1425 | struct timeval endtime; | |
1426 | gettimeofday(&starttime, NULL); | |
1427 | #endif | |
18d1226f | 1428 | |
571ef1ed | 1429 | expression_len = strlen(filter->expression); |
1430 | for(i=0;i<expression_len;i++) { | |
5f185a2b | 1431 | // debug |
72911c5d | 1432 | // g_print("%c\n ",filter->expression[i]); |
d564d2ad | 1433 | if(nest_quotes) { |
1434 | switch(filter->expression[i]) { | |
571ef1ed | 1435 | case '\\' : |
1436 | if(filter->expression[i+1] == '\"') { | |
1437 | i++; | |
1438 | } | |
1439 | break; | |
2db17921 | 1440 | case '\"': |
571ef1ed | 1441 | nest_quotes = 0; |
2db17921 | 1442 | i++; |
571ef1ed | 1443 | break; |
d564d2ad | 1444 | } |
1445 | if(a_string_spaces->len != 0) { | |
1446 | a_field_component = g_string_append( | |
1447 | a_field_component, a_string_spaces->str); | |
2db17921 | 1448 | a_string_spaces = g_string_set_size(a_string_spaces, 0); |
d564d2ad | 1449 | } |
1450 | a_field_component = g_string_append_c(a_field_component, | |
1451 | filter->expression[i]); | |
1452 | continue; | |
1453 | } | |
1454 | ||
5f185a2b | 1455 | switch(filter->expression[i]) { |
a4c292d4 | 1456 | /* |
1457 | * logical operators | |
1458 | */ | |
1459 | case '&': /* and */ | |
72911c5d | 1460 | |
1461 | /* get current tree in tree stack */ | |
5b729fcf | 1462 | t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1); |
72911c5d | 1463 | |
1464 | /* get current node at absolute right */ | |
9ab5ebd7 | 1465 | while(t1->right != LTTV_TREE_IDLE) { |
1466 | g_assert(t1->right == LTTV_TREE_NODE); | |
1467 | t1 = t1->r_child.t; | |
1468 | } | |
18d1226f | 1469 | t2 = lttv_filter_tree_new(); |
0cdc2470 | 1470 | t2->node = LTTV_LOGICAL_AND; |
72911c5d | 1471 | t1->right = LTTV_TREE_NODE; |
1472 | t1->r_child.t = t2; | |
1473 | if(not) { /* add not operator to tree */ | |
1474 | t3 = lttv_filter_tree_new(); | |
1475 | t3->node = LTTV_LOGICAL_NOT; | |
1476 | t2->left = LTTV_TREE_NODE; | |
1477 | t2->l_child.t = t3; | |
72911c5d | 1478 | t2 = t3; |
1479 | not = 0; | |
72911c5d | 1480 | } |
bb87caa7 | 1481 | if(subtree != NULL) { /* append subtree to current tree */ |
18d1226f | 1482 | t2->left = LTTV_TREE_NODE; |
1483 | t2->l_child.t = subtree; | |
f4e9dd16 | 1484 | subtree = NULL; |
bb87caa7 | 1485 | } else { /* append a simple expression */ |
9ab5ebd7 | 1486 | lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE)); |
18d1226f | 1487 | a_field_component = g_string_new(""); |
571ef1ed | 1488 | g_string_free(a_string_spaces, TRUE); |
1489 | a_string_spaces = g_string_new(""); | |
18d1226f | 1490 | t2->left = LTTV_TREE_LEAF; |
0cdc2470 | 1491 | t2->l_child.leaf = a_simple_expression; |
389ba50e | 1492 | a_simple_expression = lttv_simple_expression_new(); |
f4e9dd16 | 1493 | } |
f4e9dd16 | 1494 | break; |
aa4600f3 | 1495 | |
a4c292d4 | 1496 | case '|': /* or */ |
aa4600f3 | 1497 | |
e00d6a24 | 1498 | t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1); |
9ab5ebd7 | 1499 | while(t1->right != LTTV_TREE_IDLE) { |
1500 | g_assert(t1->right == LTTV_TREE_NODE); | |
1501 | t1 = t1->r_child.t; | |
1502 | } | |
1601b365 | 1503 | t2 = lttv_filter_tree_new(); |
0cdc2470 | 1504 | t2->node = LTTV_LOGICAL_OR; |
72911c5d | 1505 | t1->right = LTTV_TREE_NODE; |
1506 | t1->r_child.t = t2; | |
1507 | if(not) { // add not operator to tree | |
1508 | t3 = lttv_filter_tree_new(); | |
1509 | t3->node = LTTV_LOGICAL_NOT; | |
1510 | t2->left = LTTV_TREE_NODE; | |
1511 | t2->l_child.t = t3; | |
1512 | t2 = t3; | |
1513 | not = 0; | |
1514 | } | |
1515 | if(subtree != NULL) { /* append subtree to current tree */ | |
1601b365 | 1516 | t2->left = LTTV_TREE_NODE; |
1517 | t2->l_child.t = subtree; | |
1518 | subtree = NULL; | |
72911c5d | 1519 | } else { /* append a simple expression */ |
9ab5ebd7 | 1520 | lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE)); |
1601b365 | 1521 | a_field_component = g_string_new(""); |
571ef1ed | 1522 | g_string_free(a_string_spaces, TRUE); |
1523 | a_string_spaces = g_string_new(""); | |
1601b365 | 1524 | t2->left = LTTV_TREE_LEAF; |
0cdc2470 | 1525 | t2->l_child.leaf = a_simple_expression; |
389ba50e | 1526 | a_simple_expression = lttv_simple_expression_new(); |
1601b365 | 1527 | } |
f4e9dd16 | 1528 | break; |
aa4600f3 | 1529 | |
a4c292d4 | 1530 | case '^': /* xor */ |
aa4600f3 | 1531 | |
e00d6a24 | 1532 | t1 = (LttvFilterTree*)g_ptr_array_index(tree_stack,tree_stack->len-1); |
9ab5ebd7 | 1533 | while(t1->right != LTTV_TREE_IDLE) { |
1534 | g_assert(t1->right == LTTV_TREE_NODE); | |
1535 | t1 = t1->r_child.t; | |
1536 | } | |
1601b365 | 1537 | t2 = lttv_filter_tree_new(); |
0cdc2470 | 1538 | t2->node = LTTV_LOGICAL_XOR; |
72911c5d | 1539 | t1->right = LTTV_TREE_NODE; |
1540 | t1->r_child.t = t2; | |
1541 | if(not) { // add not operator to tree | |
1542 | t3 = lttv_filter_tree_new(); | |
1543 | t3->node = LTTV_LOGICAL_NOT; | |
1544 | t2->left = LTTV_TREE_NODE; | |
1545 | t2->l_child.t = t3; | |
1546 | t2 = t3; | |
1547 | not = 0; | |
1548 | } | |
bb87caa7 | 1549 | if(subtree != NULL) { /* append subtree to current tree */ |
1601b365 | 1550 | t2->left = LTTV_TREE_NODE; |
1551 | t2->l_child.t = subtree; | |
1552 | subtree = NULL; | |
bb87caa7 | 1553 | } else { /* append a simple expression */ |
9ab5ebd7 | 1554 | lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE)); |
1601b365 | 1555 | a_field_component = g_string_new(""); |
571ef1ed | 1556 | g_string_free(a_string_spaces, TRUE); |
1557 | a_string_spaces = g_string_new(""); | |
1601b365 | 1558 | t2->left = LTTV_TREE_LEAF; |
0cdc2470 | 1559 | t2->l_child.leaf = a_simple_expression; |
389ba50e | 1560 | a_simple_expression = lttv_simple_expression_new(); |
1601b365 | 1561 | } |
a4c292d4 | 1562 | break; |
aa4600f3 | 1563 | |
a4c292d4 | 1564 | case '!': /* not, or not equal (math op) */ |
aa4600f3 | 1565 | |
5f185a2b | 1566 | if(filter->expression[i+1] == '=') { /* != */ |
0cdc2470 | 1567 | g_ptr_array_add( a_field_path,(gpointer) a_field_component ); |
9ab5ebd7 | 1568 | lttv_simple_expression_assign_field(a_field_path,a_simple_expression); |
0cdc2470 | 1569 | a_field_component = g_string_new(""); |
571ef1ed | 1570 | g_string_free(a_string_spaces, TRUE); |
1571 | a_string_spaces = g_string_new(""); | |
56e29124 | 1572 | lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_NE); |
aa4600f3 | 1573 | i++; |
a4c292d4 | 1574 | } else { /* ! */ |
72911c5d | 1575 | not=1; |
a4c292d4 | 1576 | } |
1577 | break; | |
aa4600f3 | 1578 | |
a4c292d4 | 1579 | case '(': /* start of parenthesis */ |
91ad3f0a | 1580 | case '[': |
1581 | case '{': | |
aa4600f3 | 1582 | |
91ad3f0a | 1583 | p_nesting++; /* incrementing parenthesis nesting value */ |
1601b365 | 1584 | t1 = lttv_filter_tree_new(); |
72911c5d | 1585 | if(not) { /* add not operator to tree */ |
1586 | t3 = lttv_filter_tree_new(); | |
1587 | t3->node = LTTV_LOGICAL_NOT; | |
1588 | t1->right = LTTV_TREE_NODE; | |
1589 | t1->r_child.t = t3; | |
1590 | not = 0; | |
1591 | } | |
1601b365 | 1592 | g_ptr_array_add( tree_stack,(gpointer) t1 ); |
a4c292d4 | 1593 | break; |
aa4600f3 | 1594 | |
a4c292d4 | 1595 | case ')': /* end of parenthesis */ |
91ad3f0a | 1596 | case ']': |
1597 | case '}': | |
aa4600f3 | 1598 | |
91ad3f0a | 1599 | p_nesting--; /* decrementing parenthesis nesting value */ |
18d1226f | 1600 | if(p_nesting<0 || tree_stack->len<2) { |
f4e9dd16 | 1601 | g_warning("Wrong filtering options, the string\n\"%s\"\n\ |
571ef1ed | 1602 | is not valid due to parenthesis incorrect use",filter->expression); |
5f185a2b | 1603 | return FALSE; |
f4e9dd16 | 1604 | } |
56e29124 | 1605 | |
1606 | /* there must at least be the root tree left in the array */ | |
18d1226f | 1607 | g_assert(tree_stack->len>0); |
72911c5d | 1608 | |
1609 | t1 = g_ptr_array_index(tree_stack,tree_stack->len-1); | |
1610 | while(t1->right != LTTV_TREE_IDLE) { | |
1611 | t1 = t1->r_child.t; | |
1612 | } | |
1613 | if(not) { // add not operator to tree | |
1614 | g_print("ici"); | |
1615 | t3 = lttv_filter_tree_new(); | |
1616 | t3->node = LTTV_LOGICAL_NOT; | |
1617 | t1->right = LTTV_TREE_NODE; | |
1618 | t1->r_child.t = t3; | |
1619 | t1 = t3; | |
1620 | not = 0; | |
1621 | } | |
bb87caa7 | 1622 | if(subtree != NULL) { /* append subtree to current tree */ |
18d1226f | 1623 | t1->right = LTTV_TREE_NODE; |
1624 | t1->r_child.t = subtree; | |
1625 | subtree = g_ptr_array_index(tree_stack,tree_stack->len-1); | |
1626 | g_ptr_array_remove_index(tree_stack,tree_stack->len-1); | |
bb87caa7 | 1627 | } else { /* assign subtree as current tree */ |
9ab5ebd7 | 1628 | lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE)); |
18d1226f | 1629 | a_field_component = g_string_new(""); |
571ef1ed | 1630 | g_string_free(a_string_spaces, TRUE); |
1631 | a_string_spaces = g_string_new(""); | |
18d1226f | 1632 | t1->right = LTTV_TREE_LEAF; |
0cdc2470 | 1633 | t1->r_child.leaf = a_simple_expression; |
389ba50e | 1634 | a_simple_expression = lttv_simple_expression_new(); |
9ab5ebd7 | 1635 | subtree = g_ptr_array_remove_index(tree_stack,tree_stack->len-1); |
18d1226f | 1636 | } |
a4c292d4 | 1637 | break; |
1638 | ||
571ef1ed | 1639 | /* |
1640 | * mathematic operators | |
a4c292d4 | 1641 | */ |
1642 | case '<': /* lower, lower or equal */ | |
aa4600f3 | 1643 | |
1644 | g_ptr_array_add( a_field_path,(gpointer) a_field_component ); | |
9ab5ebd7 | 1645 | lttv_simple_expression_assign_field(a_field_path,a_simple_expression); |
aa4600f3 | 1646 | a_field_component = g_string_new(""); |
571ef1ed | 1647 | g_string_free(a_string_spaces, TRUE); |
1648 | a_string_spaces = g_string_new(""); | |
5f185a2b | 1649 | if(filter->expression[i+1] == '=') { /* <= */ |
a4c292d4 | 1650 | i++; |
56e29124 | 1651 | lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LE); |
1652 | } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_LT); | |
aa4600f3 | 1653 | break; |
1654 | ||
1655 | case '>': /* higher, higher or equal */ | |
1656 | ||
1657 | g_ptr_array_add( a_field_path,(gpointer) a_field_component ); | |
9ab5ebd7 | 1658 | lttv_simple_expression_assign_field(a_field_path,a_simple_expression); |
f4e9dd16 | 1659 | a_field_component = g_string_new(""); |
571ef1ed | 1660 | g_string_free(a_string_spaces, TRUE); |
1661 | a_string_spaces = g_string_new(""); | |
5f185a2b | 1662 | if(filter->expression[i+1] == '=') { /* >= */ |
a4c292d4 | 1663 | i++; |
56e29124 | 1664 | lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GE); |
1665 | } else lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_GT); | |
aa4600f3 | 1666 | break; |
1667 | ||
a4c292d4 | 1668 | case '=': /* equal */ |
aa4600f3 | 1669 | |
f4e9dd16 | 1670 | g_ptr_array_add( a_field_path,(gpointer) a_field_component ); |
9ab5ebd7 | 1671 | lttv_simple_expression_assign_field(a_field_path,a_simple_expression); |
f4e9dd16 | 1672 | a_field_component = g_string_new(""); |
571ef1ed | 1673 | g_string_free(a_string_spaces, TRUE); |
1674 | a_string_spaces = g_string_new(""); | |
56e29124 | 1675 | lttv_simple_expression_assign_operator(a_simple_expression,LTTV_FIELD_EQ); |
a4c292d4 | 1676 | break; |
aa4600f3 | 1677 | |
0769c82f | 1678 | /* |
1679 | * Field concatening caracter | |
1680 | */ | |
1681 | case '.': /* dot */ | |
aa4600f3 | 1682 | |
bb87caa7 | 1683 | /* |
1684 | * divide field expression into elements | |
1685 | * in a_field_path array. | |
4d9ff942 | 1686 | * |
1687 | * A dot can also be present in double values | |
bb87caa7 | 1688 | */ |
8ff6243c | 1689 | if(a_simple_expression->field == LTTV_FILTER_UNDEFINED) { |
bb87caa7 | 1690 | g_ptr_array_add( a_field_path,(gpointer) a_field_component ); |
1691 | a_field_component = g_string_new(""); | |
571ef1ed | 1692 | g_string_free(a_string_spaces, TRUE); |
1693 | a_string_spaces = g_string_new(""); | |
2db17921 | 1694 | } else { |
1695 | /* Operator found, we are in the value field */ | |
1696 | g_string_append_c(a_field_component, filter->expression[i]); | |
8ff6243c | 1697 | } |
1698 | break; | |
ef2b07c1 | 1699 | case ' ': /* keep spaces that are within a field component */ |
2db17921 | 1700 | if(a_field_component->len == 0) break; /* ignore */ |
571ef1ed | 1701 | else |
1702 | a_string_spaces = g_string_append_c(a_string_spaces, | |
1703 | filter->expression[i]); | |
ef2b07c1 | 1704 | |
4d9ff942 | 1705 | case '\n': /* ignore */ |
0769c82f | 1706 | break; |
d564d2ad | 1707 | case '\"': |
1708 | nest_quotes?(nest_quotes=0):(nest_quotes=1); | |
1709 | break; | |
a4c292d4 | 1710 | default: /* concatening current string */ |
d564d2ad | 1711 | if(a_string_spaces->len != 0) { |
2db17921 | 1712 | a_field_component = g_string_append( |
4ec0c904 | 1713 | a_field_component, a_string_spaces->str); |
2db17921 | 1714 | a_string_spaces = g_string_set_size(a_string_spaces, 0); |
d564d2ad | 1715 | } |
1716 | a_field_component = g_string_append_c(a_field_component, | |
1717 | filter->expression[i]); | |
a4c292d4 | 1718 | } |
1719 | } | |
1601b365 | 1720 | |
0cdc2470 | 1721 | /* |
1722 | * Preliminary check to see | |
1723 | * if tree was constructed correctly | |
1724 | */ | |
1725 | if( p_nesting>0 ) { | |
1726 | g_warning("Wrong filtering options, the string\n\"%s\"\n\ | |
571ef1ed | 1727 | is not valid due to parenthesis incorrect use",filter->expression); |
5f185a2b | 1728 | return FALSE; |
0cdc2470 | 1729 | } |
1730 | ||
1731 | if(tree_stack->len != 1) /* only root tree should remain */ | |
5f185a2b | 1732 | return FALSE; |
1601b365 | 1733 | |
72911c5d | 1734 | /* |
1735 | * processing last element of expression | |
1736 | */ | |
410c83da | 1737 | t1 = g_ptr_array_index(tree_stack,tree_stack->len-1); |
9ab5ebd7 | 1738 | while(t1->right != LTTV_TREE_IDLE) { |
1739 | g_assert(t1->right == LTTV_TREE_NODE); | |
1740 | t1 = t1->r_child.t; | |
1741 | } | |
72911c5d | 1742 | if(not) { // add not operator to tree |
1743 | t3 = lttv_filter_tree_new(); | |
1744 | t3->node = LTTV_LOGICAL_NOT; | |
1745 | t1->right = LTTV_TREE_NODE; | |
1746 | t1->r_child.t = t3; | |
1747 | t1 = t3; | |
1748 | not = 0; | |
1749 | } | |
410c83da | 1750 | if(subtree != NULL) { /* add the subtree */ |
1751 | t1->right = LTTV_TREE_NODE; | |
0cdc2470 | 1752 | t1->r_child.t = subtree; |
410c83da | 1753 | subtree = NULL; |
1754 | } else { /* add a leaf */ | |
9ab5ebd7 | 1755 | lttv_simple_expression_assign_value(a_simple_expression,g_string_free(a_field_component,FALSE)); |
56e29124 | 1756 | a_field_component = NULL; |
571ef1ed | 1757 | g_string_free(a_string_spaces, TRUE); |
1758 | a_string_spaces = NULL; | |
410c83da | 1759 | t1->right = LTTV_TREE_LEAF; |
0cdc2470 | 1760 | t1->r_child.leaf = a_simple_expression; |
56e29124 | 1761 | a_simple_expression = NULL; |
410c83da | 1762 | } |
1763 | ||
56e29124 | 1764 | |
73050a5f | 1765 | /* free the pointer array */ |
1766 | g_assert(a_field_path->len == 0); | |
1767 | g_ptr_array_free(a_field_path,TRUE); | |
56e29124 | 1768 | |
1769 | /* free the tree stack -- but keep the root tree */ | |
9354c7da | 1770 | filter->head = ltt_g_ptr_array_remove_index_slow(tree_stack,0); |
f3020899 | 1771 | g_ptr_array_free(tree_stack,TRUE); |
1772 | ||
56e29124 | 1773 | /* free the field buffer if allocated */ |
1774 | if(a_field_component != NULL) g_string_free(a_field_component,TRUE); | |
571ef1ed | 1775 | if(a_string_spaces != NULL) g_string_free(a_string_spaces, TRUE); |
ef2b07c1 | 1776 | |
56e29124 | 1777 | /* free the simple expression buffer if allocated */ |
1778 | if(a_simple_expression != NULL) lttv_simple_expression_destroy(a_simple_expression); | |
73050a5f | 1779 | |
f3020899 | 1780 | g_assert(filter->head != NULL); /* tree should exist */ |
56e29124 | 1781 | g_assert(subtree == NULL); /* remaining subtree should be included in main tree */ |
be66ef34 | 1782 | |
1783 | #ifdef TEST | |
1784 | gettimeofday(&endtime, NULL); | |
1785 | ||
1786 | /* Calcul du temps de l'algorithme */ | |
1787 | double time1 = starttime.tv_sec + (starttime.tv_usec/1000000.0); | |
1788 | double time2 = endtime.tv_sec + (endtime.tv_usec/1000000.0); | |
1789 | // g_print("Tree build took %.10f ms for strlen of %i\n",(time2-time1)*1000,strlen(filter->expression)); | |
1790 | g_print("%.10f %i\n",(time2-time1)*1000,strlen(filter->expression)); | |
1791 | #endif | |
a4c292d4 | 1792 | |
56e29124 | 1793 | /* debug */ |
c2a4581e | 1794 | g_debug("+++++++++++++++ BEGIN PRINT ++++++++++++++++\n"); |
72911c5d | 1795 | lttv_print_tree(filter->head,0) ; |
c2a4581e | 1796 | g_debug("+++++++++++++++ END PRINT ++++++++++++++++++\n"); |
56e29124 | 1797 | |
1798 | /* success */ | |
5f185a2b | 1799 | return TRUE; |
80f9611a | 1800 | |
31452f49 | 1801 | } |
1802 | ||
8c89f5a8 | 1803 | /** |
56e29124 | 1804 | * @fn void lttv_filter_destroy(LttvFilter*) |
1805 | * | |
8c89f5a8 | 1806 | * Destroy the current LttvFilter |
1807 | * @param filter pointer to the current LttvFilter | |
1808 | */ | |
1da1525d | 1809 | void |
2ea36caf | 1810 | lttv_filter_destroy(LttvFilter* filter) { |
5f185a2b | 1811 | |
571ef1ed | 1812 | if(!filter) return; |
ebcead4a | 1813 | |
571ef1ed | 1814 | if(filter->expression) |
1815 | g_free(filter->expression); | |
1816 | if(filter->head) | |
1817 | lttv_filter_tree_destroy(filter->head); | |
5f185a2b | 1818 | g_free(filter); |
1819 | ||
1da1525d | 1820 | } |
1821 | ||
150f0d33 | 1822 | /** |
8ff6243c | 1823 | * @fn LttvFilterTree* lttv_filter_tree_new() |
56e29124 | 1824 | * |
150f0d33 | 1825 | * Assign a new tree for the current expression |
1826 | * or sub expression | |
1827 | * @return pointer of LttvFilterTree | |
1828 | */ | |
5f185a2b | 1829 | LttvFilterTree* |
1830 | lttv_filter_tree_new() { | |
150f0d33 | 1831 | LttvFilterTree* tree; |
1832 | ||
e00d6a24 | 1833 | tree = g_new(LttvFilterTree,1); |
150f0d33 | 1834 | tree->node = 0; //g_new(lttv_expression,1); |
150f0d33 | 1835 | tree->left = LTTV_TREE_IDLE; |
1836 | tree->right = LTTV_TREE_IDLE; | |
f3020899 | 1837 | tree->r_child.t = NULL; |
1838 | tree->l_child.t = NULL; | |
1839 | ||
150f0d33 | 1840 | return tree; |
1841 | } | |
1842 | ||
80f9611a | 1843 | /** |
56e29124 | 1844 | * @fn void lttv_filter_append_expression(LttvFilter*,char*) |
1845 | * | |
80f9611a | 1846 | * Append a new expression to the expression |
1847 | * defined in the current filter | |
1848 | * @param filter pointer to the current LttvFilter | |
1849 | * @param expression string that must be appended | |
56e29124 | 1850 | * @return Success/Failure of operation |
80f9611a | 1851 | */ |
be66ef34 | 1852 | gboolean |
1853 | lttv_filter_append_expression(LttvFilter* filter, const char *expression) { | |
80f9611a | 1854 | |
56e29124 | 1855 | if(expression == NULL) return FALSE; |
da2e1bfb | 1856 | if(filter == NULL) return FALSE; |
0bc23ba9 | 1857 | if(expression[0] == '\0') return FALSE; /* Empty expression */ |
80f9611a | 1858 | |
da2e1bfb | 1859 | GString* s = g_string_new(""); |
1860 | if(filter->expression != NULL) { | |
4ec0c904 | 1861 | s = g_string_append(s,filter->expression); |
1862 | s = g_string_append_c(s,'&'); | |
da2e1bfb | 1863 | } |
4ec0c904 | 1864 | s = g_string_append(s,expression); |
786c5c3b | 1865 | |
1866 | g_free(filter->expression); | |
da2e1bfb | 1867 | filter->expression = g_string_free(s,FALSE); |
1868 | ||
1869 | /* TRUE if construction of tree proceeded without errors */ | |
56e29124 | 1870 | return lttv_filter_update(filter); |
80f9611a | 1871 | |
1872 | } | |
1873 | ||
1874 | /** | |
56e29124 | 1875 | * @fn void lttv_filter_clear_expression(LttvFilter*) |
1876 | * | |
80f9611a | 1877 | * Clear the filter expression from the |
1878 | * current filter and sets its pointer to NULL | |
1879 | * @param filter pointer to the current LttvFilter | |
1880 | */ | |
be66ef34 | 1881 | void |
1882 | lttv_filter_clear_expression(LttvFilter* filter) { | |
80f9611a | 1883 | |
1884 | if(filter->expression != NULL) { | |
1885 | g_free(filter->expression); | |
1886 | filter->expression = NULL; | |
1887 | } | |
1888 | ||
1889 | } | |
1890 | ||
150f0d33 | 1891 | /** |
56e29124 | 1892 | * @fn void lttv_filter_tree_destroy(LttvFilterTree*) |
1893 | * | |
150f0d33 | 1894 | * Destroys the tree and his sub-trees |
1895 | * @param tree Tree which must be destroyed | |
1896 | */ | |
5f185a2b | 1897 | void |
1898 | lttv_filter_tree_destroy(LttvFilterTree* tree) { | |
56e29124 | 1899 | |
150f0d33 | 1900 | if(tree == NULL) return; |
1901 | ||
56e29124 | 1902 | if(tree->left == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->l_child.leaf); |
150f0d33 | 1903 | else if(tree->left == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->l_child.t); |
1904 | ||
56e29124 | 1905 | if(tree->right == LTTV_TREE_LEAF) lttv_simple_expression_destroy(tree->r_child.leaf); |
150f0d33 | 1906 | else if(tree->right == LTTV_TREE_NODE) lttv_filter_tree_destroy(tree->r_child.t); |
1907 | ||
e00d6a24 | 1908 | // g_free(tree->node); |
150f0d33 | 1909 | g_free(tree); |
1910 | } | |
1911 | ||
84a333d6 | 1912 | /** |
80f9611a | 1913 | * Global parsing function for the current |
1914 | * LttvFilterTree | |
7e7af7f2 | 1915 | * @param t pointer to the current LttvFilterTree |
80f9611a | 1916 | * @param event current LttEvent, NULL if not used |
1917 | * @param tracefile current LttTracefile, NULL if not used | |
1918 | * @param trace current LttTrace, NULL if not used | |
1919 | * @param state current LttvProcessState, NULL if not used | |
4d9ff942 | 1920 | * @param context current LttvTracefileContext, NULL if not used |
1921 | * @return response of filter | |
84a333d6 | 1922 | */ |
31452f49 | 1923 | gboolean |
80f9611a | 1924 | lttv_filter_tree_parse( |
4d9ff942 | 1925 | const LttvFilterTree* t, |
1926 | const LttEvent* event, | |
1927 | const LttTracefile* tracefile, | |
1928 | const LttTrace* trace, | |
b6ef18af | 1929 | const LttvTracefileContext* context, |
1930 | const LttvProcessState* state, | |
1931 | const LttvTraceContext* tc | |
80f9611a | 1932 | /*,...*/) |
1933 | { | |
0769c82f | 1934 | |
80f9611a | 1935 | /* |
1601b365 | 1936 | * Each tree is parsed in inorder. |
1937 | * This way, it's possible to apply the left filter of the | |
1938 | * tree, then decide whether or not the right branch should | |
1939 | * be parsed depending on the linking logical operator | |
1940 | * | |
80f9611a | 1941 | * Each node consists in a |
1942 | * 1. logical operator | |
1943 | * 2. left child ( node or simple expression ) | |
1944 | * 3. right child ( node or simple expression ) | |
1945 | * | |
1946 | * When the child is a simple expression, we must | |
1947 | * before all determine if the expression refers to | |
1948 | * a structure which is whithin observation ( not NULL ). | |
1949 | * -If so, the expression is evaluated. | |
1950 | * -If not, the result is set to TRUE since this particular | |
1951 | * operation does not interfere with the lttv structure | |
1952 | * | |
1953 | * The result of each simple expression will directly | |
1954 | * affect the next branch. This way, depending on | |
1955 | * the linking logical operator, the parser will decide | |
1956 | * to explore or not the next branch. | |
1957 | * 1. AND OPERATOR | |
1958 | * -If result of left branch is 0 / FALSE | |
1959 | * then don't explore right branch and return 0; | |
1960 | * -If result of left branch is 1 / TRUE then explore | |
1961 | * 2. OR OPERATOR | |
1962 | * -If result of left branch is 1 / TRUE | |
1963 | * then don't explore right branch and return 1; | |
1964 | * -If result of left branch is 0 / FALSE then explore | |
1965 | * 3. XOR OPERATOR | |
56e29124 | 1966 | * -Result of left branch will not affect exploration of |
80f9611a | 1967 | * right branch |
1601b365 | 1968 | */ |
73050a5f | 1969 | |
80f9611a | 1970 | gboolean lresult = FALSE, rresult = FALSE; |
33e44b82 | 1971 | |
43ed82b5 | 1972 | LttvTraceState *ts = NULL; |
ae3d0f50 | 1973 | LttvTracefileState *tfs = (LttvTracefileState*)context; |
b6ef18af | 1974 | if(tc) |
1975 | ts = (LttvTraceState*)tc; | |
1976 | else if(context) | |
1977 | ts = (LttvTraceState*)context->t_context; | |
1978 | ||
1979 | if(tfs) { | |
1980 | guint cpu = tfs->cpu; | |
1981 | if(ts) | |
1982 | state = ts->running_process[cpu]; | |
1983 | } | |
0769c82f | 1984 | |
80f9611a | 1985 | /* |
1986 | * Parse left branch | |
1987 | */ | |
4d9ff942 | 1988 | if(t->left == LTTV_TREE_NODE) { |
b6ef18af | 1989 | lresult = lttv_filter_tree_parse(t->l_child.t,event,tracefile,trace,context,NULL,NULL); |
4d9ff942 | 1990 | } |
5b729fcf | 1991 | else if(t->left == LTTV_TREE_LEAF) { |
4d9ff942 | 1992 | lresult = lttv_filter_tree_parse_branch(t->l_child.leaf,event,tracefile,trace,state,context); |
0cdc2470 | 1993 | } |
4d9ff942 | 1994 | |
80f9611a | 1995 | /* |
1996 | * Parse linking operator | |
1997 | * make a cutoff if possible | |
1998 | */ | |
1999 | if((t->node & LTTV_LOGICAL_OR) && lresult == TRUE) return TRUE; | |
2000 | if((t->node & LTTV_LOGICAL_AND) && lresult == FALSE) return FALSE; | |
2001 | ||
2002 | /* | |
2003 | * Parse right branch | |
2004 | */ | |
4d9ff942 | 2005 | if(t->right == LTTV_TREE_NODE) { |
b6ef18af | 2006 | rresult = lttv_filter_tree_parse(t->r_child.t,event,tracefile,trace,context,NULL,NULL); |
4d9ff942 | 2007 | } |
5b729fcf | 2008 | else if(t->right == LTTV_TREE_LEAF) { |
4d9ff942 | 2009 | rresult = lttv_filter_tree_parse_branch(t->r_child.leaf,event,tracefile,trace,state,context); |
2010 | } | |
2bdb97c5 | 2011 | |
2bdb97c5 | 2012 | |
4d9ff942 | 2013 | /* |
2014 | * Apply and return the | |
2015 | * logical link between the | |
2016 | * two operation | |
2017 | */ | |
2018 | switch(t->node) { | |
2019 | case LTTV_LOGICAL_OR: return (lresult | rresult); | |
2020 | case LTTV_LOGICAL_AND: return (lresult & rresult); | |
72911c5d | 2021 | case LTTV_LOGICAL_NOT: |
2022 | return (t->left==LTTV_TREE_LEAF)?!lresult:((t->right==LTTV_TREE_LEAF)?!rresult:TRUE); | |
4d9ff942 | 2023 | case LTTV_LOGICAL_XOR: return (lresult ^ rresult); |
2024 | case 0: return (rresult); | |
2025 | default: | |
2026 | /* | |
2027 | * This case should never be | |
2028 | * parsed, if so, this subtree | |
2029 | * is cancelled ! | |
2030 | */ | |
2031 | return TRUE; | |
2032 | } | |
2033 | ||
2034 | } | |
2035 | ||
2036 | /** | |
4d9ff942 | 2037 | * This function parses a particular branch of the tree |
7e7af7f2 | 2038 | * @param se pointer to the current LttvSimpleExpression |
4d9ff942 | 2039 | * @param event current LttEvent, NULL if not used |
2040 | * @param tracefile current LttTracefile, NULL if not used | |
2041 | * @param trace current LttTrace, NULL if not used | |
2042 | * @param state current LttvProcessState, NULL if not used | |
2043 | * @param context current LttvTracefileContext, NULL if not used | |
2044 | * @return response of filter | |
2045 | */ | |
be66ef34 | 2046 | gboolean |
2047 | lttv_filter_tree_parse_branch( | |
4d9ff942 | 2048 | const LttvSimpleExpression* se, |
2049 | const LttEvent* event, | |
2050 | const LttTracefile* tracefile, | |
2051 | const LttTrace* trace, | |
2052 | const LttvProcessState* state, | |
2053 | const LttvTracefileContext* context) { | |
2054 | ||
9ab5ebd7 | 2055 | LttvFieldValue v; |
4d9ff942 | 2056 | v = se->value; |
2057 | switch(se->field) { | |
80f9611a | 2058 | case LTTV_FILTER_TRACE_NAME: |
4d9ff942 | 2059 | if(trace == NULL) return TRUE; |
c6832b57 | 2060 | else { |
eed2ef37 | 2061 | GQuark quark = ltt_trace_name(trace); |
c6832b57 | 2062 | return se->op((gpointer)&quark,v); |
2063 | } | |
80f9611a | 2064 | break; |
2065 | case LTTV_FILTER_TRACEFILE_NAME: | |
4d9ff942 | 2066 | if(tracefile == NULL) return TRUE; |
c6832b57 | 2067 | else { |
eed2ef37 | 2068 | GQuark quark = ltt_tracefile_name(tracefile); |
c6832b57 | 2069 | return se->op((gpointer)&quark,v); |
2070 | } | |
80f9611a | 2071 | break; |
2072 | case LTTV_FILTER_STATE_PID: | |
4d9ff942 | 2073 | if(state == NULL) return TRUE; |
2074 | else return se->op((gpointer)&state->pid,v); | |
80f9611a | 2075 | break; |
2076 | case LTTV_FILTER_STATE_PPID: | |
4d9ff942 | 2077 | if(state == NULL) return TRUE; |
2078 | else return se->op((gpointer)&state->ppid,v); | |
80f9611a | 2079 | break; |
2080 | case LTTV_FILTER_STATE_CT: | |
4d9ff942 | 2081 | if(state == NULL) return TRUE; |
80f9611a | 2082 | else { |
4d9ff942 | 2083 | return se->op((gpointer)&state->creation_time,v); |
80f9611a | 2084 | } |
2085 | break; | |
2086 | case LTTV_FILTER_STATE_IT: | |
4d9ff942 | 2087 | if(state == NULL) return TRUE; |
80f9611a | 2088 | else { |
4d9ff942 | 2089 | return se->op((gpointer)&state->insertion_time,v); |
80f9611a | 2090 | } |
2091 | break; | |
2092 | case LTTV_FILTER_STATE_P_NAME: | |
4d9ff942 | 2093 | if(state == NULL) return TRUE; |
46c40a93 | 2094 | else { |
bbd9d557 | 2095 | GQuark quark = state->name; |
c6832b57 | 2096 | return se->op((gpointer)&quark,v); |
46c40a93 | 2097 | } |
80f9611a | 2098 | break; |
d4dd4885 | 2099 | case LTTV_FILTER_STATE_T_BRAND: |
7b5f6cf1 | 2100 | if(state == NULL) return TRUE; |
2101 | else { | |
2102 | GQuark quark = state->brand; | |
2103 | return se->op((gpointer)&quark,v); | |
2104 | } | |
2105 | break; | |
80f9611a | 2106 | case LTTV_FILTER_STATE_EX_MODE: |
4d9ff942 | 2107 | if(state == NULL) return TRUE; |
2108 | else return se->op((gpointer)&state->state->t,v); | |
80f9611a | 2109 | break; |
2110 | case LTTV_FILTER_STATE_EX_SUBMODE: | |
4d9ff942 | 2111 | if(state == NULL) return TRUE; |
2112 | else return se->op((gpointer)&state->state->n,v); | |
80f9611a | 2113 | break; |
2114 | case LTTV_FILTER_STATE_P_STATUS: | |
4d9ff942 | 2115 | if(state == NULL) return TRUE; |
2116 | else return se->op((gpointer)&state->state->s,v); | |
80f9611a | 2117 | break; |
2118 | case LTTV_FILTER_STATE_CPU: | |
e3162168 | 2119 | if(state == NULL) return TRUE; |
46c40a93 | 2120 | else { |
e3162168 | 2121 | return se->op((gpointer)&state->cpu,v); |
46c40a93 | 2122 | } |
80f9611a | 2123 | break; |
2124 | case LTTV_FILTER_EVENT_NAME: | |
6471e71f | 2125 | if(event == NULL) return TRUE; |
2126 | else { | |
2127 | struct marker_info *info; | |
2128 | GQuark qtuple[2]; | |
2129 | LttTracefile *tf = context->tf; | |
2130 | qtuple[0] = ltt_tracefile_name(tracefile); | |
2131 | info = marker_get_info_from_id(tf->mdata, event->event_id); | |
2132 | g_assert(info != NULL); | |
2133 | qtuple[1] = info->name; | |
2134 | return se->op((gpointer)qtuple,v); | |
2135 | } | |
2136 | break; | |
2137 | case LTTV_FILTER_EVENT_SUBNAME: | |
4d9ff942 | 2138 | if(event == NULL) return TRUE; |
2139 | else { | |
0ad10e7f | 2140 | struct marker_info *info; |
750eb11a | 2141 | LttTracefile *tf = context->tf; |
2142 | info = marker_get_info_from_id(tf->mdata, event->event_id); | |
0ad10e7f | 2143 | g_assert(info != NULL); |
2144 | GQuark quark = info->name; | |
ffd088ef | 2145 | return se->op((gpointer)&quark,v); |
2146 | } | |
2147 | break; | |
80f9611a | 2148 | case LTTV_FILTER_EVENT_CATEGORY: |
2149 | /* | |
c6832b57 | 2150 | * TODO: Not yet implemented |
80f9611a | 2151 | */ |
4d9ff942 | 2152 | return TRUE; |
80f9611a | 2153 | break; |
2154 | case LTTV_FILTER_EVENT_TIME: | |
4d9ff942 | 2155 | if(event == NULL) return TRUE; |
46c40a93 | 2156 | else { |
2157 | LttTime time = ltt_event_time(event); | |
4d9ff942 | 2158 | return se->op((gpointer)&time,v); |
46c40a93 | 2159 | } |
80f9611a | 2160 | break; |
2161 | case LTTV_FILTER_EVENT_TSC: | |
bbd9d557 | 2162 | if(event == NULL) return TRUE; |
2163 | else { | |
2164 | LttCycleCount count = ltt_event_cycle_count(event); | |
2165 | return se->op((gpointer)&count,v); | |
2166 | } | |
80f9611a | 2167 | break; |
33bdc8dd | 2168 | case LTTV_FILTER_EVENT_TARGET_PID: |
2169 | if(context == NULL) return TRUE; | |
2170 | else { | |
2171 | guint target_pid = | |
2172 | lttv_state_get_target_pid((LttvTracefileState*)context); | |
2173 | return se->op((gpointer)&target_pid,v); | |
2174 | } | |
2175 | break; | |
80f9611a | 2176 | case LTTV_FILTER_EVENT_FIELD: |
2177 | /* | |
2178 | * TODO: Use the offset to | |
2179 | * find the dynamic field | |
2180 | * in the event struct | |
2181 | */ | |
4d9ff942 | 2182 | return TRUE; |
80f9611a | 2183 | default: |
2184 | /* | |
2185 | * This case should never be | |
4d9ff942 | 2186 | * parsed, if so, the whole |
2187 | * filtering is cancelled | |
80f9611a | 2188 | */ |
2189 | g_warning("Error while parsing the filter tree"); | |
2190 | return TRUE; | |
2191 | } | |
4d9ff942 | 2192 | |
2193 | /* should never get here */ | |
2194 | return TRUE; | |
2195 | ||
80f9611a | 2196 | } |
0769c82f | 2197 | |
4d9ff942 | 2198 | |
2199 | ||
80f9611a | 2200 | /** |
7e7af7f2 | 2201 | * Debug function. Prints tree memory allocation. |
56e29124 | 2202 | * @param t the pointer to the current LttvFilterTree |
80f9611a | 2203 | */ |
2204 | void | |
72911c5d | 2205 | lttv_print_tree(const LttvFilterTree* t, const int count) { |
0769c82f | 2206 | |
c2a4581e | 2207 | g_debug("node:%p lchild:%p rchild:%p depth:%i\n",t, //t->l_child.t,t->r_child.t); |
80f9611a | 2208 | (t->left==LTTV_TREE_NODE)?t->l_child.t:NULL, |
72911c5d | 2209 | (t->right==LTTV_TREE_NODE)?t->r_child.t:NULL, |
2210 | count); | |
c2a4581e | 2211 | g_debug("logic operator: %s\n",(t->node&1)?"OR":((t->node&2)?"AND":((t->node&4)?"NOT":((t->node&8)?"XOR":"IDLE")))); |
2212 | g_debug("|-> left branch %p is a %s\n",t->l_child.t,(t->left==LTTV_TREE_NODE)?"NODE":((t->left==LTTV_TREE_LEAF)?"LEAF":"IDLE")); | |
72911c5d | 2213 | if(t->left == LTTV_TREE_LEAF) { |
c2a4581e | 2214 | g_debug("| |-> field type number: %i\n",t->l_child.leaf->field); |
2215 | g_debug("| |-> offset is: %i\n",t->l_child.leaf->offset); | |
2216 | g_debug("| |-> operator function is: %p\n",t->l_child.leaf->op); | |
0769c82f | 2217 | } |
c2a4581e | 2218 | g_debug("|-> right branch %p is a %s\n",t->r_child.t,(t->right==LTTV_TREE_NODE)?"NODE":((t->right==LTTV_TREE_LEAF)?"LEAF":"IDLE")); |
72911c5d | 2219 | if(t->right == LTTV_TREE_LEAF) { |
c2a4581e | 2220 | g_debug("| |-> field type number: %i\n",t->r_child.leaf->field); |
2221 | g_debug("| |-> offset is: %i\n",t->r_child.leaf->offset); | |
2222 | g_debug("| |-> operator function is: %p\n",t->r_child.leaf->op); | |
80f9611a | 2223 | } |
72911c5d | 2224 | |
2225 | if(t->left == LTTV_TREE_NODE) lttv_print_tree(t->l_child.t,count+1); | |
2226 | if(t->right == LTTV_TREE_NODE) lttv_print_tree(t->r_child.t,count+1); | |
80f9611a | 2227 | } |
2228 | ||
91ad3f0a | 2229 | /** |
56e29124 | 2230 | * @fn static void module_init() |
2231 | * | |
91ad3f0a | 2232 | * Initializes the filter module and specific values |
2233 | */ | |
1a7fa682 | 2234 | static void module_init() |
2235 | { | |
91ad3f0a | 2236 | |
1a7fa682 | 2237 | } |
2238 | ||
91ad3f0a | 2239 | /** |
7e7af7f2 | 2240 | * Destroys the filter module and specific values |
91ad3f0a | 2241 | */ |
1a7fa682 | 2242 | static void module_destroy() |
2243 | { | |
56e29124 | 2244 | |
1a7fa682 | 2245 | } |
2246 | ||
2247 | ||
91ad3f0a | 2248 | LTTV_MODULE("filter", "Filters traceset and events", \ |
2249 | "Filters traceset and events specifically to user input", \ | |
1a7fa682 | 2250 | module_init, module_destroy) |
2251 | ||
2252 | ||
2253 |