Changeset 0b60d2d in mainline for uspace/app/bithenge/expression.c


Ignore:
Timestamp:
2012-08-09T04:46:44Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3c70376
Parents:
d8bd2ec
Message:

Bithenge: add subblob expressions

File:
1 edited

Legend:

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

    rd8bd2ec r0b60d2d  
    545545
    546546
     547/***************** subblob_expression                        *****************/
     548
     549typedef struct {
     550        bithenge_expression_t base;
     551        bithenge_expression_t *blob, *start, *limit;
     552        bool absolute_limit;
     553} subblob_expression_t;
     554
     555static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base)
     556{
     557        return (subblob_expression_t *)base;
     558}
     559
     560static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr)
     561{
     562        return &expr->base;
     563}
     564
     565static int subblob_expression_evaluate(bithenge_expression_t *base,
     566    bithenge_scope_t *scope, bithenge_node_t **out)
     567{
     568        subblob_expression_t *self = expression_as_subblob(base);
     569        bithenge_node_t *start_node;
     570        int rc = bithenge_expression_evaluate(self->start, scope, &start_node);
     571        if (rc != EOK)
     572                return rc;
     573        if (bithenge_node_type(start_node) != BITHENGE_NODE_INTEGER) {
     574                bithenge_node_dec_ref(start_node);
     575                return EINVAL;
     576        }
     577        bithenge_int_t start = bithenge_integer_node_value(start_node);
     578        bithenge_node_dec_ref(start_node);
     579
     580        bithenge_int_t limit = -1;
     581        if (self->limit) {
     582                bithenge_node_t *limit_node;
     583                rc = bithenge_expression_evaluate(self->limit, scope,
     584                    &limit_node);
     585                if (rc != EOK)
     586                        return rc;
     587                if (bithenge_node_type(limit_node) != BITHENGE_NODE_INTEGER) {
     588                        bithenge_node_dec_ref(limit_node);
     589                        return EINVAL;
     590                }
     591                limit = bithenge_integer_node_value(limit_node);
     592                bithenge_node_dec_ref(limit_node);
     593                if (self->absolute_limit)
     594                        limit -= start;
     595        }
     596
     597        if (start < 0 || (self->limit && limit < 0))
     598                return EINVAL;
     599
     600        bithenge_node_t *blob;
     601        rc = bithenge_expression_evaluate(self->blob, scope, &blob);
     602        if (rc != EOK)
     603                return rc;
     604        if (bithenge_node_type(blob) != BITHENGE_NODE_BLOB) {
     605                bithenge_node_dec_ref(blob);
     606                return EINVAL;
     607        }
     608
     609        if (self->limit)
     610                return bithenge_new_subblob(out, bithenge_node_as_blob(blob),
     611                    start, limit);
     612        else
     613                return bithenge_new_offset_blob(out,
     614                    bithenge_node_as_blob(blob), start);
     615}
     616
     617static void subblob_expression_destroy(bithenge_expression_t *base)
     618{
     619        subblob_expression_t *self = expression_as_subblob(base);
     620        bithenge_expression_dec_ref(self->start);
     621        bithenge_expression_dec_ref(self->limit);
     622        free(self);
     623}
     624
     625static const bithenge_expression_ops_t subblob_expression_ops = {
     626        .evaluate = subblob_expression_evaluate,
     627        .destroy = subblob_expression_destroy,
     628};
     629
     630/** Create an expression that gets a subblob. Takes references to @a blob,
     631 * @a start, and @a limit.
     632 * @param[out] out Holds the new expression.
     633 * @param blob Calculates the blob.
     634 * @param start Calculates the start offset within the blob.
     635 * @param limit Calculates the limit. Can be NULL, in which case an offset blob
     636 * is returned.
     637 * @param absolute_limit If true, the limit is an absolute offset; otherwise,
     638 * it is relative to the start.
     639 * @return EOK on success or an error code from errno.h. */
     640int bithenge_subblob_expression(bithenge_expression_t **out,
     641    bithenge_expression_t *blob, bithenge_expression_t *start,
     642    bithenge_expression_t *limit, bool absolute_limit)
     643{
     644        int rc;
     645        subblob_expression_t *self = malloc(sizeof(*self));
     646        if (!self) {
     647                rc = ENOMEM;
     648                goto error;
     649        }
     650
     651        rc = bithenge_init_expression(subblob_as_expression(self),
     652            &subblob_expression_ops);
     653        if (rc != EOK)
     654                goto error;
     655
     656        self->blob = blob;
     657        self->start = start;
     658        self->limit = limit;
     659        self->absolute_limit = absolute_limit;
     660        *out = subblob_as_expression(self);
     661        return EOK;
     662
     663error:
     664        bithenge_expression_dec_ref(blob);
     665        bithenge_expression_dec_ref(start);
     666        bithenge_expression_dec_ref(limit);
     667        free(self);
     668        return rc;
     669}
     670
    547671/***************** param_wrapper                             *****************/
    548672
Note: See TracChangeset for help on using the changeset viewer.