HelenOS sources
This source file includes following definitions.
- compose_as_transform
- transform_as_compose
- compose_apply
- compose_prefix_length
- compose_destroy
- bithenge_new_composed_transform
- if_as_transform
- transform_as_if
- if_transform_choose
- if_transform_apply
- if_transform_prefix_length
- if_transform_destroy
- bithenge_if_transform
- partial_as_transform
- transform_as_partial
- partial_transform_apply
- partial_transform_destroy
- bithenge_partial_transform
#include <stdlib.h>
#include <bithenge/compound.h>
#include <bithenge/expression.h>
#include <bithenge/transform.h>
#include <bithenge/tree.h>
#include "common.h"
typedef struct {
bithenge_transform_t base;
bithenge_transform_t **xforms;
size_t num;
} compose_transform_t;
static bithenge_transform_t *compose_as_transform(compose_transform_t *xform)
{
return &xform->base;
}
static compose_transform_t *transform_as_compose(bithenge_transform_t *xform)
{
return (compose_transform_t *)xform;
}
static errno_t compose_apply(bithenge_transform_t *base, bithenge_scope_t *scope,
bithenge_node_t *in, bithenge_node_t **out)
{
errno_t rc;
compose_transform_t *self = transform_as_compose(base);
bithenge_node_inc_ref(in);
size_t i = self->num;
while (i-- != 0) {
bithenge_node_t *tmp;
rc = bithenge_transform_apply(self->xforms[i], scope, in,
&tmp);
bithenge_node_dec_ref(in);
if (rc != EOK)
return rc;
in = tmp;
}
*out = in;
return EOK;
}
static errno_t compose_prefix_length(bithenge_transform_t *base,
bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
{
compose_transform_t *self = transform_as_compose(base);
return bithenge_transform_prefix_length(self->xforms[self->num - 1],
scope, blob, out);
}
static void compose_destroy(bithenge_transform_t *base)
{
compose_transform_t *self = transform_as_compose(base);
for (size_t i = 0; i < self->num; i++)
bithenge_transform_dec_ref(self->xforms[i]);
free(self->xforms);
free(self);
}
static const bithenge_transform_ops_t compose_transform_ops = {
.apply = compose_apply,
.prefix_length = compose_prefix_length,
.destroy = compose_destroy,
};
errno_t bithenge_new_composed_transform(bithenge_transform_t **out,
bithenge_transform_t **xforms, size_t num)
{
if (num == 0) {
} else if (num == 1) {
*out = xforms[0];
free(xforms);
return EOK;
}
errno_t rc;
compose_transform_t *self = malloc(sizeof(*self));
if (!self) {
rc = ENOMEM;
goto error;
}
rc = bithenge_init_transform(compose_as_transform(self),
&compose_transform_ops, 0);
if (rc != EOK)
goto error;
self->xforms = xforms;
self->num = num;
*out = compose_as_transform(self);
return EOK;
error:
for (size_t i = 0; i < num; i++)
bithenge_transform_dec_ref(xforms[i]);
free(xforms);
free(self);
return rc;
}
typedef struct {
bithenge_transform_t base;
bithenge_expression_t *expr;
bithenge_transform_t *true_xform, *false_xform;
} if_transform_t;
static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
{
return &self->base;
}
static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
{
return (if_transform_t *)base;
}
static errno_t if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
bool *out)
{
bithenge_node_t *cond_node;
errno_t rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
if (rc != EOK)
return rc;
if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
bithenge_node_dec_ref(cond_node);
return EINVAL;
}
*out = bithenge_boolean_node_value(cond_node);
bithenge_node_dec_ref(cond_node);
return EOK;
}
static errno_t if_transform_apply(bithenge_transform_t *base,
bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
{
if_transform_t *self = transform_as_if(base);
bool cond;
errno_t rc = if_transform_choose(self, scope, &cond);
if (rc != EOK)
return rc;
return bithenge_transform_apply(
cond ? self->true_xform : self->false_xform, scope, in, out);
}
static errno_t if_transform_prefix_length(bithenge_transform_t *base,
bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
{
if_transform_t *self = transform_as_if(base);
bool cond;
errno_t rc = if_transform_choose(self, scope, &cond);
if (rc != EOK)
return rc;
return bithenge_transform_prefix_length(
cond ? self->true_xform : self->false_xform, scope, in, out);
}
static void if_transform_destroy(bithenge_transform_t *base)
{
if_transform_t *self = transform_as_if(base);
bithenge_expression_dec_ref(self->expr);
bithenge_transform_dec_ref(self->true_xform);
bithenge_transform_dec_ref(self->false_xform);
free(self);
}
static const bithenge_transform_ops_t if_transform_ops = {
.apply = if_transform_apply,
.prefix_length = if_transform_prefix_length,
.destroy = if_transform_destroy,
};
errno_t bithenge_if_transform(bithenge_transform_t **out,
bithenge_expression_t *expr, bithenge_transform_t *true_xform,
bithenge_transform_t *false_xform)
{
errno_t rc;
if_transform_t *self = malloc(sizeof(*self));
if (!self) {
rc = ENOMEM;
goto error;
}
rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
0);
if (rc != EOK)
goto error;
self->expr = expr;
self->true_xform = true_xform;
self->false_xform = false_xform;
*out = if_as_transform(self);
return EOK;
error:
free(self);
bithenge_expression_dec_ref(expr);
bithenge_transform_dec_ref(true_xform);
bithenge_transform_dec_ref(false_xform);
return rc;
}
typedef struct {
bithenge_transform_t base;
bithenge_transform_t *xform;
} partial_transform_t;
static inline bithenge_transform_t *partial_as_transform(
partial_transform_t *self)
{
return &self->base;
}
static inline partial_transform_t *transform_as_partial(
bithenge_transform_t *base)
{
return (partial_transform_t *)base;
}
static errno_t partial_transform_apply(bithenge_transform_t *base,
bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
{
partial_transform_t *self = transform_as_partial(base);
if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
return EINVAL;
return bithenge_transform_prefix_apply(self->xform, scope,
bithenge_node_as_blob(in), out, NULL);
}
static void partial_transform_destroy(bithenge_transform_t *base)
{
partial_transform_t *self = transform_as_partial(base);
bithenge_transform_dec_ref(self->xform);
free(self);
}
static const bithenge_transform_ops_t partial_transform_ops = {
.apply = partial_transform_apply,
.destroy = partial_transform_destroy,
};
errno_t bithenge_partial_transform(bithenge_transform_t **out,
bithenge_transform_t *xform)
{
errno_t rc;
partial_transform_t *self = malloc(sizeof(*self));
if (!self) {
rc = ENOMEM;
goto error;
}
rc = bithenge_init_transform(partial_as_transform(self),
&partial_transform_ops, 0);
if (rc != EOK)
goto error;
self->xform = xform;
*out = partial_as_transform(self);
return EOK;
error:
free(self);
bithenge_transform_dec_ref(xform);
return rc;
}
HelenOS homepage, sources at GitHub