Skip to content

Commit 422dbfb

Browse files
authored
Merge pull request #134 from alltilla/filterx-cache-json-file-deep-freeze
filterx: `cache_json_file()` deep freeze
2 parents fc096ff + 1f04874 commit 422dbfb

7 files changed

+96
-12
lines changed

lib/filterx/filterx-eval.c

+4
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ filterx_format_last_error(void)
129129
void
130130
filterx_eval_store_weak_ref(FilterXObject *object)
131131
{
132+
/* Frozen objects do not need weak refs. */
133+
if (object && filterx_object_is_frozen(object))
134+
return;
135+
132136
FilterXEvalContext *context = filterx_eval_get_context();
133137

134138
if (object && !object->weak_referenced)

lib/filterx/filterx-weakrefs.c

+3
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,8 @@ filterx_weakref_get(FilterXWeakRef *self)
7373
* validate if it's valid, we just assume it is until our Scope has not
7474
* been terminated yet */
7575

76+
if (!self)
77+
return NULL;
78+
7679
return filterx_object_ref(self->object);
7780
}

lib/filterx/object-json-array.c

+11
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,17 @@ filterx_json_array_to_json_literal(FilterXObject *s)
361361
return json_object_to_json_string_ext(self->jso, JSON_C_TO_STRING_PLAIN);
362362
}
363363

364+
struct json_object *
365+
filterx_json_array_get_value(FilterXObject *s)
366+
{
367+
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_array)))
368+
return NULL;
369+
370+
FilterXJsonArray *self = (FilterXJsonArray *) s;
371+
372+
return self->jso;
373+
}
374+
364375
FILTERX_DEFINE_TYPE(json_array, FILTERX_TYPE_NAME(list),
365376
.is_mutable = TRUE,
366377
.truthy = _truthy,

lib/filterx/object-json-object.c

+11
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,17 @@ filterx_json_object_to_json_literal(FilterXObject *s)
259259
return json_object_to_json_string_ext(self->jso, JSON_C_TO_STRING_PLAIN);
260260
}
261261

262+
struct json_object *
263+
filterx_json_object_get_value(FilterXObject *s)
264+
{
265+
if (!filterx_object_is_type(s, &FILTERX_TYPE_NAME(json_object)))
266+
return NULL;
267+
268+
FilterXJsonObject *self = (FilterXJsonObject *) s;
269+
270+
return self->jso;
271+
}
272+
262273
FILTERX_DEFINE_TYPE(json_object, FILTERX_TYPE_NAME(dict),
263274
.is_mutable = TRUE,
264275
.truthy = _truthy,

lib/filterx/object-json.c

+7-9
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
#include "filterx/object-dict-interface.h"
2828
#include "filterx/object-list-interface.h"
2929
#include "filterx/object-message-value.h"
30-
#include "filterx/filterx-weakrefs.h"
3130
#include "filterx/filterx-eval.h"
3231

3332
#include "scanner/list-scanner/list-scanner.h"
@@ -73,8 +72,8 @@ filterx_json_deep_copy(struct json_object *jso)
7372
return clone;
7473
}
7574

76-
static FilterXObject *
77-
_convert_json_to_object(FilterXObject *self, FilterXWeakRef *root_container, struct json_object *jso)
75+
FilterXObject *
76+
filterx_json_convert_json_to_object(FilterXObject *root_obj, FilterXWeakRef *root_container, struct json_object *jso)
7877
{
7978
switch (json_object_get_type(jso))
8079
{
@@ -90,10 +89,10 @@ _convert_json_to_object(FilterXObject *self, FilterXWeakRef *root_container, str
9089
return filterx_string_new(json_object_get_string(jso), -1);
9190
case json_type_array:
9291
return filterx_json_array_new_sub(json_object_get(jso),
93-
filterx_weakref_get(root_container) ? : filterx_object_ref(self));
92+
filterx_weakref_get(root_container) ? : filterx_object_ref(root_obj));
9493
case json_type_object:
9594
return filterx_json_object_new_sub(json_object_get(jso),
96-
filterx_weakref_get(root_container) ? : filterx_object_ref(self));
95+
filterx_weakref_get(root_container) ? : filterx_object_ref(root_obj));
9796
default:
9897
g_assert_not_reached();
9998
}
@@ -124,7 +123,7 @@ filterx_json_convert_json_to_object_cached(FilterXObject *self, FilterXWeakRef *
124123
*/
125124

126125
if (JSON_C_MAJOR_VERSION == 0 && JSON_C_MINOR_VERSION < 14)
127-
return _convert_json_to_object(self, root_container, jso);
126+
return filterx_json_convert_json_to_object(self, root_container, jso);
128127

129128
json_object_set_double(jso, json_object_get_double(jso));
130129
}
@@ -134,9 +133,8 @@ filterx_json_convert_json_to_object_cached(FilterXObject *self, FilterXWeakRef *
134133
if (filterx_obj)
135134
return filterx_object_ref(filterx_obj);
136135

137-
filterx_obj = _convert_json_to_object(self, root_container, jso);
138-
if (!filterx_object_is_frozen(self))
139-
filterx_json_associate_cached_object(jso, filterx_obj);
136+
filterx_obj = filterx_json_convert_json_to_object(self, root_container, jso);
137+
filterx_json_associate_cached_object(jso, filterx_obj);
140138
return filterx_obj;
141139
}
142140

lib/filterx/object-json.h

+6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#define OBJECT_JSON_H_INCLUDED
2525

2626
#include "filterx/filterx-object.h"
27+
#include "filterx/filterx-weakrefs.h"
2728
#include "compat/json.h"
2829

2930
typedef struct FilterXJsonObject_ FilterXJsonObject;
@@ -49,6 +50,11 @@ const gchar *filterx_json_to_json_literal(FilterXObject *s);
4950
const gchar *filterx_json_object_to_json_literal(FilterXObject *s);
5051
const gchar *filterx_json_array_to_json_literal(FilterXObject *s);
5152

53+
FilterXObject *filterx_json_convert_json_to_object(FilterXObject *root_obj, FilterXWeakRef *root_container,
54+
struct json_object *jso);
5255
void filterx_json_associate_cached_object(struct json_object *jso, FilterXObject *filterx_object);
5356

57+
struct json_object *filterx_json_object_get_value(FilterXObject *s);
58+
struct json_object *filterx_json_array_get_value(FilterXObject *s);
59+
5460
#endif

modules/json/filterx-cache-json-file.c

+54-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "filterx-cache-json-file.h"
2424
#include "filterx/object-json.h"
2525
#include "filterx/object-string.h"
26+
#include "filterx/object-list-interface.h"
27+
#include "filterx/object-dict-interface.h"
2628
#include "filterx/expr-literal.h"
2729
#include "filterx/filterx-eval.h"
2830
#include "scratch-buffers.h"
@@ -54,6 +56,7 @@ typedef struct FilterXFunctionCacheJsonFile_
5456
FilterXFunction super;
5557
gchar *filepath;
5658
FilterXObject *cached_json;
59+
GPtrArray *frozen_objects;
5760
} FilterXFuntionCacheJsonFile;
5861

5962
static gchar *
@@ -143,11 +146,56 @@ _free(FilterXExpr *s)
143146
FilterXFuntionCacheJsonFile *self = (FilterXFuntionCacheJsonFile *) s;
144147

145148
g_free(self->filepath);
146-
if (self->cached_json)
147-
filterx_object_unfreeze_and_free(self->cached_json);
149+
g_ptr_array_unref(self->frozen_objects);
148150
filterx_function_free_method(&self->super);
149151
}
150152

153+
static void _deep_freeze(FilterXFuntionCacheJsonFile *self, FilterXObject *object);
154+
155+
static void
156+
_deep_freeze_dict(FilterXFuntionCacheJsonFile *self, FilterXObject *object)
157+
{
158+
struct json_object_iter itr;
159+
json_object_object_foreachC(filterx_json_object_get_value(object), itr)
160+
{
161+
struct json_object *elem_jso = itr.val;
162+
FilterXObject *elem_object = filterx_json_convert_json_to_object(self->cached_json, NULL, elem_jso);
163+
_deep_freeze(self, elem_object);
164+
filterx_json_associate_cached_object(elem_jso, elem_object);
165+
}
166+
}
167+
168+
static void
169+
_deep_freeze_list(FilterXFuntionCacheJsonFile *self, FilterXObject *object)
170+
{
171+
struct json_object *jso = filterx_json_object_get_value(object);
172+
guint64 len = json_object_array_length(jso);
173+
174+
for (guint64 i = 0; i < len; i++)
175+
{
176+
struct json_object *elem_jso = json_object_array_get_idx(jso, i);
177+
FilterXObject *elem_object = filterx_json_convert_json_to_object(self->cached_json, NULL, elem_jso);
178+
_deep_freeze(self, elem_object);
179+
filterx_json_associate_cached_object(elem_jso, elem_object);
180+
}
181+
}
182+
183+
static void
184+
_deep_freeze(FilterXFuntionCacheJsonFile *self, FilterXObject *object)
185+
{
186+
if (!object)
187+
return;
188+
189+
if (filterx_object_freeze(object))
190+
g_ptr_array_add(self->frozen_objects, object);
191+
192+
if (filterx_object_is_type(object, &FILTERX_TYPE_NAME(json_object)))
193+
_deep_freeze_dict(self, object);
194+
195+
if (filterx_object_is_type(object, &FILTERX_TYPE_NAME(json_array)))
196+
_deep_freeze_list(self, object);
197+
}
198+
151199
FilterXFunction *
152200
filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunctionArgs *args, GError **error)
153201
{
@@ -157,6 +205,8 @@ filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunction
157205
self->super.super.eval = _eval;
158206
self->super.super.free_fn = _free;
159207

208+
self->frozen_objects = g_ptr_array_new_with_free_func((GDestroyNotify) filterx_object_unfreeze_and_free);
209+
160210
self->filepath = _extract_filepath(args, error);
161211
if (!self->filepath)
162212
goto error;
@@ -165,7 +215,8 @@ filterx_function_cache_json_file_new(const gchar *function_name, FilterXFunction
165215
if (!self->cached_json)
166216
goto error;
167217

168-
filterx_object_freeze(self->cached_json);
218+
_deep_freeze(self, self->cached_json);
219+
169220
filterx_function_args_free(args);
170221
return &self->super;
171222

0 commit comments

Comments
 (0)