Changeset 5e718d9 in mainline for uspace/lib/bithenge/expression.c


Ignore:
Timestamp:
2012-08-21T10:04:16Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
67edca6
Parents:
0da6c04 (diff), 6a97f2e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with upstream (lp:~wtachi/helenos/bithenge)

File:
1 moved

Legend:

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

    r0da6c04 r5e718d9  
    4040#include "blob.h"
    4141#include "expression.h"
     42#include "os.h"
    4243#include "transform.h"
    4344#include "tree.h"
     
    5354        assert(ops->evaluate);
    5455        assert(ops->destroy);
     56        if (bithenge_should_fail())
     57                return ENOMEM;
    5558        self->ops = ops;
    5659        self->refs = 1;
     
    8891    bithenge_scope_t *scope, bithenge_node_t **out)
    8992{
     93        int rc;
    9094        binary_expression_t *self = expression_as_binary(base);
    9195        bithenge_node_t *a, *b;
    92         int rc = bithenge_expression_evaluate(self->a, scope, &a);
     96        rc = bithenge_expression_evaluate(self->a, scope, &a);
    9397        if (rc != EOK)
    9498                return rc;
    95         rc = bithenge_expression_evaluate(self->b, scope, &b);
    96         if (rc != EOK) {
    97                 bithenge_node_dec_ref(a);
    98                 return rc;
     99        if (self->op != BITHENGE_EXPRESSION_CONCAT) {
     100                rc = bithenge_expression_evaluate(self->b, scope, &b);
     101                if (rc != EOK) {
     102                        bithenge_node_dec_ref(a);
     103                        return rc;
     104                }
    99105        }
    100106
     
    102108        /* Assigning 0 only to make the compiler happy. */
    103109        bithenge_int_t a_int = 0, b_int = 0;
     110        bool a_bool = false, b_bool = false, out_bool = false;
    104111        switch (self->op) {
    105112        case BITHENGE_EXPRESSION_ADD: /* fallthrough */
    106113        case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
    107         case BITHENGE_EXPRESSION_MULTIPLY:
     114        case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
     115        case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */
     116        case BITHENGE_EXPRESSION_MODULO: /* fallthrough */
     117        case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */
     118        case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */
     119        case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */
     120        case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
    108121                rc = EINVAL;
    109122                if (bithenge_node_type(a) != BITHENGE_NODE_INTEGER)
     
    114127                b_int = bithenge_integer_node_value(b);
    115128                break;
     129        case BITHENGE_EXPRESSION_AND: /* fallthrough */
     130        case BITHENGE_EXPRESSION_OR:
     131                rc = EINVAL;
     132                if (bithenge_node_type(a) != BITHENGE_NODE_BOOLEAN)
     133                        goto error;
     134                if (bithenge_node_type(b) != BITHENGE_NODE_BOOLEAN)
     135                        goto error;
     136                a_bool = bithenge_boolean_node_value(a);
     137                b_bool = bithenge_boolean_node_value(b);
     138                break;
     139        case BITHENGE_EXPRESSION_CONCAT:
     140                if (bithenge_node_type(a) != BITHENGE_NODE_BLOB)
     141                        goto error;
     142                break;
    116143        default:
    117144                break;
     
    128155                rc = bithenge_new_integer_node(out, a_int * b_int);
    129156                break;
     157        case BITHENGE_EXPRESSION_INTEGER_DIVIDE:
     158                /* Integer division can behave in three major ways when the
     159                  operands are signed: truncated, floored, or Euclidean. When
     160                 * b > 0, we give the same result as floored and Euclidean;
     161                 * otherwise, we currently raise an error. See
     162                 * https://en.wikipedia.org/wiki/Modulo_operation and its
     163                 * references. */
     164                if (b_int <= 0) {
     165                        rc = EINVAL;
     166                        break;
     167                }
     168                rc = bithenge_new_integer_node(out,
     169                    (a_int / b_int) + (a_int % b_int < 0 ? -1 : 0));
     170                break;
     171        case BITHENGE_EXPRESSION_MODULO:
     172                /* This is consistent with division; see above. */
     173                if (b_int <= 0) {
     174                        rc = EINVAL;
     175                        break;
     176                }
     177                rc = bithenge_new_integer_node(out,
     178                    (a_int % b_int) + (a_int % b_int < 0 ? b_int : 0));
     179                break;
     180        case BITHENGE_EXPRESSION_LESS_THAN:
     181                rc = bithenge_new_boolean_node(out, a_int < b_int);
     182                break;
     183        case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL:
     184                rc = bithenge_new_boolean_node(out, a_int <= b_int);
     185                break;
     186        case BITHENGE_EXPRESSION_GREATER_THAN:
     187                rc = bithenge_new_boolean_node(out, a_int > b_int);
     188                break;
     189        case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
     190                rc = bithenge_new_boolean_node(out, a_int >= b_int);
     191                break;
    130192        case BITHENGE_EXPRESSION_EQUALS:
    131                 rc = bithenge_new_boolean_node(out, bithenge_node_equal(a, b));
     193                rc = bithenge_node_equal(&out_bool, a, b);
     194                if (rc != EOK)
     195                        break;
     196                rc = bithenge_new_boolean_node(out, out_bool);
     197                break;
     198        case BITHENGE_EXPRESSION_NOT_EQUALS:
     199                rc = bithenge_node_equal(&out_bool, a, b);
     200                if (rc != EOK)
     201                        break;
     202                rc = bithenge_new_boolean_node(out, !out_bool);
     203                break;
     204        case BITHENGE_EXPRESSION_AND:
     205                rc = bithenge_new_boolean_node(out, a_bool && b_bool);
     206                break;
     207        case BITHENGE_EXPRESSION_OR:
     208                rc = bithenge_new_boolean_node(out, a_bool || b_bool);
     209                break;
     210        case BITHENGE_EXPRESSION_MEMBER:
     211                rc = bithenge_node_get(a, b, out);
     212                b = NULL;
     213                break;
     214        case BITHENGE_EXPRESSION_CONCAT:
     215                bithenge_expression_inc_ref(self->b);
     216                bithenge_scope_inc_ref(scope);
     217                rc = bithenge_concat_blob_lazy(out, bithenge_node_as_blob(a),
     218                    self->b, scope);
     219                a = NULL;
     220                b = NULL;
    132221                break;
    133222        case BITHENGE_EXPRESSION_INVALID_BINARY_OP:
     
    197286    bithenge_scope_t *scope, bithenge_node_t **out)
    198287{
    199         for (; scope && !bithenge_scope_is_barrier(scope);
    200             scope = bithenge_scope_outer(scope)) {
     288        for (; scope; scope = bithenge_scope_outer(scope)) {
    201289                *out = bithenge_scope_in_node(scope);
    202290                if (*out)
     
    220308int bithenge_in_node_expression(bithenge_expression_t **out)
    221309{
     310        if (bithenge_should_fail())
     311                return ENOMEM;
    222312        bithenge_expression_inc_ref(&in_node_expression);
    223313        *out = &in_node_expression;
     
    392482
    393483
    394 /***************** member_expression                         *****************/
    395 
    396 typedef struct {
    397         bithenge_expression_t base;
    398         bithenge_expression_t *expr;
    399         bithenge_node_t *key;
    400 } member_expression_t;
    401 
    402 static member_expression_t *expression_as_member(bithenge_expression_t *base)
    403 {
    404         return (member_expression_t *)base;
    405 }
    406 
    407 static bithenge_expression_t *member_as_expression(member_expression_t *expr)
    408 {
    409         return &expr->base;
    410 }
    411 
    412 static int member_expression_evaluate(bithenge_expression_t *base,
    413     bithenge_scope_t *scope, bithenge_node_t **out)
    414 {
    415         member_expression_t *self = expression_as_member(base);
    416         bithenge_node_t *node;
    417         int rc = bithenge_expression_evaluate(self->expr, scope, &node);
    418         if (rc != EOK)
    419                 return rc;
    420         bithenge_node_inc_ref(self->key);
    421         rc = bithenge_node_get(node, self->key, out);
    422         bithenge_node_dec_ref(node);
    423         return rc;
    424 }
    425 
    426 static void member_expression_destroy(bithenge_expression_t *base)
    427 {
    428         member_expression_t *self = expression_as_member(base);
    429         bithenge_expression_dec_ref(self->expr);
    430         bithenge_node_dec_ref(self->key);
    431         free(self);
    432 }
    433 
    434 static const bithenge_expression_ops_t member_expression_ops = {
    435         .evaluate = member_expression_evaluate,
    436         .destroy = member_expression_destroy,
    437 };
    438 
    439 /** Create an expression that gets a member from a node. Takes references to
    440  * @a expr and @a key.
    441  * @param[out] out Holds the new expression.
    442  * @param expr Calculates the node to get the member of.
    443  * @param key The member to get.
    444  * @return EOK on success or an error code from errno.h. */
    445 int bithenge_member_expression(bithenge_expression_t **out,
    446     bithenge_expression_t *expr, bithenge_node_t *key)
    447 {
    448         int rc;
    449         member_expression_t *self = malloc(sizeof(*self));
    450         if (!self) {
    451                 rc = ENOMEM;
    452                 goto error;
    453         }
    454 
    455         rc = bithenge_init_expression(member_as_expression(self),
    456             &member_expression_ops);
    457         if (rc != EOK)
    458                 goto error;
    459 
    460         self->expr = expr;
    461         self->key = key;
    462         *out = member_as_expression(self);
    463         return EOK;
    464 
    465 error:
    466         bithenge_expression_dec_ref(expr);
    467         bithenge_node_dec_ref(key);
    468         free(self);
    469         return rc;
    470 }
    471 
    472 
    473 
    474484/***************** scope_member_expression                   *****************/
    475485
     
    497507        for (; scope && !bithenge_scope_is_barrier(scope);
    498508            scope = bithenge_scope_outer(scope)) {
     509                bithenge_node_t *cur = bithenge_scope_get_current_node(scope);
     510                if (!cur)
     511                        continue;
    499512                bithenge_node_inc_ref(self->key);
    500                 bithenge_node_t *cur = bithenge_scope_get_current_node(scope);
    501513                int rc = bithenge_node_get(cur, self->key, out);
    502514                bithenge_node_dec_ref(cur);
     
    504516                        return rc;
    505517        }
    506         return ENOENT;
     518        return bithenge_scope_error(scope, "No scope member %t", self->key);
    507519}
    508520
     
    519531};
    520532
     533/** Create an expression that gets a member from one of the current nodes being
     534 * created. It searches from the current scope outwards, stopping at barrier
     535 * scopes.
     536 * @param[out] out Holds the new expression.
     537 * @param key The key to search for in nodes being created.
     538 * @return EOK on success or an error code from errno.h. */
    521539int bithenge_scope_member_expression(bithenge_expression_t **out,
    522540    bithenge_node_t *key)
     
    545563
    546564
     565
     566/***************** subblob_expression                        *****************/
     567
     568typedef struct {
     569        bithenge_expression_t base;
     570        bithenge_expression_t *blob, *start, *limit;
     571        bool absolute_limit;
     572} subblob_expression_t;
     573
     574static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base)
     575{
     576        return (subblob_expression_t *)base;
     577}
     578
     579static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr)
     580{
     581        return &expr->base;
     582}
     583
     584static int subblob_expression_evaluate(bithenge_expression_t *base,
     585    bithenge_scope_t *scope, bithenge_node_t **out)
     586{
     587        subblob_expression_t *self = expression_as_subblob(base);
     588        bithenge_node_t *start_node;
     589        int rc = bithenge_expression_evaluate(self->start, scope, &start_node);
     590        if (rc != EOK)
     591                return rc;
     592        if (bithenge_node_type(start_node) != BITHENGE_NODE_INTEGER) {
     593                bithenge_node_dec_ref(start_node);
     594                return EINVAL;
     595        }
     596        bithenge_int_t start = bithenge_integer_node_value(start_node);
     597        bithenge_node_dec_ref(start_node);
     598
     599        bithenge_int_t limit = -1;
     600        if (self->limit) {
     601                bithenge_node_t *limit_node;
     602                rc = bithenge_expression_evaluate(self->limit, scope,
     603                    &limit_node);
     604                if (rc != EOK)
     605                        return rc;
     606                if (bithenge_node_type(limit_node) != BITHENGE_NODE_INTEGER) {
     607                        bithenge_node_dec_ref(limit_node);
     608                        return EINVAL;
     609                }
     610                limit = bithenge_integer_node_value(limit_node);
     611                bithenge_node_dec_ref(limit_node);
     612                if (self->absolute_limit)
     613                        limit -= start;
     614        }
     615
     616        if (start < 0 || (self->limit && limit < 0))
     617                return EINVAL;
     618
     619        bithenge_node_t *blob;
     620        rc = bithenge_expression_evaluate(self->blob, scope, &blob);
     621        if (rc != EOK)
     622                return rc;
     623        if (bithenge_node_type(blob) != BITHENGE_NODE_BLOB) {
     624                bithenge_node_dec_ref(blob);
     625                return EINVAL;
     626        }
     627
     628        if (self->limit)
     629                return bithenge_new_subblob(out, bithenge_node_as_blob(blob),
     630                    start, limit);
     631        else
     632                return bithenge_new_offset_blob(out,
     633                    bithenge_node_as_blob(blob), start);
     634}
     635
     636static void subblob_expression_destroy(bithenge_expression_t *base)
     637{
     638        subblob_expression_t *self = expression_as_subblob(base);
     639        bithenge_expression_dec_ref(self->blob);
     640        bithenge_expression_dec_ref(self->start);
     641        bithenge_expression_dec_ref(self->limit);
     642        free(self);
     643}
     644
     645static const bithenge_expression_ops_t subblob_expression_ops = {
     646        .evaluate = subblob_expression_evaluate,
     647        .destroy = subblob_expression_destroy,
     648};
     649
     650/** Create an expression that gets a subblob. Takes references to @a blob,
     651 * @a start, and @a limit.
     652 * @param[out] out Holds the new expression.
     653 * @param blob Calculates the blob.
     654 * @param start Calculates the start offset within the blob.
     655 * @param limit Calculates the limit. Can be NULL, in which case an offset blob
     656 * is returned.
     657 * @param absolute_limit If true, the limit is an absolute offset; otherwise,
     658 * it is relative to the start.
     659 * @return EOK on success or an error code from errno.h. */
     660int bithenge_subblob_expression(bithenge_expression_t **out,
     661    bithenge_expression_t *blob, bithenge_expression_t *start,
     662    bithenge_expression_t *limit, bool absolute_limit)
     663{
     664        int rc;
     665        subblob_expression_t *self = malloc(sizeof(*self));
     666        if (!self) {
     667                rc = ENOMEM;
     668                goto error;
     669        }
     670
     671        rc = bithenge_init_expression(subblob_as_expression(self),
     672            &subblob_expression_ops);
     673        if (rc != EOK)
     674                goto error;
     675
     676        self->blob = blob;
     677        self->start = start;
     678        self->limit = limit;
     679        self->absolute_limit = absolute_limit;
     680        *out = subblob_as_expression(self);
     681        return EOK;
     682
     683error:
     684        bithenge_expression_dec_ref(blob);
     685        bithenge_expression_dec_ref(start);
     686        bithenge_expression_dec_ref(limit);
     687        free(self);
     688        return rc;
     689}
    547690
    548691/***************** param_wrapper                             *****************/
     
    798941{
    799942        expression_transform_t *self = transform_as_expression(base);
    800         *out_size = 0;
     943        if (out_size)
     944                *out_size = 0;
    801945        return bithenge_expression_evaluate(self->expr, scope, out_node);
    802946}
     
    840984
    841985
    842 /***************** if_transform                              *****************/
     986/***************** concat_blob                    *****************/
    843987
    844988typedef struct {
    845         bithenge_transform_t base;
    846         bithenge_expression_t *expr;
    847         bithenge_transform_t *true_xform, *false_xform;
    848 } if_transform_t;
    849 
    850 static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
    851 {
    852         return &self->base;
    853 }
    854 
    855 static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
    856 {
    857         return (if_transform_t *)base;
    858 }
    859 
    860 static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
    861     bool *out)
    862 {
    863         bithenge_node_t *cond_node;
    864         int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
     989        bithenge_blob_t base;
     990        bithenge_blob_t *a, *b;
     991        aoff64_t a_size;
     992        bithenge_expression_t *b_expr;
     993        bithenge_scope_t *scope;
     994} concat_blob_t;
     995
     996static inline concat_blob_t *blob_as_concat(bithenge_blob_t *base)
     997{
     998        return (concat_blob_t *)base;
     999}
     1000
     1001static inline bithenge_blob_t *concat_as_blob(concat_blob_t *blob)
     1002{
     1003        return &blob->base;
     1004}
     1005
     1006static int concat_blob_evaluate_b(concat_blob_t *self)
     1007{
     1008        if (self->b)
     1009                return EOK;
     1010        bithenge_node_t *b_node;
     1011        int rc = bithenge_expression_evaluate(self->b_expr, self->scope,
     1012            &b_node);
    8651013        if (rc != EOK)
    8661014                return rc;
    867         if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
    868                 bithenge_node_dec_ref(cond_node);
    869                 return EINVAL;
    870         }
    871         *out = bithenge_boolean_node_value(cond_node);
    872         bithenge_node_dec_ref(cond_node);
    873         return EOK;
    874 }
    875 
    876 static int if_transform_apply(bithenge_transform_t *base,
    877     bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
    878 {
    879         if_transform_t *self = transform_as_if(base);
    880         bool cond;
    881         int rc = if_transform_choose(self, scope, &cond);
     1015        if (bithenge_node_type(b_node) != BITHENGE_NODE_BLOB) {
     1016                bithenge_node_dec_ref(b_node);
     1017                return bithenge_scope_error(self->scope,
     1018                    "Concatenation arguments must be blobs");
     1019        }
     1020        self->b = bithenge_node_as_blob(b_node);
     1021        bithenge_expression_dec_ref(self->b_expr);
     1022        bithenge_scope_dec_ref(self->scope);
     1023        self->b_expr = NULL;
     1024        self->scope = NULL;
     1025        return EOK;
     1026}
     1027
     1028static int concat_blob_size(bithenge_blob_t *base, aoff64_t *size)
     1029{
     1030        concat_blob_t *self = blob_as_concat(base);
     1031        int rc = concat_blob_evaluate_b(self);
    8821032        if (rc != EOK)
    8831033                return rc;
    884         return bithenge_transform_apply(
    885             cond ? self->true_xform : self->false_xform, scope, in, out);
    886 }
    887 
    888 static int if_transform_prefix_length(bithenge_transform_t *base,
    889     bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
    890 {
    891         if_transform_t *self = transform_as_if(base);
    892         bool cond;
    893         int rc = if_transform_choose(self, scope, &cond);
    894         if (rc != EOK)
    895                 return rc;
    896         return bithenge_transform_prefix_length(
    897             cond ? self->true_xform : self->false_xform, scope, in, out);
    898 }
    899 
    900 static void if_transform_destroy(bithenge_transform_t *base)
    901 {
    902         if_transform_t *self = transform_as_if(base);
    903         bithenge_expression_dec_ref(self->expr);
    904         bithenge_transform_dec_ref(self->true_xform);
    905         bithenge_transform_dec_ref(self->false_xform);
    906         free(self);
    907 }
    908 
    909 static const bithenge_transform_ops_t if_transform_ops = {
    910         .apply = if_transform_apply,
    911         .prefix_length = if_transform_prefix_length,
    912         .destroy = if_transform_destroy,
     1034        rc = bithenge_blob_size(self->b, size);
     1035        *size += self->a_size;
     1036        return rc;
     1037}
     1038
     1039static int concat_blob_read(bithenge_blob_t *base, aoff64_t offset,
     1040    char *buffer, aoff64_t *size)
     1041{
     1042        int rc;
     1043        concat_blob_t *self = blob_as_concat(base);
     1044
     1045        aoff64_t a_size = 0, b_size = 0;
     1046        if (offset < self->a_size) {
     1047                a_size = *size;
     1048                rc = bithenge_blob_read(self->a, offset, buffer, &a_size);
     1049                if (rc != EOK)
     1050                        return rc;
     1051        }
     1052        if (offset + *size > self->a_size) {
     1053                rc = concat_blob_evaluate_b(self);
     1054                if (rc != EOK)
     1055                        return rc;
     1056                b_size = *size - a_size;
     1057                rc = bithenge_blob_read(self->b,
     1058                    offset + a_size - self->a_size, buffer + a_size, &b_size);
     1059                if (rc != EOK)
     1060                        return rc;
     1061        }
     1062        assert(a_size + b_size <= *size);
     1063        *size = a_size + b_size;
     1064        return EOK;
     1065}
     1066
     1067static int concat_blob_read_bits(bithenge_blob_t *base, aoff64_t offset,
     1068    char *buffer, aoff64_t *size, bool little_endian)
     1069{
     1070        int rc;
     1071        concat_blob_t *self = blob_as_concat(base);
     1072
     1073        aoff64_t a_size = 0, b_size = 0;
     1074        if (offset < self->a_size) {
     1075                a_size = *size;
     1076                rc = bithenge_blob_read_bits(self->a, offset, buffer, &a_size,
     1077                    little_endian);
     1078                if (rc != EOK)
     1079                        return rc;
     1080        }
     1081        if (offset + *size > self->a_size) {
     1082                rc = concat_blob_evaluate_b(self);
     1083                if (rc != EOK)
     1084                        return rc;
     1085                b_size = *size - a_size;
     1086                assert(a_size % 8 == 0); /* TODO: don't require this */
     1087                rc = bithenge_blob_read_bits(self->b,
     1088                    offset + a_size - self->a_size, buffer + a_size / 8,
     1089                    &b_size, little_endian);
     1090                if (rc != EOK)
     1091                        return rc;
     1092        }
     1093        assert(a_size + b_size <= *size);
     1094        *size = a_size + b_size;
     1095        return EOK;
     1096}
     1097
     1098static void concat_blob_destroy(bithenge_blob_t *base)
     1099{
     1100        concat_blob_t *self = blob_as_concat(base);
     1101        bithenge_blob_dec_ref(self->a);
     1102        bithenge_blob_dec_ref(self->b);
     1103        bithenge_expression_dec_ref(self->b_expr);
     1104        bithenge_scope_dec_ref(self->scope);
     1105        free(self);
     1106}
     1107
     1108static const bithenge_random_access_blob_ops_t concat_blob_ops = {
     1109        .size = concat_blob_size,
     1110        .read = concat_blob_read,
     1111        .read_bits = concat_blob_read_bits,
     1112        .destroy = concat_blob_destroy,
    9131113};
    9141114
    915 /** Create a transform that applies either of two transforms depending on a
    916  * boolean expression. Takes references to @a expr, @a true_xform, and
    917  * @a false_xform.
    918  * @param[out] out Holds the new transform.
    919  * @param expr The boolean expression to evaluate.
    920  * @param true_xform The transform to apply if the expression is true.
    921  * @param false_xform The transform to apply if the expression is false.
     1115/** Create a concatenated blob. Takes references to @a a and @a b.
     1116 * @param[out] out Holds the new blob.
     1117 * @param a The first blob.
     1118 * @param b The second blob.
    9221119 * @return EOK on success or an error code from errno.h. */
    923 int bithenge_if_transform(bithenge_transform_t **out,
    924     bithenge_expression_t *expr, bithenge_transform_t *true_xform,
    925     bithenge_transform_t *false_xform)
    926 {
    927         int rc;
    928         if_transform_t *self = malloc(sizeof(*self));
     1120int bithenge_concat_blob(bithenge_node_t **out, bithenge_blob_t *a,
     1121    bithenge_blob_t *b)
     1122{
     1123        assert(out);
     1124        assert(a);
     1125        assert(b);
     1126        int rc;
     1127        concat_blob_t *self = malloc(sizeof(*self));
    9291128        if (!self) {
    9301129                rc = ENOMEM;
     
    9321131        }
    9331132
    934         rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
    935             0);
    936         if (rc != EOK)
    937                 goto error;
    938 
    939         self->expr = expr;
    940         self->true_xform = true_xform;
    941         self->false_xform = false_xform;
    942         *out = if_as_transform(self);
     1133        rc = bithenge_blob_size(a, &self->a_size);
     1134        if (rc != EOK)
     1135                goto error;
     1136
     1137        rc = bithenge_init_random_access_blob(concat_as_blob(self),
     1138            &concat_blob_ops);
     1139        if (rc != EOK)
     1140                goto error;
     1141        self->a = a;
     1142        self->b = b;
     1143        self->b_expr = NULL;
     1144        self->scope = NULL;
     1145        *out = bithenge_blob_as_node(concat_as_blob(self));
    9431146        return EOK;
    9441147
    9451148error:
    946         free(self);
    947         bithenge_expression_dec_ref(expr);
    948         bithenge_transform_dec_ref(true_xform);
    949         bithenge_transform_dec_ref(false_xform);
     1149        bithenge_blob_dec_ref(a);
     1150        bithenge_blob_dec_ref(b);
     1151        free(self);
     1152        return rc;
     1153}
     1154
     1155/** Create a lazy concatenated blob. Takes references to @a a, @a b_expr, and
     1156 * @a scope.
     1157 * @param[out] out Holds the new blob.
     1158 * @param a The first blob.
     1159 * @param b_expr An expression to calculate the second blob.
     1160 * @param scope The scope in which @a b_expr should be evaluated.
     1161 * @return EOK on success or an error code from errno.h. */
     1162int bithenge_concat_blob_lazy(bithenge_node_t **out, bithenge_blob_t *a,
     1163    bithenge_expression_t *b_expr, bithenge_scope_t *scope)
     1164{
     1165        assert(out);
     1166        assert(a);
     1167        assert(b_expr);
     1168        assert(scope);
     1169        int rc;
     1170        concat_blob_t *self = malloc(sizeof(*self));
     1171        if (!self) {
     1172                rc = ENOMEM;
     1173                goto error;
     1174        }
     1175
     1176        rc = bithenge_blob_size(a, &self->a_size);
     1177        if (rc != EOK)
     1178                goto error;
     1179
     1180        rc = bithenge_init_random_access_blob(concat_as_blob(self),
     1181            &concat_blob_ops);
     1182        if (rc != EOK)
     1183                goto error;
     1184        self->a = a;
     1185        self->b = NULL;
     1186        self->b_expr = b_expr;
     1187        self->scope = scope;
     1188        *out = bithenge_blob_as_node(concat_as_blob(self));
     1189        return EOK;
     1190
     1191error:
     1192        bithenge_blob_dec_ref(a);
     1193        bithenge_expression_dec_ref(b_expr);
     1194        bithenge_scope_dec_ref(scope);
     1195        free(self);
    9501196        return rc;
    9511197}
Note: See TracChangeset for help on using the changeset viewer.