From 2f0fae4e74350c4d7cd3f4fbc78cf1a4afce5fe0 Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Sat, 1 Jun 2024 19:34:56 +0200 Subject: [PATCH 1/5] filterx: return NULL for NULL weakref getter Signed-off-by: Attila Szakacs --- lib/filterx/filterx-weakrefs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/filterx/filterx-weakrefs.c b/lib/filterx/filterx-weakrefs.c index 9083b8b96d..49ac4416ba 100644 --- a/lib/filterx/filterx-weakrefs.c +++ b/lib/filterx/filterx-weakrefs.c @@ -73,5 +73,8 @@ filterx_weakref_get(FilterXWeakRef *self) * validate if it's valid, we just assume it is until our Scope has not * been terminated yet */ + if (!self) + return NULL; + return filterx_object_ref(self->object); } From 8685e1e39987cfa8de0495ecf4307df83998f30e Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Sat, 1 Jun 2024 19:36:31 +0200 Subject: [PATCH 2/5] filterx: do not store weak refs for frozen objects Signed-off-by: Attila Szakacs --- lib/filterx/filterx-eval.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/filterx/filterx-eval.c b/lib/filterx/filterx-eval.c index 86166463c4..7dacdc6983 100644 --- a/lib/filterx/filterx-eval.c +++ b/lib/filterx/filterx-eval.c @@ -129,6 +129,10 @@ filterx_format_last_error(void) void filterx_eval_store_weak_ref(FilterXObject *object) { + /* Frozen objects do not need weak refs. */ + if (object && filterx_object_is_frozen(object)) + return; + FilterXEvalContext *context = filterx_eval_get_context(); if (object && !object->weak_referenced) From 8cbc235aec1273180a765b8079ccaa275d11ddaa Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Sat, 1 Jun 2024 19:35:33 +0200 Subject: [PATCH 3/5] filterx: expose filterx_json_convert_json_to_object() Signed-off-by: Attila Szakacs --- lib/filterx/object-json.c | 13 ++++++------- lib/filterx/object-json.h | 3 +++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/lib/filterx/object-json.c b/lib/filterx/object-json.c index 1faead17e8..a2793e8d3e 100644 --- a/lib/filterx/object-json.c +++ b/lib/filterx/object-json.c @@ -27,7 +27,6 @@ #include "filterx/object-dict-interface.h" #include "filterx/object-list-interface.h" #include "filterx/object-message-value.h" -#include "filterx/filterx-weakrefs.h" #include "filterx/filterx-eval.h" #include "scanner/list-scanner/list-scanner.h" @@ -73,8 +72,8 @@ filterx_json_deep_copy(struct json_object *jso) return clone; } -static FilterXObject * -_convert_json_to_object(FilterXObject *self, FilterXWeakRef *root_container, struct json_object *jso) +FilterXObject * +filterx_json_convert_json_to_object(FilterXObject *root_obj, FilterXWeakRef *root_container, struct json_object *jso) { switch (json_object_get_type(jso)) { @@ -90,10 +89,10 @@ _convert_json_to_object(FilterXObject *self, FilterXWeakRef *root_container, str return filterx_string_new(json_object_get_string(jso), -1); case json_type_array: return filterx_json_array_new_sub(json_object_get(jso), - filterx_weakref_get(root_container) ? : filterx_object_ref(self)); + filterx_weakref_get(root_container) ? : filterx_object_ref(root_obj)); case json_type_object: return filterx_json_object_new_sub(json_object_get(jso), - filterx_weakref_get(root_container) ? : filterx_object_ref(self)); + filterx_weakref_get(root_container) ? : filterx_object_ref(root_obj)); default: g_assert_not_reached(); } @@ -124,7 +123,7 @@ filterx_json_convert_json_to_object_cached(FilterXObject *self, FilterXWeakRef * */ if (JSON_C_MAJOR_VERSION == 0 && JSON_C_MINOR_VERSION < 14) - return _convert_json_to_object(self, root_container, jso); + return filterx_json_convert_json_to_object(self, root_container, jso); json_object_set_double(jso, json_object_get_double(jso)); } @@ -134,7 +133,7 @@ filterx_json_convert_json_to_object_cached(FilterXObject *self, FilterXWeakRef * if (filterx_obj) return filterx_object_ref(filterx_obj); - filterx_obj = _convert_json_to_object(self, root_container, jso); + filterx_obj = filterx_json_convert_json_to_object(self, root_container, jso); if (!filterx_object_is_frozen(self)) filterx_json_associate_cached_object(jso, filterx_obj); return filterx_obj; diff --git a/lib/filterx/object-json.h b/lib/filterx/object-json.h index 4dc2260bb8..72b42b4e7b 100644 --- a/lib/filterx/object-json.h +++ b/lib/filterx/object-json.h @@ -24,6 +24,7 @@ #define OBJECT_JSON_H_INCLUDED #include "filterx/filterx-object.h" +#include "filterx/filterx-weakrefs.h" #include "compat/json.h" typedef struct FilterXJsonObject_ FilterXJsonObject; @@ -49,6 +50,8 @@ const gchar *filterx_json_to_json_literal(FilterXObject *s); const gchar *filterx_json_object_to_json_literal(FilterXObject *s); const gchar *filterx_json_array_to_json_literal(FilterXObject *s); +FilterXObject *filterx_json_convert_json_to_object(FilterXObject *root_obj, FilterXWeakRef *root_container, + struct json_object *jso); void filterx_json_associate_cached_object(struct json_object *jso, FilterXObject *filterx_object); #endif From c89b0dd36a3bda939b43af3a2c3b1f489558e832 Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Sat, 1 Jun 2024 19:36:12 +0200 Subject: [PATCH 4/5] filterx: add get_value() for json types Signed-off-by: Attila Szakacs --- lib/filterx/object-json-array.c | 11 +++++++++++ lib/filterx/object-json-object.c | 11 +++++++++++ lib/filterx/object-json.h | 3 +++ 3 files changed, 25 insertions(+) diff --git a/lib/filterx/object-json-array.c b/lib/filterx/object-json-array.c index ebe7a101e5..f61566f16a 100644 --- a/lib/filterx/object-json-array.c +++ b/lib/filterx/object-json-array.c @@ -361,6 +361,17 @@ filterx_json_array_to_json_literal(FilterXObject *s) return json_object_to_json_string_ext(self->jso, JSON_C_TO_STRING_PLAIN); } +struct json_object * +filterx_json_array_get_value(FilterXObject *s) +{ + if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array))) + return NULL; + + FilterXJsonArray *self = (FilterXJsonArray *) s; + + return self->jso; +} + FILTERX_DEFINE_TYPE(json_array, FILTERX_TYPE_NAME(list), .is_mutable = TRUE, .truthy = _truthy, diff --git a/lib/filterx/object-json-object.c b/lib/filterx/object-json-object.c index 0e10076018..bb9bb619ee 100644 --- a/lib/filterx/object-json-object.c +++ b/lib/filterx/object-json-object.c @@ -259,6 +259,17 @@ filterx_json_object_to_json_literal(FilterXObject *s) return json_object_to_json_string_ext(self->jso, JSON_C_TO_STRING_PLAIN); } +struct json_object * +filterx_json_object_get_value(FilterXObject *s) +{ + if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object))) + return NULL; + + FilterXJsonObject *self = (FilterXJsonObject *) s; + + return self->jso; +} + FILTERX_DEFINE_TYPE(json_object, FILTERX_TYPE_NAME(dict), .is_mutable = TRUE, .truthy = _truthy, diff --git a/lib/filterx/object-json.h b/lib/filterx/object-json.h index 72b42b4e7b..023bf9b4a9 100644 --- a/lib/filterx/object-json.h +++ b/lib/filterx/object-json.h @@ -54,4 +54,7 @@ FilterXObject *filterx_json_convert_json_to_object(FilterXObject *root_obj, Filt struct json_object *jso); void filterx_json_associate_cached_object(struct json_object *jso, FilterXObject *filterx_object); +struct json_object *filterx_json_object_get_value(FilterXObject *s); +struct json_object *filterx_json_array_get_value(FilterXObject *s); + #endif From 1f04874847590c8be1f8077be901577118b57abd Mon Sep 17 00:00:00 2001 From: Attila Szakacs Date: Sat, 1 Jun 2024 19:37:19 +0200 Subject: [PATCH 5/5] json: deep freeze objects in cache_json_file() filterx fn Signed-off-by: Attila Szakacs --- lib/filterx/object-json.c | 3 +- modules/json/filterx-cache-json-file.c | 57 ++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/lib/filterx/object-json.c b/lib/filterx/object-json.c index a2793e8d3e..11261f894d 100644 --- a/lib/filterx/object-json.c +++ b/lib/filterx/object-json.c @@ -134,8 +134,7 @@ filterx_json_convert_json_to_object_cached(FilterXObject *self, FilterXWeakRef * return filterx_object_ref(filterx_obj); filterx_obj = filterx_json_convert_json_to_object(self, root_container, jso); - if (!filterx_object_is_frozen(self)) - filterx_json_associate_cached_object(jso, filterx_obj); + filterx_json_associate_cached_object(jso, filterx_obj); return filterx_obj; } diff --git a/modules/json/filterx-cache-json-file.c b/modules/json/filterx-cache-json-file.c index a0ca7483fc..ff3fc6abbc 100644 --- a/modules/json/filterx-cache-json-file.c +++ b/modules/json/filterx-cache-json-file.c @@ -23,6 +23,8 @@ #include "filterx-cache-json-file.h" #include "filterx/object-json.h" #include "filterx/object-string.h" +#include "filterx/object-list-interface.h" +#include "filterx/object-dict-interface.h" #include "filterx/expr-literal.h" #include "filterx/filterx-eval.h" #include "scratch-buffers.h" @@ -54,6 +56,7 @@ typedef struct FilterXFunctionCacheJsonFile_ FilterXFunction super; gchar *filepath; FilterXObject *cached_json; + GPtrArray *frozen_objects; } FilterXFuntionCacheJsonFile; static gchar * @@ -143,11 +146,56 @@ _free(FilterXExpr *s) FilterXFuntionCacheJsonFile *self = (FilterXFuntionCacheJsonFile *) s; g_free(self->filepath); - if (self->cached_json) - filterx_object_unfreeze_and_free(self->cached_json); + g_ptr_array_unref(self->frozen_objects); filterx_function_free_method(&self->super); } +static void _deep_freeze(FilterXFuntionCacheJsonFile *self, FilterXObject *object); + +static void +_deep_freeze_dict(FilterXFuntionCacheJsonFile *self, FilterXObject *object) +{ + struct json_object_iter itr; + json_object_object_foreachC(filterx_json_object_get_value(object), itr) + { + struct json_object *elem_jso = itr.val; + FilterXObject *elem_object = filterx_json_convert_json_to_object(self->cached_json, NULL, elem_jso); + _deep_freeze(self, elem_object); + filterx_json_associate_cached_object(elem_jso, elem_object); + } +} + +static void +_deep_freeze_list(FilterXFuntionCacheJsonFile *self, FilterXObject *object) +{ + struct json_object *jso = filterx_json_object_get_value(object); + guint64 len = json_object_array_length(jso); + + for (guint64 i = 0; i < len; i++) + { + struct json_object *elem_jso = json_object_array_get_idx(jso, i); + FilterXObject *elem_object = filterx_json_convert_json_to_object(self->cached_json, NULL, elem_jso); + _deep_freeze(self, elem_object); + filterx_json_associate_cached_object(elem_jso, elem_object); + } +} + +static void +_deep_freeze(FilterXFuntionCacheJsonFile *self, FilterXObject *object) +{ + if (!object) + return; + + if (filterx_object_freeze(object)) + g_ptr_array_add(self->frozen_objects, object); + + if (filterx_object_is_type(object, &FILTERX_TYPE_NAME(json_object))) + _deep_freeze_dict(self, object); + + if (filterx_object_is_type(object, &FILTERX_TYPE_NAME(json_array))) + _deep_freeze_list(self, object); +} + FilterXFunction * filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error) { @@ -157,6 +205,8 @@ filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunction self->super.super.eval = _eval; self->super.super.free_fn = _free; + self->frozen_objects = g_ptr_array_new_with_free_func((GDestroyNotify) filterx_object_unfreeze_and_free); + self->filepath = _extract_filepath(args, error); if (!self->filepath) goto error; @@ -165,7 +215,8 @@ filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunction if (!self->cached_json) goto error; - filterx_object_freeze(self->cached_json); + _deep_freeze(self, self->cached_json); + filterx_function_args_free(args); return &self->super;