Changeset 5e718d9 in mainline for uspace/lib/bithenge/sequence.c
- Timestamp:
- 2012-08-21T10:04:16Z (12 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 67edca6
- Parents:
- 0da6c04 (diff), 6a97f2e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/bithenge/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,
Note:
See TracChangeset
for help on using the changeset viewer.