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) 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); } 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.c b/lib/filterx/object-json.c index 1faead17e8..11261f894d 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,9 +133,8 @@ 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); - if (!filterx_object_is_frozen(self)) - filterx_json_associate_cached_object(jso, filterx_obj); + filterx_obj = filterx_json_convert_json_to_object(self, root_container, jso); + 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..023bf9b4a9 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,11 @@ 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); +struct json_object *filterx_json_object_get_value(FilterXObject *s); +struct json_object *filterx_json_array_get_value(FilterXObject *s); + #endif 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;