2013-09-19 21:51:49 +00:00
|
|
|
#include "expression.h"
|
2013-10-12 16:05:30 +00:00
|
|
|
#include "fieldset.h"
|
2013-09-19 21:51:49 +00:00
|
|
|
|
|
|
|
#include "../lib/xalloc.h"
|
2013-09-13 19:32:17 +00:00
|
|
|
|
2013-09-19 22:19:12 +00:00
|
|
|
/* Static helper functions */
|
|
|
|
|
|
|
|
static node_t* alloc_node();
|
2013-09-20 18:35:07 +00:00
|
|
|
static int eval_gt_node(node_t *node, fieldset_t *fields);
|
|
|
|
static int eval_lt_node(node_t *node, fieldset_t *fields);
|
|
|
|
static int eval_eq_node(node_t *node, fieldset_t *fields);
|
|
|
|
static int eval_lt_eq_node(node_t *node, fieldset_t *fields);
|
|
|
|
static int eval_gt_eq_node(node_t *node, fieldset_t *fields);
|
|
|
|
|
2013-09-19 22:19:12 +00:00
|
|
|
|
|
|
|
static node_t* alloc_node()
|
2013-09-13 19:32:17 +00:00
|
|
|
{
|
2013-09-19 21:51:49 +00:00
|
|
|
node_t *node = xmalloc(sizeof(node_t));
|
2013-09-13 19:32:17 +00:00
|
|
|
memset(node, 0, sizeof(node_t));
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2013-09-20 18:35:07 +00:00
|
|
|
static int eval_gt_node(node_t *node, fieldset_t *fields)
|
|
|
|
{
|
|
|
|
int index = node->left_child->value.field.index;
|
|
|
|
uint64_t expected = node->right_child->value.int_literal;
|
|
|
|
uint64_t actual = fs_get_uint64_by_index(fields, index);
|
|
|
|
return (actual > expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eval_lt_node(node_t *node, fieldset_t *fields)
|
|
|
|
{
|
|
|
|
int index = node->left_child->value.field.index;
|
|
|
|
uint64_t expected = node->right_child->value.int_literal;
|
|
|
|
uint64_t actual = fs_get_uint64_by_index(fields, index);
|
|
|
|
return (actual < expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eval_eq_node(node_t *node, fieldset_t *fields)
|
|
|
|
{
|
|
|
|
node_t *literal = node->right_child;
|
|
|
|
int index = node->left_child->value.field.index;
|
|
|
|
char *expected, *actual;
|
|
|
|
switch (literal->type) {
|
|
|
|
case STRING:
|
|
|
|
expected = literal->value.string_literal;
|
|
|
|
actual = fs_get_string_by_index(fields, index);
|
|
|
|
return (strcmp(expected, actual) == 0);
|
|
|
|
break;
|
|
|
|
case INT:
|
|
|
|
return (fs_get_uint64_by_index(fields, index) == literal->value.int_literal);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
printf("wat\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eval_lt_eq_node(node_t *node, fieldset_t *fields)
|
|
|
|
{
|
|
|
|
return !(eval_gt_node(node, fields));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int eval_gt_eq_node(node_t *node, fieldset_t *fields)
|
|
|
|
{
|
|
|
|
return !(eval_lt_node(node, fields));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-19 22:19:12 +00:00
|
|
|
/* Exposed functions */
|
|
|
|
|
2013-09-13 19:32:17 +00:00
|
|
|
node_t* make_op_node(enum operation op)
|
|
|
|
{
|
|
|
|
node_t* node = alloc_node();
|
|
|
|
node->type = OP;
|
|
|
|
node->value.op = op;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
node_t* make_field_node(char *fieldname)
|
|
|
|
{
|
|
|
|
node_t *node = alloc_node();
|
|
|
|
node->type = FIELD;
|
2013-09-19 22:19:12 +00:00
|
|
|
node->value.field.fieldname = fieldname;
|
2013-09-13 19:32:17 +00:00
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
node_t* make_string_node(char *literal)
|
|
|
|
{
|
|
|
|
node_t *node = alloc_node();
|
|
|
|
node->type = STRING;
|
|
|
|
node->value.string_literal = literal;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
|
|
|
node_t* make_int_node(int literal)
|
|
|
|
{
|
|
|
|
node_t *node = alloc_node();
|
|
|
|
node->type = INT;
|
|
|
|
node->value.int_literal = literal;
|
|
|
|
return node;
|
|
|
|
}
|
|
|
|
|
2013-10-12 16:52:15 +00:00
|
|
|
int evaluate_expression(node_t *root, fieldset_t *fields)
|
|
|
|
{
|
2013-09-20 18:35:07 +00:00
|
|
|
if (!root) return 1;
|
|
|
|
switch (root->type) { /* XXX Not sure if runs */
|
|
|
|
case FIELD:
|
|
|
|
case STRING:
|
|
|
|
case INT:
|
|
|
|
return 1;
|
|
|
|
case OP:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (root->value.op) {
|
|
|
|
case GT:
|
|
|
|
return eval_gt_node(root, fields);
|
|
|
|
case LT:
|
|
|
|
return eval_lt_node(root, fields);
|
|
|
|
case EQ:
|
|
|
|
return eval_eq_node(root, fields);
|
|
|
|
case NEQ:
|
|
|
|
return (!eval_eq_node(root, fields));
|
|
|
|
case LT_EQ:
|
|
|
|
return eval_lt_eq_node(root, fields);
|
|
|
|
case GT_EQ:
|
|
|
|
return eval_gt_eq_node(root, fields);
|
|
|
|
case AND:
|
|
|
|
return (evaluate_expression(root->left_child, fields)
|
|
|
|
&& evaluate_expression(root->right_child, fields));
|
|
|
|
case OR:
|
|
|
|
return (evaluate_expression(root->left_child, fields)
|
|
|
|
|| evaluate_expression(root->right_child, fields));
|
|
|
|
}
|
|
|
|
return 0;
|
2013-09-13 19:32:17 +00:00
|
|
|
}
|
|
|
|
|
2013-10-12 16:52:15 +00:00
|
|
|
void print_expression(node_t *root)
|
|
|
|
{
|
2013-09-13 19:32:17 +00:00
|
|
|
if (!root) return;
|
|
|
|
printf("%s", "( ");
|
|
|
|
print_expression(root->left_child);
|
|
|
|
switch (root->type) {
|
|
|
|
case OP:
|
|
|
|
printf(" %i ", root->value.op);
|
|
|
|
break;
|
|
|
|
case FIELD:
|
2013-09-19 22:19:12 +00:00
|
|
|
printf(" (%s", root->value.field.fieldname);
|
2013-09-13 19:32:17 +00:00
|
|
|
break;
|
|
|
|
case STRING:
|
|
|
|
printf("%s) ", root->value.string_literal);
|
|
|
|
break;
|
|
|
|
case INT:
|
2013-09-20 18:35:07 +00:00
|
|
|
printf(" %llu) ", (long long unsigned) root->value.int_literal);
|
2013-09-13 19:32:17 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
print_expression(root->right_child);
|
|
|
|
printf("%s", " )");
|
|
|
|
}
|