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

Changeset 04a7435f in mainline for uspace/app/bithenge/transform.c


Ignore:
Timestamp:
2012-06-26T19:56:26Z (10 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
978ccaf1
Parents:
f2da0bb
Message:

Bithenge: add the struct transform

File:
1 edited

Legend:

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

    rf2da0bb r04a7435f  
    4141#include "transform.h"
    4242
     43/** Initialize a new transform.
     44 * @param[out] xform Transform to initialize.
     45 * @param[in] ops Operations provided by the transform.
     46 * @return EOK or an error code from errno.h. */
     47int bithenge_new_transform(bithenge_transform_t *xform,
     48    const bithenge_transform_ops_t *ops)
     49{
     50        assert(ops);
     51        assert(ops->apply);
     52        assert(ops->destroy);
     53        xform->ops = ops;
     54        xform->refs = 1;
     55        return EOK;
     56}
     57
    4358static int transform_indestructible(bithenge_transform_t *xform)
    4459{
     
    125140bithenge_named_transform_t *bithenge_primitive_transforms = primitive_transforms;
    126141
     142typedef struct {
     143        bithenge_node_t base;
     144        struct struct_transform *transform;
     145        bithenge_blob_t *blob;
     146} struct_node_t;
     147
     148typedef struct struct_transform {
     149        bithenge_transform_t base;
     150        bithenge_named_transform_t *subtransforms;
     151} struct_transform_t;
     152
     153static bithenge_node_t *struct_as_node(struct_node_t *node)
     154{
     155        return &node->base;
     156}
     157
     158static struct_node_t *node_as_struct(bithenge_node_t *node)
     159{
     160        return (struct_node_t *)node;
     161}
     162
     163static bithenge_transform_t *struct_as_transform(struct_transform_t *xform)
     164{
     165        return &xform->base;
     166}
     167
     168static struct_transform_t *transform_as_struct(bithenge_transform_t *xform)
     169{
     170        return (struct_transform_t *)xform;
     171}
     172
     173static int struct_node_for_one(const char *name,
     174    bithenge_transform_t *subxform, bithenge_blob_t **blob,
     175    bithenge_for_each_func_t func, void *data)
     176{
     177        int rc;
     178        bithenge_node_t *subxform_result = NULL;
     179
     180        aoff64_t sub_size;
     181        rc = bithenge_transform_prefix_length(subxform, *blob, &sub_size);
     182        if (rc != EOK)
     183                goto error;
     184
     185        bithenge_node_t *subblob_node;
     186        bithenge_blob_inc_ref(*blob);
     187        rc = bithenge_new_subblob(&subblob_node, *blob, 0, sub_size);
     188        if (rc != EOK)
     189                goto error;
     190
     191        rc = bithenge_transform_apply(subxform, subblob_node,
     192            &subxform_result);
     193        bithenge_node_dec_ref(subblob_node);
     194        if (rc != EOK)
     195                goto error;
     196
     197        if (name) {
     198                bithenge_node_t *name_node;
     199                rc = bithenge_new_string_node(&name_node, name, false);
     200                if (rc != EOK)
     201                        goto error;
     202                rc = func(name_node, subxform_result, data);
     203                subxform_result = NULL;
     204                if (rc != EOK)
     205                        goto error;
     206        } else {
     207                if (bithenge_node_type(subxform_result) !=
     208                    BITHENGE_NODE_INTERNAL) {
     209                        rc = EINVAL;
     210                        goto error;
     211                }
     212                rc = bithenge_node_for_each(subxform_result, func, data);
     213                if (rc != EOK)
     214                        goto error;
     215        }
     216
     217        bithenge_node_t *blob_node;
     218        rc = bithenge_new_offset_blob(&blob_node, *blob, sub_size);
     219        *blob = NULL;
     220        if (rc != EOK)
     221                goto error;
     222        *blob = bithenge_node_as_blob(blob_node);
     223
     224error:
     225        bithenge_node_dec_ref(subxform_result);
     226        return rc;
     227}
     228
     229static int struct_node_for_each(bithenge_node_t *base,
     230    bithenge_for_each_func_t func, void *data)
     231{
     232        int rc = EOK;
     233        struct_node_t *struct_node = node_as_struct(base);
     234        bithenge_named_transform_t *subxforms =
     235            struct_node->transform->subtransforms;
     236
     237        bithenge_node_t *blob_node = NULL;
     238        bithenge_blob_t *blob = NULL;
     239        bithenge_blob_inc_ref(struct_node->blob);
     240        rc = bithenge_new_offset_blob(&blob_node, struct_node->blob, 0);
     241        if (rc != EOK) {
     242                blob = NULL;
     243                goto error;
     244        }
     245        blob = bithenge_node_as_blob(blob_node);
     246
     247        for (size_t i = 0; subxforms[i].transform; i++) {
     248                rc = struct_node_for_one(subxforms[i].name,
     249                    subxforms[i].transform, &blob, func, data);
     250                if (rc != EOK)
     251                        goto error;
     252        }
     253
     254        aoff64_t remaining;
     255        rc = bithenge_blob_size(blob, &remaining);
     256        if (rc != EOK)
     257                goto error;
     258        if (remaining != 0) {
     259                rc = EINVAL;
     260                goto error;
     261        }
     262
     263error:
     264        bithenge_blob_dec_ref(blob);
     265        return rc;
     266}
     267
     268static int struct_node_destroy(bithenge_node_t *base)
     269{
     270        struct_node_t *node = node_as_struct(base);
     271        bithenge_transform_dec_ref(struct_as_transform(node->transform));
     272        bithenge_blob_dec_ref(node->blob);
     273        free(node);
     274        return EOK;
     275}
     276
     277static const bithenge_internal_node_ops_t struct_node_ops = {
     278        .for_each = struct_node_for_each,
     279        .destroy = struct_node_destroy,
     280};
     281
     282static int struct_transform_apply(bithenge_transform_t *xform,
     283    bithenge_node_t *in, bithenge_node_t **out)
     284{
     285        struct_transform_t *struct_transform = transform_as_struct(xform);
     286        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     287                return EINVAL;
     288        struct_node_t *node = malloc(sizeof(*node));
     289        if (!node)
     290                return ENOMEM;
     291        int rc = bithenge_init_internal_node(struct_as_node(node),
     292            &struct_node_ops);
     293        if (rc != EOK) {
     294                free(node);
     295                return rc;
     296        }
     297        bithenge_transform_inc_ref(xform);
     298        node->transform = struct_transform;
     299        bithenge_node_inc_ref(in);
     300        node->blob = bithenge_node_as_blob(in);
     301        *out = struct_as_node(node);
     302        return EOK;
     303}
     304
     305static int struct_transform_prefix_length(bithenge_transform_t *xform,
     306    bithenge_blob_t *blob, aoff64_t *out)
     307{
     308        struct_transform_t *struct_transform = transform_as_struct(xform);
     309        int rc = EOK;
     310        bithenge_node_t *node;
     311        bithenge_blob_inc_ref(blob);
     312        rc = bithenge_new_offset_blob(&node, blob, 0);
     313        blob = NULL;
     314        if (rc != EOK)
     315                goto error;
     316        blob = bithenge_node_as_blob(node);
     317        *out = 0;
     318        for (size_t i = 0; struct_transform->subtransforms[i].transform; i++) {
     319                bithenge_transform_t *subxform =
     320                    struct_transform->subtransforms[i].transform;
     321                aoff64_t sub_size;
     322                rc = bithenge_transform_prefix_length(subxform, blob, &sub_size);
     323                if (rc != EOK)
     324                        goto error;
     325                *out += sub_size;
     326                rc = bithenge_new_offset_blob(&node, blob, sub_size);
     327                blob = NULL;
     328                if (rc != EOK)
     329                        goto error;
     330                blob = bithenge_node_as_blob(node);
     331        }
     332error:
     333        bithenge_blob_dec_ref(blob);
     334        return EOK;
     335}
     336
     337static void free_subtransforms(bithenge_named_transform_t *subtransforms)
     338{
     339        for (size_t i = 0; subtransforms[i].transform; i++) {
     340                free((void *)subtransforms[i].name);
     341                bithenge_transform_dec_ref(subtransforms[i].transform);
     342        }
     343        free(subtransforms);
     344}
     345
     346static int struct_transform_destroy(bithenge_transform_t *xform)
     347{
     348        struct_transform_t *struct_transform = transform_as_struct(xform);
     349        free_subtransforms(struct_transform->subtransforms);
     350        free(struct_transform);
     351        return EOK;
     352}
     353
     354static bithenge_transform_ops_t struct_transform_ops = {
     355        .apply = struct_transform_apply,
     356        .prefix_length = struct_transform_prefix_length,
     357        .destroy = struct_transform_destroy,
     358};
     359
     360/** Create a struct transform. The transform will apply its subtransforms
     361 * sequentially to a blob to create an internal node. Each result is either
     362 * given a key from @a subtransforms or, if the name is NULL, the result's keys
     363 * and values are merged into the struct transform's result. This function
     364 * takes ownership of @a subtransforms and the names and references therein.
     365 * @param[out] out Stores the created transform.
     366 * @param subtransforms The subtransforms and field names.
     367 * @return EOK on success or an error code from errno.h. */
     368int bithenge_new_struct(bithenge_transform_t **out,
     369    bithenge_named_transform_t *subtransforms)
     370{
     371        int rc;
     372        struct_transform_t *struct_transform =
     373            malloc(sizeof(*struct_transform));
     374        if (!struct_transform) {
     375                rc = ENOMEM;
     376                goto error;
     377        }
     378        rc = bithenge_new_transform(struct_as_transform(struct_transform),
     379            &struct_transform_ops);
     380        if (rc != EOK)
     381                goto error;
     382        struct_transform->subtransforms = subtransforms;
     383        *out = struct_as_transform(struct_transform);
     384        return EOK;
     385error:
     386        free_subtransforms(subtransforms);
     387        free(struct_transform);
     388        return rc;
     389}
     390
    127391/** @}
    128392 */
Note: See TracChangeset for help on using the changeset viewer.