Changeset 5e718d9 in mainline for uspace/lib/bithenge/expression.c
- Timestamp:
- 2012-08-21T10:04:16Z (12 years ago)
- 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. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/bithenge/expression.c
r0da6c04 r5e718d9 40 40 #include "blob.h" 41 41 #include "expression.h" 42 #include "os.h" 42 43 #include "transform.h" 43 44 #include "tree.h" … … 53 54 assert(ops->evaluate); 54 55 assert(ops->destroy); 56 if (bithenge_should_fail()) 57 return ENOMEM; 55 58 self->ops = ops; 56 59 self->refs = 1; … … 88 91 bithenge_scope_t *scope, bithenge_node_t **out) 89 92 { 93 int rc; 90 94 binary_expression_t *self = expression_as_binary(base); 91 95 bithenge_node_t *a, *b; 92 intrc = bithenge_expression_evaluate(self->a, scope, &a);96 rc = bithenge_expression_evaluate(self->a, scope, &a); 93 97 if (rc != EOK) 94 98 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 } 99 105 } 100 106 … … 102 108 /* Assigning 0 only to make the compiler happy. */ 103 109 bithenge_int_t a_int = 0, b_int = 0; 110 bool a_bool = false, b_bool = false, out_bool = false; 104 111 switch (self->op) { 105 112 case BITHENGE_EXPRESSION_ADD: /* fallthrough */ 106 113 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: 108 121 rc = EINVAL; 109 122 if (bithenge_node_type(a) != BITHENGE_NODE_INTEGER) … … 114 127 b_int = bithenge_integer_node_value(b); 115 128 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; 116 143 default: 117 144 break; … … 128 155 rc = bithenge_new_integer_node(out, a_int * b_int); 129 156 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; 130 192 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; 132 221 break; 133 222 case BITHENGE_EXPRESSION_INVALID_BINARY_OP: … … 197 286 bithenge_scope_t *scope, bithenge_node_t **out) 198 287 { 199 for (; scope && !bithenge_scope_is_barrier(scope); 200 scope = bithenge_scope_outer(scope)) { 288 for (; scope; scope = bithenge_scope_outer(scope)) { 201 289 *out = bithenge_scope_in_node(scope); 202 290 if (*out) … … 220 308 int bithenge_in_node_expression(bithenge_expression_t **out) 221 309 { 310 if (bithenge_should_fail()) 311 return ENOMEM; 222 312 bithenge_expression_inc_ref(&in_node_expression); 223 313 *out = &in_node_expression; … … 392 482 393 483 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 to440 * @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 474 484 /***************** scope_member_expression *****************/ 475 485 … … 497 507 for (; scope && !bithenge_scope_is_barrier(scope); 498 508 scope = bithenge_scope_outer(scope)) { 509 bithenge_node_t *cur = bithenge_scope_get_current_node(scope); 510 if (!cur) 511 continue; 499 512 bithenge_node_inc_ref(self->key); 500 bithenge_node_t *cur = bithenge_scope_get_current_node(scope);501 513 int rc = bithenge_node_get(cur, self->key, out); 502 514 bithenge_node_dec_ref(cur); … … 504 516 return rc; 505 517 } 506 return ENOENT;518 return bithenge_scope_error(scope, "No scope member %t", self->key); 507 519 } 508 520 … … 519 531 }; 520 532 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. */ 521 539 int bithenge_scope_member_expression(bithenge_expression_t **out, 522 540 bithenge_node_t *key) … … 545 563 546 564 565 566 /***************** subblob_expression *****************/ 567 568 typedef struct { 569 bithenge_expression_t base; 570 bithenge_expression_t *blob, *start, *limit; 571 bool absolute_limit; 572 } subblob_expression_t; 573 574 static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base) 575 { 576 return (subblob_expression_t *)base; 577 } 578 579 static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr) 580 { 581 return &expr->base; 582 } 583 584 static 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 636 static 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 645 static 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. */ 660 int 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 683 error: 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 } 547 690 548 691 /***************** param_wrapper *****************/ … … 798 941 { 799 942 expression_transform_t *self = transform_as_expression(base); 800 *out_size = 0; 943 if (out_size) 944 *out_size = 0; 801 945 return bithenge_expression_evaluate(self->expr, scope, out_node); 802 946 } … … 840 984 841 985 842 /***************** if_transform*****************/986 /***************** concat_blob *****************/ 843 987 844 988 typedef 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 996 static inline concat_blob_t *blob_as_concat(bithenge_blob_t *base) 997 { 998 return (concat_blob_t *)base; 999 } 1000 1001 static inline bithenge_blob_t *concat_as_blob(concat_blob_t *blob) 1002 { 1003 return &blob->base; 1004 } 1005 1006 static 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); 865 1013 if (rc != EOK) 866 1014 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 1028 static 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); 882 1032 if (rc != EOK) 883 1033 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 1039 static 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 1067 static 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 1098 static 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 1108 static 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, 913 1113 }; 914 1114 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. 922 1119 * @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)); 1120 int 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)); 929 1128 if (!self) { 930 1129 rc = ENOMEM; … … 932 1131 } 933 1132 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)); 943 1146 return EOK; 944 1147 945 1148 error: 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. */ 1162 int 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 1191 error: 1192 bithenge_blob_dec_ref(a); 1193 bithenge_expression_dec_ref(b_expr); 1194 bithenge_scope_dec_ref(scope); 1195 free(self); 950 1196 return rc; 951 1197 }
Note:
See TracChangeset
for help on using the changeset viewer.