diff --git a/lib/filterx/Makefile.am b/lib/filterx/Makefile.am index 8b495f5051..69b2172795 100644 --- a/lib/filterx/Makefile.am +++ b/lib/filterx/Makefile.am @@ -12,6 +12,7 @@ filterxinclude_HEADERS = \ lib/filterx/expr-setattr.h \ lib/filterx/expr-get-subscript.h \ lib/filterx/expr-set-subscript.h \ + lib/filterx/expr-plus.h \ lib/filterx/expr-variable.h \ lib/filterx/expr-comparison.h \ lib/filterx/filterx-object.h \ @@ -54,6 +55,7 @@ filterx_sources = \ lib/filterx/expr-setattr.c \ lib/filterx/expr-get-subscript.c \ lib/filterx/expr-set-subscript.c \ + lib/filterx/expr-plus.c \ lib/filterx/expr-variable.c \ lib/filterx/expr-comparison.c \ lib/filterx/filterx-object.c \ diff --git a/lib/filterx/expr-plus.c b/lib/filterx/expr-plus.c new file mode 100644 index 0000000000..dfcab844b7 --- /dev/null +++ b/lib/filterx/expr-plus.c @@ -0,0 +1,56 @@ +#include "expr-plus.h" +#include "object-string.h" +#include "filterx-eval.h" +#include "scratch-buffers.h" + +typedef struct FilterXOperatorPlus +{ + FilterXBinaryOp super; +} FilterXOperatorPlus; + +static FilterXObject * +_eval(FilterXExpr *s) +{ + FilterXOperatorPlus *self = (FilterXOperatorPlus *) s; + + FilterXObject *lhs_object = filterx_expr_eval(self->super.lhs); + if (!lhs_object) + { + return NULL; + } + + FilterXObject *rhs_object = filterx_expr_eval(self->super.rhs); + if (!rhs_object) + { + filterx_object_unref(lhs_object); + return NULL; + } + + if (filterx_object_is_type(lhs_object, &FILTERX_TYPE_NAME(string)) && + filterx_object_is_type(rhs_object, &FILTERX_TYPE_NAME(string))) + { + gsize lhs_len, rhs_len; + const gchar *lhs_value = filterx_string_get_value(lhs_object, &lhs_len); + const gchar *rhs_value = filterx_string_get_value(rhs_object, &rhs_len); + GString *buffer = scratch_buffers_alloc(); + + g_string_append_len(buffer, lhs_value, lhs_len); + g_string_append_len(buffer, rhs_value, rhs_len); + /* FIXME: support taking over the already allocated space */ + return filterx_string_new(buffer->str, buffer->len); + } + + filterx_eval_push_error("operator+ only works on strings", s, NULL); + filterx_object_unref(lhs_object); + filterx_object_unref(rhs_object); + return NULL; +} + +FilterXExpr * +filterx_operator_plus_new(FilterXExpr *lhs, FilterXExpr *rhs) +{ + FilterXOperatorPlus *self = g_new0(FilterXOperatorPlus, 1); + filterx_binary_op_init_instance(&self->super, lhs, rhs); + self->super.super.eval = _eval; + return &self->super.super; +} diff --git a/lib/filterx/expr-plus.h b/lib/filterx/expr-plus.h new file mode 100644 index 0000000000..acb51c4a99 --- /dev/null +++ b/lib/filterx/expr-plus.h @@ -0,0 +1,8 @@ +#ifndef FILTERX_EXPR_PLUS_H_INCLUDED +#define FILTERX_EXPR_PLUS_H_INCLUDED + +#include "filterx-expr.h" + +FilterXExpr *filterx_operator_plus_new(FilterXExpr *lhs, FilterXExpr *rhs); + +#endif diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index d0f6bf136a..0d41f392f6 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -52,6 +52,7 @@ #include "filterx/expr-literal-generator.h" #include "filterx/expr-shorthand.h" #include "filterx/expr-regexp.h" +#include "filterx/expr-plus.h" #include "template/templates.h" @@ -299,6 +300,7 @@ expr | expr KW_STR_GT expr { $$ = filterx_comparison_new($1, $3, FCMPX_STRING_BASED | FCMPX_GT); } | expr KW_TAV_EQ expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_EQ); } | expr KW_TAV_NE expr { $$ = filterx_comparison_new($1, $3, FCMPX_TYPE_AND_VALUE_BASED | FCMPX_NE ); } + | expr '+' expr { $$ = filterx_operator_plus_new($1, $3); } | '(' expr ')' { $$ = $2; } | ternary { $$ = $1; } | KW_ISSET '(' expr ')' { $$ = filterx_isset_new($3); }