Changeset c3437d9 in mainline for uspace/app/bithenge/sequence.c
- Timestamp:
- 2012-08-04T03:51:15Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0ce0103
- Parents:
- e3f2765
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bithenge/sequence.c
re3f2765 rc3437d9 44 44 45 45 46 /***************** seq_node *****************/ 47 46 48 typedef struct { 47 49 bithenge_node_t base; … … 236 238 bithenge_blob_dec_ref(self->blob); 237 239 free(self->ends); 240 } 241 242 static void seq_node_set_num_xforms(seq_node_t *self, 243 bithenge_int_t num_xforms) 244 { 245 self->num_xforms = num_xforms; 238 246 } 239 247 … … 270 278 271 279 280 /***************** bithenge_new_struct *****************/ 281 272 282 typedef struct { 273 283 bithenge_transform_t base; … … 581 591 582 592 593 /***************** bithenge_repeat_transform *****************/ 594 583 595 typedef struct { 584 596 bithenge_transform_t base; … … 636 648 rc = seq_node_subtransform(repeat_as_seq(self), 637 649 &subxform_result, i); 638 if (rc != EOK && self->count == -1) { 650 if ((rc == EINVAL || rc == ENOENT) && self->count == -1) { 651 self->count = i; 652 seq_node_set_num_xforms(repeat_as_seq(self), 653 self->count); 639 654 rc = EOK; 640 655 break; … … 845 860 } 846 861 862 863 864 /***************** bithenge_do_while_transform *****************/ 865 866 typedef struct { 867 bithenge_transform_t base; 868 bithenge_expression_t *expr; 869 bithenge_transform_t *xform; 870 } do_while_transform_t; 871 872 static inline bithenge_transform_t *do_while_as_transform( 873 do_while_transform_t *self) 874 { 875 return &self->base; 876 } 877 878 static inline do_while_transform_t *transform_as_do_while( 879 bithenge_transform_t *base) 880 { 881 return (do_while_transform_t *)base; 882 } 883 884 typedef struct { 885 seq_node_t base; 886 bool prefix; 887 bithenge_expression_t *expr; 888 bithenge_transform_t *xform; 889 bithenge_int_t count; 890 } do_while_node_t; 891 892 static seq_node_t *do_while_as_seq(do_while_node_t *self) 893 { 894 return &self->base; 895 } 896 897 static do_while_node_t *seq_as_do_while(seq_node_t *base) 898 { 899 return (do_while_node_t *)base; 900 } 901 902 static bithenge_node_t *do_while_as_node(do_while_node_t *self) 903 { 904 return seq_as_node(do_while_as_seq(self)); 905 } 906 907 static do_while_node_t *node_as_do_while(bithenge_node_t *base) 908 { 909 return seq_as_do_while(node_as_seq(base)); 910 } 911 912 static int do_while_node_for_each(bithenge_node_t *base, 913 bithenge_for_each_func_t func, void *data) 914 { 915 int rc = EOK; 916 do_while_node_t *self = node_as_do_while(base); 917 918 for (bithenge_int_t i = 0; ; i++) { 919 bithenge_node_t *subxform_result; 920 rc = seq_node_subtransform(do_while_as_seq(self), 921 &subxform_result, i); 922 if (rc != EOK) 923 return rc; 924 925 bithenge_node_t *key_node; 926 rc = bithenge_new_integer_node(&key_node, i); 927 if (rc != EOK) { 928 bithenge_node_dec_ref(subxform_result); 929 return rc; 930 } 931 bithenge_node_inc_ref(subxform_result); 932 rc = func(key_node, subxform_result, data); 933 if (rc != EOK) { 934 bithenge_node_dec_ref(subxform_result); 935 return rc; 936 } 937 938 bithenge_scope_t scope; 939 bithenge_scope_init(&scope); 940 rc = bithenge_scope_copy(&scope, 941 seq_node_scope(do_while_as_seq(self))); 942 bithenge_scope_set_current_node(&scope, subxform_result); 943 if (rc != EOK) { 944 bithenge_scope_destroy(&scope); 945 return rc; 946 } 947 bithenge_node_t *expr_result; 948 rc = bithenge_expression_evaluate(self->expr, &scope, 949 &expr_result); 950 bithenge_scope_destroy(&scope); 951 if (rc != EOK) 952 return rc; 953 if (bithenge_node_type(expr_result) != BITHENGE_NODE_BOOLEAN) { 954 bithenge_node_dec_ref(expr_result); 955 return EINVAL; 956 } 957 bool cond = bithenge_boolean_node_value(expr_result); 958 bithenge_node_dec_ref(expr_result); 959 if (!cond) { 960 self->count = i + 1; 961 seq_node_set_num_xforms(do_while_as_seq(self), 962 self->count); 963 break; 964 } 965 } 966 967 if (!self->prefix) { 968 bool complete; 969 rc = seq_node_complete(do_while_as_seq(self), &complete); 970 if (rc != EOK) 971 return rc; 972 if (!complete) 973 return EINVAL; 974 } 975 976 return rc; 977 } 978 979 static void do_while_node_destroy(bithenge_node_t *base) 980 { 981 do_while_node_t *self = node_as_do_while(base); 982 seq_node_destroy(do_while_as_seq(self)); 983 bithenge_expression_dec_ref(self->expr); 984 bithenge_transform_dec_ref(self->xform); 985 free(self); 986 } 987 988 static const bithenge_internal_node_ops_t do_while_node_ops = { 989 .for_each = do_while_node_for_each, 990 .destroy = do_while_node_destroy, 991 }; 992 993 static int do_while_node_get_transform(seq_node_t *base, 994 bithenge_transform_t **out, bithenge_int_t index) 995 { 996 do_while_node_t *self = seq_as_do_while(base); 997 *out = self->xform; 998 bithenge_transform_inc_ref(*out); 999 return EOK; 1000 } 1001 1002 static const seq_node_ops_t do_while_node_seq_ops = { 1003 .get_transform = do_while_node_get_transform, 1004 }; 1005 1006 static int do_while_transform_make_node(do_while_transform_t *self, 1007 bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob, 1008 bool prefix) 1009 { 1010 do_while_node_t *node = malloc(sizeof(*node)); 1011 if (!node) 1012 return ENOMEM; 1013 1014 int rc = bithenge_init_internal_node(do_while_as_node(node), 1015 &do_while_node_ops); 1016 if (rc != EOK) { 1017 free(node); 1018 return rc; 1019 } 1020 1021 rc = seq_node_init(do_while_as_seq(node), &do_while_node_seq_ops, 1022 scope, blob, -1, false); 1023 if (rc != EOK) { 1024 free(node); 1025 return rc; 1026 } 1027 1028 bithenge_transform_inc_ref(self->xform); 1029 node->xform = self->xform; 1030 bithenge_expression_inc_ref(self->expr); 1031 node->expr = self->expr; 1032 node->prefix = prefix; 1033 node->count = -1; 1034 *out = do_while_as_node(node); 1035 return EOK; 1036 } 1037 1038 static int do_while_transform_apply(bithenge_transform_t *base, 1039 bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out) 1040 { 1041 do_while_transform_t *self = transform_as_do_while(base); 1042 if (bithenge_node_type(in) != BITHENGE_NODE_BLOB) 1043 return EINVAL; 1044 return do_while_transform_make_node(self, out, scope, 1045 bithenge_node_as_blob(in), false); 1046 } 1047 1048 static int for_each_noop(bithenge_node_t *key, bithenge_node_t *value, 1049 void *data) 1050 { 1051 bithenge_node_dec_ref(key); 1052 bithenge_node_dec_ref(value); 1053 return EOK; 1054 } 1055 1056 static int do_while_transform_prefix_apply(bithenge_transform_t *base, 1057 bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node, 1058 aoff64_t *out_size) 1059 { 1060 do_while_transform_t *self = transform_as_do_while(base); 1061 int rc = do_while_transform_make_node(self, out_node, scope, blob, 1062 true); 1063 if (rc != EOK) 1064 return rc; 1065 1066 rc = bithenge_node_for_each(*out_node, for_each_noop, NULL); 1067 if (rc != EOK) { 1068 bithenge_node_dec_ref(*out_node); 1069 return rc; 1070 } 1071 1072 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, 1073 node_as_do_while(*out_node)->count); 1074 if (rc != EOK) { 1075 bithenge_node_dec_ref(*out_node); 1076 return rc; 1077 } 1078 1079 return EOK; 1080 } 1081 1082 static void do_while_transform_destroy(bithenge_transform_t *base) 1083 { 1084 do_while_transform_t *self = transform_as_do_while(base); 1085 bithenge_transform_dec_ref(self->xform); 1086 bithenge_expression_dec_ref(self->expr); 1087 free(self); 1088 } 1089 1090 static const bithenge_transform_ops_t do_while_transform_ops = { 1091 .apply = do_while_transform_apply, 1092 .prefix_apply = do_while_transform_prefix_apply, 1093 .destroy = do_while_transform_destroy, 1094 }; 1095 1096 /** Create a transform that applies its subtransform while an expression on the 1097 * result returns true. Takes a reference to @a xform and @a expr. 1098 * @param[out] out Holds the new transform. 1099 * @param xform The subtransform to apply repeatedly. 1100 * @param expr Applied in the result of each application of @a xform to 1101 * determine whether there will be more. 1102 * @return EOK on success or an error code from errno.h. */ 1103 int bithenge_do_while_transform(bithenge_transform_t **out, 1104 bithenge_transform_t *xform, bithenge_expression_t *expr) 1105 { 1106 int rc; 1107 do_while_transform_t *self = malloc(sizeof(*self)); 1108 if (!self) { 1109 rc = ENOMEM; 1110 goto error; 1111 } 1112 1113 rc = bithenge_init_transform(do_while_as_transform(self), 1114 &do_while_transform_ops, 0); 1115 if (rc != EOK) 1116 goto error; 1117 1118 self->expr = expr; 1119 self->xform = xform; 1120 *out = do_while_as_transform(self); 1121 return EOK; 1122 1123 error: 1124 free(self); 1125 bithenge_expression_dec_ref(expr); 1126 bithenge_transform_dec_ref(xform); 1127 return rc; 1128 } 1129 847 1130 /** @} 848 1131 */
Note:
See TracChangeset
for help on using the changeset viewer.