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

Changeset ee7cc3c in mainline


Ignore:
Timestamp:
2012-08-02T22:29:50Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
0caaaa00
Parents:
0f8062a4
Message:

Bithenge: add (untested) repeat transform

Location:
uspace/app/bithenge
Files:
2 edited

Legend:

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

    r0f8062a4 ree7cc3c  
    3737#include <stdlib.h>
    3838#include "blob.h"
     39#include "expression.h"
    3940#include "os.h"
    4041#include "sequence.h"
     
    528529}
    529530
     531
     532
     533typedef struct {
     534        bithenge_transform_t base;
     535        bithenge_expression_t *expr;
     536        bithenge_transform_t *xform;
     537} repeat_transform_t;
     538
     539static inline bithenge_transform_t *repeat_as_transform(
     540    repeat_transform_t *self)
     541{
     542        return &self->base;
     543}
     544
     545static inline repeat_transform_t *transform_as_repeat(
     546    bithenge_transform_t *base)
     547{
     548        return (repeat_transform_t *)base;
     549}
     550
     551typedef struct {
     552        seq_node_t base;
     553        bool prefix;
     554        bithenge_int_t count;
     555        bithenge_transform_t *xform;
     556} repeat_node_t;
     557
     558static seq_node_t *repeat_as_seq(repeat_node_t *self)
     559{
     560        return &self->base;
     561}
     562
     563static repeat_node_t *seq_as_repeat(seq_node_t *base)
     564{
     565        return (repeat_node_t *)base;
     566}
     567
     568static bithenge_node_t *repeat_as_node(repeat_node_t *self)
     569{
     570        return seq_as_node(repeat_as_seq(self));
     571}
     572
     573static repeat_node_t *node_as_repeat(bithenge_node_t *base)
     574{
     575        return seq_as_repeat(node_as_seq(base));
     576}
     577
     578static int repeat_node_for_each(bithenge_node_t *base,
     579    bithenge_for_each_func_t func, void *data)
     580{
     581        int rc = EOK;
     582        repeat_node_t *self = node_as_repeat(base);
     583
     584        for (bithenge_int_t i = 0; i < self->count; i++) {
     585                bithenge_node_t *subxform_result;
     586                rc = seq_node_subtransform(repeat_as_seq(self),
     587                    &subxform_result, i);
     588                if (rc != EOK)
     589                        return rc;
     590
     591                bithenge_node_t *key_node;
     592                rc = bithenge_new_integer_node(&key_node, i);
     593                if (rc != EOK) {
     594                        bithenge_node_dec_ref(subxform_result);
     595                        return rc;
     596                }
     597                rc = func(key_node, subxform_result, data);
     598                if (rc != EOK)
     599                        return rc;
     600        }
     601
     602        if (!self->prefix) {
     603                bool complete;
     604                rc = seq_node_complete(repeat_as_seq(self), &complete);
     605                if (rc != EOK)
     606                        return rc;
     607                if (!complete)
     608                        return EINVAL;
     609        }
     610
     611        return rc;
     612}
     613
     614static int repeat_node_get(bithenge_node_t *base, bithenge_node_t *key,
     615    bithenge_node_t **out)
     616{
     617        repeat_node_t *self = node_as_repeat(base);
     618
     619        if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) {
     620                bithenge_node_dec_ref(key);
     621                return ENOENT;
     622        }
     623
     624        bithenge_int_t index = bithenge_integer_node_value(key);
     625        bithenge_node_dec_ref(key);
     626        if (index < 0 || index >= self->count)
     627                return ENOENT;
     628        return seq_node_subtransform(repeat_as_seq(self), out, index);
     629}
     630
     631static void repeat_node_destroy(bithenge_node_t *base)
     632{
     633        repeat_node_t *self = node_as_repeat(base);
     634        seq_node_destroy(repeat_as_seq(self));
     635        bithenge_transform_dec_ref(self->xform);
     636        free(self);
     637}
     638
     639static const bithenge_internal_node_ops_t repeat_node_ops = {
     640        .for_each = repeat_node_for_each,
     641        .get = repeat_node_get,
     642        .destroy = repeat_node_destroy,
     643};
     644
     645static int repeat_node_get_transform(seq_node_t *base,
     646    bithenge_transform_t **out, bithenge_int_t index)
     647{
     648        repeat_node_t *self = seq_as_repeat(base);
     649        *out = self->xform;
     650        bithenge_transform_inc_ref(*out);
     651        return EOK;
     652}
     653
     654static const seq_node_ops_t repeat_node_seq_ops = {
     655        .get_transform = repeat_node_get_transform,
     656};
     657
     658static int repeat_transform_make_node(repeat_transform_t *self,
     659    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
     660    bool prefix)
     661{
     662        bithenge_int_t count;
     663        bithenge_node_t *count_node;
     664        int rc = bithenge_expression_evaluate(self->expr, scope, &count_node);
     665        if (rc != EOK)
     666                return rc;
     667        if (bithenge_node_type(count_node) != BITHENGE_NODE_INTEGER) {
     668                bithenge_node_dec_ref(count_node);
     669                return EINVAL;
     670        }
     671        count = bithenge_integer_node_value(count_node);
     672        bithenge_node_dec_ref(count_node);
     673        if (count < 0)
     674                return EINVAL;
     675
     676        repeat_node_t *node = malloc(sizeof(*node));
     677        if (!node)
     678                return ENOMEM;
     679
     680        rc = bithenge_init_internal_node(repeat_as_node(node),
     681            &repeat_node_ops);
     682        if (rc != EOK) {
     683                free(node);
     684                return rc;
     685        }
     686
     687        rc = seq_node_init(repeat_as_seq(node), &repeat_node_seq_ops, scope,
     688            blob, count);
     689        if (rc != EOK) {
     690                free(node);
     691                return rc;
     692        }
     693
     694        bithenge_transform_inc_ref(self->xform);
     695        node->xform = self->xform;
     696        node->count = count;
     697        *out = repeat_as_node(node);
     698        return EOK;
     699}
     700
     701static int repeat_transform_prefix_apply(bithenge_transform_t *base,
     702    bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
     703    aoff64_t *out_size)
     704{
     705        repeat_transform_t *self = transform_as_repeat(base);
     706        int rc = repeat_transform_make_node(self, out_node, scope, blob, true);
     707        if (rc != EOK)
     708                return rc;
     709
     710        bithenge_int_t count = node_as_repeat(*out_node)->count;
     711        rc = seq_node_field_offset(node_as_seq(*out_node), out_size, count);
     712        if (rc != EOK) {
     713                bithenge_node_dec_ref(*out_node);
     714                return rc;
     715        }
     716        return EOK;
     717}
     718
     719static void repeat_transform_destroy(bithenge_transform_t *base)
     720{
     721        repeat_transform_t *self = transform_as_repeat(base);
     722        bithenge_transform_dec_ref(self->xform);
     723        bithenge_expression_dec_ref(self->expr);
     724        free(self);
     725}
     726
     727static const bithenge_transform_ops_t repeat_transform_ops = {
     728        .prefix_apply = repeat_transform_prefix_apply,
     729        .destroy = repeat_transform_destroy,
     730};
     731
     732/** Create a transform that applies its subtransform repeatedly. Takes a
     733 * reference to @a xform and @a expr.
     734 * @param[out] out Holds the new transform.
     735 * @param xform The subtransform to apply repeatedly.
     736 * @param expr Used to calculate the number of times @a xform will be applied.
     737 * May be NULL, in which case @a xform will be applied indefinitely.
     738 * @return EOK on success or an error code from errno.h. */
     739int bithenge_repeat_transform(bithenge_transform_t **out,
     740    bithenge_transform_t *xform, bithenge_expression_t *expr)
     741{
     742        int rc;
     743        repeat_transform_t *self = malloc(sizeof(*self));
     744        if (!self) {
     745                rc = ENOMEM;
     746                goto error;
     747        }
     748
     749        rc = bithenge_init_transform(repeat_as_transform(self),
     750            &repeat_transform_ops, 0);
     751        if (rc != EOK)
     752                goto error;
     753
     754        self->expr = expr;
     755        self->xform = xform;
     756        *out = repeat_as_transform(self);
     757        return EOK;
     758
     759error:
     760        free(self);
     761        bithenge_expression_dec_ref(expr);
     762        bithenge_transform_dec_ref(xform);
     763        return rc;
     764}
     765
    530766/** @}
    531767 */
  • uspace/app/bithenge/sequence.h

    r0f8062a4 ree7cc3c  
    4242int bithenge_new_struct(bithenge_transform_t **,
    4343    bithenge_named_transform_t *);
     44int bithenge_repeat_transform(bithenge_transform_t **, bithenge_transform_t *,
     45    bithenge_expression_t *);
    4446
    4547#endif
Note: See TracChangeset for help on using the changeset viewer.