Changeset 04a7435f in mainline


Ignore:
Timestamp:
2012-06-26T19:56:26Z (12 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
978ccaf1
Parents:
f2da0bb
Message:

Bithenge: add the struct transform

Location:
uspace/app/bithenge
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/Makefile.linux

    rf2da0bb r04a7435f  
    2727#
    2828
    29 CFLAGS += -fexec-charset=UTF-8 -finput-charset=UTF-8 -Wall -Wextra -Werror -Wno-clobbered -Wno-unused-parameter -Wmissing-prototypes -std=gnu99 -Werror-implicit-function-declaration -Wwrite-strings -pipe
     29CFLAGS += -fexec-charset=UTF-8 -finput-charset=UTF-8 -std=gnu99 -pipe
     30CFLAGS += -Wall -Wextra -Werror -Wno-clobbered -Wno-unused-parameter -Wmissing-prototypes -Werror-implicit-function-declaration -Wwrite-strings
     31CFLAGS += -g
    3032CFLAGS += -Ilinux
    3133
  • uspace/app/bithenge/blob.c

    rf2da0bb r04a7435f  
    296296}
    297297
     298typedef struct {
     299        bithenge_blob_t base;
     300        bithenge_blob_t *source;
     301        aoff64_t offset;
     302        aoff64_t size;
     303        bool size_matters;
     304} subblob_t;
     305
     306static inline subblob_t *blob_as_subblob(bithenge_blob_t *base)
     307{
     308        return (subblob_t *)base;
     309}
     310
     311static inline bithenge_blob_t *subblob_as_blob(subblob_t *blob)
     312{
     313        return &blob->base;
     314}
     315
     316static int subblob_size(bithenge_blob_t *base, aoff64_t *size)
     317{
     318        subblob_t *blob = blob_as_subblob(base);
     319        if (blob->size_matters) {
     320                *size = blob->size;
     321                return EOK;
     322        } else {
     323                int rc = bithenge_blob_size(blob->source, size);
     324                *size -= blob->offset;
     325                return rc;
     326        }
     327}
     328
     329static int subblob_read(bithenge_blob_t *base, aoff64_t offset,
     330    char *buffer, aoff64_t *size)
     331{
     332        subblob_t *blob = blob_as_subblob(base);
     333        if (blob->size_matters) {
     334                if (offset > blob->size)
     335                        return EINVAL;
     336                *size = min(*size, blob->size - offset);
     337        }
     338        offset += blob->offset;
     339        return bithenge_blob_read(blob->source, offset, buffer, size);
     340}
     341
     342static int subblob_destroy(bithenge_blob_t *base)
     343{
     344        subblob_t *blob = blob_as_subblob(base);
     345        bithenge_blob_dec_ref(blob->source);
     346        free(blob);
     347        return EOK;
     348}
     349
     350static const bithenge_random_access_blob_ops_t subblob_ops = {
     351        .size = subblob_size,
     352        .read = subblob_read,
     353        .destroy = subblob_destroy,
     354};
     355
     356static bool is_subblob(bithenge_blob_t *blob)
     357{
     358        return blob->base.blob_ops == &subblob_ops;
     359}
     360
     361static int new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
     362    aoff64_t offset, aoff64_t size, bool size_matters)
     363{
     364        assert(out);
     365        assert(source);
     366        int rc;
     367        subblob_t *blob = 0;
     368
     369        if (is_subblob(source)) {
     370                /* We can do some optimizations this way */
     371                if (!size_matters)
     372                        size = 0;
     373                subblob_t *source_subblob = blob_as_subblob(source);
     374                if (source_subblob->size_matters &&
     375                    offset + size > source_subblob->size) {
     376                        rc = EINVAL;
     377                        goto error;
     378                }
     379
     380                if (source->base.refs == 1) {
     381                        source_subblob->offset += offset;
     382                        source_subblob->size -= offset;
     383                        if (size_matters) {
     384                                source_subblob->size_matters = true;
     385                                source_subblob->size = size;
     386                        }
     387                        *out = bithenge_blob_as_node(source);
     388                        return EOK;
     389                }
     390
     391                if (!size_matters && source_subblob->size_matters) {
     392                        size_matters = true;
     393                        size = source_subblob->size - offset;
     394                }
     395                offset += source_subblob->offset;
     396                source = source_subblob->source;
     397                bithenge_blob_inc_ref(source);
     398                bithenge_blob_dec_ref(subblob_as_blob(source_subblob));
     399        }
     400
     401        blob = malloc(sizeof(*blob));
     402        if (!blob) {
     403                rc = ENOMEM;
     404                goto error;
     405        }
     406        rc = bithenge_new_random_access_blob(subblob_as_blob(blob),
     407            &subblob_ops);
     408        if (rc != EOK)
     409                goto error;
     410        blob->source = source;
     411        blob->offset = offset;
     412        blob->size = size;
     413        blob->size_matters = size_matters;
     414        *out = bithenge_blob_as_node(subblob_as_blob(blob));
     415        return EOK;
     416
     417error:
     418        bithenge_blob_dec_ref(source);
     419        free(blob);
     420        return rc;
     421}
     422
     423/** Create a blob from data offset within another blob. This function takes
     424 * ownership of a reference to @a blob.
     425 * @param[out] out Stores the created blob node. On error, this is unchanged.
     426 * @param[in] source The input blob.
     427 * @param offset The offset within the input blob at which the new blob will start.
     428 * @return EOK on success or an error code from errno.h. */
     429int bithenge_new_offset_blob(bithenge_node_t **out, bithenge_blob_t *source,
     430    aoff64_t offset)
     431{
     432        return new_subblob(out, source, offset, 0, false);
     433}
     434
     435/** Create a blob from part of another blob. This function takes ownership of a
     436 * reference to @a blob.
     437 * @param[out] out Stores the created blob node. On error, this is unchanged.
     438 * @param[in] source The input blob.
     439 * @param offset The offset within the input blob at which the new blob will start.
     440 * @param size The size of the new blob.
     441 * @return EOK on success or an error code from errno.h. */
     442int bithenge_new_subblob(bithenge_node_t **out, bithenge_blob_t *source,
     443    aoff64_t offset, aoff64_t size)
     444{
     445        return new_subblob(out, source, offset, size, true);
     446}
     447
    298448/** Check whether the contents of two blobs are equal.
    299449 * @memberof bithenge_blob_t
  • uspace/app/bithenge/blob.h

    rf2da0bb r04a7435f  
    170170}
    171171
     172static inline int bithenge_blob_inc_ref(bithenge_blob_t *blob)
     173{
     174        return bithenge_node_inc_ref(bithenge_blob_as_node(blob));
     175}
     176
     177static inline int bithenge_blob_dec_ref(bithenge_blob_t *blob)
     178{
     179        if (!blob)
     180                return EOK;
     181        return bithenge_node_dec_ref(bithenge_blob_as_node(blob));
     182}
     183
    172184int bithenge_new_random_access_blob(bithenge_blob_t *blob,
    173185    const bithenge_random_access_blob_ops_t *ops);
     
    182194    size_t len, bool needs_free);
    183195
     196int bithenge_new_offset_blob(bithenge_node_t **out, bithenge_blob_t *blob,
     197    aoff64_t offset);
     198
     199int bithenge_new_subblob(bithenge_node_t **out, bithenge_blob_t *blob,
     200    aoff64_t offset, aoff64_t size);
     201
    184202bool bithenge_blob_equal(bithenge_blob_t *a, bithenge_blob_t *b);
    185203
  • uspace/app/bithenge/print.c

    rf2da0bb r04a7435f  
    4949{
    5050        print_internal_data_t *data = (print_internal_data_t *)data_;
    51         int rc;
     51        int rc = EOK;
    5252        if (!data->first)
    5353                printf(", ");
     
    5959        rc = bithenge_print_node(data->type, key);
    6060        if (rc != EOK)
    61                 return rc;
     61                goto end;
    6262        if (add_quotes)
    6363                printf("\"");
     
    6565        rc = bithenge_print_node(data->type, value);
    6666        if (rc != EOK)
    67                 return rc;
    68         return EOK;
     67                goto end;
     68end:
     69        bithenge_node_dec_ref(key);
     70        bithenge_node_dec_ref(value);
     71        return rc;
    6972}
    7073
  • uspace/app/bithenge/script.c

    rf2da0bb r04a7435f  
    5353        TOKEN_EOF,
    5454        TOKEN_IDENTIFIER,
     55        TOKEN_LEFT_ARROW,
    5556
    5657        /* Keywords */
     58        TOKEN_STRUCT,
    5759        TOKEN_TRANSFORM,
    5860} token_type_t;
     
    181183                if (!value) {
    182184                        error_errno(state, ENOMEM);
     185                } else if (!str_cmp(value, "struct")) {
     186                        state->token = TOKEN_STRUCT;
     187                        free(value);
    183188                } else if (!str_cmp(value, "transform")) {
    184189                        state->token = TOKEN_TRANSFORM;
     
    188193                        state->token_string = value;
    189194                }
     195        } else if (ch == '<') {
     196                state->token = ch;
     197                state->buffer_pos++;
     198                if (state->buffer[state->buffer_pos] == '-') {
     199                        state->buffer_pos++;
     200                        state->token = TOKEN_LEFT_ARROW;
     201                }
    190202        } else {
    191203                state->token = ch;
     
    207219}
    208220
     221/** Reallocate memory and handle failure by setting the error in the state. If
     222 * an error occurs, the existing pointer will be returned. */
     223static void *state_realloc(state_t *state, void *ptr, size_t size)
     224{
     225        if (state->error != EOK)
     226                return ptr;
     227        void *result = realloc(ptr, size);
     228        if (result == NULL) {
     229                error_errno(state, ENOMEM);
     230                return ptr;
     231        }
     232        return result;
     233}
     234
    209235/** Expect and consume a certain token. If the next token is of the wrong type,
    210236 * an error is caused. */
     
    255281
    256282/** Add a named transform. This function takes ownership of the name and a
    257  * reference to the transform. */
     283 * reference to the transform. If an error has occurred, either may be null. */
    258284static void add_named_transform(state_t *state, bithenge_transform_t *xform, char *name)
    259285{
     
    269295        entry->next = state->transform_list;
    270296        state->transform_list = entry;
     297}
     298
     299static bithenge_transform_t *parse_transform(state_t *state);
     300
     301static bithenge_transform_t *parse_struct(state_t *state)
     302{
     303        size_t num = 0;
     304        bithenge_named_transform_t *subxforms;
     305        /* We keep an extra space for the {NULL, NULL} terminator. */
     306        subxforms = state_malloc(state, sizeof(*subxforms));
     307        expect(state, TOKEN_STRUCT);
     308        expect(state, '{');
     309        while (state->error == EOK && state->token != '}') {
     310                expect(state, '.');
     311                subxforms[num].name = expect_identifier(state);
     312                expect(state, TOKEN_LEFT_ARROW);
     313                subxforms[num].transform = parse_transform(state);
     314                expect(state, ';');
     315                num++;
     316                subxforms = state_realloc(state, subxforms,
     317                    (num + 1)*sizeof(*subxforms));
     318        }
     319        expect(state, '}');
     320
     321        if (state->error != EOK) {
     322                while (num--) {
     323                        free((void *)subxforms[num].name);
     324                        bithenge_transform_dec_ref(subxforms[num].transform);
     325                }
     326                free(subxforms);
     327                return NULL;
     328        }
     329
     330        subxforms[num].name = NULL;
     331        subxforms[num].transform = NULL;
     332        bithenge_transform_t *result;
     333        int rc = bithenge_new_struct(&result, subxforms);
     334        if (rc != EOK) {
     335                error_errno(state, rc);
     336                return NULL;
     337        }
     338        return result;
    271339}
    272340
     
    282350                next_token(state);
    283351                return result;
     352        } else if (state->token == TOKEN_STRUCT) {
     353                return parse_struct(state);
    284354        } else {
    285355                syntax_error(state, "unexpected (transform expected)");
  • uspace/app/bithenge/test.c

    rf2da0bb r04a7435f  
    6969                bithenge_node_dec_ref(node);
    7070        } else {
    71                 bithenge_transform_t *transform;
     71                bithenge_transform_t *transform = NULL;
     72                bithenge_node_t *node = NULL, *node2 = NULL;
    7273                rc = bithenge_parse_script(argv[1], &transform);
    7374                if (rc != EOK) {
    7475                        printf("Error parsing script: %s\n", str_error(rc));
    75                         return 1;
     76                        goto error;
    7677                }
    7778
    78                 bithenge_node_t *node, *node2;
    7979                int rc = bithenge_node_from_source(&node, argv[2]);
    8080                if (rc != EOK) {
    8181                        printf("Error creating node from source: %s\n", str_error(rc));
    82                         return 1;
     82                        goto error;
    8383                }
    8484
     
    8686                if (rc != EOK) {
    8787                        printf("Error applying transform: %s\n", str_error(rc));
    88                         return 1;
     88                        goto error;
    8989                }
    9090
    9191                bithenge_node_dec_ref(node);
     92                node = NULL;
    9293                bithenge_transform_dec_ref(transform);
     94                transform = NULL;
    9395
    9496                rc = bithenge_print_node(BITHENGE_PRINT_PYTHON, node2);
    9597                if (rc != EOK) {
    9698                        printf("Error printing node: %s\n", str_error(rc));
    97                         return 1;
     99                        goto error;
    98100                }
    99101                bithenge_node_dec_ref(node2);
     102                node2 = NULL;
    100103                printf("\n");
     104
     105                return 0;
     106
     107error:
     108                bithenge_node_dec_ref(node);
     109                bithenge_node_dec_ref(node2);
     110                bithenge_transform_dec_ref(transform);
     111                return 1;
    101112        }
    102113
  • 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 */
  • uspace/app/bithenge/transform.h

    rf2da0bb r04a7435f  
    4444typedef struct {
    4545        /** @privatesection */
    46         const struct bithenge_transform_ops_t *ops;
     46        const struct bithenge_transform_ops *ops;
    4747        unsigned int refs;
    4848} bithenge_transform_t;
    4949
    5050/** Operations that may be provided by a transform. */
    51 typedef struct bithenge_transform_ops_t {
     51typedef struct bithenge_transform_ops {
    5252        /** @copydoc bithenge_transform_t::bithenge_transform_apply */
    5353        int (*apply)(bithenge_transform_t *xform, bithenge_node_t *in, bithenge_node_t **out);
     
    5555        int (*prefix_length)(bithenge_transform_t *xform, bithenge_blob_t *blob, aoff64_t *out);
    5656        /** Destroy the transform.
    57          * @param blob The transform.
     57         * @param xform The transform.
    5858         * @return EOK on success or an error code from errno.h. */
    5959        int (*destroy)(bithenge_transform_t *xform);
     
    127127extern bithenge_named_transform_t *bithenge_primitive_transforms;
    128128
     129int bithenge_new_transform(bithenge_transform_t *xform,
     130    const bithenge_transform_ops_t *ops);
     131
     132int bithenge_new_struct(bithenge_transform_t **out,
     133    bithenge_named_transform_t *subtransforms);
     134
    129135#endif
    130136
  • uspace/app/bithenge/tree.c

    rf2da0bb r04a7435f  
    105105        simple_internal_node_t *node = node_as_simple(base);
    106106        for (bithenge_int_t i = 0; i < node->len; i++) {
     107                bithenge_node_inc_ref(node->nodes[2*i+0]);
     108                bithenge_node_inc_ref(node->nodes[2*i+1]);
    107109                rc = func(node->nodes[2*i+0], node->nodes[2*i+1], data);
    108110                if (rc != EOK)
     
    132134};
    133135
     136/** Initialize an internal node.
     137 * @memberof bithenge_node_t
     138 * @param[out] node The node.
     139 * @param[in] ops The operations provided.
     140 * @return EOK on success or an error code from errno.h. */
     141int bithenge_init_internal_node(bithenge_node_t *node,
     142    const bithenge_internal_node_ops_t *ops)
     143{
     144        node->type = BITHENGE_NODE_INTERNAL;
     145        node->refs = 1;
     146        node->internal_ops = ops;
     147        return EOK;
     148}
     149
    134150/** Create an internal node from a set of keys and values. This function takes
    135151 * ownership of a reference to the key and value nodes, and optionally the
     
    146162    bithenge_node_t **nodes, bithenge_int_t len, bool needs_free)
    147163{
     164        int rc;
    148165        assert(out);
    149166        simple_internal_node_t *node = malloc(sizeof(*node));
    150167        if (!node) {
    151                 for (bithenge_int_t i = 0; i < 2 * len; i++)
    152                         bithenge_node_dec_ref(nodes[i]);
    153                 if (needs_free)
    154                         free(nodes);
    155                 return ENOMEM;
    156         }
    157         node->base.type = BITHENGE_NODE_INTERNAL;
    158         node->base.refs = 1;
    159         node->base.internal_ops = &simple_internal_node_ops;
     168                rc = ENOMEM;
     169                goto error;
     170        }
     171        rc = bithenge_init_internal_node(simple_as_node(node),
     172            &simple_internal_node_ops);
     173        if (rc != EOK)
     174                goto error;
    160175        node->nodes = nodes;
    161176        node->len = len;
     
    163178        *out = simple_as_node(node);
    164179        return EOK;
     180error:
     181        for (bithenge_int_t i = 0; i < 2 * len; i++)
     182                bithenge_node_dec_ref(nodes[i]);
     183        if (needs_free)
     184                free(nodes);
     185        free(node);
     186        return rc;
    165187}
    166188
     
    201223/** Create a string node.
    202224 * @memberof bithenge_node_t
    203  * @param[out] out Stores the created string node.
     225 * @param[out] out Stores the created string node. On error, this is unchanged.
    204226 * @param value The value for the node to hold.
    205227 * @param needs_free Whether the string should be freed when the node is
  • uspace/app/bithenge/tree.h

    rf2da0bb r04a7435f  
    8181} bithenge_node_t;
    8282
    83 /** A callback function used to iterate over a node's children.
     83/** A callback function used to iterate over a node's children. It takes
     84 * ownership of a reference to both the key and the value.
    8485 * @memberof bithenge_node_t
    8586 * @param key The key.
     
    161162}
    162163
     164int bithenge_init_internal_node(bithenge_node_t *,
     165    const bithenge_internal_node_ops_t *);
    163166int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **,
    164167    bithenge_int_t, bool needs_free);
Note: See TracChangeset for help on using the changeset viewer.