Changeset 5e718d9 in mainline for uspace/lib/bithenge
- Timestamp:
- 2012-08-21T10:04:16Z (13 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. - Location:
- uspace/lib/bithenge
- Files:
-
- 7 added
- 22 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/bithenge/blob.c
r0da6c04 r5e718d9 58 58 assert(ops->size); 59 59 60 if (bithenge_should_fail()) 61 return ENOMEM; 62 60 63 blob->base.type = BITHENGE_NODE_BLOB; 61 64 blob->base.refs = 1; … … 195 198 { 196 199 memory_blob_t *blob = blob_as_memory(base); 200 if (bithenge_should_fail()) 201 return EIO; 197 202 *size = blob->size; 198 203 return EOK; … … 223 228 .destroy = memory_destroy, 224 229 }; 225 226 /** Create a blob node from data. Unlike with @a227 * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a228 * new buffer and the original data can be changed after this call. The blob229 * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is230 * used.231 * @memberof bithenge_blob_t232 * @param[out] out Stores the created blob node.233 * @param[in] data The data.234 * @param len The length of the data.235 * @return EOK on success or an error code from errno.h. */236 int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,237 size_t len)238 {239 int rc;240 assert(data || !len);241 242 memory_blob_t *blob = malloc(sizeof(*blob));243 if (!blob)244 return ENOMEM;245 rc = bithenge_init_random_access_blob(memory_as_blob(blob),246 &memory_ops);247 if (rc != EOK) {248 free(blob);249 return rc;250 }251 char *buffer = malloc(len);252 if (!buffer) {253 free(blob);254 return rc;255 }256 memcpy(buffer, data, len);257 blob->buffer = buffer;258 blob->size = len;259 blob->needs_free = true;260 *out = bithenge_blob_as_node(memory_as_blob(blob));261 return EOK;262 }263 230 264 231 /** Create a blob node from a buffer. The buffer must exist as long as the blob … … 280 247 281 248 memory_blob_t *blob = malloc(sizeof(*blob)); 282 if (!blob) 283 return ENOMEM; 249 if (!blob) { 250 rc = ENOMEM; 251 goto error; 252 } 284 253 rc = bithenge_init_random_access_blob(memory_as_blob(blob), 285 254 &memory_ops); 286 if (rc != EOK) { 287 free(blob); 288 return rc; 289 } 255 if (rc != EOK) 256 goto error; 290 257 blob->buffer = buffer; 291 258 blob->size = len; … … 293 260 *out = bithenge_blob_as_node(memory_as_blob(blob)); 294 261 return EOK; 295 } 262 263 error: 264 if (needs_free) 265 free((void *)buffer); 266 free(blob); 267 return rc; 268 } 269 270 /** Create a blob node from data. Unlike with @a 271 * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a 272 * new buffer and the original data can be changed after this call. The blob 273 * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is 274 * used. 275 * @memberof bithenge_blob_t 276 * @param[out] out Stores the created blob node. 277 * @param[in] data The data. 278 * @param len The length of the data. 279 * @return EOK on success or an error code from errno.h. */ 280 int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data, 281 size_t len) 282 { 283 char *buffer = malloc(len); 284 if (!buffer) 285 return ENOMEM; 286 memcpy(buffer, data, len); 287 288 return bithenge_new_blob_from_buffer(out, buffer, len, true); 289 } 290 291 296 292 297 293 typedef struct { … … 461 457 /** Check whether the contents of two blobs are equal. 462 458 * @memberof bithenge_blob_t 459 * @param[out] out Holds whether the blobs are equal. 463 460 * @param a, b Blobs to compare. 464 * @return Whether the blobs are equal. If an error occurs, returns false.465 */ 466 bool bithenge_blob_equal(bithenge_blob_t *a, bithenge_blob_t *b)461 * @return EOK on success, or an error code from errno.h. 462 */ 463 int bithenge_blob_equal(bool *out, bithenge_blob_t *a, bithenge_blob_t *b) 467 464 { 468 465 assert(a); … … 476 473 rc = bithenge_blob_read(a, offset, buffer_a, &size_a); 477 474 if (rc != EOK) 478 return false;475 return rc; 479 476 rc = bithenge_blob_read(b, offset, buffer_b, &size_b); 480 477 if (rc != EOK) 481 return false; 482 if (size_a != size_b || bcmp(buffer_a, buffer_b, size_a)) 483 return false; 478 return rc; 479 if (size_a != size_b || bcmp(buffer_a, buffer_b, size_a)) { 480 *out = false; 481 return EOK; 482 } 484 483 offset += size_a; 485 484 } while (size_a == sizeof(buffer_a)); 486 return true; 485 *out = true; 486 return EOK; 487 487 } 488 488 -
uspace/lib/bithenge/blob.h
r0da6c04 r5e718d9 233 233 } 234 234 235 /** @memberof bithenge_blob_t */ 235 236 int bithenge_init_random_access_blob(bithenge_blob_t *, 236 237 const bithenge_random_access_blob_ops_t *); 238 /** @memberof bithenge_sequential_blob_t */ 237 239 int bithenge_init_sequential_blob(bithenge_sequential_blob_t *, 238 240 const bithenge_sequential_blob_ops_t *); 241 /** @memberof bithenge_blob_t */ 239 242 int bithenge_new_blob_from_data(bithenge_node_t **, const void *, size_t); 243 /** @memberof bithenge_blob_t */ 240 244 int bithenge_new_blob_from_buffer(bithenge_node_t **, const void *, size_t, 241 245 bool); … … 243 247 int bithenge_new_subblob(bithenge_node_t **, bithenge_blob_t *, aoff64_t, 244 248 aoff64_t); 245 bool bithenge_blob_equal(bithenge_blob_t *, bithenge_blob_t *); 249 /** @memberof bithenge_blob_t */ 250 int bithenge_blob_equal(bool *, bithenge_blob_t *, bithenge_blob_t *); 246 251 247 252 #endif -
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 } -
uspace/lib/bithenge/expression.h
r0da6c04 r5e718d9 38 38 #define BITHENGE_EXPRESSION_H_ 39 39 40 #include "blob.h" 40 41 #include "transform.h" 41 42 #include "tree.h" … … 73 74 return; 74 75 assert(self->ops); 76 assert(self->refs > 0); 75 77 if (--self->refs == 0) 76 78 self->ops->destroy(self); … … 91 93 } 92 94 95 /** The binary operators supported by @a bithenge_binary_expression(). */ 93 96 typedef enum { 94 97 BITHENGE_EXPRESSION_INVALID_BINARY_OP, 98 95 99 BITHENGE_EXPRESSION_ADD, 96 100 BITHENGE_EXPRESSION_SUBTRACT, 97 101 BITHENGE_EXPRESSION_MULTIPLY, 102 BITHENGE_EXPRESSION_INTEGER_DIVIDE, 103 BITHENGE_EXPRESSION_MODULO, 104 105 BITHENGE_EXPRESSION_LESS_THAN, 106 BITHENGE_EXPRESSION_GREATER_THAN, 107 BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL, 108 BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL, 98 109 BITHENGE_EXPRESSION_EQUALS, 110 BITHENGE_EXPRESSION_NOT_EQUALS, 111 112 BITHENGE_EXPRESSION_AND, 113 BITHENGE_EXPRESSION_OR, 114 115 BITHENGE_EXPRESSION_MEMBER, 116 BITHENGE_EXPRESSION_CONCAT, 99 117 } bithenge_binary_op_t; 100 118 … … 107 125 int bithenge_param_expression(bithenge_expression_t **, int); 108 126 int bithenge_const_expression(bithenge_expression_t **, bithenge_node_t *); 109 int bithenge_member_expression(bithenge_expression_t **,110 bithenge_expression_t *, bithenge_node_t *);111 127 int bithenge_scope_member_expression(bithenge_expression_t **, 112 128 bithenge_node_t *); 129 int bithenge_subblob_expression(bithenge_expression_t **, 130 bithenge_expression_t *, bithenge_expression_t *, bithenge_expression_t *, 131 bool); 113 132 int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *, 114 133 bithenge_expression_t **); … … 117 136 int bithenge_inputless_transform(bithenge_transform_t **, 118 137 bithenge_expression_t *); 119 int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *, 120 bithenge_transform_t *, bithenge_transform_t *); 138 139 int bithenge_concat_blob(bithenge_node_t **, bithenge_blob_t *, 140 bithenge_blob_t *); 141 int bithenge_concat_blob_lazy(bithenge_node_t **, bithenge_blob_t *, 142 bithenge_expression_t *, bithenge_scope_t *); 121 143 122 144 #endif -
uspace/lib/bithenge/file.c
r0da6c04 r5e718d9 79 79 return ELIMIT; 80 80 if (lseek(blob->fd, offset, SEEK_SET) < 0) 81 return errno ;81 return errno == EINVAL ? EIO : errno; 82 82 83 83 ssize_t amount_read; -
uspace/lib/bithenge/helenos/block.c
r0da6c04 r5e718d9 37 37 38 38 #include <assert.h> 39 #include <block.h> 39 40 #include <errno.h> 40 #include <libblock.h>41 41 #include <loc.h> 42 42 #include <macros.h> -
uspace/lib/bithenge/helenos/os.h
r0da6c04 r5e718d9 27 27 */ 28 28 29 #ifndef BITHENGE_ OS_H_30 #define BITHENGE_ OS_H_29 #ifndef BITHENGE_HELENOS_OS_H_ 30 #define BITHENGE_HELENOS_OS_H_ 31 31 32 32 #include <bool.h> -
uspace/lib/bithenge/linux/os.h
r0da6c04 r5e718d9 27 27 */ 28 28 29 #ifndef BITHENGE_ OS_H_30 #define BITHENGE_ OS_H_29 #ifndef BITHENGE_LINUX_OS_H_ 30 #define BITHENGE_LINUX_OS_H_ 31 31 32 32 #include <endian.h> -
uspace/lib/bithenge/print.c
r0da6c04 r5e718d9 38 38 39 39 #include <errno.h> 40 #include <stdarg.h> 40 41 #include <stdio.h> 41 42 #include "blob.h" … … 47 48 bool first; 48 49 int depth; 50 char *buffer; 51 size_t buffer_size; 49 52 } state_t; 50 53 54 static void state_printf(state_t *state, const char *format, ...) 55 { 56 va_list ap; 57 va_start(ap, format); 58 if (state->buffer) { 59 int rc = vsnprintf(state->buffer, state->buffer_size, format, 60 ap); 61 if (rc > 0 && (size_t)rc >= state->buffer_size) 62 rc = state->buffer_size - 1; 63 if (rc > 0) { 64 state->buffer += rc; 65 state->buffer_size -= rc; 66 } 67 } else { 68 vprintf(format, ap); 69 } 70 va_end(ap); 71 } 72 51 73 static int print_node(state_t *, bithenge_node_t *); 52 74 53 75 static void newline(state_t *state) 54 76 { 55 printf("\n");77 state_printf(state, "\n"); 56 78 for (int i = 0; i < state->depth; i++) { 57 printf(" ");79 state_printf(state, " "); 58 80 } 59 81 } … … 74 96 int rc = EOK; 75 97 if (!state->first) 76 printf(",");98 state_printf(state, ","); 77 99 newline(state); 78 100 state->first = false; … … 80 102 && bithenge_node_type(key) != BITHENGE_NODE_STRING; 81 103 if (add_quotes) 82 printf("\"");104 state_printf(state, "\""); 83 105 rc = print_node(state, key); 84 106 if (rc != EOK) 85 107 goto end; 86 108 if (add_quotes) 87 printf("\"");88 printf(": ");109 state_printf(state, "\""); 110 state_printf(state, ": "); 89 111 rc = print_node(state, value); 90 112 if (rc != EOK) … … 99 121 { 100 122 int rc; 101 printf("{");123 state_printf(state, "{"); 102 124 increase_depth(state); 103 125 state->first = true; … … 109 131 newline(state); 110 132 state->first = false; 111 printf("}");133 state_printf(state, "}"); 112 134 return EOK; 113 135 } … … 118 140 switch (state->type) { 119 141 case BITHENGE_PRINT_PYTHON: 120 printf(value ? "True" : "False");142 state_printf(state, value ? "True" : "False"); 121 143 break; 122 144 case BITHENGE_PRINT_JSON: 123 printf(value ? "true" : "false");145 state_printf(state, value ? "true" : "false"); 124 146 break; 125 147 } … … 130 152 { 131 153 bithenge_int_t value = bithenge_integer_node_value(node); 132 printf("%" BITHENGE_PRId, value);154 state_printf(state, "%" BITHENGE_PRId, value); 133 155 return EOK; 134 156 } … … 137 159 { 138 160 const char *value = bithenge_string_node_value(node); 139 printf("\"");161 state_printf(state, "\""); 140 162 for (string_iterator_t i = string_iterator(value); !string_iterator_done(&i); ) { 141 163 wchar_t ch; … … 144 166 return rc; 145 167 if (ch == '"' || ch == '\\') { 146 printf("\\%lc", (wint_t) ch);168 state_printf(state, "\\%lc", (wint_t) ch); 147 169 } else if (ch <= 0x1f) { 148 printf("\\u%04x", (unsigned int) ch);170 state_printf(state, "\\u%04x", (unsigned int) ch); 149 171 } else { 150 printf("%lc", (wint_t) ch);172 state_printf(state, "%lc", (wint_t) ch); 151 173 } 152 174 } 153 printf("\"");175 state_printf(state, "\""); 154 176 return EOK; 155 177 } … … 159 181 bithenge_blob_t *blob = bithenge_node_as_blob(node); 160 182 aoff64_t pos = 0; 161 charbuffer[1024];183 uint8_t buffer[1024]; 162 184 aoff64_t size = sizeof(buffer); 163 185 int rc; 164 printf(state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\""); 186 state_printf(state, 187 state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\""); 165 188 do { 166 rc = bithenge_blob_read(blob, pos, buffer, &size);189 rc = bithenge_blob_read(blob, pos, (char *)buffer, &size); 167 190 if (rc != EOK) 168 191 return rc; 169 192 for (aoff64_t i = 0; i < size; i++) 170 printf("\\x%02x", (unsigned int)(uint8_t)buffer[i]); 193 state_printf(state, "\\x%02x", 194 (unsigned int)buffer[i]); 171 195 pos += size; 172 196 } while (size == sizeof(buffer)); 173 printf("\"");197 state_printf(state, "\""); 174 198 return EOK; 175 199 } … … 192 216 } 193 217 194 /** Print a tree as text .218 /** Print a tree as text to stdout. 195 219 * @param type The format to use. 196 220 * @param tree The root node of the tree to print. … … 198 222 int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree) 199 223 { 200 state_t state = {type, true, 0 };224 state_t state = {type, true, 0, NULL, 0}; 201 225 return print_node(&state, tree); 202 226 } 203 227 228 /** Print a tree as text into a buffer. 229 * @param[in,out] str Holds a pointer to the buffer; changed to point to the 230 * null character. 231 * @param[in,out] size Holds the size of the buffer; changed to hold the 232 * remaining size. 233 * @param type The format to use. 234 * @param tree The root node of the tree to print. 235 * @return EOK on success or an error code from errno.h. */ 236 int bithenge_print_node_to_string(char **str, size_t *size, 237 bithenge_print_type_t type, bithenge_node_t *tree) 238 { 239 state_t state = {type, true, 0, *str, *size}; 240 int rc = print_node(&state, tree); 241 *str = state.buffer; 242 *size = state.buffer_size; 243 return rc; 244 } 245 204 246 /** @} 205 247 */ -
uspace/lib/bithenge/print.h
r0da6c04 r5e718d9 51 51 52 52 int bithenge_print_node(bithenge_print_type_t, bithenge_node_t *); 53 int bithenge_print_node_to_string(char **, size_t *, bithenge_print_type_t, 54 bithenge_node_t *); 53 55 54 56 #endif -
uspace/lib/bithenge/script.c
r0da6c04 r5e718d9 38 38 #include <stdio.h> 39 39 #include <stdlib.h> 40 #include "compound.h" 40 41 #include "expression.h" 41 42 #include "os.h" … … 45 46 #include "tree.h" 46 47 48 /** @cond internal */ 49 #define BUFFER_SIZE 4096 50 /** @endcond */ 51 47 52 /** Tokens with more characters than this may be read incorrectly. */ 48 #define MAX_TOKEN_SIZE 256 49 #define BUFFER_SIZE 4096 50 51 /** Single-character symbols are represented by the character itself. Every53 static const int MAX_TOKEN_SIZE = 256; 54 55 /** @cond internal 56 * Single-character symbols are represented by the character itself. Every 52 57 * other token uses one of these values: */ 53 58 typedef enum { 54 TOKEN_EQUALS = -128, 55 TOKEN_ERROR, 59 TOKEN_ERROR = -128, 60 61 TOKEN_AND, 62 TOKEN_CONCAT, 63 TOKEN_EQUALS, 56 64 TOKEN_EOF, 65 TOKEN_GREATER_THAN_OR_EQUAL, 57 66 TOKEN_IDENTIFIER, 58 67 TOKEN_INTEGER, 68 TOKEN_INTEGER_DIVIDE, 59 69 TOKEN_LEFT_ARROW, 70 TOKEN_LESS_THAN_OR_EQUAL, 71 TOKEN_NOT_EQUAL, 72 TOKEN_OR, 60 73 61 74 /* Keywords */ … … 65 78 TOKEN_IF, 66 79 TOKEN_IN, 80 TOKEN_PARTIAL, 67 81 TOKEN_REPEAT, 68 82 TOKEN_STRUCT, … … 72 86 TOKEN_WHILE, 73 87 } token_type_t; 88 /** @endcond */ 74 89 75 90 /** Singly-linked list of named transforms. */ … … 232 247 state->token = TOKEN_IN; 233 248 free(value); 249 } else if (!str_cmp(value, "partial")) { 250 state->token = TOKEN_PARTIAL; 251 free(value); 234 252 } else if (!str_cmp(value, "repeat")) { 235 253 state->token = TOKEN_REPEAT; … … 267 285 state->buffer_pos++; 268 286 state->token = TOKEN_LEFT_ARROW; 287 } else if (state->buffer[state->buffer_pos] == '=') { 288 state->buffer_pos++; 289 state->token = TOKEN_LESS_THAN_OR_EQUAL; 290 } 291 } else if (ch == '>') { 292 state->token = ch; 293 state->buffer_pos++; 294 if (state->buffer[state->buffer_pos] == '=') { 295 state->buffer_pos++; 296 state->token = TOKEN_GREATER_THAN_OR_EQUAL; 269 297 } 270 298 } else if (ch == '=') { … … 275 303 state->buffer_pos++; 276 304 } 305 } else if (ch == '/') { 306 state->token = ch; 307 state->buffer_pos++; 308 if (state->buffer[state->buffer_pos] == '/') { 309 state->token = TOKEN_INTEGER_DIVIDE; 310 state->buffer_pos++; 311 } 312 } else if (ch == '!') { 313 state->token = ch; 314 state->buffer_pos++; 315 if (state->buffer[state->buffer_pos] == '=') { 316 state->token = TOKEN_NOT_EQUAL; 317 state->buffer_pos++; 318 } 319 } else if (ch == '&') { 320 state->token = ch; 321 state->buffer_pos++; 322 if (state->buffer[state->buffer_pos] == '&') { 323 state->token = TOKEN_AND; 324 state->buffer_pos++; 325 } 326 } else if (ch == '|') { 327 state->token = ch; 328 state->buffer_pos++; 329 if (state->buffer[state->buffer_pos] == '|') { 330 state->token = TOKEN_OR; 331 state->buffer_pos++; 332 } 333 } else if (ch == '+') { 334 state->token = ch; 335 state->buffer_pos++; 336 if (state->buffer[state->buffer_pos] == '+') { 337 state->token = TOKEN_CONCAT; 338 state->buffer_pos++; 339 } 277 340 } else { 278 341 state->token = ch; … … 380 443 /***************** Expressions *****************/ 381 444 445 /** @cond internal */ 382 446 typedef enum { 383 447 PRECEDENCE_NONE, 448 PRECEDENCE_AND, 384 449 PRECEDENCE_EQUALS, 450 PRECEDENCE_COMPARE, 385 451 PRECEDENCE_ADD, 386 452 PRECEDENCE_MULTIPLY, 387 453 } precedence_t; 454 /** @endcond */ 388 455 389 456 static bithenge_binary_op_t token_as_binary_operator(token_type_t token) … … 396 463 case '*': 397 464 return BITHENGE_EXPRESSION_MULTIPLY; 465 case TOKEN_INTEGER_DIVIDE: 466 return BITHENGE_EXPRESSION_INTEGER_DIVIDE; 467 case '%': 468 return BITHENGE_EXPRESSION_MODULO; 469 case '<': 470 return BITHENGE_EXPRESSION_LESS_THAN; 471 case TOKEN_LESS_THAN_OR_EQUAL: 472 return BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL; 473 case '>': 474 return BITHENGE_EXPRESSION_GREATER_THAN; 475 case TOKEN_GREATER_THAN_OR_EQUAL: 476 return BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL; 398 477 case TOKEN_EQUALS: 399 478 return BITHENGE_EXPRESSION_EQUALS; 479 case TOKEN_NOT_EQUAL: 480 return BITHENGE_EXPRESSION_NOT_EQUALS; 481 case TOKEN_AND: 482 return BITHENGE_EXPRESSION_AND; 483 case TOKEN_OR: 484 return BITHENGE_EXPRESSION_OR; 485 case TOKEN_CONCAT: 486 return BITHENGE_EXPRESSION_CONCAT; 400 487 default: 401 488 return BITHENGE_EXPRESSION_INVALID_BINARY_OP; … … 407 494 switch (op) { 408 495 case BITHENGE_EXPRESSION_ADD: /* fallthrough */ 409 case BITHENGE_EXPRESSION_SUBTRACT: 496 case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */ 497 case BITHENGE_EXPRESSION_CONCAT: 410 498 return PRECEDENCE_ADD; 411 case BITHENGE_EXPRESSION_MULTIPLY: 499 case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */ 500 case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */ 501 case BITHENGE_EXPRESSION_MODULO: 412 502 return PRECEDENCE_MULTIPLY; 413 case BITHENGE_EXPRESSION_EQUALS: 503 case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */ 504 case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */ 505 case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */ 506 case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL: 507 return PRECEDENCE_COMPARE; 508 case BITHENGE_EXPRESSION_EQUALS: /* fallthrough */ 509 case BITHENGE_EXPRESSION_NOT_EQUALS: 414 510 return PRECEDENCE_EQUALS; 511 case BITHENGE_EXPRESSION_AND: /* fallthrough */ 512 case BITHENGE_EXPRESSION_OR: 513 return PRECEDENCE_AND; 415 514 default: 416 515 assert(false); … … 480 579 } 481 580 581 next_token(state); 582 482 583 bithenge_expression_t *expr; 483 584 rc = bithenge_param_expression(&expr, i); … … 486 587 return NULL; 487 588 } 488 489 next_token(state);490 491 589 return expr; 492 590 } else if (state->token == '.') { … … 530 628 } 531 629 630 static bithenge_expression_t *parse_postfix_expression(state_t *state) 631 { 632 int rc; 633 bithenge_expression_t *expr = parse_term(state); 634 while (state->error == EOK) { 635 if (state->token == '.') { 636 next_token(state); 637 638 const char *id = expect_identifier(state); 639 640 if (state->error != EOK) { 641 free((char *)id); 642 bithenge_expression_dec_ref(expr); 643 return NULL; 644 } 645 646 bithenge_node_t *key = NULL; 647 rc = bithenge_new_string_node(&key, id, true); 648 if (rc != EOK) { 649 error_errno(state, rc); 650 bithenge_expression_dec_ref(expr); 651 return NULL; 652 } 653 654 bithenge_expression_t *key_expr; 655 rc = bithenge_const_expression(&key_expr, key); 656 if (rc != EOK) { 657 error_errno(state, rc); 658 bithenge_expression_dec_ref(expr); 659 return NULL; 660 } 661 662 rc = bithenge_binary_expression(&expr, 663 BITHENGE_EXPRESSION_MEMBER, expr, key_expr); 664 if (rc != EOK) { 665 error_errno(state, rc); 666 return NULL; 667 } 668 } else if (state->token == '[') { 669 next_token(state); 670 bithenge_expression_t *start = parse_expression(state); 671 bool absolute_limit = false; 672 if (state->token == ',' || state->token == ':') { 673 absolute_limit = state->token == ':'; 674 next_token(state); 675 bithenge_expression_t *limit = NULL; 676 if (!(state->token == ']' && absolute_limit)) 677 limit = parse_expression(state); 678 expect(state, ']'); 679 680 if (state->error != EOK) { 681 bithenge_expression_dec_ref(expr); 682 bithenge_expression_dec_ref(start); 683 bithenge_expression_dec_ref(limit); 684 return NULL; 685 } 686 rc = bithenge_subblob_expression(&expr, expr, start, 687 limit, absolute_limit); 688 if (rc != EOK) { 689 error_errno(state, rc); 690 return NULL; 691 } 692 } else if (state->token == ']') { 693 next_token(state); 694 695 if (state->error != EOK) { 696 bithenge_expression_dec_ref(expr); 697 bithenge_expression_dec_ref(start); 698 return NULL; 699 } 700 rc = bithenge_binary_expression(&expr, 701 BITHENGE_EXPRESSION_MEMBER, expr, start); 702 if (rc != EOK) { 703 error_errno(state, rc); 704 return NULL; 705 } 706 } else { 707 syntax_error(state, "expected ',', ':', or ']'"); 708 bithenge_expression_dec_ref(expr); 709 bithenge_expression_dec_ref(start); 710 return NULL; 711 } 712 } else { 713 break; 714 } 715 } 716 return expr; 717 } 718 532 719 static bithenge_expression_t *parse_expression_precedence(state_t *state, 533 720 precedence_t prev_precedence) 534 721 { 535 bithenge_expression_t *expr = parse_ term(state);722 bithenge_expression_t *expr = parse_postfix_expression(state); 536 723 while (state->error == EOK) { 537 724 bithenge_binary_op_t op = … … 544 731 next_token(state); 545 732 546 bithenge_expression_t *expr2 = parse_term(state); 733 bithenge_expression_t *expr2 = 734 parse_expression_precedence(state, precedence); 547 735 if (state->error != EOK) { 548 736 bithenge_expression_dec_ref(expr2); … … 550 738 } 551 739 int rc = bithenge_binary_expression(&expr, op, expr, expr2); 552 if (rc != EOK) 553 error_errno(state, rc); 740 if (rc != EOK) { 741 expr = NULL; 742 error_errno(state, rc); 743 } 554 744 } 555 745 if (state->error != EOK) { … … 759 949 int rc = bithenge_if_transform(&switch_xform, exprs[num], 760 950 xforms[num], switch_xform); 761 if (rc != EOK) 762 error_errno(state, rc); 951 if (rc != EOK) { 952 switch_xform = NULL; 953 error_errno(state, rc); 954 } 763 955 } 764 956 … … 827 1019 } 828 1020 return do_while_xform; 1021 } 1022 1023 static bithenge_transform_t *parse_partial(state_t *state) 1024 { 1025 expect(state, TOKEN_PARTIAL); 1026 bithenge_transform_t *offset_xform = NULL; 1027 if (state->token == '(') { 1028 next_token(state); 1029 bithenge_expression_t *offset = parse_expression(state); 1030 expect(state, ')'); 1031 1032 bithenge_expression_t *in_expr; 1033 int rc = bithenge_in_node_expression(&in_expr); 1034 if (rc != EOK) 1035 error_errno(state, rc); 1036 if (state->error != EOK) { 1037 bithenge_expression_dec_ref(offset); 1038 return NULL; 1039 } 1040 1041 rc = bithenge_subblob_expression(&offset, in_expr, offset, 1042 NULL, true); 1043 if (rc != EOK) { 1044 error_errno(state, rc); 1045 return NULL; 1046 } 1047 1048 rc = bithenge_expression_transform(&offset_xform, offset); 1049 if (rc != EOK) { 1050 error_errno(state, rc); 1051 return NULL; 1052 } 1053 } 1054 expect(state, '{'); 1055 bithenge_transform_t *xform = parse_transform(state); 1056 expect(state, '}'); 1057 if (state->error != EOK) { 1058 bithenge_transform_dec_ref(offset_xform); 1059 bithenge_transform_dec_ref(xform); 1060 return NULL; 1061 } 1062 1063 int rc = bithenge_partial_transform(&xform, xform); 1064 if (rc != EOK) { 1065 error_errno(state, rc); 1066 bithenge_transform_dec_ref(offset_xform); 1067 return NULL; 1068 } 1069 1070 if (offset_xform) { 1071 bithenge_transform_t **xforms = malloc(2 * sizeof(*xforms)); 1072 if (!xforms) { 1073 error_errno(state, ENOMEM); 1074 bithenge_transform_dec_ref(xform); 1075 bithenge_transform_dec_ref(offset_xform); 1076 return NULL; 1077 } 1078 xforms[0] = xform; 1079 xforms[1] = offset_xform; 1080 rc = bithenge_new_composed_transform(&xform, xforms, 2); 1081 if (rc != EOK) { 1082 error_errno(state, rc); 1083 return NULL; 1084 } 1085 } 1086 1087 return xform; 829 1088 } 830 1089 … … 910 1169 } else if (state->token == TOKEN_IF) { 911 1170 return parse_if(state, false); 1171 } else if (state->token == TOKEN_PARTIAL) { 1172 return parse_partial(state); 912 1173 } else if (state->token == TOKEN_REPEAT) { 913 1174 return parse_repeat(state); … … 939 1200 if (state->error != EOK) 940 1201 break; 941 xforms[num] = parse_transform_no_compose(state); 942 num++; 1202 xforms[num++] = parse_transform_no_compose(state); 943 1203 } 944 1204 if (state->error != EOK) { 945 while (xforms && num --)946 bithenge_transform_dec_ref(xforms[ num]);1205 while (xforms && num > 1) 1206 bithenge_transform_dec_ref(xforms[--num]); 947 1207 free(xforms); 948 1208 bithenge_transform_dec_ref(result); … … 982 1242 } 983 1243 1244 bithenge_transform_t *barrier = NULL; 1245 if (state->error == EOK) { 1246 int rc = bithenge_new_barrier_transform(&barrier, 1247 state->num_params); 1248 if (rc != EOK) { 1249 barrier = NULL; 1250 error_errno(state, rc); 1251 } 1252 } 1253 1254 add_named_transform(state, barrier, name); 1255 984 1256 expect(state, '='); 985 1257 bithenge_transform_t *xform = parse_transform(state); … … 987 1259 988 1260 if (state->error == EOK) { 989 int rc = bithenge_ new_barrier_transform(&xform, xform,990 state->num_params);991 if (rc != EOK) {992 xform = NULL;993 error_errno(state, rc); 994 995 } 996 997 add_named_transform(state, xform, name);1261 int rc = bithenge_barrier_transform_set_subtransform(barrier, 1262 xform); 1263 xform = NULL; 1264 if (rc != EOK) 1265 error_errno(state, rc); 1266 } 1267 1268 if (state->error != EOK) 1269 bithenge_transform_dec_ref(xform); 998 1270 999 1271 for (int i = 0; i < state->num_params; i++) -
uspace/lib/bithenge/sequence.c
r0da6c04 r5e718d9 418 418 struct_node_t *node = node_as_struct(base); 419 419 420 /* We didn't inc_ref for the scope in struct_transform_make_node, so 421 * make sure it doesn't try to dec_ref. */ 422 seq_node_scope(struct_as_seq(node))->current_node = NULL; 423 seq_node_destroy(struct_as_seq(node)); 420 /* Treat the scope carefully because of the circular reference. In 421 * struct_transform_make_node, things are set up so node owns a 422 * reference to the scope, but scope doesn't own a reference to node, 423 * so node's reference count is too low. */ 424 bithenge_scope_t *scope = seq_node_scope(struct_as_seq(node)); 425 if (scope->refs == 1) { 426 /* Mostly normal destroy, but we didn't inc_ref(node) for the 427 * scope in struct_transform_make_node, so make sure it doesn't 428 * try to dec_ref. */ 429 scope->current_node = NULL; 430 seq_node_destroy(struct_as_seq(node)); 431 } else if (scope->refs > 1) { 432 /* The scope is still needed, but node isn't otherwise needed. 433 * Switch things around so scope owns a reference to node, but 434 * not vice versa, and scope's reference count is too low. */ 435 bithenge_node_inc_ref(base); 436 bithenge_scope_dec_ref(scope); 437 return; 438 } else { 439 /* This happens after the previous case, when scope is no 440 * longer used and is being destroyed. Since scope is already 441 * being destroyed, set it to NULL here so we don't try to 442 * destroy it twice. */ 443 struct_as_seq(node)->scope = NULL; 444 seq_node_destroy(struct_as_seq(node)); 445 } 424 446 425 447 bithenge_transform_dec_ref(struct_as_transform(node->transform)); … … 466 488 return rc; 467 489 } 490 491 rc = seq_node_init(struct_as_seq(node), &struct_node_seq_ops, inner, 492 blob, self->num_subtransforms, false); 493 if (rc != EOK) { 494 bithenge_scope_dec_ref(inner); 495 free(node); 496 return rc; 497 } 498 499 bithenge_transform_inc_ref(struct_as_transform(self)); 500 node->transform = self; 501 node->prefix = prefix; 502 468 503 /* We should inc_ref(node) here, but that would make a cycle. Instead, 469 504 * we leave it 1 too low, so that when the only remaining use of node … … 471 506 * struct_node_destroy. */ 472 507 bithenge_scope_set_current_node(inner, struct_as_node(node)); 473 474 rc = seq_node_init(struct_as_seq(node), &struct_node_seq_ops, inner,475 blob, self->num_subtransforms, false);476 508 bithenge_scope_dec_ref(inner); 477 if (rc != EOK) { 478 free(node); 479 return rc; 480 } 481 482 bithenge_transform_inc_ref(struct_as_transform(self)); 483 node->transform = self; 484 node->prefix = prefix; 509 485 510 *out = struct_as_node(node); 486 511 … … 524 549 return rc; 525 550 526 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, 527 self->num_subtransforms); 528 if (rc != EOK) { 529 bithenge_node_dec_ref(*out_node); 530 return rc; 551 if (out_size) { 552 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, 553 self->num_subtransforms); 554 if (rc != EOK) { 555 bithenge_node_dec_ref(*out_node); 556 return rc; 557 } 531 558 } 532 559 … … 595 622 /***************** bithenge_repeat_transform *****************/ 596 623 624 /* TODO: ignore errors */ 625 597 626 typedef struct { 598 627 bithenge_transform_t base; … … 793 822 return rc; 794 823 795 bithenge_int_t count = node_as_repeat(*out_node)->count; 796 if (count != -1) { 797 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, count); 798 if (rc != EOK) { 799 bithenge_node_dec_ref(*out_node); 800 return rc; 801 } 802 } else { 803 *out_size = 0; 804 for (count = 1; ; count++) { 805 aoff64_t size; 824 if (out_size) { 825 bithenge_int_t count = node_as_repeat(*out_node)->count; 826 if (count != -1) { 806 827 rc = seq_node_field_offset(node_as_seq(*out_node), 807 &size, count); 808 if (rc != EOK) 809 break; 810 *out_size = size; 828 out_size, count); 829 if (rc != EOK) { 830 bithenge_node_dec_ref(*out_node); 831 return rc; 832 } 833 } else { 834 *out_size = 0; 835 for (count = 1; ; count++) { 836 aoff64_t size; 837 rc = seq_node_field_offset( 838 node_as_seq(*out_node), &size, count); 839 if (rc == EINVAL || rc == ENOENT) 840 break; 841 if (rc != EOK) { 842 bithenge_node_dec_ref(*out_node); 843 return rc; 844 } 845 *out_size = size; 846 } 811 847 } 812 848 } … … 886 922 typedef struct { 887 923 seq_node_t base; 888 bool prefix;889 924 bithenge_expression_t *expr; 890 925 bithenge_transform_t *xform; … … 966 1001 } 967 1002 968 if (!self->prefix) {969 bool complete;970 rc = seq_node_complete(do_while_as_seq(self), &complete);971 if (rc != EOK)972 return rc;973 if (!complete)974 return EINVAL;975 }976 977 1003 return rc; 978 1004 } … … 1006 1032 1007 1033 static int do_while_transform_make_node(do_while_transform_t *self, 1008 bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob, 1009 bool prefix) 1034 bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob) 1010 1035 { 1011 1036 do_while_node_t *node = malloc(sizeof(*node)); … … 1031 1056 bithenge_expression_inc_ref(self->expr); 1032 1057 node->expr = self->expr; 1033 node->prefix = prefix;1034 1058 node->count = -1; 1035 1059 *out = do_while_as_node(node); 1036 1060 return EOK; 1037 }1038 1039 static int do_while_transform_apply(bithenge_transform_t *base,1040 bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)1041 {1042 do_while_transform_t *self = transform_as_do_while(base);1043 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)1044 return EINVAL;1045 return do_while_transform_make_node(self, out, scope,1046 bithenge_node_as_blob(in), false);1047 1061 } 1048 1062 … … 1060 1074 { 1061 1075 do_while_transform_t *self = transform_as_do_while(base); 1062 int rc = do_while_transform_make_node(self, out_node, scope, blob, 1063 true); 1076 int rc = do_while_transform_make_node(self, out_node, scope, blob); 1064 1077 if (rc != EOK) 1065 1078 return rc; 1066 1079 1067 rc = bithenge_node_for_each(*out_node, for_each_noop, NULL); 1068 if (rc != EOK) { 1069 bithenge_node_dec_ref(*out_node); 1070 return rc; 1071 } 1072 1073 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, 1074 node_as_do_while(*out_node)->count); 1075 if (rc != EOK) { 1076 bithenge_node_dec_ref(*out_node); 1077 return rc; 1080 if (out_size) { 1081 rc = bithenge_node_for_each(*out_node, for_each_noop, NULL); 1082 if (rc != EOK) { 1083 bithenge_node_dec_ref(*out_node); 1084 return rc; 1085 } 1086 1087 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, 1088 node_as_do_while(*out_node)->count); 1089 if (rc != EOK) { 1090 bithenge_node_dec_ref(*out_node); 1091 return rc; 1092 } 1078 1093 } 1079 1094 … … 1090 1105 1091 1106 static const bithenge_transform_ops_t do_while_transform_ops = { 1092 .apply = do_while_transform_apply,1093 1107 .prefix_apply = do_while_transform_prefix_apply, 1094 1108 .destroy = do_while_transform_destroy, -
uspace/lib/bithenge/transform.c
r0da6c04 r5e718d9 37 37 #include <assert.h> 38 38 #include <errno.h> 39 #include <stdarg.h> 39 40 #include <stdlib.h> 40 41 #include "blob.h" 42 #include "os.h" 43 #include "print.h" 41 44 #include "transform.h" 45 46 47 48 /***************** transform *****************/ 42 49 43 50 /** Initialize a new transform. … … 56 63 assert(ops->apply || ops->prefix_apply); 57 64 assert(ops->destroy); 65 if (bithenge_should_fail()) 66 return ENOMEM; 58 67 self->ops = ops; 59 68 self->refs = 1; … … 137 146 * @param[out] out_node Holds the result of applying this transform to the 138 147 * prefix. 139 * @param[out] out_size Holds the size of the prefix. 148 * @param[out] out_size Holds the size of the prefix. Can be null, in which 149 * case the size is not determined. 140 150 * @return EOK on success, ENOTSUP if not supported, or another error code from 141 151 * errno.h. */ … … 152 162 return ENOTSUP; 153 163 154 int rc = bithenge_transform_prefix_length(self, scope, blob, out_size); 164 aoff64_t size; 165 int rc = bithenge_transform_prefix_length(self, scope, blob, &size); 155 166 if (rc != EOK) 156 167 return rc; 157 168 bithenge_node_t *prefix_blob; 158 169 bithenge_blob_inc_ref(blob); 159 rc = bithenge_new_subblob(&prefix_blob, blob, 0, *out_size);170 rc = bithenge_new_subblob(&prefix_blob, blob, 0, size); 160 171 if (rc != EOK) 161 172 return rc; 162 173 rc = bithenge_transform_apply(self, scope, prefix_blob, out_node); 163 174 bithenge_node_dec_ref(prefix_blob); 175 if (out_size) 176 *out_size = size; 164 177 return rc; 165 178 } 179 180 181 182 /***************** scope *****************/ 166 183 167 184 /** Create a transform scope. It must be dereferenced with @a 168 185 * bithenge_scope_dec_ref after it is used. Takes ownership of nothing. 186 * @memberof bithenge_scope_t 169 187 * @param[out] out Holds the new scope. 170 188 * @param outer The outer scope, or NULL. … … 179 197 bithenge_scope_inc_ref(outer); 180 198 self->outer = outer; 199 self->error = NULL; 181 200 self->barrier = false; 182 201 self->num_params = 0; … … 189 208 190 209 /** Dereference a transform scope. 191 * @param self The scope to dereference. */ 210 * @memberof bithenge_scope_t 211 * @param self The scope to dereference, or NULL. */ 192 212 void bithenge_scope_dec_ref(bithenge_scope_t *self) 193 213 { … … 201 221 bithenge_scope_dec_ref(self->outer); 202 222 free(self->params); 223 free(self->error); 203 224 free(self); 204 225 } 205 226 206 227 /** Get the outer scope of a scope, which may be NULL. 228 * @memberof bithenge_scope_t 207 229 * @param self The scope to examine. 208 230 * @return The outer scope, which may be NULL. */ … … 212 234 } 213 235 236 /** Get the error message stored in the scope, which may be NULL. The error 237 * message only exists as long as the scope does. 238 * @memberof bithenge_scope_t 239 * @param scope The scope to get the error message from. 240 * @return The error message, or NULL. */ 241 const char *bithenge_scope_get_error(bithenge_scope_t *scope) 242 { 243 return scope->error; 244 } 245 246 /** Set the error message for the scope. The error message is stored in the 247 * outermost scope, but if any scope already has an error message this error 248 * message is ignored. 249 * @memberof bithenge_scope_t 250 * @param scope The scope. 251 * @param format The format string. 252 * @return EINVAL normally, or another error code from errno.h. */ 253 int bithenge_scope_error(bithenge_scope_t *scope, const char *format, ...) 254 { 255 if (scope->error) 256 return EINVAL; 257 while (scope->outer) { 258 scope = scope->outer; 259 if (scope->error) 260 return EINVAL; 261 } 262 size_t space_left = 256; 263 scope->error = malloc(space_left); 264 if (!scope->error) 265 return ENOMEM; 266 char *out = scope->error; 267 va_list ap; 268 va_start(ap, format); 269 270 while (*format) { 271 if (format[0] == '%' && format[1] == 't') { 272 format += 2; 273 int rc = bithenge_print_node_to_string(&out, 274 &space_left, BITHENGE_PRINT_PYTHON, 275 va_arg(ap, bithenge_node_t *)); 276 if (rc != EOK) { 277 va_end(ap); 278 return rc; 279 } 280 } else { 281 const char *end = str_chr(format, '%'); 282 if (!end) 283 end = format + str_length(format); 284 size_t size = min((size_t)(end - format), 285 space_left - 1); 286 memcpy(out, format, size); 287 format = end; 288 out += size; 289 space_left -= size; 290 } 291 } 292 *out = '\0'; 293 294 va_end(ap); 295 return EINVAL; 296 } 297 214 298 /** Get the current node being created, which may be NULL. 299 * @memberof bithenge_scope_t 215 300 * @param scope The scope to get the current node from. 216 301 * @return The node being created, or NULL. */ … … 223 308 224 309 /** Set the current node being created. Takes a reference to @a node. 310 * @memberof bithenge_scope_t 225 311 * @param scope The scope to set the current node in. 226 312 * @param node The current node being created, or NULL. */ … … 233 319 234 320 /** Get the current input node, which may be NULL. 321 * @memberof bithenge_scope_t 235 322 * @param scope The scope to get the current input node from. 236 323 * @return The input node, or NULL. */ … … 243 330 244 331 /** Set the current input node. Takes a reference to @a node. 332 * @memberof bithenge_scope_t 245 333 * @param scope The scope to set the input node in. 246 334 * @param node The input node, or NULL. */ … … 252 340 253 341 /** Set a scope as a barrier. 342 * @memberof bithenge_scope_t 254 343 * @param self The scope to change. */ 255 344 void bithenge_scope_set_barrier(bithenge_scope_t *self) … … 260 349 /** Check whether a scope is a barrier, meaning that variable lookup stops at 261 350 * it. 351 * @memberof bithenge_scope_t 262 352 * @param self The scope to check. 263 353 * @return Whether the scope is a barrier. */ … … 270 360 * bithenge_scope_set_param. This must not be called on a scope that already 271 361 * has parameters. 362 * @memberof bithenge_scope_t 272 363 * @param scope The scope in which to allocate parameters. 273 364 * @param num_params The number of parameters to allocate. … … 284 375 } 285 376 286 /** Set a parameter. Takes a reference to @a value. Note that range checking is377 /** Set a parameter. Takes a reference to @a node. Note that range checking is 287 378 * not done in release builds. 379 * @memberof bithenge_scope_t 288 380 * @param scope The scope in which to allocate parameters. 289 381 * @param i The index of the parameter to set. 290 * @param value The value to store in the parameter.382 * @param node The value to store in the parameter. 291 383 * @return EOK on success or an error code from errno.h. */ 292 384 int bithenge_scope_set_param( bithenge_scope_t *scope, int i, … … 295 387 assert(scope); 296 388 assert(i >= 0 && i < scope->num_params); 389 if (bithenge_should_fail()) { 390 bithenge_node_dec_ref(node); 391 return ENOMEM; 392 } 297 393 scope->params[i] = node; 298 394 return EOK; … … 300 396 301 397 /** Get a parameter. Note that range checking is not done in release builds. 398 * @memberof bithenge_scope_t 302 399 * @param scope The scope to get the parameter from. 303 400 * @param i The index of the parameter to set. … … 318 415 } 319 416 417 418 419 /***************** barrier_transform *****************/ 420 320 421 typedef struct { 321 422 bithenge_transform_t base; … … 344 445 return rc; 345 446 bithenge_scope_set_barrier(inner_scope); 346 rc = bithenge_transform_apply(self->transform, scope, in, out); 447 bithenge_scope_set_in_node(inner_scope, in); 448 rc = bithenge_transform_apply(self->transform, inner_scope, in, out); 347 449 bithenge_scope_dec_ref(inner_scope); 348 450 return rc; … … 358 460 return rc; 359 461 bithenge_scope_set_barrier(inner_scope); 360 rc = bithenge_transform_prefix_length(self->transform, scope, in, out); 462 bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in)); 463 rc = bithenge_transform_prefix_length(self->transform, inner_scope, in, 464 out); 361 465 bithenge_scope_dec_ref(inner_scope); 362 466 return rc; … … 373 477 return rc; 374 478 bithenge_scope_set_barrier(inner_scope); 375 rc = bithenge_transform_prefix_apply(self->transform, scope, in, 479 bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in)); 480 rc = bithenge_transform_prefix_apply(self->transform, inner_scope, in, 376 481 out_node, out_length); 377 482 bithenge_scope_dec_ref(inner_scope); … … 393 498 }; 394 499 500 /** Set the subtransform of a barrier transform. This must be done before the 501 * barrier transform is used. Takes a reference to @a transform. 502 * @param base The barrier transform. 503 * @param transform The subtransform to use for all operations. 504 * @return EOK on success or an error code from errno.h. */ 505 int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *base, 506 bithenge_transform_t *transform) 507 { 508 assert(transform); 509 assert(bithenge_transform_num_params(transform) == 0); 510 511 if (bithenge_should_fail()) { 512 bithenge_transform_dec_ref(transform); 513 return ENOMEM; 514 } 515 516 barrier_transform_t *self = transform_as_barrier(base); 517 assert(!self->transform); 518 self->transform = transform; 519 return EOK; 520 } 521 395 522 /** Create a wrapper transform that creates a new scope. This ensures nothing 396 523 * from the outer scope is passed in, other than parameters. The wrapper may 397 * have a different value for num_params. T akes a reference to @a transform,398 * which it will use for all operations.524 * have a different value for num_params. The subtransform must be set with @a 525 * bithenge_barrier_transform_set_subtransform before the result is used. 399 526 * @param[out] out Holds the created transform. 400 * @param transform The transform to wrap.401 527 * @param num_params The number of parameters to require, which may be 0. 402 528 * @return EOK on success or an error code from errno.h. */ 403 int bithenge_new_barrier_transform(bithenge_transform_t **out, 404 bithenge_transform_t *transform, int num_params) 405 { 406 assert(transform); 407 assert(bithenge_transform_num_params(transform) == 0); 408 529 int bithenge_new_barrier_transform(bithenge_transform_t **out, int num_params) 530 { 409 531 int rc; 410 532 barrier_transform_t *self = malloc(sizeof(*self)); … … 417 539 if (rc != EOK) 418 540 goto error; 419 self->transform = transform;541 self->transform = NULL; 420 542 *out = barrier_as_transform(self); 421 543 return EOK; 422 544 error: 423 bithenge_transform_dec_ref(transform);424 545 free(self); 425 546 return rc; … … 480 601 { 481 602 char buffer; 482 *out_size = 1; 483 int rc = bithenge_blob_read_bits(blob, 0, &buffer, out_size, true); 484 if (rc != EOK) 485 return rc; 486 if (*out_size != 1) 487 return EINVAL; 603 aoff64_t size = 1; 604 int rc = bithenge_blob_read_bits(blob, 0, &buffer, &size, true); 605 if (rc != EOK) 606 return rc; 607 if (size != 1) 608 return EINVAL; 609 if (out_size) 610 *out_size = size; 488 611 return bithenge_new_boolean_node(out_node, (buffer & 1) != 0); 489 612 } … … 758 881 } 759 882 883 /** @cond internal */ 760 884 #define MAKE_UINT_TRANSFORM(NAME, TYPE, ENDIAN, PREFIX_LENGTH_FUNC) \ 761 885 static int NAME##_apply(bithenge_transform_t *self, \ … … 795 919 MAKE_UINT_TRANSFORM(uint32le, uint32_t, uint32_t_le2host, prefix_length_4); 796 920 MAKE_UINT_TRANSFORM(uint32be, uint32_t, uint32_t_be2host, prefix_length_4); 797 MAKE_UINT_TRANSFORM(uint64le, uint64_t, uint32_t_le2host, prefix_length_8); 798 MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint32_t_be2host, prefix_length_8); 921 MAKE_UINT_TRANSFORM(uint64le, uint64_t, uint64_t_le2host, prefix_length_8); 922 MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint64_t_be2host, prefix_length_8); 923 /** @endcond */ 799 924 800 925 … … 822 947 return EINVAL; 823 948 824 *out_size = num_bits;949 aoff64_t size = num_bits; 825 950 uint8_t buffer[sizeof(bithenge_int_t)]; 826 rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, out_size,951 rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, &size, 827 952 little_endian); 828 953 if (rc != EOK) 829 954 return rc; 830 if (*out_size != (aoff64_t)num_bits) 831 return EINVAL; 955 if (size != (aoff64_t)num_bits) 956 return EINVAL; 957 if (out_size) 958 *out_size = size; 832 959 833 960 bithenge_int_t result = 0; … … 948 1075 bithenge_named_transform_t *bithenge_primitive_transforms = primitive_transforms; 949 1076 950 typedef struct {951 bithenge_transform_t base;952 bithenge_transform_t **xforms;953 size_t num;954 } compose_transform_t;955 956 static bithenge_transform_t *compose_as_transform(compose_transform_t *xform)957 {958 return &xform->base;959 }960 961 static compose_transform_t *transform_as_compose(bithenge_transform_t *xform)962 {963 return (compose_transform_t *)xform;964 }965 966 static int compose_apply(bithenge_transform_t *base, bithenge_scope_t *scope,967 bithenge_node_t *in, bithenge_node_t **out)968 {969 int rc;970 compose_transform_t *self = transform_as_compose(base);971 bithenge_node_inc_ref(in);972 973 /* i ranges from (self->num - 1) to 0 inside the loop. */974 for (size_t i = self->num; i--; ) {975 bithenge_node_t *tmp;976 rc = bithenge_transform_apply(self->xforms[i], scope, in,977 &tmp);978 bithenge_node_dec_ref(in);979 if (rc != EOK)980 return rc;981 in = tmp;982 }983 984 *out = in;985 return rc;986 }987 988 static int compose_prefix_length(bithenge_transform_t *base,989 bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)990 {991 compose_transform_t *self = transform_as_compose(base);992 return bithenge_transform_prefix_length(self->xforms[self->num - 1],993 scope, blob, out);994 }995 996 static void compose_destroy(bithenge_transform_t *base)997 {998 compose_transform_t *self = transform_as_compose(base);999 for (size_t i = 0; i < self->num; i++)1000 bithenge_transform_dec_ref(self->xforms[i]);1001 free(self->xforms);1002 free(self);1003 }1004 1005 static const bithenge_transform_ops_t compose_transform_ops = {1006 .apply = compose_apply,1007 .prefix_length = compose_prefix_length,1008 .destroy = compose_destroy,1009 };1010 1011 /** Create a composition of multiple transforms. When the result is applied to a1012 * node, each transform is applied in turn, with the last transform applied1013 * first. @a xforms may contain any number of transforms or no transforms at1014 * all. This function takes ownership of @a xforms and the references therein.1015 * @param[out] out Holds the result.1016 * @param[in] xforms The transforms to apply.1017 * @param num The number of transforms.1018 * @return EOK on success or an error code from errno.h. */1019 int bithenge_new_composed_transform(bithenge_transform_t **out,1020 bithenge_transform_t **xforms, size_t num)1021 {1022 if (num == 0) {1023 /* TODO: optimize */1024 } else if (num == 1) {1025 *out = xforms[0];1026 free(xforms);1027 return EOK;1028 }1029 1030 int rc;1031 compose_transform_t *self = malloc(sizeof(*self));1032 if (!self) {1033 rc = ENOMEM;1034 goto error;1035 }1036 rc = bithenge_init_transform(compose_as_transform(self),1037 &compose_transform_ops, 0);1038 if (rc != EOK)1039 goto error;1040 self->xforms = xforms;1041 self->num = num;1042 *out = compose_as_transform(self);1043 return EOK;1044 error:1045 for (size_t i = 0; i < num; i++)1046 bithenge_transform_dec_ref(xforms[i]);1047 free(xforms);1048 free(self);1049 return rc;1050 }1051 1052 1077 /** @} 1053 1078 */ -
uspace/lib/bithenge/transform.h
r0da6c04 r5e718d9 54 54 unsigned int refs; 55 55 struct bithenge_scope *outer; 56 char *error; 56 57 bool barrier; 57 58 int num_params; … … 61 62 } bithenge_scope_t; 62 63 63 static inline void bithenge_scope_inc_ref(bithenge_scope_t *self) { 64 /** Increment a scope's reference count. 65 * @memberof bithenge_scope_t 66 * @param self The scope to reference. */ 67 static inline void bithenge_scope_inc_ref(bithenge_scope_t *self) 68 { 69 assert(self); 64 70 self->refs++; 65 71 } … … 109 115 return; 110 116 assert(self->ops); 117 assert(self->refs > 0); 111 118 if (--self->refs == 0) 112 119 self->ops->destroy(self); … … 115 122 /** A transform with a name. */ 116 123 typedef struct { 124 /** The transform's name. */ 117 125 const char *name; 126 /** The transform. */ 118 127 bithenge_transform_t *transform; 119 128 } bithenge_named_transform_t; 120 129 130 /** Transform that decodes an 8-bit unsigned integer */ 131 extern bithenge_transform_t bithenge_uint8_transform; 132 /** Transform that decodes a 16-bit little-endian unsigned integer */ 133 extern bithenge_transform_t bithenge_uint16le_transform; 134 /** Transform that decodes a 16-bit big-endian unsigned integer */ 135 extern bithenge_transform_t bithenge_uint16be_transform; 136 /** Transform that decodes a 32-bit little-endian unsigned integer */ 137 extern bithenge_transform_t bithenge_uint32le_transform; 138 /** Transform that decodes a 32-bit big-endian unsigned integer */ 139 extern bithenge_transform_t bithenge_uint32be_transform; 140 /** Transform that decodes a 64-bit little-endian unsigned integer */ 141 extern bithenge_transform_t bithenge_uint64le_transform; 142 /** Transform that decodes a 64-bit big-endian unsigned integer */ 143 extern bithenge_transform_t bithenge_uint64be_transform; 144 145 /** @cond */ 121 146 extern bithenge_transform_t bithenge_ascii_transform; 122 147 extern bithenge_transform_t bithenge_bit_transform; … … 126 151 extern bithenge_transform_t bithenge_known_length_transform; 127 152 extern bithenge_transform_t bithenge_nonzero_boolean_transform; 128 extern bithenge_transform_t bithenge_uint8_transform;129 extern bithenge_transform_t bithenge_uint16le_transform;130 extern bithenge_transform_t bithenge_uint16be_transform;131 extern bithenge_transform_t bithenge_uint32le_transform;132 extern bithenge_transform_t bithenge_uint32be_transform;133 extern bithenge_transform_t bithenge_uint64le_transform;134 extern bithenge_transform_t bithenge_uint64be_transform;135 153 extern bithenge_transform_t bithenge_uint_le_transform; 136 154 extern bithenge_transform_t bithenge_uint_be_transform; 137 155 extern bithenge_transform_t bithenge_zero_terminated_transform; 138 156 extern bithenge_named_transform_t *bithenge_primitive_transforms; 139 157 /** @endcond */ 158 159 /** @memberof bithenge_transform_t */ 140 160 int bithenge_init_transform(bithenge_transform_t *, 141 161 const bithenge_transform_ops_t *, int); 162 /** @memberof bithenge_transform_t */ 142 163 int bithenge_transform_apply(bithenge_transform_t *, bithenge_scope_t *, 143 164 bithenge_node_t *, bithenge_node_t **); 165 /** @memberof bithenge_transform_t */ 144 166 int bithenge_transform_prefix_length(bithenge_transform_t *, 145 167 bithenge_scope_t *, bithenge_blob_t *, aoff64_t *); 168 /** @memberof bithenge_transform_t */ 146 169 int bithenge_transform_prefix_apply(bithenge_transform_t *, bithenge_scope_t *, 147 170 bithenge_blob_t *, bithenge_node_t **, aoff64_t *); 148 int bithenge_new_barrier_transform(bithenge_transform_t **, 149 bithenge_transform_t *, int); 150 int bithenge_new_composed_transform(bithenge_transform_t **, 151 bithenge_transform_t **, size_t); 152 171 int bithenge_new_barrier_transform(bithenge_transform_t **, int); 172 int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *, 173 bithenge_transform_t *); 174 175 /** @memberof bithenge_scope_t */ 153 176 int bithenge_scope_new(bithenge_scope_t **, bithenge_scope_t *); 177 /** @memberof bithenge_scope_t */ 154 178 void bithenge_scope_dec_ref(bithenge_scope_t *); 179 /** @memberof bithenge_scope_t */ 155 180 bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *); 181 /** @memberof bithenge_scope_t */ 182 const char *bithenge_scope_get_error(bithenge_scope_t *); 183 /** @memberof bithenge_scope_t */ 184 int bithenge_scope_error(bithenge_scope_t *, const char *, ...); 185 /** @memberof bithenge_scope_t */ 156 186 bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *); 187 /** @memberof bithenge_scope_t */ 157 188 void bithenge_scope_set_current_node(bithenge_scope_t *, bithenge_node_t *); 189 /** @memberof bithenge_scope_t */ 158 190 bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *); 191 /** @memberof bithenge_scope_t */ 159 192 void bithenge_scope_set_in_node(bithenge_scope_t *, bithenge_node_t *); 193 /** @memberof bithenge_scope_t */ 160 194 void bithenge_scope_set_barrier(bithenge_scope_t *); 195 /** @memberof bithenge_scope_t */ 161 196 bool bithenge_scope_is_barrier(bithenge_scope_t *); 197 /** @memberof bithenge_scope_t */ 162 198 int bithenge_scope_alloc_params(bithenge_scope_t *, int); 199 /** @memberof bithenge_scope_t */ 163 200 int bithenge_scope_set_param(bithenge_scope_t *, int, bithenge_node_t *); 201 /** @memberof bithenge_scope_t */ 164 202 int bithenge_scope_get_param(bithenge_scope_t *, int, bithenge_node_t **); 165 203 -
uspace/lib/bithenge/tree.c
r0da6c04 r5e718d9 76 76 if (!node) 77 77 return; 78 assert (node->refs > 0); 78 79 if (--node->refs == 0) 79 80 node_destroy(node); … … 89 90 { 90 91 get_for_each_data_t *data = (get_for_each_data_t *)raw_data; 91 bool equal = bithenge_node_equal(key, data->key); 92 bool equal; 93 int rc = bithenge_node_equal(&equal, key, data->key); 92 94 bithenge_node_dec_ref(key); 95 if (rc != EOK) 96 return rc; 93 97 if (equal) { 94 98 *data->out = value; … … 101 105 /** Get a child of a node. Takes ownership of the key. If the node does not 102 106 * provide this function, for_each will be used as an alternative, which may be 103 * very slow. 104 * @memberof bithenge_node_t 105 * @param self The internal node to find a child of. 107 * very slow. Also works for blob nodes to find the byte value at a given 108 * index. 109 * @memberof bithenge_node_t 110 * @param self The internal/blob node to find a child of. 106 111 * @param key The key to search for. 107 112 * @param[out] out Holds the found node. … … 111 116 bithenge_node_t **out) 112 117 { 118 if (self->type == BITHENGE_NODE_BLOB) { 119 if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) { 120 bithenge_node_dec_ref(key); 121 return ENOENT; 122 } 123 bithenge_int_t offset = bithenge_integer_node_value(key); 124 bithenge_node_dec_ref(key); 125 uint8_t byte; 126 aoff64_t size = 1; 127 int rc = bithenge_blob_read(bithenge_node_as_blob(self), 128 offset, (char *)&byte, &size); 129 if (rc != EOK) 130 return rc; 131 if (size != 1) 132 return ENOENT; 133 134 return bithenge_new_integer_node(out, byte); 135 } 136 113 137 assert(self->type == BITHENGE_NODE_INTERNAL); 114 138 if (self->internal_ops->get) … … 174 198 int bithenge_new_empty_internal_node(bithenge_node_t **out) 175 199 { 200 if (bithenge_should_fail()) 201 return ENOMEM; 176 202 bithenge_node_inc_ref(&empty_internal_node); 177 203 *out = &empty_internal_node; … … 277 303 { 278 304 assert(out); 305 if (bithenge_should_fail()) 306 return ENOMEM; 279 307 *out = value ? &true_node : &false_node; 280 308 (*out)->refs++; … … 327 355 * internal nodes. Takes ownership of nothing. 328 356 * @memberof bithenge_node_t 357 * @param[out] out Holds whether the nodes are equal. 329 358 * @param a, b Nodes to compare. 330 * @return Whether the nodes are equal. If an error occurs, returns false. 331 * @todo Add support for internal nodes. 332 */ 333 bool bithenge_node_equal(bithenge_node_t *a, bithenge_node_t *b) 334 { 335 if (a->type != b->type) 336 return false; 359 * @return EOK on success or an error code from errno.h. 360 * @todo Add support for internal nodes. */ 361 int bithenge_node_equal(bool *out, bithenge_node_t *a, bithenge_node_t *b) 362 { 363 if (a->type != b->type) { 364 *out = false; 365 return EOK; 366 } 337 367 switch (a->type) { 338 368 case BITHENGE_NODE_INTERNAL: 339 return false; 369 *out = false; 370 return EOK; 340 371 case BITHENGE_NODE_BOOLEAN: 341 return a->boolean_value == b->boolean_value; 372 *out = a->boolean_value == b->boolean_value; 373 return EOK; 342 374 case BITHENGE_NODE_INTEGER: 343 return a->integer_value == b->integer_value; 375 *out = a->integer_value == b->integer_value; 376 return EOK; 344 377 case BITHENGE_NODE_STRING: 345 return !str_cmp(a->string_value.ptr, b->string_value.ptr); 378 *out = !str_cmp(a->string_value.ptr, b->string_value.ptr); 379 return EOK; 346 380 case BITHENGE_NODE_BLOB: 347 return bithenge_blob_equal( bithenge_node_as_blob(a),381 return bithenge_blob_equal(out, bithenge_node_as_blob(a), 348 382 bithenge_node_as_blob(b)); 349 383 } 350 return false;384 return EINVAL; 351 385 } 352 386 -
uspace/lib/bithenge/tree.h
r0da6c04 r5e718d9 56 56 } bithenge_node_type_t; 57 57 58 /** A tree node. It can have any of the types in @a bithenge_node_type_t. */ 58 59 typedef struct bithenge_node_t { 59 60 /** @privatesection */ … … 61 62 unsigned int refs; 62 63 union { 64 /** @privatesection */ 63 65 const struct bithenge_internal_node_ops_t *internal_ops; 64 66 bool boolean_value; 65 67 bithenge_int_t integer_value; 66 68 struct { 69 /** @privatesection */ 67 70 const char *ptr; 68 71 bool needs_free; … … 111 114 } 112 115 116 /** @memberof bithenge_node_t */ 113 117 void bithenge_node_dec_ref(bithenge_node_t *node); 114 118 … … 126 130 } 127 131 132 /** @memberof bithenge_node_t */ 128 133 int bithenge_node_get(bithenge_node_t *, bithenge_node_t *, 129 134 bithenge_node_t **); … … 159 164 } 160 165 166 /** @memberof bithenge_node_t */ 161 167 int bithenge_init_internal_node(bithenge_node_t *, 162 168 const bithenge_internal_node_ops_t *); 169 /** @memberof bithenge_node_t */ 163 170 int bithenge_new_empty_internal_node(bithenge_node_t **); 171 /** @memberof bithenge_node_t */ 164 172 int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **, 165 173 bithenge_int_t, bool needs_free); 174 /** @memberof bithenge_node_t */ 166 175 int bithenge_new_boolean_node(bithenge_node_t **, bool); 176 /** @memberof bithenge_node_t */ 167 177 int bithenge_new_integer_node(bithenge_node_t **, bithenge_int_t); 178 /** @memberof bithenge_node_t */ 168 179 int bithenge_new_string_node(bithenge_node_t **, const char *, bool); 169 bool bithenge_node_equal(bithenge_node_t *, bithenge_node_t *); 180 /** @memberof bithenge_node_t */ 181 int bithenge_node_equal(bool *, bithenge_node_t *, bithenge_node_t *); 170 182 171 183 #endif
Note:
See TracChangeset
for help on using the changeset viewer.