diff --git a/lib/stack.c b/lib/stack.c index 8dfe0db..3ebe921 100644 --- a/lib/stack.c +++ b/lib/stack.c @@ -24,7 +24,7 @@ void free_stack(stack_t* stack) xfree(stack); } -void push(stack_t* stack, void* elt) +void stack_push(stack_t* stack, void* elt) { if (stack->cur_size == stack->max_size) { stack->max_size *= 2; @@ -33,8 +33,17 @@ void push(stack_t* stack, void* elt) stack->arr[stack->cur_size++] = elt; } -void* pop(stack_t* stack) +void stack_pop(stack_t* stack) { - void* res = stack->arr[--stack->cur_size]; - return res; + --stack->cur_size; +} + +void* stack_peek(stack_t* stack) +{ + return stack->arr[stack->cur_size - 1]; +} + +int stack_is_empty(stack_t* stack) +{ + return (stack->cur_size == 0); } diff --git a/lib/stack.h b/lib/stack.h index 9417238..c3dec83 100644 --- a/lib/stack.h +++ b/lib/stack.h @@ -9,7 +9,10 @@ typedef struct stack stack_t; stack_t* alloc_stack(size_t size); void free_stack(stack_t* stack); -void push(stack_t* stack, void* elt); -void* pop(stack_t* stack); +void stack_push(stack_t* stack, void* elt); +void stack_pop(stack_t* stack); +void* stack_peek(stack_t* stack); + +int stack_is_empty(stack_t* stack); #endif /* ZMAP_STACK_H */ \ No newline at end of file diff --git a/src/expression.c b/src/expression.c index 354b805..352c925 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1,6 +1,8 @@ #include "expression.h" -#include "fieldset.H" +#include "fieldset.h" + +#include "../lib/stack.h" #include "../lib/xalloc.h" /* Static helper functions */ @@ -83,6 +85,7 @@ node_t* make_field_node(char *fieldname) node_t *node = alloc_node(); node->type = FIELD; node->value.field.fieldname = fieldname; + node->result = 1; return node; } @@ -91,6 +94,7 @@ node_t* make_string_node(char *literal) node_t *node = alloc_node(); node->type = STRING; node->value.string_literal = literal; + node->result = 1; return node; } @@ -99,6 +103,7 @@ node_t* make_int_node(int literal) node_t *node = alloc_node(); node->type = INT; node->value.int_literal = literal; + node->result = 1; return node; } @@ -135,6 +140,88 @@ int evaluate_expression(node_t *root, fieldset_t *fields) { return 0; } +int evaluate_expression_fast(node_t *root, fieldset_t *fields) { + stack_t* s; + node_t* node; + if (!root) return 1; + s = alloc_stack(16); /* XXX Find a way to guess/know this better */ + root->evaluated = 0; + stack_push(s, root); + int result = 1; + while (!stack_is_empty(s) && result) { + node = (node_t *) stack_peek(s); + if (node->type != OP) { + continue; + } + if (node->value.op == AND) { + if (!node->right_child->evaluated) { + stack_push(s, node->right_child); + } + if (!node->left_child->evaluated) { + stack_push(s, node->left_child); + continue; + } + + stack_pop(s); + if (!(node->left_child->result && node->right_child->result)) { + node->evaluated = 1; + result = 0; + } + node->left_child->evaluated = 0; + node->right_child->evaluated = 0; + } else if (node->value.op == OR) { + if (!node->right_child->evaluated) { + stack_push(s, node->right_child); + } + if (!node->left_child->evaluated) { + stack_push(s, node->left_child); + continue; + } + + stack_pop(s); + if (!(node->left_child->result || node->right_child->result)) { + node->evaluated = 1; + result = 0; + } + node->left_child->evaluated = 0; + node->right_child->evaluated = 0; + + } else { + stack_pop(s); + switch (node->value.op) { + case GT: + node->result = eval_gt_node(node, fields); + break; + case LT: + node->result = eval_lt_node(node, fields); + break; + case EQ: + node->result = eval_eq_node(node, fields); + break; + case NEQ: + node->result = !(eval_eq_node(node, fields)); + break; + case LT_EQ: + node->result = eval_lt_eq_node(node, fields); + break; + case GT_EQ: + node->result = eval_gt_eq_node(node, fields); + break; + default: + exit(-1); + break; + } + node->evaluated = 1; + if (stack_is_empty(s)) { + result = node->result; + node->evaluated = 0; + } + } + } + free_stack(s); + return result; +} + void print_expression(node_t *root) { if (!root) return; printf("%s", "( "); diff --git a/src/expression.h b/src/expression.h index d65668d..e44ee2f 100644 --- a/src/expression.h +++ b/src/expression.h @@ -23,8 +23,8 @@ struct field_id { union node_value { struct field_id field; - char *string_literal; uint64_t int_literal; + char *string_literal; enum operation op; }; @@ -33,6 +33,8 @@ typedef struct node { struct node *right_child; enum node_type type; union node_value value; + int evaluated; + int result; } node_t; node_t* make_op_node(enum operation op); @@ -45,6 +47,8 @@ node_t* make_int_node(int literal); int evaluate_expression(node_t *root, fieldset_t *fields); +int evaluate_expression_fast(node_t *root, fieldset_t *fields); + void print_expression(node_t *root); #endif /* ZMAP_TREE_H */ \ No newline at end of file