Changeset ee7cc3c in mainline
- Timestamp:
- 2012-08-02T22:29:50Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0caaaa00
- Parents:
- 0f8062a4
- Location:
- uspace/app/bithenge
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/sequence.c
r0f8062a4 ree7cc3c 37 37 #include <stdlib.h> 38 38 #include "blob.h" 39 #include "expression.h" 39 40 #include "os.h" 40 41 #include "sequence.h" … … 528 529 } 529 530 531 532 533 typedef struct { 534 bithenge_transform_t base; 535 bithenge_expression_t *expr; 536 bithenge_transform_t *xform; 537 } repeat_transform_t; 538 539 static inline bithenge_transform_t *repeat_as_transform( 540 repeat_transform_t *self) 541 { 542 return &self->base; 543 } 544 545 static inline repeat_transform_t *transform_as_repeat( 546 bithenge_transform_t *base) 547 { 548 return (repeat_transform_t *)base; 549 } 550 551 typedef struct { 552 seq_node_t base; 553 bool prefix; 554 bithenge_int_t count; 555 bithenge_transform_t *xform; 556 } repeat_node_t; 557 558 static seq_node_t *repeat_as_seq(repeat_node_t *self) 559 { 560 return &self->base; 561 } 562 563 static repeat_node_t *seq_as_repeat(seq_node_t *base) 564 { 565 return (repeat_node_t *)base; 566 } 567 568 static bithenge_node_t *repeat_as_node(repeat_node_t *self) 569 { 570 return seq_as_node(repeat_as_seq(self)); 571 } 572 573 static repeat_node_t *node_as_repeat(bithenge_node_t *base) 574 { 575 return seq_as_repeat(node_as_seq(base)); 576 } 577 578 static int repeat_node_for_each(bithenge_node_t *base, 579 bithenge_for_each_func_t func, void *data) 580 { 581 int rc = EOK; 582 repeat_node_t *self = node_as_repeat(base); 583 584 for (bithenge_int_t i = 0; i < self->count; i++) { 585 bithenge_node_t *subxform_result; 586 rc = seq_node_subtransform(repeat_as_seq(self), 587 &subxform_result, i); 588 if (rc != EOK) 589 return rc; 590 591 bithenge_node_t *key_node; 592 rc = bithenge_new_integer_node(&key_node, i); 593 if (rc != EOK) { 594 bithenge_node_dec_ref(subxform_result); 595 return rc; 596 } 597 rc = func(key_node, subxform_result, data); 598 if (rc != EOK) 599 return rc; 600 } 601 602 if (!self->prefix) { 603 bool complete; 604 rc = seq_node_complete(repeat_as_seq(self), &complete); 605 if (rc != EOK) 606 return rc; 607 if (!complete) 608 return EINVAL; 609 } 610 611 return rc; 612 } 613 614 static int repeat_node_get(bithenge_node_t *base, bithenge_node_t *key, 615 bithenge_node_t **out) 616 { 617 repeat_node_t *self = node_as_repeat(base); 618 619 if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) { 620 bithenge_node_dec_ref(key); 621 return ENOENT; 622 } 623 624 bithenge_int_t index = bithenge_integer_node_value(key); 625 bithenge_node_dec_ref(key); 626 if (index < 0 || index >= self->count) 627 return ENOENT; 628 return seq_node_subtransform(repeat_as_seq(self), out, index); 629 } 630 631 static void repeat_node_destroy(bithenge_node_t *base) 632 { 633 repeat_node_t *self = node_as_repeat(base); 634 seq_node_destroy(repeat_as_seq(self)); 635 bithenge_transform_dec_ref(self->xform); 636 free(self); 637 } 638 639 static const bithenge_internal_node_ops_t repeat_node_ops = { 640 .for_each = repeat_node_for_each, 641 .get = repeat_node_get, 642 .destroy = repeat_node_destroy, 643 }; 644 645 static int repeat_node_get_transform(seq_node_t *base, 646 bithenge_transform_t **out, bithenge_int_t index) 647 { 648 repeat_node_t *self = seq_as_repeat(base); 649 *out = self->xform; 650 bithenge_transform_inc_ref(*out); 651 return EOK; 652 } 653 654 static const seq_node_ops_t repeat_node_seq_ops = { 655 .get_transform = repeat_node_get_transform, 656 }; 657 658 static int repeat_transform_make_node(repeat_transform_t *self, 659 bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob, 660 bool prefix) 661 { 662 bithenge_int_t count; 663 bithenge_node_t *count_node; 664 int rc = bithenge_expression_evaluate(self->expr, scope, &count_node); 665 if (rc != EOK) 666 return rc; 667 if (bithenge_node_type(count_node) != BITHENGE_NODE_INTEGER) { 668 bithenge_node_dec_ref(count_node); 669 return EINVAL; 670 } 671 count = bithenge_integer_node_value(count_node); 672 bithenge_node_dec_ref(count_node); 673 if (count < 0) 674 return EINVAL; 675 676 repeat_node_t *node = malloc(sizeof(*node)); 677 if (!node) 678 return ENOMEM; 679 680 rc = bithenge_init_internal_node(repeat_as_node(node), 681 &repeat_node_ops); 682 if (rc != EOK) { 683 free(node); 684 return rc; 685 } 686 687 rc = seq_node_init(repeat_as_seq(node), &repeat_node_seq_ops, scope, 688 blob, count); 689 if (rc != EOK) { 690 free(node); 691 return rc; 692 } 693 694 bithenge_transform_inc_ref(self->xform); 695 node->xform = self->xform; 696 node->count = count; 697 *out = repeat_as_node(node); 698 return EOK; 699 } 700 701 static int repeat_transform_prefix_apply(bithenge_transform_t *base, 702 bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node, 703 aoff64_t *out_size) 704 { 705 repeat_transform_t *self = transform_as_repeat(base); 706 int rc = repeat_transform_make_node(self, out_node, scope, blob, true); 707 if (rc != EOK) 708 return rc; 709 710 bithenge_int_t count = node_as_repeat(*out_node)->count; 711 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, count); 712 if (rc != EOK) { 713 bithenge_node_dec_ref(*out_node); 714 return rc; 715 } 716 return EOK; 717 } 718 719 static void repeat_transform_destroy(bithenge_transform_t *base) 720 { 721 repeat_transform_t *self = transform_as_repeat(base); 722 bithenge_transform_dec_ref(self->xform); 723 bithenge_expression_dec_ref(self->expr); 724 free(self); 725 } 726 727 static const bithenge_transform_ops_t repeat_transform_ops = { 728 .prefix_apply = repeat_transform_prefix_apply, 729 .destroy = repeat_transform_destroy, 730 }; 731 732 /** Create a transform that applies its subtransform repeatedly. Takes a 733 * reference to @a xform and @a expr. 734 * @param[out] out Holds the new transform. 735 * @param xform The subtransform to apply repeatedly. 736 * @param expr Used to calculate the number of times @a xform will be applied. 737 * May be NULL, in which case @a xform will be applied indefinitely. 738 * @return EOK on success or an error code from errno.h. */ 739 int bithenge_repeat_transform(bithenge_transform_t **out, 740 bithenge_transform_t *xform, bithenge_expression_t *expr) 741 { 742 int rc; 743 repeat_transform_t *self = malloc(sizeof(*self)); 744 if (!self) { 745 rc = ENOMEM; 746 goto error; 747 } 748 749 rc = bithenge_init_transform(repeat_as_transform(self), 750 &repeat_transform_ops, 0); 751 if (rc != EOK) 752 goto error; 753 754 self->expr = expr; 755 self->xform = xform; 756 *out = repeat_as_transform(self); 757 return EOK; 758 759 error: 760 free(self); 761 bithenge_expression_dec_ref(expr); 762 bithenge_transform_dec_ref(xform); 763 return rc; 764 } 765 530 766 /** @} 531 767 */ -
uspace/app/bithenge/sequence.h
r0f8062a4 ree7cc3c 42 42 int bithenge_new_struct(bithenge_transform_t **, 43 43 bithenge_named_transform_t *); 44 int bithenge_repeat_transform(bithenge_transform_t **, bithenge_transform_t *, 45 bithenge_expression_t *); 44 46 45 47 #endif
Note:
See TracChangeset
for help on using the changeset viewer.