Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset cb4a66d2 in mainline


Ignore:
Timestamp:
2012-08-01T23:43:10Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
b8d45e9e
Parents:
47a728e1
Message:

Bithenge: add transform_prefix_apply

  • makes struct nodes more efficient in some cases.
  • will make certain future transforms easier to implement.
Location:
uspace/app/bithenge
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/transform.c

    r47a728e1 rcb4a66d2  
    5454{
    5555        assert(ops);
    56         assert(ops->apply);
     56        assert(ops->apply || ops->prefix_apply);
    5757        assert(ops->destroy);
    5858        self->ops = ops;
     
    6565{
    6666        assert(false);
     67}
     68
     69/** Apply a transform. Takes ownership of nothing.
     70 * @memberof bithenge_transform_t
     71 * @param self The transform.
     72 * @param scope The scope.
     73 * @param in The input tree.
     74 * @param[out] out Where the output tree will be stored.
     75 * @return EOK on success or an error code from errno.h. */
     76int bithenge_transform_apply(bithenge_transform_t *self,
     77    bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
     78{
     79        assert(self);
     80        assert(self->ops);
     81        if (self->ops->apply)
     82                return self->ops->apply(self, scope, in, out);
     83
     84        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     85                return EINVAL;
     86        aoff64_t self_size, whole_size;
     87        int rc = bithenge_transform_prefix_apply(self, scope,
     88            bithenge_node_as_blob(in), out, &self_size);
     89        if (rc != EOK)
     90                return rc;
     91        rc = bithenge_blob_size(bithenge_node_as_blob(in), &whole_size);
     92        if (rc == EOK && whole_size != self_size)
     93                rc = EINVAL;
     94        if (rc != EOK) {
     95                bithenge_node_dec_ref(*out);
     96                return rc;
     97        }
     98        return EOK;
     99}
     100
     101/** Find the length of the prefix of a blob this transform can use as input. In
     102 * other words, figure out how many bytes this transform will use up.  This
     103 * method is optional and can return an error, but it must succeed for struct
     104 * subtransforms. Takes ownership of nothing.
     105 * @memberof bithenge_transform_t
     106 * @param self The transform.
     107 * @param scope The scope.
     108 * @param blob The blob.
     109 * @param[out] out Where the prefix length will be stored.
     110 * @return EOK on success, ENOTSUP if not supported, or another error code from
     111 * errno.h. */
     112int bithenge_transform_prefix_length(bithenge_transform_t *self,
     113    bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
     114{
     115        assert(self);
     116        assert(self->ops);
     117        if (self->ops->prefix_length)
     118                return self->ops->prefix_length(self, scope, blob, out);
     119        if (!self->ops->prefix_apply)
     120                return ENOTSUP;
     121
     122        bithenge_node_t *node;
     123        int rc = bithenge_transform_prefix_apply(self, scope, blob, &node,
     124            out);
     125        if (rc != EOK)
     126                return rc;
     127        bithenge_node_dec_ref(node);
     128        return EOK;
     129}
     130
     131/** Apply this transform to a prefix of a blob. In other words, feed as much of
     132 * the blob into this transform as possible. Takes ownership of nothing.
     133 * @memberof bithenge_transform_t
     134 * @param self The transform.
     135 * @param scope The scope.
     136 * @param blob The blob.
     137 * @param[out] out_node Holds the result of applying this transform to the
     138 * prefix.
     139 * @param[out] out_size Holds the size of the prefix.
     140 * @return EOK on success, ENOTSUP if not supported, or another error code from
     141 * errno.h. */
     142int bithenge_transform_prefix_apply(bithenge_transform_t *self,
     143    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
     144    aoff64_t *out_size)
     145{
     146        assert(self);
     147        assert(self->ops);
     148        if (self->ops->prefix_apply)
     149                return self->ops->prefix_apply(self, scope, blob, out_node,
     150                    out_size);
     151        if (!self->ops->prefix_length)
     152                return ENOTSUP;
     153
     154        int rc = bithenge_transform_prefix_length(self, scope, blob, out_size);
     155        if (rc != EOK)
     156                return rc;
     157        bithenge_node_t *prefix_blob;
     158        bithenge_blob_inc_ref(blob);
     159        rc = bithenge_new_subblob(&prefix_blob, blob, 0, *out_size);
     160        if (rc != EOK)
     161                return rc;
     162        rc = bithenge_transform_apply(self, scope, prefix_blob, out_node);
     163        bithenge_node_dec_ref(prefix_blob);
     164        return rc;
    67165}
    68166
     
    471569    size_t index)
    472570{
    473         aoff64_t start_pos, end_pos;
     571        aoff64_t start_pos;
    474572        int rc = struct_node_field_offset(self, &start_pos, index);
    475573        if (rc != EOK)
    476574                return rc;
    477         rc = struct_node_field_offset(self, &end_pos, index + 1);
    478         if (rc != EOK)
    479                 return rc;
    480 
    481         bithenge_node_t *blob_node;
    482         bithenge_blob_inc_ref(self->blob);
    483         rc = bithenge_new_subblob(&blob_node, self->blob, start_pos,
    484             end_pos - start_pos);
    485         if (rc != EOK)
    486                 return rc;
    487 
    488         rc = bithenge_transform_apply(
    489             self->transform->subtransforms[index].transform, &self->scope,
    490             blob_node, out);
    491         bithenge_node_dec_ref(blob_node);
    492         if (rc != EOK)
    493                 return rc;
     575
     576        if (index == self->num_ends) {
     577                /* We can apply the subtransform and cache its prefix length at
     578                 * the same time. */
     579                bithenge_node_t *blob_node;
     580                bithenge_blob_inc_ref(self->blob);
     581                rc = bithenge_new_offset_blob(&blob_node, self->blob,
     582                    start_pos);
     583                if (rc != EOK)
     584                        return rc;
     585
     586                aoff64_t size;
     587                rc = bithenge_transform_prefix_apply(
     588                    self->transform->subtransforms[index].transform,
     589                    &self->scope, bithenge_node_as_blob(blob_node), out,
     590                    &size);
     591                bithenge_node_dec_ref(blob_node);
     592                if (rc != EOK)
     593                        return rc;
     594
     595                self->ends[self->num_ends++] = start_pos + size;
     596        } else {
     597                aoff64_t end_pos;
     598                int rc = struct_node_field_offset(self, &end_pos, index + 1);
     599                if (rc != EOK)
     600                        return rc;
     601
     602                bithenge_node_t *blob_node;
     603                bithenge_blob_inc_ref(self->blob);
     604                rc = bithenge_new_subblob(&blob_node, self->blob, start_pos,
     605                    end_pos - start_pos);
     606                if (rc != EOK)
     607                        return rc;
     608
     609                rc = bithenge_transform_apply(
     610                    self->transform->subtransforms[index].transform,
     611                    &self->scope, blob_node, out);
     612                bithenge_node_dec_ref(blob_node);
     613                if (rc != EOK)
     614                        return rc;
     615        }
    494616
    495617        return EOK;
     
    692814}
    693815
     816static int struct_transform_prefix_apply(bithenge_transform_t *base,
     817    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
     818    aoff64_t *out_size)
     819{
     820        struct_transform_t *self = transform_as_struct(base);
     821        int rc = struct_transform_make_node(self, out_node, scope, blob,
     822            true);
     823        if (rc != EOK)
     824                return rc;
     825
     826        rc = struct_node_field_offset(node_as_struct(*out_node), out_size,
     827            self->num_subtransforms);
     828        if (rc != EOK) {
     829                bithenge_node_dec_ref(*out_node);
     830                return rc;
     831        }
     832
     833        return EOK;
     834}
     835
    694836static void free_subtransforms(bithenge_named_transform_t *subtransforms)
    695837{
     
    711853        .apply = struct_transform_apply,
    712854        .prefix_length = struct_transform_prefix_length,
     855        .prefix_apply = struct_transform_prefix_apply,
    713856        .destroy = struct_transform_destroy,
    714857};
  • uspace/app/bithenge/transform.h

    r47a728e1 rcb4a66d2  
    5757} bithenge_scope_t;
    5858
    59 /** Operations that may be provided by a transform. */
     59/** Operations that may be provided by a transform. All transforms must provide
     60 * apply and/or prefix_apply. To be used in struct transforms and repeat
     61 * transforms, transforms must provide prefix_length and/or prefix_apply. */
    6062typedef struct bithenge_transform_ops {
    6163        /** @copydoc bithenge_transform_t::bithenge_transform_apply */
     
    6567        int (*prefix_length)(bithenge_transform_t *self,
    6668            bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out);
     69        /** @copydoc bithenge_transform_t::bithenge_transform_prefix_apply */
     70        int (*prefix_apply)(bithenge_transform_t *self,
     71            bithenge_scope_t *scope, bithenge_blob_t *blob,
     72            bithenge_node_t **out_node, aoff64_t *out_size);
    6773        /** Destroy the transform.
    6874         * @param self The transform. */
     
    191197        assert(self);
    192198        return self->num_params;
    193 }
    194 
    195 /** Apply a transform. Takes ownership of nothing.
    196  * @memberof bithenge_transform_t
    197  * @param self The transform.
    198  * @param scope The scope.
    199  * @param in The input tree.
    200  * @param[out] out Where the output tree will be stored.
    201  * @return EOK on success or an error code from errno.h. */
    202 static inline int bithenge_transform_apply(bithenge_transform_t *self,
    203     bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
    204 {
    205         assert(self);
    206         assert(self->ops);
    207         return self->ops->apply(self, scope, in, out);
    208 }
    209 
    210 /** Find the length of the prefix of a blob this transform can use as input. In
    211  * other words, figure out how many bytes this transform will use up.  This
    212  * method is optional and can return an error, but it must succeed for struct
    213  * subtransforms. Takes ownership of nothing.
    214  * @memberof bithenge_transform_t
    215  * @param self The transform.
    216  * @param scope The scope.
    217  * @param blob The blob.
    218  * @param[out] out Where the prefix length will be stored.
    219  * @return EOK on success, ENOTSUP if not supported, or another error code from
    220  * errno.h. */
    221 static inline int bithenge_transform_prefix_length(bithenge_transform_t *self,
    222     bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
    223 {
    224         assert(self);
    225         assert(self->ops);
    226         if (!self->ops->prefix_length)
    227                 return ENOTSUP;
    228         return self->ops->prefix_length(self, scope, blob, out);
    229199}
    230200
     
    269239int bithenge_init_transform(bithenge_transform_t *,
    270240    const bithenge_transform_ops_t *, int);
     241int bithenge_transform_apply(bithenge_transform_t *, bithenge_scope_t *,
     242    bithenge_node_t *, bithenge_node_t **);
     243int bithenge_transform_prefix_length(bithenge_transform_t *,
     244    bithenge_scope_t *, bithenge_blob_t *, aoff64_t *);
     245int bithenge_transform_prefix_apply(bithenge_transform_t *, bithenge_scope_t *,
     246    bithenge_blob_t *, bithenge_node_t **, aoff64_t *);
    271247int bithenge_new_param_transform(bithenge_transform_t **,
    272248    bithenge_transform_t *, int);
Note: See TracChangeset for help on using the changeset viewer.