From 7ee0cbfb4499b2dbbf966f9191532f9ab7dbfc5e Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Thu, 28 Nov 2024 10:17:21 +0100 Subject: [PATCH] filterx: implement set_fields() If there are overrides defined for the field, we first iterate through them, and if there is an expression that successfully evaluated, we set it. If overrides were not effective, and the field already has a value, we are done with this field, we leave it as it is. If, however it did not have a value, we iterate through the defaults, like we did with the overrides, and set the field accordingly. Signed-off-by: Attila Szakacs --- lib/filterx/func-set-fields.c | 77 ++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/lib/filterx/func-set-fields.c b/lib/filterx/func-set-fields.c index e3ef8f327..e7193eef8 100644 --- a/lib/filterx/func-set-fields.c +++ b/lib/filterx/func-set-fields.c @@ -24,6 +24,7 @@ #include "filterx/func-set-fields.h" #include "filterx/object-string.h" +#include "filterx/object-primitive.h" #include "filterx/object-dict-interface.h" #include "filterx/expr-literal.h" #include "filterx/expr-literal-generator.h" @@ -127,11 +128,83 @@ typedef struct FilterXFunctionSetFields_ GArray *fields; } FilterXFunctionSetFields; +static gboolean +_set_with_fallbacks(FilterXObject *dict_unwrapped, FilterXObject *key, GPtrArray *values) +{ + gboolean changed = FALSE; + + if (!values || values->len == 0) + return changed; + + for (guint i = 0; i < values->len; i++) + { + FilterXExpr *value = g_ptr_array_index(values, i); + FilterXObject *value_obj = filterx_expr_eval(value); + if (!value_obj) + { + filterx_eval_clear_errors(); + continue; + } + + FilterXObject *value_obj_cloned = filterx_object_clone(value_obj); + filterx_object_unref(value_obj); + + if (!filterx_object_set_subscript(dict_unwrapped, key, &value_obj_cloned)) + { + filterx_object_unref(value_obj_cloned); + continue; + } + + filterx_object_unref(value_obj_cloned); + changed = TRUE; + break; + } + + return changed; +} + +static void +_process_field(Field *field, FilterXObject *dict_unwrapped) +{ + gboolean changed = _set_with_fallbacks(dict_unwrapped, field->key, field->overrides); + if (changed) + return; + + if (filterx_object_is_key_set(dict_unwrapped, field->key)) + return; + + _set_with_fallbacks(dict_unwrapped, field->key, field->defaults); +} + static FilterXObject * _eval(FilterXExpr *s) { - // TODO: implement - return NULL; + FilterXFunctionSetFields *self = (FilterXFunctionSetFields *) s; + + gboolean success = FALSE; + + FilterXObject *dict = filterx_expr_eval(self->dict); + if (!dict) + goto exit; + + FilterXObject *dict_unwrapped = filterx_ref_unwrap_rw(dict); + if (!filterx_object_is_type(dict_unwrapped, &FILTERX_TYPE_NAME(dict))) + { + filterx_eval_push_error("First argument must be a dict. " FILTERX_FUNC_SET_FIELDS_USAGE, s, NULL); + goto exit; + } + + for (guint i = 0; i < self->fields->len; i++) + { + Field *field = &g_array_index(self->fields, Field, i); + _process_field(field, dict_unwrapped); + } + + success = TRUE; + +exit: + filterx_object_unref(dict); + return success ? filterx_boolean_new(TRUE) : NULL; } static gboolean