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

Changeset 600f5d1 in mainline


Ignore:
Timestamp:
2012-06-27T20:10:30Z (8 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
master
Children:
02dcb20
Parents:
978ccaf1
Message:

Bithenge: add composition, ascii, and zero_terminated

Location:
uspace/app/bithenge
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/helenos/os.h

    r978ccaf1 r600f5d1  
    3535#include <macros.h>
    3636#include <mem.h>
     37#include <stdlib.h>
    3738#include <str.h>
    3839#include <str_error.h>
     
    6768}
    6869
     70static inline void *memchr(const void *s, int c, size_t n)
     71{
     72        for (size_t i = 0; i < n; i++)
     73                if (((char *)s)[i] == c)
     74                        return (void *)(s + i);
     75        return NULL;
     76}
     77
    6978#endif
  • uspace/app/bithenge/script.c

    r978ccaf1 r600f5d1  
    177177                return;
    178178        } else if (isalpha(ch)) {
    179                 while (isalnum(state->buffer[state->buffer_pos]))
     179                while (isalnum(state->buffer[state->buffer_pos])
     180                    || state->buffer[state->buffer_pos] == '_')
    180181                        state->buffer_pos++;
    181182                char *value = str_ndup(state->buffer + state->old_buffer_pos,
     
    308309        expect(state, '{');
    309310        while (state->error == EOK && state->token != '}') {
    310                 expect(state, '.');
    311                 subxforms[num].name = expect_identifier(state);
    312                 expect(state, TOKEN_LEFT_ARROW);
     311                if (state->token == '.') {
     312                        expect(state, '.');
     313                        subxforms[num].name = expect_identifier(state);
     314                        expect(state, TOKEN_LEFT_ARROW);
     315                } else {
     316                        subxforms[num].name = NULL;
     317                        expect(state, TOKEN_LEFT_ARROW);
     318                }
    313319                subxforms[num].transform = parse_transform(state);
    314320                expect(state, ';');
     
    339345}
    340346
    341 /** Parse a transform.
     347/** Parse a transform without composition.
    342348 * @return The parsed transform, or NULL if an error occurred. */
    343 static bithenge_transform_t *parse_transform(state_t *state)
     349static bithenge_transform_t *parse_transform_no_compose(state_t *state)
    344350{
    345351        if (state->token == TOKEN_IDENTIFIER) {
     
    356362                return NULL;
    357363        }
     364}
     365
     366/** Parse a transform.
     367 * @return The parsed transform, or NULL if an error occurred. */
     368static bithenge_transform_t *parse_transform(state_t *state)
     369{
     370        bithenge_transform_t *result = parse_transform_no_compose(state);
     371        bithenge_transform_t **xforms = NULL;
     372        size_t num = 1;
     373        while (state->token == TOKEN_LEFT_ARROW) {
     374                expect(state, TOKEN_LEFT_ARROW);
     375                xforms = state_realloc(state, xforms,
     376                    (num + 1) * sizeof(*xforms));
     377                if (state->error != EOK)
     378                        break;
     379                xforms[num] = parse_transform_no_compose(state);
     380                num++;
     381        }
     382        if (state->error != EOK) {
     383                while (xforms && num--)
     384                        bithenge_transform_dec_ref(xforms[num]);
     385                free(xforms);
     386                bithenge_transform_dec_ref(result);
     387                return NULL;
     388        }
     389        if (xforms) {
     390                xforms[0] = result;
     391                int rc = bithenge_new_composed_transform(&result, xforms, num);
     392                if (rc != EOK) {
     393                        error_errno(state, rc);
     394                        return NULL;
     395                }
     396        }
     397        return result;
    358398}
    359399
  • 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 */
  • uspace/app/bithenge/transform.h

    r978ccaf1 r600f5d1  
    118118} bithenge_named_transform_t;
    119119
     120extern bithenge_transform_t bithenge_ascii_transform;
    120121extern bithenge_transform_t bithenge_uint32le_transform;
    121122extern bithenge_transform_t bithenge_uint32be_transform;
     123extern bithenge_transform_t bithenge_zero_terminated_transform;
    122124extern bithenge_named_transform_t *bithenge_primitive_transforms;
    123125
    124126int bithenge_init_transform(bithenge_transform_t *self,
    125127    const bithenge_transform_ops_t *ops);
    126 
    127128int bithenge_new_struct(bithenge_transform_t **out,
    128129    bithenge_named_transform_t *subtransforms);
     130int bithenge_new_composed_transform(bithenge_transform_t **,
     131    bithenge_transform_t **, size_t);
    129132
    130133#endif
  • uspace/app/bithenge/tree.c

    r978ccaf1 r600f5d1  
    226226        assert(out);
    227227        bithenge_node_t *self = malloc(sizeof(*self));
    228         if (!self)
     228        if (!self) {
     229                if (needs_free)
     230                        free((void *)value);
    229231                return ENOMEM;
     232        }
    230233        self->type = BITHENGE_NODE_STRING;
    231234        self->refs = 1;
Note: See TracChangeset for help on using the changeset viewer.