| 136 | } |
| 137 | |
| 138 | static errno_t seq_node_subtransform(seq_node_t *self, bithenge_node_t **out, |
| 139 | size_t index) |
| 140 | { |
| 141 | aoff64_t start_pos; |
| 142 | errno_t rc = seq_node_field_offset(self, &start_pos, index); |
| 143 | if (rc != EOK) |
| 144 | return rc; |
| 145 | |
| 146 | bithenge_transform_t *subxform; |
| 147 | rc = self->ops->get_transform(self, &subxform, index); |
| 148 | if (rc != EOK) |
| 149 | return rc; |
| 150 | |
| 151 | if (index == self->num_ends) { |
| 152 | /* |
| 153 | * We can apply the subtransform and cache its prefix length at |
| 154 | * the same time. |
| 155 | */ |
| 156 | bithenge_node_t *blob_node; |
| 157 | bithenge_blob_inc_ref(self->blob); |
| 158 | rc = bithenge_new_offset_blob(&blob_node, self->blob, |
| 159 | start_pos); |
| 160 | if (rc != EOK) { |
| 161 | bithenge_transform_dec_ref(subxform); |
| 162 | return rc; |
| 163 | } |
| 164 | |
| 165 | if (self->end_on_empty) { |
| 166 | bool empty; |
| 167 | rc = bithenge_blob_empty( |
| 168 | bithenge_node_as_blob(blob_node), &empty); |
| 169 | if (rc == EOK && empty) { |
| 170 | self->num_xforms = self->num_ends; |
| 171 | rc = ENOENT; |
| 172 | } |
| 173 | if (rc != EOK) { |
| 174 | bithenge_transform_dec_ref(subxform); |
| 175 | bithenge_node_dec_ref(blob_node); |
| 176 | return rc; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | aoff64_t size; |
| 181 | rc = bithenge_transform_prefix_apply(subxform, self->scope, |
| 182 | bithenge_node_as_blob(blob_node), out, &size); |
| 183 | bithenge_node_dec_ref(blob_node); |
| 184 | bithenge_transform_dec_ref(subxform); |
| 185 | if (rc != EOK) |
| 186 | return rc; |
| 187 | |
| 188 | if (self->num_xforms == -1) { |
| 189 | aoff64_t *new_ends = realloc(self->ends, |
| 190 | (self->num_ends + 1) * sizeof(*new_ends)); |
| 191 | if (!new_ends) |
| 192 | return ENOMEM; |
| 193 | self->ends = new_ends; |
| 194 | } |
| 195 | self->ends[self->num_ends++] = start_pos + size; |
no test coverage detected