Skip to content

Commit

Permalink
merge: getattr opt
Browse files Browse the repository at this point in the history
  • Loading branch information
bazsi committed Jan 9, 2025
1 parent 830c565 commit d940c50
Showing 1 changed file with 97 additions and 13 deletions.
110 changes: 97 additions & 13 deletions lib/filterx/expr-getattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,47 +31,74 @@ typedef struct _FilterXGetAttr
FilterXExpr super;
FilterXExpr *operand;
FilterXObject *attr;
FilterXObject **path;
} FilterXGetAttr;

static FilterXObject *
_eval_operand(FilterXGetAttr *self, FilterXObject **attr)
{
FilterXObject *o = filterx_expr_eval_typed(self->operand);

if (!o)
return NULL;

*attr = self->attr;
if (*attr)
return o;

FilterXObject *next_o;
*attr = self->path[0];
for (gint i = 0; self->path[i] && self->path[i+1]; i++)
{
next_o = filterx_object_getattr(o, *attr);
if (!o)
break;
filterx_object_unref(o);
o = next_o;
*attr = self->path[i+1];
}
return o;
}

static FilterXObject *
_eval_getattr(FilterXExpr *s)
{
FilterXGetAttr *self = (FilterXGetAttr *) s;
FilterXObject *attr;

FilterXObject *variable = filterx_expr_eval_typed(self->operand);

FilterXObject *variable = _eval_operand(self, &attr);
if (!variable)
return NULL;

FilterXObject *attr = filterx_object_getattr(variable, self->attr);
if (!attr)
FilterXObject *value = filterx_object_getattr(variable, attr);
if (!value)
{
filterx_eval_push_error("Attribute lookup failed", s, self->attr);
filterx_eval_push_error("Attribute lookup failed", s, attr);
goto exit;
}
exit:
filterx_object_unref(variable);
return attr;
return value;
}

static gboolean
_unset(FilterXExpr *s)
{
FilterXGetAttr *self = (FilterXGetAttr *) s;

FilterXObject *attr;
gboolean result = FALSE;

FilterXObject *variable = filterx_expr_eval_typed(self->operand);
FilterXObject *variable = _eval_operand(self, &attr);
if (!variable)
return FALSE;

if (variable->readonly)
{
filterx_eval_push_error("Object unset-attr failed, object is readonly", s, self->attr);
filterx_eval_push_error("Object unset-attr failed, object is readonly", s, attr);
goto exit;
}

result = filterx_object_unset_key(variable, self->attr);
result = filterx_object_unset_key(variable, attr);

exit:
filterx_object_unref(variable);
Expand All @@ -82,22 +109,66 @@ static gboolean
_isset(FilterXExpr *s)
{
FilterXGetAttr *self = (FilterXGetAttr *) s;
FilterXObject *variable = filterx_expr_eval_typed(self->operand);
FilterXObject *attr;
FilterXObject *variable = _eval_operand(self, &attr);
if (!variable)
return FALSE;

gboolean result = filterx_object_is_key_set(variable, self->attr);
gboolean result = filterx_object_is_key_set(variable, attr);

filterx_object_unref(variable);
return result;
}

static void
_rollup_child_getattr(FilterXGetAttr *self, FilterXGetAttr *child)
{
/* turn a list of getattrs into a single getattr with a path argument */
GPtrArray *path = g_ptr_array_new();

if (child->attr)
{
/* if this is an unoptimized FilterXGetAttr, let's use the "attr" member */
g_ptr_array_add(path, filterx_object_ref(child->attr));
g_assert(child->path == NULL);
}
else
{
/* optimized GetAttr, copy the entire path into ours */
for (gint i = 0; child->path[i]; i++)
{
g_ptr_array_add(path, filterx_object_ref(child->path[i]));
}
}

/* we are the last getattr so append it to the end */
g_ptr_array_add(path, self->attr);
/* null termination */
g_ptr_array_add(path, NULL);

/* replace self->attr with self->path */
self->attr = NULL;
self->path = (FilterXObject **) g_ptr_array_free(path, FALSE);
}

static FilterXExpr *
_optimize(FilterXExpr *s)
{
FilterXGetAttr *self = (FilterXGetAttr *) s;

self->operand = filterx_expr_optimize(self->operand);
if (filterx_expr_is_getattr(self->operand))
{
FilterXGetAttr *child = (FilterXGetAttr *) self->operand;

_rollup_child_getattr(self, child);
self->operand = filterx_expr_ref(child->operand);

filterx_expr_unref(&child->super);

/* we need to return a ref */
return filterx_expr_ref(s);
}
return NULL;
}

Expand Down Expand Up @@ -125,7 +196,20 @@ static void
_free(FilterXExpr *s)
{
FilterXGetAttr *self = (FilterXGetAttr *) s;
filterx_object_unref(self->attr);

if (self->attr)
{
filterx_object_unref(self->attr);
g_assert(self->path == NULL);
}
else
{
for (gint i = 0; self->path[i]; i++)
filterx_object_unref(self->path[i]);
g_free(self->path);
g_assert(self->attr == NULL);
}

filterx_expr_unref(self->operand);
filterx_expr_free_method(s);
}
Expand Down

0 comments on commit d940c50

Please sign in to comment.