Changeset 0f8062a4 in mainline
- Timestamp:
- 2012-08-02T22:08:59Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- ee7cc3c
- Parents:
- b8d45e9e
- Location:
- uspace/app/bithenge
- Files:
-
- 2 added
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/Makefile
rb8d45e9e r0f8062a4 39 39 print.c \ 40 40 script.c \ 41 sequence.c \ 41 42 source.c \ 42 43 test.c \ -
uspace/app/bithenge/Makefile.linux
rb8d45e9e r0f8062a4 40 40 print.c \ 41 41 script.c \ 42 sequence.c \ 42 43 source.c \ 43 44 test.c \ -
uspace/app/bithenge/script.c
rb8d45e9e r0f8062a4 41 41 #include "os.h" 42 42 #include "script.h" 43 #include "sequence.h" 43 44 #include "transform.h" 44 45 #include "tree.h" -
uspace/app/bithenge/transform.c
rb8d45e9e r0f8062a4 618 618 typedef struct { 619 619 bithenge_transform_t base; 620 bithenge_named_transform_t *subtransforms;621 size_t num_subtransforms;622 } struct_transform_t;623 624 typedef struct {625 bithenge_node_t base;626 bithenge_scope_t scope;627 struct_transform_t *transform;628 bithenge_blob_t *blob;629 aoff64_t *ends;630 size_t num_ends;631 bool prefix;632 } struct_node_t;633 634 static bithenge_node_t *struct_as_node(struct_node_t *node)635 {636 return &node->base;637 }638 639 static struct_node_t *node_as_struct(bithenge_node_t *node)640 {641 return (struct_node_t *)node;642 }643 644 static bithenge_transform_t *struct_as_transform(struct_transform_t *xform)645 {646 return &xform->base;647 }648 649 static struct_transform_t *transform_as_struct(bithenge_transform_t *xform)650 {651 return (struct_transform_t *)xform;652 }653 654 static int struct_node_field_offset(struct_node_t *self, aoff64_t *out,655 size_t index)656 {657 if (index == 0) {658 *out = 0;659 return EOK;660 }661 index--;662 aoff64_t prev_offset =663 self->num_ends ? self->ends[self->num_ends - 1] : 0;664 for (; self->num_ends <= index; self->num_ends++) {665 bithenge_node_t *subblob_node;666 bithenge_blob_inc_ref(self->blob);667 int rc = bithenge_new_offset_blob(&subblob_node, self->blob,668 prev_offset);669 if (rc != EOK)670 return rc;671 672 bithenge_blob_t *subblob = bithenge_node_as_blob(subblob_node);673 aoff64_t field_size;674 rc = bithenge_transform_prefix_length(675 self->transform->subtransforms[self->num_ends].transform,676 &self->scope, subblob, &field_size);677 bithenge_node_dec_ref(subblob_node);678 if (rc != EOK)679 return rc;680 681 prev_offset = self->ends[self->num_ends] =682 prev_offset + field_size;683 }684 *out = self->ends[index];685 return EOK;686 }687 688 static int struct_node_subtransform(struct_node_t *self, bithenge_node_t **out,689 size_t index)690 {691 aoff64_t start_pos;692 int rc = struct_node_field_offset(self, &start_pos, index);693 if (rc != EOK)694 return rc;695 696 if (index == self->num_ends) {697 /* We can apply the subtransform and cache its prefix length at698 * the same time. */699 bithenge_node_t *blob_node;700 bithenge_blob_inc_ref(self->blob);701 rc = bithenge_new_offset_blob(&blob_node, self->blob,702 start_pos);703 if (rc != EOK)704 return rc;705 706 aoff64_t size;707 rc = bithenge_transform_prefix_apply(708 self->transform->subtransforms[index].transform,709 &self->scope, bithenge_node_as_blob(blob_node), out,710 &size);711 bithenge_node_dec_ref(blob_node);712 if (rc != EOK)713 return rc;714 715 self->ends[self->num_ends++] = start_pos + size;716 } else {717 aoff64_t end_pos;718 int rc = struct_node_field_offset(self, &end_pos, index + 1);719 if (rc != EOK)720 return rc;721 722 bithenge_node_t *blob_node;723 bithenge_blob_inc_ref(self->blob);724 rc = bithenge_new_subblob(&blob_node, self->blob, start_pos,725 end_pos - start_pos);726 if (rc != EOK)727 return rc;728 729 rc = bithenge_transform_apply(730 self->transform->subtransforms[index].transform,731 &self->scope, blob_node, out);732 bithenge_node_dec_ref(blob_node);733 if (rc != EOK)734 return rc;735 }736 737 return EOK;738 }739 740 static int struct_node_for_each(bithenge_node_t *base,741 bithenge_for_each_func_t func, void *data)742 {743 int rc = EOK;744 struct_node_t *self = node_as_struct(base);745 bithenge_named_transform_t *subxforms =746 self->transform->subtransforms;747 748 for (size_t i = 0; subxforms[i].transform; i++) {749 bithenge_node_t *subxform_result;750 rc = struct_node_subtransform(self, &subxform_result, i);751 if (rc != EOK)752 return rc;753 754 if (subxforms[i].name) {755 bithenge_node_t *name_node;756 rc = bithenge_new_string_node(&name_node,757 subxforms[i].name, false);758 if (rc == EOK) {759 rc = func(name_node, subxform_result, data);760 subxform_result = NULL;761 }762 } else {763 if (bithenge_node_type(subxform_result) !=764 BITHENGE_NODE_INTERNAL) {765 rc = EINVAL;766 } else {767 rc = bithenge_node_for_each(subxform_result,768 func, data);769 }770 }771 bithenge_node_dec_ref(subxform_result);772 if (rc != EOK)773 return rc;774 }775 776 if (!self->prefix) {777 aoff64_t blob_size, end_pos;778 rc = bithenge_blob_size(self->blob, &blob_size);779 if (rc != EOK)780 return rc;781 rc = struct_node_field_offset(self, &end_pos,782 self->transform->num_subtransforms);783 if (rc != EOK)784 return rc;785 if (blob_size != end_pos) {786 rc = EINVAL;787 return rc;788 }789 }790 791 return rc;792 }793 794 static int struct_node_get(bithenge_node_t *base, bithenge_node_t *key,795 bithenge_node_t **out)796 {797 struct_node_t *self = node_as_struct(base);798 799 if (bithenge_node_type(key) != BITHENGE_NODE_STRING) {800 bithenge_node_dec_ref(key);801 return ENOENT;802 }803 const char *name = bithenge_string_node_value(key);804 805 for (size_t i = 0; self->transform->subtransforms[i].transform; i++) {806 if (self->transform->subtransforms[i].name807 && !str_cmp(name, self->transform->subtransforms[i].name)) {808 bithenge_node_dec_ref(key);809 return struct_node_subtransform(self, out, i);810 }811 }812 813 for (size_t i = 0; self->transform->subtransforms[i].transform; i++) {814 if (self->transform->subtransforms[i].name)815 continue;816 bithenge_node_t *subxform_result;817 int rc = struct_node_subtransform(self, &subxform_result, i);818 if (rc != EOK) {819 bithenge_node_dec_ref(key);820 return rc;821 }822 if (bithenge_node_type(subxform_result) !=823 BITHENGE_NODE_INTERNAL) {824 bithenge_node_dec_ref(subxform_result);825 bithenge_node_dec_ref(key);826 return EINVAL;827 }828 bithenge_node_inc_ref(key);829 rc = bithenge_node_get(subxform_result, key, out);830 bithenge_node_dec_ref(subxform_result);831 if (rc != ENOENT) {832 bithenge_node_dec_ref(key);833 return rc;834 }835 }836 837 bithenge_node_dec_ref(key);838 return ENOENT;839 }840 841 static void struct_node_destroy(bithenge_node_t *base)842 {843 struct_node_t *node = node_as_struct(base);844 845 /* We didn't inc_ref for the scope in struct_transform_make_node, so846 * make sure it doesn't try to dec_ref. */847 node->scope.current_node = NULL;848 bithenge_scope_destroy(&node->scope);849 850 bithenge_transform_dec_ref(struct_as_transform(node->transform));851 bithenge_blob_dec_ref(node->blob);852 free(node->ends);853 free(node);854 }855 856 static const bithenge_internal_node_ops_t struct_node_ops = {857 .for_each = struct_node_for_each,858 .get = struct_node_get,859 .destroy = struct_node_destroy,860 };861 862 static int struct_transform_make_node(struct_transform_t *self,863 bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,864 bool prefix)865 {866 struct_node_t *node = malloc(sizeof(*node));867 if (!node)868 return ENOMEM;869 870 bithenge_scope_init(&node->scope);871 int rc = bithenge_scope_copy(&node->scope, scope);872 if (rc != EOK) {873 free(node);874 return rc;875 }876 877 node->ends = malloc(sizeof(*node->ends) * self->num_subtransforms);878 if (!node->ends) {879 bithenge_scope_destroy(&node->scope);880 free(node);881 return ENOMEM;882 }883 884 rc = bithenge_init_internal_node(struct_as_node(node),885 &struct_node_ops);886 if (rc != EOK) {887 bithenge_scope_destroy(&node->scope);888 free(node->ends);889 free(node);890 return rc;891 }892 893 bithenge_transform_inc_ref(struct_as_transform(self));894 bithenge_blob_inc_ref(blob);895 node->transform = self;896 node->blob = blob;897 node->prefix = prefix;898 node->num_ends = 0;899 *out = struct_as_node(node);900 901 /* We should inc_ref(*out) here, but that would make a cycle. Instead,902 * we leave it 1 too low, so that when the only remaining use of *out903 * is the scope, *out will be destroyed. Also see the comment in904 * struct_node_destroy. */905 bithenge_scope_set_current_node(&node->scope, *out);906 907 return EOK;908 }909 910 static int struct_transform_apply(bithenge_transform_t *base,911 bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)912 {913 struct_transform_t *self = transform_as_struct(base);914 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)915 return EINVAL;916 return struct_transform_make_node(self, out, scope,917 bithenge_node_as_blob(in), false);918 }919 920 static int struct_transform_prefix_length(bithenge_transform_t *base,921 bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)922 {923 struct_transform_t *self = transform_as_struct(base);924 bithenge_node_t *struct_node;925 int rc = struct_transform_make_node(self, &struct_node, scope, blob,926 true);927 if (rc != EOK)928 return rc;929 930 rc = struct_node_field_offset(node_as_struct(struct_node), out,931 self->num_subtransforms);932 bithenge_node_dec_ref(struct_node);933 return rc;934 }935 936 static int struct_transform_prefix_apply(bithenge_transform_t *base,937 bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,938 aoff64_t *out_size)939 {940 struct_transform_t *self = transform_as_struct(base);941 int rc = struct_transform_make_node(self, out_node, scope, blob,942 true);943 if (rc != EOK)944 return rc;945 946 rc = struct_node_field_offset(node_as_struct(*out_node), out_size,947 self->num_subtransforms);948 if (rc != EOK) {949 bithenge_node_dec_ref(*out_node);950 return rc;951 }952 953 return EOK;954 }955 956 static void free_subtransforms(bithenge_named_transform_t *subtransforms)957 {958 for (size_t i = 0; subtransforms[i].transform; i++) {959 free((void *)subtransforms[i].name);960 bithenge_transform_dec_ref(subtransforms[i].transform);961 }962 free(subtransforms);963 }964 965 static void struct_transform_destroy(bithenge_transform_t *base)966 {967 struct_transform_t *self = transform_as_struct(base);968 free_subtransforms(self->subtransforms);969 free(self);970 }971 972 static bithenge_transform_ops_t struct_transform_ops = {973 .apply = struct_transform_apply,974 .prefix_length = struct_transform_prefix_length,975 .prefix_apply = struct_transform_prefix_apply,976 .destroy = struct_transform_destroy,977 };978 979 /** Create a struct transform. The transform will apply its subtransforms980 * sequentially to a blob to create an internal node. Each result is either981 * given a key from @a subtransforms or, if the name is NULL, the result's keys982 * and values are merged into the struct transform's result. This function983 * takes ownership of @a subtransforms and the names and references therein.984 * @param[out] out Stores the created transform.985 * @param subtransforms The subtransforms and field names.986 * @return EOK on success or an error code from errno.h. */987 int bithenge_new_struct(bithenge_transform_t **out,988 bithenge_named_transform_t *subtransforms)989 {990 int rc;991 struct_transform_t *self = malloc(sizeof(*self));992 if (!self) {993 rc = ENOMEM;994 goto error;995 }996 rc = bithenge_init_transform(struct_as_transform(self),997 &struct_transform_ops, 0);998 if (rc != EOK)999 goto error;1000 self->subtransforms = subtransforms;1001 self->num_subtransforms = 0;1002 for (self->num_subtransforms = 0;1003 subtransforms[self->num_subtransforms].transform;1004 self->num_subtransforms++);1005 *out = struct_as_transform(self);1006 return EOK;1007 error:1008 free_subtransforms(subtransforms);1009 free(self);1010 return rc;1011 }1012 1013 typedef struct {1014 bithenge_transform_t base;1015 620 bithenge_transform_t **xforms; 1016 621 size_t num; -
uspace/app/bithenge/transform.h
rb8d45e9e r0f8062a4 134 134 int bithenge_new_scope_transform(bithenge_transform_t **, 135 135 bithenge_transform_t *, int); 136 int bithenge_new_struct(bithenge_transform_t **,137 bithenge_named_transform_t *);138 136 int bithenge_new_composed_transform(bithenge_transform_t **, 139 137 bithenge_transform_t **, size_t);
Note:
See TracChangeset
for help on using the changeset viewer.