Changeset c3437d9 in mainline for uspace/app/bithenge/sequence.c


Ignore:
Timestamp:
2012-08-04T03:51:15Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0ce0103
Parents:
e3f2765
Message:

Bithenge: add do{}while() transforms

File:
1 edited

Legend:

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

    re3f2765 rc3437d9  
    4444
    4545
     46/***************** seq_node                                  *****************/
     47
    4648typedef struct {
    4749        bithenge_node_t base;
     
    236238        bithenge_blob_dec_ref(self->blob);
    237239        free(self->ends);
     240}
     241
     242static void seq_node_set_num_xforms(seq_node_t *self,
     243    bithenge_int_t num_xforms)
     244{
     245        self->num_xforms = num_xforms;
    238246}
    239247
     
    270278
    271279
     280/***************** bithenge_new_struct                       *****************/
     281
    272282typedef struct {
    273283        bithenge_transform_t base;
     
    581591
    582592
     593/***************** bithenge_repeat_transform                 *****************/
     594
    583595typedef struct {
    584596        bithenge_transform_t base;
     
    636648                rc = seq_node_subtransform(repeat_as_seq(self),
    637649                    &subxform_result, i);
    638                 if (rc != EOK && self->count == -1) {
     650                if ((rc == EINVAL || rc == ENOENT) && self->count == -1) {
     651                        self->count = i;
     652                        seq_node_set_num_xforms(repeat_as_seq(self),
     653                            self->count);
    639654                        rc = EOK;
    640655                        break;
     
    845860}
    846861
     862
     863
     864/***************** bithenge_do_while_transform               *****************/
     865
     866typedef struct {
     867        bithenge_transform_t base;
     868        bithenge_expression_t *expr;
     869        bithenge_transform_t *xform;
     870} do_while_transform_t;
     871
     872static inline bithenge_transform_t *do_while_as_transform(
     873    do_while_transform_t *self)
     874{
     875        return &self->base;
     876}
     877
     878static inline do_while_transform_t *transform_as_do_while(
     879    bithenge_transform_t *base)
     880{
     881        return (do_while_transform_t *)base;
     882}
     883
     884typedef struct {
     885        seq_node_t base;
     886        bool prefix;
     887        bithenge_expression_t *expr;
     888        bithenge_transform_t *xform;
     889        bithenge_int_t count;
     890} do_while_node_t;
     891
     892static seq_node_t *do_while_as_seq(do_while_node_t *self)
     893{
     894        return &self->base;
     895}
     896
     897static do_while_node_t *seq_as_do_while(seq_node_t *base)
     898{
     899        return (do_while_node_t *)base;
     900}
     901
     902static bithenge_node_t *do_while_as_node(do_while_node_t *self)
     903{
     904        return seq_as_node(do_while_as_seq(self));
     905}
     906
     907static do_while_node_t *node_as_do_while(bithenge_node_t *base)
     908{
     909        return seq_as_do_while(node_as_seq(base));
     910}
     911
     912static int do_while_node_for_each(bithenge_node_t *base,
     913    bithenge_for_each_func_t func, void *data)
     914{
     915        int rc = EOK;
     916        do_while_node_t *self = node_as_do_while(base);
     917
     918        for (bithenge_int_t i = 0; ; i++) {
     919                bithenge_node_t *subxform_result;
     920                rc = seq_node_subtransform(do_while_as_seq(self),
     921                    &subxform_result, i);
     922                if (rc != EOK)
     923                        return rc;
     924
     925                bithenge_node_t *key_node;
     926                rc = bithenge_new_integer_node(&key_node, i);
     927                if (rc != EOK) {
     928                        bithenge_node_dec_ref(subxform_result);
     929                        return rc;
     930                }
     931                bithenge_node_inc_ref(subxform_result);
     932                rc = func(key_node, subxform_result, data);
     933                if (rc != EOK) {
     934                        bithenge_node_dec_ref(subxform_result);
     935                        return rc;
     936                }
     937
     938                bithenge_scope_t scope;
     939                bithenge_scope_init(&scope);
     940                rc = bithenge_scope_copy(&scope,
     941                    seq_node_scope(do_while_as_seq(self)));
     942                bithenge_scope_set_current_node(&scope, subxform_result);
     943                if (rc != EOK) {
     944                        bithenge_scope_destroy(&scope);
     945                        return rc;
     946                }
     947                bithenge_node_t *expr_result;
     948                rc = bithenge_expression_evaluate(self->expr, &scope,
     949                    &expr_result);
     950                bithenge_scope_destroy(&scope);
     951                if (rc != EOK)
     952                        return rc;
     953                if (bithenge_node_type(expr_result) != BITHENGE_NODE_BOOLEAN) {
     954                        bithenge_node_dec_ref(expr_result);
     955                        return EINVAL;
     956                }
     957                bool cond = bithenge_boolean_node_value(expr_result);
     958                bithenge_node_dec_ref(expr_result);
     959                if (!cond) {
     960                        self->count = i + 1;
     961                        seq_node_set_num_xforms(do_while_as_seq(self),
     962                            self->count);
     963                        break;
     964                }
     965        }
     966
     967        if (!self->prefix) {
     968                bool complete;
     969                rc = seq_node_complete(do_while_as_seq(self), &complete);
     970                if (rc != EOK)
     971                        return rc;
     972                if (!complete)
     973                        return EINVAL;
     974        }
     975
     976        return rc;
     977}
     978
     979static void do_while_node_destroy(bithenge_node_t *base)
     980{
     981        do_while_node_t *self = node_as_do_while(base);
     982        seq_node_destroy(do_while_as_seq(self));
     983        bithenge_expression_dec_ref(self->expr);
     984        bithenge_transform_dec_ref(self->xform);
     985        free(self);
     986}
     987
     988static const bithenge_internal_node_ops_t do_while_node_ops = {
     989        .for_each = do_while_node_for_each,
     990        .destroy = do_while_node_destroy,
     991};
     992
     993static int do_while_node_get_transform(seq_node_t *base,
     994    bithenge_transform_t **out, bithenge_int_t index)
     995{
     996        do_while_node_t *self = seq_as_do_while(base);
     997        *out = self->xform;
     998        bithenge_transform_inc_ref(*out);
     999        return EOK;
     1000}
     1001
     1002static const seq_node_ops_t do_while_node_seq_ops = {
     1003        .get_transform = do_while_node_get_transform,
     1004};
     1005
     1006static int do_while_transform_make_node(do_while_transform_t *self,
     1007    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
     1008    bool prefix)
     1009{
     1010        do_while_node_t *node = malloc(sizeof(*node));
     1011        if (!node)
     1012                return ENOMEM;
     1013
     1014        int rc = bithenge_init_internal_node(do_while_as_node(node),
     1015            &do_while_node_ops);
     1016        if (rc != EOK) {
     1017                free(node);
     1018                return rc;
     1019        }
     1020
     1021        rc = seq_node_init(do_while_as_seq(node), &do_while_node_seq_ops,
     1022            scope, blob, -1, false);
     1023        if (rc != EOK) {
     1024                free(node);
     1025                return rc;
     1026        }
     1027
     1028        bithenge_transform_inc_ref(self->xform);
     1029        node->xform = self->xform;
     1030        bithenge_expression_inc_ref(self->expr);
     1031        node->expr = self->expr;
     1032        node->prefix = prefix;
     1033        node->count = -1;
     1034        *out = do_while_as_node(node);
     1035        return EOK;
     1036}
     1037
     1038static int do_while_transform_apply(bithenge_transform_t *base,
     1039    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     1040{
     1041        do_while_transform_t *self = transform_as_do_while(base);
     1042        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     1043                return EINVAL;
     1044        return do_while_transform_make_node(self, out, scope,
     1045            bithenge_node_as_blob(in), false);
     1046}
     1047
     1048static int for_each_noop(bithenge_node_t *key, bithenge_node_t *value,
     1049    void *data)
     1050{
     1051        bithenge_node_dec_ref(key);
     1052        bithenge_node_dec_ref(value);
     1053        return EOK;
     1054}
     1055
     1056static int do_while_transform_prefix_apply(bithenge_transform_t *base,
     1057    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
     1058    aoff64_t *out_size)
     1059{
     1060        do_while_transform_t *self = transform_as_do_while(base);
     1061        int rc = do_while_transform_make_node(self, out_node, scope, blob,
     1062            true);
     1063        if (rc != EOK)
     1064                return rc;
     1065
     1066        rc = bithenge_node_for_each(*out_node, for_each_noop, NULL);
     1067        if (rc != EOK) {
     1068                bithenge_node_dec_ref(*out_node);
     1069                return rc;
     1070        }
     1071
     1072        rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
     1073            node_as_do_while(*out_node)->count);
     1074        if (rc != EOK) {
     1075                bithenge_node_dec_ref(*out_node);
     1076                return rc;
     1077        }
     1078
     1079        return EOK;
     1080}
     1081
     1082static void do_while_transform_destroy(bithenge_transform_t *base)
     1083{
     1084        do_while_transform_t *self = transform_as_do_while(base);
     1085        bithenge_transform_dec_ref(self->xform);
     1086        bithenge_expression_dec_ref(self->expr);
     1087        free(self);
     1088}
     1089
     1090static const bithenge_transform_ops_t do_while_transform_ops = {
     1091        .apply = do_while_transform_apply,
     1092        .prefix_apply = do_while_transform_prefix_apply,
     1093        .destroy = do_while_transform_destroy,
     1094};
     1095
     1096/** Create a transform that applies its subtransform while an expression on the
     1097 * result returns true. Takes a reference to @a xform and @a expr.
     1098 * @param[out] out Holds the new transform.
     1099 * @param xform The subtransform to apply repeatedly.
     1100 * @param expr Applied in the result of each application of @a xform to
     1101 * determine whether there will be more.
     1102 * @return EOK on success or an error code from errno.h. */
     1103int bithenge_do_while_transform(bithenge_transform_t **out,
     1104    bithenge_transform_t *xform, bithenge_expression_t *expr)
     1105{
     1106        int rc;
     1107        do_while_transform_t *self = malloc(sizeof(*self));
     1108        if (!self) {
     1109                rc = ENOMEM;
     1110                goto error;
     1111        }
     1112
     1113        rc = bithenge_init_transform(do_while_as_transform(self),
     1114            &do_while_transform_ops, 0);
     1115        if (rc != EOK)
     1116                goto error;
     1117
     1118        self->expr = expr;
     1119        self->xform = xform;
     1120        *out = do_while_as_transform(self);
     1121        return EOK;
     1122
     1123error:
     1124        free(self);
     1125        bithenge_expression_dec_ref(expr);
     1126        bithenge_transform_dec_ref(xform);
     1127        return rc;
     1128}
     1129
    8471130/** @}
    8481131 */
Note: See TracChangeset for help on using the changeset viewer.