Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 10334c2e in mainline for uspace/app/bithenge/expression.c


Ignore:
Timestamp:
2012-07-30T01:40:55Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
20ac1a4
Parents:
d1e580a
Message:

Bithenge: add if_transform

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/expression.c

    rd1e580a r10334c2e  
    417417}
    418418
     419typedef struct {
     420        bithenge_transform_t base;
     421        bithenge_expression_t *expr;
     422        bithenge_transform_t *true_xform, *false_xform;
     423} if_transform_t;
     424
     425static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
     426{
     427        return &self->base;
     428}
     429
     430static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
     431{
     432        return (if_transform_t *)base;
     433}
     434
     435static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
     436    bool *out)
     437{
     438        bithenge_node_t *cond_node;
     439        int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
     440        if (rc != EOK)
     441                return rc;
     442        if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
     443                bithenge_node_dec_ref(cond_node);
     444                return EINVAL;
     445        }
     446        *out = bithenge_boolean_node_value(cond_node);
     447        bithenge_node_dec_ref(cond_node);
     448        return EOK;
     449}
     450
     451static int if_transform_apply(bithenge_transform_t *base,
     452    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     453{
     454        if_transform_t *self = transform_as_if(base);
     455        bool cond;
     456        int rc = if_transform_choose(self, scope, &cond);
     457        if (rc != EOK)
     458                return rc;
     459        return bithenge_transform_apply(
     460            cond ? self->true_xform : self->false_xform, scope, in, out);
     461}
     462
     463static int if_transform_prefix_length(bithenge_transform_t *base,
     464    bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
     465{
     466        if_transform_t *self = transform_as_if(base);
     467        bool cond;
     468        int rc = if_transform_choose(self, scope, &cond);
     469        if (rc != EOK)
     470                return rc;
     471        return bithenge_transform_prefix_length(
     472            cond ? self->true_xform : self->false_xform, scope, in, out);
     473}
     474
     475static void if_transform_destroy(bithenge_transform_t *base)
     476{
     477        if_transform_t *self = transform_as_if(base);
     478        bithenge_expression_dec_ref(self->expr);
     479        bithenge_transform_dec_ref(self->true_xform);
     480        bithenge_transform_dec_ref(self->false_xform);
     481        free(self);
     482}
     483
     484static const bithenge_transform_ops_t if_transform_ops = {
     485        .apply = if_transform_apply,
     486        .prefix_length = if_transform_prefix_length,
     487        .destroy = if_transform_destroy,
     488};
     489
     490/** Create a transform that applies either of two transforms depending on a
     491 * boolean expression. Takes references to @a expr, @a true_xform, and
     492 * @a false_xform.
     493 * @param[out] out Holds the new transform.
     494 * @param expr The boolean expression to evaluate.
     495 * @param true_xform The transform to apply if the expression is true.
     496 * @param false_xform The transform to apply if the expression is false. */
     497int bithenge_if_transform(bithenge_transform_t **out,
     498    bithenge_expression_t *expr, bithenge_transform_t *true_xform,
     499    bithenge_transform_t *false_xform)
     500{
     501        int rc;
     502        if_transform_t *self = malloc(sizeof(*self));
     503        if (!self) {
     504                rc = ENOMEM;
     505                goto error;
     506        }
     507
     508        rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
     509            0);
     510        if (rc != EOK)
     511                goto error;
     512
     513        self->expr = expr;
     514        self->true_xform = true_xform;
     515        self->false_xform = false_xform;
     516        *out = if_as_transform(self);
     517        return EOK;
     518
     519error:
     520        free(self);
     521        bithenge_expression_dec_ref(expr);
     522        bithenge_transform_dec_ref(true_xform);
     523        bithenge_transform_dec_ref(false_xform);
     524        return rc;
     525}
     526
    419527/** @}
    420528 */
Note: See TracChangeset for help on using the changeset viewer.