Changeset 600f5d1 in mainline for uspace/app/bithenge/transform.c


Ignore:
Timestamp:
2012-06-27T20:10:30Z (13 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
02dcb20
Parents:
978ccaf1
Message:

Bithenge: add composition, ascii, and zero_terminated

File:
1 edited

Legend:

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

    r978ccaf1 r600f5d1  
    6161}
    6262
     63static int ascii_apply(bithenge_transform_t *self,
     64    bithenge_node_t *in, bithenge_node_t **out)
     65{
     66        int rc;
     67        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     68                return EINVAL;
     69        bithenge_blob_t *blob = bithenge_node_as_blob(in);
     70        aoff64_t size;
     71        rc = bithenge_blob_size(blob, &size);
     72        if (rc != EOK)
     73                return rc;
     74
     75        char *buffer = malloc(size + 1);
     76        if (!buffer)
     77                return ENOMEM;
     78        aoff64_t size_read = size;
     79        rc = bithenge_blob_read(blob, 0, buffer, &size_read);
     80        if (rc != EOK) {
     81                free(buffer);
     82                return rc;
     83        }
     84        if (size_read != size) {
     85                free(buffer);
     86                return EINVAL;
     87        }
     88        buffer[size] = '\0';
     89
     90        /* TODO: what if the OS encoding is incompatible with ASCII? */
     91        return bithenge_new_string_node(out, buffer, true);
     92}
     93
     94static const bithenge_transform_ops_t ascii_ops = {
     95        .apply = ascii_apply,
     96        .destroy = transform_indestructible,
     97};
     98
     99/** The ASCII text transform. */
     100bithenge_transform_t bithenge_ascii_transform = {
     101        &ascii_ops, 1
     102};
     103
    63104static int uint32le_apply(bithenge_transform_t *self, bithenge_node_t *in,
    64105    bithenge_node_t **out)
     
    130171};
    131172
     173static int zero_terminated_apply(bithenge_transform_t *self,
     174    bithenge_node_t *in, bithenge_node_t **out)
     175{
     176        int rc;
     177        if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
     178                return EINVAL;
     179        bithenge_blob_t *blob = bithenge_node_as_blob(in);
     180        aoff64_t size;
     181        rc = bithenge_blob_size(blob, &size);
     182        if (rc != EOK)
     183                return rc;
     184        if (size < 1)
     185                return EINVAL;
     186        char ch;
     187        aoff64_t size_read = 1;
     188        rc = bithenge_blob_read(blob, size - 1, &ch, &size_read);
     189        if (rc != EOK)
     190                return rc;
     191        if (size_read != 1 || ch != '\0')
     192                return EINVAL;
     193        bithenge_blob_inc_ref(blob);
     194        return bithenge_new_subblob(out, blob, 0, size - 1);
     195}
     196
     197static int zero_terminated_prefix_length(bithenge_transform_t *self,
     198    bithenge_blob_t *blob, aoff64_t *out)
     199{
     200        int rc;
     201        char buffer[4096];
     202        aoff64_t offset = 0, size_read = sizeof(buffer);
     203        do {
     204                rc = bithenge_blob_read(blob, offset, buffer, &size_read);
     205                if (rc != EOK)
     206                        return rc;
     207                char *found = memchr(buffer, '\0', size_read);
     208                if (found) {
     209                        *out = found - buffer + offset + 1;
     210                        return EOK;
     211                }
     212                offset += size_read;
     213        } while (size_read == sizeof(buffer));
     214        return EINVAL;
     215}
     216
     217static const bithenge_transform_ops_t zero_terminated_ops = {
     218        .apply = zero_terminated_apply,
     219        .prefix_length = zero_terminated_prefix_length,
     220        .destroy = transform_indestructible,
     221};
     222
     223/** The zero-terminated data transform. */
     224bithenge_transform_t bithenge_zero_terminated_transform = {
     225        &zero_terminated_ops, 1
     226};
     227
    132228static bithenge_named_transform_t primitive_transforms[] = {
     229        {"ascii", &bithenge_ascii_transform},
    133230        {"uint32le", &bithenge_uint32le_transform},
    134231        {"uint32be", &bithenge_uint32be_transform},
     232        {"zero_terminated", &bithenge_zero_terminated_transform},
    135233        {NULL, NULL}
    136234};
     
    367465{
    368466        int rc;
    369         struct_transform_t *self =
    370             malloc(sizeof(*self));
     467        struct_transform_t *self = malloc(sizeof(*self));
    371468        if (!self) {
    372469                rc = ENOMEM;
     
    386483}
    387484
     485typedef struct {
     486        bithenge_transform_t base;
     487        bithenge_transform_t **xforms;
     488        size_t num;
     489} compose_transform_t;
     490
     491static bithenge_transform_t *compose_as_transform(compose_transform_t *xform)
     492{
     493        return &xform->base;
     494}
     495
     496static compose_transform_t *transform_as_compose(bithenge_transform_t *xform)
     497{
     498        return (compose_transform_t *)xform;
     499}
     500
     501static int compose_apply(bithenge_transform_t *base, bithenge_node_t *in,
     502    bithenge_node_t **out)
     503{
     504        int rc;
     505        compose_transform_t *self = transform_as_compose(base);
     506        bithenge_node_inc_ref(in);
     507
     508        /* i ranges from (self->num - 1) to 0 inside the loop. */
     509        for (size_t i = self->num; i--; ) {
     510                bithenge_node_t *tmp;
     511                rc = bithenge_transform_apply(self->xforms[i], in, &tmp);
     512                bithenge_node_dec_ref(in);
     513                if (rc != EOK)
     514                        return rc;
     515                in = tmp;
     516        }
     517
     518        *out = in;
     519        return rc;
     520}
     521
     522static int compose_prefix_length(bithenge_transform_t *base,
     523    bithenge_blob_t *blob, aoff64_t *out)
     524{
     525        compose_transform_t *self = transform_as_compose(base);
     526        return bithenge_transform_prefix_length(self->xforms[self->num - 1],
     527            blob, out);
     528}
     529
     530static void compose_destroy(bithenge_transform_t *base)
     531{
     532        compose_transform_t *self = transform_as_compose(base);
     533        for (size_t i = 0; i < self->num; i++)
     534                bithenge_transform_dec_ref(self->xforms[i]);
     535        free(self->xforms);
     536        free(self);
     537}
     538
     539static const bithenge_transform_ops_t compose_transform_ops = {
     540        .apply = compose_apply,
     541        .prefix_length = compose_prefix_length,
     542        .destroy = compose_destroy,
     543};
     544
     545/** Create a composition of multiple transforms. When the result is applied to a
     546 * node, each transform is applied in turn, with the last transform applied
     547 * first. @a xforms may contain any number of transforms or no transforms at
     548 * all. This function takes ownership of @a xforms and the references therein.
     549 * @param[out] out Holds the result.
     550 * @param[in] xforms The transforms to apply.
     551 * @param num The number of transforms.
     552 * @return EOK on success or an error code from errno.h. */
     553int bithenge_new_composed_transform(bithenge_transform_t **out,
     554    bithenge_transform_t **xforms, size_t num)
     555{
     556        if (num == 0) {
     557                /* TODO: optimize */
     558        } else if (num == 1) {
     559                *out = xforms[0];
     560                free(xforms);
     561                return EOK;
     562        }
     563
     564        int rc;
     565        compose_transform_t *self = malloc(sizeof(*self));
     566        if (!self) {
     567                rc = ENOMEM;
     568                goto error;
     569        }
     570        rc = bithenge_init_transform(compose_as_transform(self),
     571            &compose_transform_ops);
     572        if (rc != EOK)
     573                goto error;
     574        self->xforms = xforms;
     575        self->num = num;
     576        *out = compose_as_transform(self);
     577        return EOK;
     578error:
     579        for (size_t i = 0; i < num; i++)
     580                bithenge_transform_dec_ref(xforms[i]);
     581        free(xforms);
     582        free(self);
     583        return rc;
     584}
     585
    388586/** @}
    389587 */
Note: See TracChangeset for help on using the changeset viewer.