Changeset 5e718d9 in mainline for uspace/lib/bithenge


Ignore:
Timestamp:
2012-08-21T10:04:16Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
67edca6
Parents:
0da6c04 (diff), 6a97f2e (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with upstream (lp:~wtachi/helenos/bithenge)

Location:
uspace/lib/bithenge
Files:
7 added
22 moved

Legend:

Unmodified
Added
Removed
  • uspace/lib/bithenge/blob.c

    r0da6c04 r5e718d9  
    5858        assert(ops->size);
    5959
     60        if (bithenge_should_fail())
     61                return ENOMEM;
     62
    6063        blob->base.type = BITHENGE_NODE_BLOB;
    6164        blob->base.refs = 1;
     
    195198{
    196199        memory_blob_t *blob = blob_as_memory(base);
     200        if (bithenge_should_fail())
     201                return EIO;
    197202        *size = blob->size;
    198203        return EOK;
     
    223228        .destroy = memory_destroy,
    224229};
    225 
    226 /** Create a blob node from data. Unlike with @a
    227  * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a
    228  * new buffer and the original data can be changed after this call. The blob
    229  * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is
    230  * used.
    231  * @memberof bithenge_blob_t
    232  * @param[out] out Stores the created blob node.
    233  * @param[in] data The data.
    234  * @param len The length of the data.
    235  * @return EOK on success or an error code from errno.h. */
    236 int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,
    237     size_t len)
    238 {
    239         int rc;
    240         assert(data || !len);
    241 
    242         memory_blob_t *blob = malloc(sizeof(*blob));
    243         if (!blob)
    244                 return ENOMEM;
    245         rc = bithenge_init_random_access_blob(memory_as_blob(blob),
    246             &memory_ops);
    247         if (rc != EOK) {
    248                 free(blob);
    249                 return rc;
    250         }
    251         char *buffer = malloc(len);
    252         if (!buffer) {
    253                 free(blob);
    254                 return rc;
    255         }
    256         memcpy(buffer, data, len);
    257         blob->buffer = buffer;
    258         blob->size = len;
    259         blob->needs_free = true;
    260         *out = bithenge_blob_as_node(memory_as_blob(blob));
    261         return EOK;
    262 }
    263230
    264231/** Create a blob node from a buffer. The buffer must exist as long as the blob
     
    280247
    281248        memory_blob_t *blob = malloc(sizeof(*blob));
    282         if (!blob)
    283                 return ENOMEM;
     249        if (!blob) {
     250                rc = ENOMEM;
     251                goto error;
     252        }
    284253        rc = bithenge_init_random_access_blob(memory_as_blob(blob),
    285254            &memory_ops);
    286         if (rc != EOK) {
    287                 free(blob);
    288                 return rc;
    289         }
     255        if (rc != EOK)
     256                goto error;
    290257        blob->buffer = buffer;
    291258        blob->size = len;
     
    293260        *out = bithenge_blob_as_node(memory_as_blob(blob));
    294261        return EOK;
    295 }
     262       
     263error:
     264        if (needs_free)
     265                free((void *)buffer);
     266        free(blob);
     267        return rc;
     268}
     269
     270/** Create a blob node from data. Unlike with @a
     271 * bithenge_blob_t::bithenge_new_blob_from_buffer, the data is copied into a
     272 * new buffer and the original data can be changed after this call. The blob
     273 * must be freed with @a bithenge_node_t::bithenge_node_destroy after it is
     274 * used.
     275 * @memberof bithenge_blob_t
     276 * @param[out] out Stores the created blob node.
     277 * @param[in] data The data.
     278 * @param len The length of the data.
     279 * @return EOK on success or an error code from errno.h. */
     280int bithenge_new_blob_from_data(bithenge_node_t **out, const void *data,
     281    size_t len)
     282{
     283        char *buffer = malloc(len);
     284        if (!buffer)
     285                return ENOMEM;
     286        memcpy(buffer, data, len);
     287
     288        return bithenge_new_blob_from_buffer(out, buffer, len, true);
     289}
     290
     291
    296292
    297293typedef struct {
     
    461457/** Check whether the contents of two blobs are equal.
    462458 * @memberof bithenge_blob_t
     459 * @param[out] out Holds whether the blobs are equal.
    463460 * @param a, b Blobs to compare.
    464  * @return Whether the blobs are equal. If an error occurs, returns false.
    465  */
    466 bool bithenge_blob_equal(bithenge_blob_t *a, bithenge_blob_t *b)
     461 * @return EOK on success, or an error code from errno.h.
     462 */
     463int bithenge_blob_equal(bool *out, bithenge_blob_t *a, bithenge_blob_t *b)
    467464{
    468465        assert(a);
     
    476473                rc = bithenge_blob_read(a, offset, buffer_a, &size_a);
    477474                if (rc != EOK)
    478                         return false;
     475                        return rc;
    479476                rc = bithenge_blob_read(b, offset, buffer_b, &size_b);
    480477                if (rc != EOK)
    481                         return false;
    482                 if (size_a != size_b || bcmp(buffer_a, buffer_b, size_a))
    483                         return false;
     478                        return rc;
     479                if (size_a != size_b || bcmp(buffer_a, buffer_b, size_a)) {
     480                        *out = false;
     481                        return EOK;
     482                }
    484483                offset += size_a;
    485484        } while (size_a == sizeof(buffer_a));
    486         return true;
     485        *out = true;
     486        return EOK;
    487487}
    488488
  • uspace/lib/bithenge/blob.h

    r0da6c04 r5e718d9  
    233233}
    234234
     235/** @memberof bithenge_blob_t */
    235236int bithenge_init_random_access_blob(bithenge_blob_t *,
    236237    const bithenge_random_access_blob_ops_t *);
     238/** @memberof bithenge_sequential_blob_t */
    237239int bithenge_init_sequential_blob(bithenge_sequential_blob_t *,
    238240    const bithenge_sequential_blob_ops_t *);
     241/** @memberof bithenge_blob_t */
    239242int bithenge_new_blob_from_data(bithenge_node_t **, const void *, size_t);
     243/** @memberof bithenge_blob_t */
    240244int bithenge_new_blob_from_buffer(bithenge_node_t **, const void *, size_t,
    241245    bool);
     
    243247int bithenge_new_subblob(bithenge_node_t **, bithenge_blob_t *, aoff64_t,
    244248    aoff64_t);
    245 bool bithenge_blob_equal(bithenge_blob_t *, bithenge_blob_t *);
     249/** @memberof bithenge_blob_t */
     250int bithenge_blob_equal(bool *, bithenge_blob_t *, bithenge_blob_t *);
    246251
    247252#endif
  • uspace/lib/bithenge/expression.c

    r0da6c04 r5e718d9  
    4040#include "blob.h"
    4141#include "expression.h"
     42#include "os.h"
    4243#include "transform.h"
    4344#include "tree.h"
     
    5354        assert(ops->evaluate);
    5455        assert(ops->destroy);
     56        if (bithenge_should_fail())
     57                return ENOMEM;
    5558        self->ops = ops;
    5659        self->refs = 1;
     
    8891    bithenge_scope_t *scope, bithenge_node_t **out)
    8992{
     93        int rc;
    9094        binary_expression_t *self = expression_as_binary(base);
    9195        bithenge_node_t *a, *b;
    92         int rc = bithenge_expression_evaluate(self->a, scope, &a);
     96        rc = bithenge_expression_evaluate(self->a, scope, &a);
    9397        if (rc != EOK)
    9498                return rc;
    95         rc = bithenge_expression_evaluate(self->b, scope, &b);
    96         if (rc != EOK) {
    97                 bithenge_node_dec_ref(a);
    98                 return rc;
     99        if (self->op != BITHENGE_EXPRESSION_CONCAT) {
     100                rc = bithenge_expression_evaluate(self->b, scope, &b);
     101                if (rc != EOK) {
     102                        bithenge_node_dec_ref(a);
     103                        return rc;
     104                }
    99105        }
    100106
     
    102108        /* Assigning 0 only to make the compiler happy. */
    103109        bithenge_int_t a_int = 0, b_int = 0;
     110        bool a_bool = false, b_bool = false, out_bool = false;
    104111        switch (self->op) {
    105112        case BITHENGE_EXPRESSION_ADD: /* fallthrough */
    106113        case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
    107         case BITHENGE_EXPRESSION_MULTIPLY:
     114        case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
     115        case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */
     116        case BITHENGE_EXPRESSION_MODULO: /* fallthrough */
     117        case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */
     118        case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */
     119        case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */
     120        case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
    108121                rc = EINVAL;
    109122                if (bithenge_node_type(a) != BITHENGE_NODE_INTEGER)
     
    114127                b_int = bithenge_integer_node_value(b);
    115128                break;
     129        case BITHENGE_EXPRESSION_AND: /* fallthrough */
     130        case BITHENGE_EXPRESSION_OR:
     131                rc = EINVAL;
     132                if (bithenge_node_type(a) != BITHENGE_NODE_BOOLEAN)
     133                        goto error;
     134                if (bithenge_node_type(b) != BITHENGE_NODE_BOOLEAN)
     135                        goto error;
     136                a_bool = bithenge_boolean_node_value(a);
     137                b_bool = bithenge_boolean_node_value(b);
     138                break;
     139        case BITHENGE_EXPRESSION_CONCAT:
     140                if (bithenge_node_type(a) != BITHENGE_NODE_BLOB)
     141                        goto error;
     142                break;
    116143        default:
    117144                break;
     
    128155                rc = bithenge_new_integer_node(out, a_int * b_int);
    129156                break;
     157        case BITHENGE_EXPRESSION_INTEGER_DIVIDE:
     158                /* Integer division can behave in three major ways when the
     159                  operands are signed: truncated, floored, or Euclidean. When
     160                 * b > 0, we give the same result as floored and Euclidean;
     161                 * otherwise, we currently raise an error. See
     162                 * https://en.wikipedia.org/wiki/Modulo_operation and its
     163                 * references. */
     164                if (b_int <= 0) {
     165                        rc = EINVAL;
     166                        break;
     167                }
     168                rc = bithenge_new_integer_node(out,
     169                    (a_int / b_int) + (a_int % b_int < 0 ? -1 : 0));
     170                break;
     171        case BITHENGE_EXPRESSION_MODULO:
     172                /* This is consistent with division; see above. */
     173                if (b_int <= 0) {
     174                        rc = EINVAL;
     175                        break;
     176                }
     177                rc = bithenge_new_integer_node(out,
     178                    (a_int % b_int) + (a_int % b_int < 0 ? b_int : 0));
     179                break;
     180        case BITHENGE_EXPRESSION_LESS_THAN:
     181                rc = bithenge_new_boolean_node(out, a_int < b_int);
     182                break;
     183        case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL:
     184                rc = bithenge_new_boolean_node(out, a_int <= b_int);
     185                break;
     186        case BITHENGE_EXPRESSION_GREATER_THAN:
     187                rc = bithenge_new_boolean_node(out, a_int > b_int);
     188                break;
     189        case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
     190                rc = bithenge_new_boolean_node(out, a_int >= b_int);
     191                break;
    130192        case BITHENGE_EXPRESSION_EQUALS:
    131                 rc = bithenge_new_boolean_node(out, bithenge_node_equal(a, b));
     193                rc = bithenge_node_equal(&out_bool, a, b);
     194                if (rc != EOK)
     195                        break;
     196                rc = bithenge_new_boolean_node(out, out_bool);
     197                break;
     198        case BITHENGE_EXPRESSION_NOT_EQUALS:
     199                rc = bithenge_node_equal(&out_bool, a, b);
     200                if (rc != EOK)
     201                        break;
     202                rc = bithenge_new_boolean_node(out, !out_bool);
     203                break;
     204        case BITHENGE_EXPRESSION_AND:
     205                rc = bithenge_new_boolean_node(out, a_bool && b_bool);
     206                break;
     207        case BITHENGE_EXPRESSION_OR:
     208                rc = bithenge_new_boolean_node(out, a_bool || b_bool);
     209                break;
     210        case BITHENGE_EXPRESSION_MEMBER:
     211                rc = bithenge_node_get(a, b, out);
     212                b = NULL;
     213                break;
     214        case BITHENGE_EXPRESSION_CONCAT:
     215                bithenge_expression_inc_ref(self->b);
     216                bithenge_scope_inc_ref(scope);
     217                rc = bithenge_concat_blob_lazy(out, bithenge_node_as_blob(a),
     218                    self->b, scope);
     219                a = NULL;
     220                b = NULL;
    132221                break;
    133222        case BITHENGE_EXPRESSION_INVALID_BINARY_OP:
     
    197286    bithenge_scope_t *scope, bithenge_node_t **out)
    198287{
    199         for (; scope && !bithenge_scope_is_barrier(scope);
    200             scope = bithenge_scope_outer(scope)) {
     288        for (; scope; scope = bithenge_scope_outer(scope)) {
    201289                *out = bithenge_scope_in_node(scope);
    202290                if (*out)
     
    220308int bithenge_in_node_expression(bithenge_expression_t **out)
    221309{
     310        if (bithenge_should_fail())
     311                return ENOMEM;
    222312        bithenge_expression_inc_ref(&in_node_expression);
    223313        *out = &in_node_expression;
     
    392482
    393483
    394 /***************** member_expression                         *****************/
    395 
    396 typedef struct {
    397         bithenge_expression_t base;
    398         bithenge_expression_t *expr;
    399         bithenge_node_t *key;
    400 } member_expression_t;
    401 
    402 static member_expression_t *expression_as_member(bithenge_expression_t *base)
    403 {
    404         return (member_expression_t *)base;
    405 }
    406 
    407 static bithenge_expression_t *member_as_expression(member_expression_t *expr)
    408 {
    409         return &expr->base;
    410 }
    411 
    412 static int member_expression_evaluate(bithenge_expression_t *base,
    413     bithenge_scope_t *scope, bithenge_node_t **out)
    414 {
    415         member_expression_t *self = expression_as_member(base);
    416         bithenge_node_t *node;
    417         int rc = bithenge_expression_evaluate(self->expr, scope, &node);
    418         if (rc != EOK)
    419                 return rc;
    420         bithenge_node_inc_ref(self->key);
    421         rc = bithenge_node_get(node, self->key, out);
    422         bithenge_node_dec_ref(node);
    423         return rc;
    424 }
    425 
    426 static void member_expression_destroy(bithenge_expression_t *base)
    427 {
    428         member_expression_t *self = expression_as_member(base);
    429         bithenge_expression_dec_ref(self->expr);
    430         bithenge_node_dec_ref(self->key);
    431         free(self);
    432 }
    433 
    434 static const bithenge_expression_ops_t member_expression_ops = {
    435         .evaluate = member_expression_evaluate,
    436         .destroy = member_expression_destroy,
    437 };
    438 
    439 /** Create an expression that gets a member from a node. Takes references to
    440  * @a expr and @a key.
    441  * @param[out] out Holds the new expression.
    442  * @param expr Calculates the node to get the member of.
    443  * @param key The member to get.
    444  * @return EOK on success or an error code from errno.h. */
    445 int bithenge_member_expression(bithenge_expression_t **out,
    446     bithenge_expression_t *expr, bithenge_node_t *key)
    447 {
    448         int rc;
    449         member_expression_t *self = malloc(sizeof(*self));
    450         if (!self) {
    451                 rc = ENOMEM;
    452                 goto error;
    453         }
    454 
    455         rc = bithenge_init_expression(member_as_expression(self),
    456             &member_expression_ops);
    457         if (rc != EOK)
    458                 goto error;
    459 
    460         self->expr = expr;
    461         self->key = key;
    462         *out = member_as_expression(self);
    463         return EOK;
    464 
    465 error:
    466         bithenge_expression_dec_ref(expr);
    467         bithenge_node_dec_ref(key);
    468         free(self);
    469         return rc;
    470 }
    471 
    472 
    473 
    474484/***************** scope_member_expression                   *****************/
    475485
     
    497507        for (; scope && !bithenge_scope_is_barrier(scope);
    498508            scope = bithenge_scope_outer(scope)) {
     509                bithenge_node_t *cur = bithenge_scope_get_current_node(scope);
     510                if (!cur)
     511                        continue;
    499512                bithenge_node_inc_ref(self->key);
    500                 bithenge_node_t *cur = bithenge_scope_get_current_node(scope);
    501513                int rc = bithenge_node_get(cur, self->key, out);
    502514                bithenge_node_dec_ref(cur);
     
    504516                        return rc;
    505517        }
    506         return ENOENT;
     518        return bithenge_scope_error(scope, "No scope member %t", self->key);
    507519}
    508520
     
    519531};
    520532
     533/** Create an expression that gets a member from one of the current nodes being
     534 * created. It searches from the current scope outwards, stopping at barrier
     535 * scopes.
     536 * @param[out] out Holds the new expression.
     537 * @param key The key to search for in nodes being created.
     538 * @return EOK on success or an error code from errno.h. */
    521539int bithenge_scope_member_expression(bithenge_expression_t **out,
    522540    bithenge_node_t *key)
     
    545563
    546564
     565
     566/***************** subblob_expression                        *****************/
     567
     568typedef struct {
     569        bithenge_expression_t base;
     570        bithenge_expression_t *blob, *start, *limit;
     571        bool absolute_limit;
     572} subblob_expression_t;
     573
     574static subblob_expression_t *expression_as_subblob(bithenge_expression_t *base)
     575{
     576        return (subblob_expression_t *)base;
     577}
     578
     579static bithenge_expression_t *subblob_as_expression(subblob_expression_t *expr)
     580{
     581        return &expr->base;
     582}
     583
     584static int subblob_expression_evaluate(bithenge_expression_t *base,
     585    bithenge_scope_t *scope, bithenge_node_t **out)
     586{
     587        subblob_expression_t *self = expression_as_subblob(base);
     588        bithenge_node_t *start_node;
     589        int rc = bithenge_expression_evaluate(self->start, scope, &start_node);
     590        if (rc != EOK)
     591                return rc;
     592        if (bithenge_node_type(start_node) != BITHENGE_NODE_INTEGER) {
     593                bithenge_node_dec_ref(start_node);
     594                return EINVAL;
     595        }
     596        bithenge_int_t start = bithenge_integer_node_value(start_node);
     597        bithenge_node_dec_ref(start_node);
     598
     599        bithenge_int_t limit = -1;
     600        if (self->limit) {
     601                bithenge_node_t *limit_node;
     602                rc = bithenge_expression_evaluate(self->limit, scope,
     603                    &limit_node);
     604                if (rc != EOK)
     605                        return rc;
     606                if (bithenge_node_type(limit_node) != BITHENGE_NODE_INTEGER) {
     607                        bithenge_node_dec_ref(limit_node);
     608                        return EINVAL;
     609                }
     610                limit = bithenge_integer_node_value(limit_node);
     611                bithenge_node_dec_ref(limit_node);
     612                if (self->absolute_limit)
     613                        limit -= start;
     614        }
     615
     616        if (start < 0 || (self->limit && limit < 0))
     617                return EINVAL;
     618
     619        bithenge_node_t *blob;
     620        rc = bithenge_expression_evaluate(self->blob, scope, &blob);
     621        if (rc != EOK)
     622                return rc;
     623        if (bithenge_node_type(blob) != BITHENGE_NODE_BLOB) {
     624                bithenge_node_dec_ref(blob);
     625                return EINVAL;
     626        }
     627
     628        if (self->limit)
     629                return bithenge_new_subblob(out, bithenge_node_as_blob(blob),
     630                    start, limit);
     631        else
     632                return bithenge_new_offset_blob(out,
     633                    bithenge_node_as_blob(blob), start);
     634}
     635
     636static void subblob_expression_destroy(bithenge_expression_t *base)
     637{
     638        subblob_expression_t *self = expression_as_subblob(base);
     639        bithenge_expression_dec_ref(self->blob);
     640        bithenge_expression_dec_ref(self->start);
     641        bithenge_expression_dec_ref(self->limit);
     642        free(self);
     643}
     644
     645static const bithenge_expression_ops_t subblob_expression_ops = {
     646        .evaluate = subblob_expression_evaluate,
     647        .destroy = subblob_expression_destroy,
     648};
     649
     650/** Create an expression that gets a subblob. Takes references to @a blob,
     651 * @a start, and @a limit.
     652 * @param[out] out Holds the new expression.
     653 * @param blob Calculates the blob.
     654 * @param start Calculates the start offset within the blob.
     655 * @param limit Calculates the limit. Can be NULL, in which case an offset blob
     656 * is returned.
     657 * @param absolute_limit If true, the limit is an absolute offset; otherwise,
     658 * it is relative to the start.
     659 * @return EOK on success or an error code from errno.h. */
     660int bithenge_subblob_expression(bithenge_expression_t **out,
     661    bithenge_expression_t *blob, bithenge_expression_t *start,
     662    bithenge_expression_t *limit, bool absolute_limit)
     663{
     664        int rc;
     665        subblob_expression_t *self = malloc(sizeof(*self));
     666        if (!self) {
     667                rc = ENOMEM;
     668                goto error;
     669        }
     670
     671        rc = bithenge_init_expression(subblob_as_expression(self),
     672            &subblob_expression_ops);
     673        if (rc != EOK)
     674                goto error;
     675
     676        self->blob = blob;
     677        self->start = start;
     678        self->limit = limit;
     679        self->absolute_limit = absolute_limit;
     680        *out = subblob_as_expression(self);
     681        return EOK;
     682
     683error:
     684        bithenge_expression_dec_ref(blob);
     685        bithenge_expression_dec_ref(start);
     686        bithenge_expression_dec_ref(limit);
     687        free(self);
     688        return rc;
     689}
    547690
    548691/***************** param_wrapper                             *****************/
     
    798941{
    799942        expression_transform_t *self = transform_as_expression(base);
    800         *out_size = 0;
     943        if (out_size)
     944                *out_size = 0;
    801945        return bithenge_expression_evaluate(self->expr, scope, out_node);
    802946}
     
    840984
    841985
    842 /***************** if_transform                              *****************/
     986/***************** concat_blob                    *****************/
    843987
    844988typedef struct {
    845         bithenge_transform_t base;
    846         bithenge_expression_t *expr;
    847         bithenge_transform_t *true_xform, *false_xform;
    848 } if_transform_t;
    849 
    850 static inline bithenge_transform_t *if_as_transform(if_transform_t *self)
    851 {
    852         return &self->base;
    853 }
    854 
    855 static inline if_transform_t *transform_as_if(bithenge_transform_t *base)
    856 {
    857         return (if_transform_t *)base;
    858 }
    859 
    860 static int if_transform_choose(if_transform_t *self, bithenge_scope_t *scope,
    861     bool *out)
    862 {
    863         bithenge_node_t *cond_node;
    864         int rc = bithenge_expression_evaluate(self->expr, scope, &cond_node);
     989        bithenge_blob_t base;
     990        bithenge_blob_t *a, *b;
     991        aoff64_t a_size;
     992        bithenge_expression_t *b_expr;
     993        bithenge_scope_t *scope;
     994} concat_blob_t;
     995
     996static inline concat_blob_t *blob_as_concat(bithenge_blob_t *base)
     997{
     998        return (concat_blob_t *)base;
     999}
     1000
     1001static inline bithenge_blob_t *concat_as_blob(concat_blob_t *blob)
     1002{
     1003        return &blob->base;
     1004}
     1005
     1006static int concat_blob_evaluate_b(concat_blob_t *self)
     1007{
     1008        if (self->b)
     1009                return EOK;
     1010        bithenge_node_t *b_node;
     1011        int rc = bithenge_expression_evaluate(self->b_expr, self->scope,
     1012            &b_node);
    8651013        if (rc != EOK)
    8661014                return rc;
    867         if (bithenge_node_type(cond_node) != BITHENGE_NODE_BOOLEAN) {
    868                 bithenge_node_dec_ref(cond_node);
    869                 return EINVAL;
    870         }
    871         *out = bithenge_boolean_node_value(cond_node);
    872         bithenge_node_dec_ref(cond_node);
    873         return EOK;
    874 }
    875 
    876 static int if_transform_apply(bithenge_transform_t *base,
    877     bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
    878 {
    879         if_transform_t *self = transform_as_if(base);
    880         bool cond;
    881         int rc = if_transform_choose(self, scope, &cond);
     1015        if (bithenge_node_type(b_node) != BITHENGE_NODE_BLOB) {
     1016                bithenge_node_dec_ref(b_node);
     1017                return bithenge_scope_error(self->scope,
     1018                    "Concatenation arguments must be blobs");
     1019        }
     1020        self->b = bithenge_node_as_blob(b_node);
     1021        bithenge_expression_dec_ref(self->b_expr);
     1022        bithenge_scope_dec_ref(self->scope);
     1023        self->b_expr = NULL;
     1024        self->scope = NULL;
     1025        return EOK;
     1026}
     1027
     1028static int concat_blob_size(bithenge_blob_t *base, aoff64_t *size)
     1029{
     1030        concat_blob_t *self = blob_as_concat(base);
     1031        int rc = concat_blob_evaluate_b(self);
    8821032        if (rc != EOK)
    8831033                return rc;
    884         return bithenge_transform_apply(
    885             cond ? self->true_xform : self->false_xform, scope, in, out);
    886 }
    887 
    888 static int if_transform_prefix_length(bithenge_transform_t *base,
    889     bithenge_scope_t *scope, bithenge_blob_t *in, aoff64_t *out)
    890 {
    891         if_transform_t *self = transform_as_if(base);
    892         bool cond;
    893         int rc = if_transform_choose(self, scope, &cond);
    894         if (rc != EOK)
    895                 return rc;
    896         return bithenge_transform_prefix_length(
    897             cond ? self->true_xform : self->false_xform, scope, in, out);
    898 }
    899 
    900 static void if_transform_destroy(bithenge_transform_t *base)
    901 {
    902         if_transform_t *self = transform_as_if(base);
    903         bithenge_expression_dec_ref(self->expr);
    904         bithenge_transform_dec_ref(self->true_xform);
    905         bithenge_transform_dec_ref(self->false_xform);
    906         free(self);
    907 }
    908 
    909 static const bithenge_transform_ops_t if_transform_ops = {
    910         .apply = if_transform_apply,
    911         .prefix_length = if_transform_prefix_length,
    912         .destroy = if_transform_destroy,
     1034        rc = bithenge_blob_size(self->b, size);
     1035        *size += self->a_size;
     1036        return rc;
     1037}
     1038
     1039static int concat_blob_read(bithenge_blob_t *base, aoff64_t offset,
     1040    char *buffer, aoff64_t *size)
     1041{
     1042        int rc;
     1043        concat_blob_t *self = blob_as_concat(base);
     1044
     1045        aoff64_t a_size = 0, b_size = 0;
     1046        if (offset < self->a_size) {
     1047                a_size = *size;
     1048                rc = bithenge_blob_read(self->a, offset, buffer, &a_size);
     1049                if (rc != EOK)
     1050                        return rc;
     1051        }
     1052        if (offset + *size > self->a_size) {
     1053                rc = concat_blob_evaluate_b(self);
     1054                if (rc != EOK)
     1055                        return rc;
     1056                b_size = *size - a_size;
     1057                rc = bithenge_blob_read(self->b,
     1058                    offset + a_size - self->a_size, buffer + a_size, &b_size);
     1059                if (rc != EOK)
     1060                        return rc;
     1061        }
     1062        assert(a_size + b_size <= *size);
     1063        *size = a_size + b_size;
     1064        return EOK;
     1065}
     1066
     1067static int concat_blob_read_bits(bithenge_blob_t *base, aoff64_t offset,
     1068    char *buffer, aoff64_t *size, bool little_endian)
     1069{
     1070        int rc;
     1071        concat_blob_t *self = blob_as_concat(base);
     1072
     1073        aoff64_t a_size = 0, b_size = 0;
     1074        if (offset < self->a_size) {
     1075                a_size = *size;
     1076                rc = bithenge_blob_read_bits(self->a, offset, buffer, &a_size,
     1077                    little_endian);
     1078                if (rc != EOK)
     1079                        return rc;
     1080        }
     1081        if (offset + *size > self->a_size) {
     1082                rc = concat_blob_evaluate_b(self);
     1083                if (rc != EOK)
     1084                        return rc;
     1085                b_size = *size - a_size;
     1086                assert(a_size % 8 == 0); /* TODO: don't require this */
     1087                rc = bithenge_blob_read_bits(self->b,
     1088                    offset + a_size - self->a_size, buffer + a_size / 8,
     1089                    &b_size, little_endian);
     1090                if (rc != EOK)
     1091                        return rc;
     1092        }
     1093        assert(a_size + b_size <= *size);
     1094        *size = a_size + b_size;
     1095        return EOK;
     1096}
     1097
     1098static void concat_blob_destroy(bithenge_blob_t *base)
     1099{
     1100        concat_blob_t *self = blob_as_concat(base);
     1101        bithenge_blob_dec_ref(self->a);
     1102        bithenge_blob_dec_ref(self->b);
     1103        bithenge_expression_dec_ref(self->b_expr);
     1104        bithenge_scope_dec_ref(self->scope);
     1105        free(self);
     1106}
     1107
     1108static const bithenge_random_access_blob_ops_t concat_blob_ops = {
     1109        .size = concat_blob_size,
     1110        .read = concat_blob_read,
     1111        .read_bits = concat_blob_read_bits,
     1112        .destroy = concat_blob_destroy,
    9131113};
    9141114
    915 /** Create a transform that applies either of two transforms depending on a
    916  * boolean expression. Takes references to @a expr, @a true_xform, and
    917  * @a false_xform.
    918  * @param[out] out Holds the new transform.
    919  * @param expr The boolean expression to evaluate.
    920  * @param true_xform The transform to apply if the expression is true.
    921  * @param false_xform The transform to apply if the expression is false.
     1115/** Create a concatenated blob. Takes references to @a a and @a b.
     1116 * @param[out] out Holds the new blob.
     1117 * @param a The first blob.
     1118 * @param b The second blob.
    9221119 * @return EOK on success or an error code from errno.h. */
    923 int bithenge_if_transform(bithenge_transform_t **out,
    924     bithenge_expression_t *expr, bithenge_transform_t *true_xform,
    925     bithenge_transform_t *false_xform)
    926 {
    927         int rc;
    928         if_transform_t *self = malloc(sizeof(*self));
     1120int bithenge_concat_blob(bithenge_node_t **out, bithenge_blob_t *a,
     1121    bithenge_blob_t *b)
     1122{
     1123        assert(out);
     1124        assert(a);
     1125        assert(b);
     1126        int rc;
     1127        concat_blob_t *self = malloc(sizeof(*self));
    9291128        if (!self) {
    9301129                rc = ENOMEM;
     
    9321131        }
    9331132
    934         rc = bithenge_init_transform(if_as_transform(self), &if_transform_ops,
    935             0);
    936         if (rc != EOK)
    937                 goto error;
    938 
    939         self->expr = expr;
    940         self->true_xform = true_xform;
    941         self->false_xform = false_xform;
    942         *out = if_as_transform(self);
     1133        rc = bithenge_blob_size(a, &self->a_size);
     1134        if (rc != EOK)
     1135                goto error;
     1136
     1137        rc = bithenge_init_random_access_blob(concat_as_blob(self),
     1138            &concat_blob_ops);
     1139        if (rc != EOK)
     1140                goto error;
     1141        self->a = a;
     1142        self->b = b;
     1143        self->b_expr = NULL;
     1144        self->scope = NULL;
     1145        *out = bithenge_blob_as_node(concat_as_blob(self));
    9431146        return EOK;
    9441147
    9451148error:
    946         free(self);
    947         bithenge_expression_dec_ref(expr);
    948         bithenge_transform_dec_ref(true_xform);
    949         bithenge_transform_dec_ref(false_xform);
     1149        bithenge_blob_dec_ref(a);
     1150        bithenge_blob_dec_ref(b);
     1151        free(self);
     1152        return rc;
     1153}
     1154
     1155/** Create a lazy concatenated blob. Takes references to @a a, @a b_expr, and
     1156 * @a scope.
     1157 * @param[out] out Holds the new blob.
     1158 * @param a The first blob.
     1159 * @param b_expr An expression to calculate the second blob.
     1160 * @param scope The scope in which @a b_expr should be evaluated.
     1161 * @return EOK on success or an error code from errno.h. */
     1162int bithenge_concat_blob_lazy(bithenge_node_t **out, bithenge_blob_t *a,
     1163    bithenge_expression_t *b_expr, bithenge_scope_t *scope)
     1164{
     1165        assert(out);
     1166        assert(a);
     1167        assert(b_expr);
     1168        assert(scope);
     1169        int rc;
     1170        concat_blob_t *self = malloc(sizeof(*self));
     1171        if (!self) {
     1172                rc = ENOMEM;
     1173                goto error;
     1174        }
     1175
     1176        rc = bithenge_blob_size(a, &self->a_size);
     1177        if (rc != EOK)
     1178                goto error;
     1179
     1180        rc = bithenge_init_random_access_blob(concat_as_blob(self),
     1181            &concat_blob_ops);
     1182        if (rc != EOK)
     1183                goto error;
     1184        self->a = a;
     1185        self->b = NULL;
     1186        self->b_expr = b_expr;
     1187        self->scope = scope;
     1188        *out = bithenge_blob_as_node(concat_as_blob(self));
     1189        return EOK;
     1190
     1191error:
     1192        bithenge_blob_dec_ref(a);
     1193        bithenge_expression_dec_ref(b_expr);
     1194        bithenge_scope_dec_ref(scope);
     1195        free(self);
    9501196        return rc;
    9511197}
  • uspace/lib/bithenge/expression.h

    r0da6c04 r5e718d9  
    3838#define BITHENGE_EXPRESSION_H_
    3939
     40#include "blob.h"
    4041#include "transform.h"
    4142#include "tree.h"
     
    7374                return;
    7475        assert(self->ops);
     76        assert(self->refs > 0);
    7577        if (--self->refs == 0)
    7678                self->ops->destroy(self);
     
    9193}
    9294
     95/** The binary operators supported by @a bithenge_binary_expression(). */
    9396typedef enum {
    9497        BITHENGE_EXPRESSION_INVALID_BINARY_OP,
     98
    9599        BITHENGE_EXPRESSION_ADD,
    96100        BITHENGE_EXPRESSION_SUBTRACT,
    97101        BITHENGE_EXPRESSION_MULTIPLY,
     102        BITHENGE_EXPRESSION_INTEGER_DIVIDE,
     103        BITHENGE_EXPRESSION_MODULO,
     104
     105        BITHENGE_EXPRESSION_LESS_THAN,
     106        BITHENGE_EXPRESSION_GREATER_THAN,
     107        BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL,
     108        BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL,
    98109        BITHENGE_EXPRESSION_EQUALS,
     110        BITHENGE_EXPRESSION_NOT_EQUALS,
     111
     112        BITHENGE_EXPRESSION_AND,
     113        BITHENGE_EXPRESSION_OR,
     114
     115        BITHENGE_EXPRESSION_MEMBER,
     116        BITHENGE_EXPRESSION_CONCAT,
    99117} bithenge_binary_op_t;
    100118
     
    107125int bithenge_param_expression(bithenge_expression_t **, int);
    108126int bithenge_const_expression(bithenge_expression_t **, bithenge_node_t *);
    109 int bithenge_member_expression(bithenge_expression_t **,
    110     bithenge_expression_t *, bithenge_node_t *);
    111127int bithenge_scope_member_expression(bithenge_expression_t **,
    112128    bithenge_node_t *);
     129int bithenge_subblob_expression(bithenge_expression_t **,
     130    bithenge_expression_t *, bithenge_expression_t *, bithenge_expression_t *,
     131    bool);
    113132int bithenge_param_wrapper(bithenge_transform_t **, bithenge_transform_t *,
    114133    bithenge_expression_t **);
     
    117136int bithenge_inputless_transform(bithenge_transform_t **,
    118137    bithenge_expression_t *);
    119 int bithenge_if_transform(bithenge_transform_t **, bithenge_expression_t *,
    120     bithenge_transform_t *, bithenge_transform_t *);
     138
     139int bithenge_concat_blob(bithenge_node_t **, bithenge_blob_t *,
     140    bithenge_blob_t *);
     141int bithenge_concat_blob_lazy(bithenge_node_t **, bithenge_blob_t *,
     142    bithenge_expression_t *, bithenge_scope_t *);
    121143
    122144#endif
  • uspace/lib/bithenge/file.c

    r0da6c04 r5e718d9  
    7979                return ELIMIT;
    8080        if (lseek(blob->fd, offset, SEEK_SET) < 0)
    81                 return errno;
     81                return errno == EINVAL ? EIO : errno;
    8282
    8383        ssize_t amount_read;
  • uspace/lib/bithenge/helenos/block.c

    r0da6c04 r5e718d9  
    3737
    3838#include <assert.h>
     39#include <block.h>
    3940#include <errno.h>
    40 #include <libblock.h>
    4141#include <loc.h>
    4242#include <macros.h>
  • uspace/lib/bithenge/helenos/os.h

    r0da6c04 r5e718d9  
    2727 */
    2828
    29 #ifndef BITHENGE_OS_H_
    30 #define BITHENGE_OS_H_
     29#ifndef BITHENGE_HELENOS_OS_H_
     30#define BITHENGE_HELENOS_OS_H_
    3131
    3232#include <bool.h>
  • uspace/lib/bithenge/linux/os.h

    r0da6c04 r5e718d9  
    2727 */
    2828
    29 #ifndef BITHENGE_OS_H_
    30 #define BITHENGE_OS_H_
     29#ifndef BITHENGE_LINUX_OS_H_
     30#define BITHENGE_LINUX_OS_H_
    3131
    3232#include <endian.h>
  • uspace/lib/bithenge/print.c

    r0da6c04 r5e718d9  
    3838
    3939#include <errno.h>
     40#include <stdarg.h>
    4041#include <stdio.h>
    4142#include "blob.h"
     
    4748        bool first;
    4849        int depth;
     50        char *buffer;
     51        size_t buffer_size;
    4952} state_t;
    5053
     54static void state_printf(state_t *state, const char *format, ...)
     55{
     56        va_list ap;
     57        va_start(ap, format);
     58        if (state->buffer) {
     59                int rc = vsnprintf(state->buffer, state->buffer_size, format,
     60                    ap);
     61                if (rc > 0 && (size_t)rc >= state->buffer_size)
     62                        rc = state->buffer_size - 1;
     63                if (rc > 0) {
     64                        state->buffer += rc;
     65                        state->buffer_size -= rc;
     66                }
     67        } else {
     68                vprintf(format, ap);
     69        }
     70        va_end(ap);
     71}
     72
    5173static int print_node(state_t *, bithenge_node_t *);
    5274
    5375static void newline(state_t *state)
    5476{
    55         printf("\n");
     77        state_printf(state, "\n");
    5678        for (int i = 0; i < state->depth; i++) {
    57                 printf("    ");
     79                state_printf(state, "    ");
    5880        }
    5981}
     
    7496        int rc = EOK;
    7597        if (!state->first)
    76                 printf(",");
     98                state_printf(state, ",");
    7799        newline(state);
    78100        state->first = false;
     
    80102            && bithenge_node_type(key) != BITHENGE_NODE_STRING;
    81103        if (add_quotes)
    82                 printf("\"");
     104                state_printf(state, "\"");
    83105        rc = print_node(state, key);
    84106        if (rc != EOK)
    85107                goto end;
    86108        if (add_quotes)
    87                 printf("\"");
    88         printf(": ");
     109                state_printf(state, "\"");
     110        state_printf(state, ": ");
    89111        rc = print_node(state, value);
    90112        if (rc != EOK)
     
    99121{
    100122        int rc;
    101         printf("{");
     123        state_printf(state, "{");
    102124        increase_depth(state);
    103125        state->first = true;
     
    109131                newline(state);
    110132        state->first = false;
    111         printf("}");
     133        state_printf(state, "}");
    112134        return EOK;
    113135}
     
    118140        switch (state->type) {
    119141        case BITHENGE_PRINT_PYTHON:
    120                 printf(value ? "True" : "False");
     142                state_printf(state, value ? "True" : "False");
    121143                break;
    122144        case BITHENGE_PRINT_JSON:
    123                 printf(value ? "true" : "false");
     145                state_printf(state, value ? "true" : "false");
    124146                break;
    125147        }
     
    130152{
    131153        bithenge_int_t value = bithenge_integer_node_value(node);
    132         printf("%" BITHENGE_PRId, value);
     154        state_printf(state, "%" BITHENGE_PRId, value);
    133155        return EOK;
    134156}
     
    137159{
    138160        const char *value = bithenge_string_node_value(node);
    139         printf("\"");
     161        state_printf(state, "\"");
    140162        for (string_iterator_t i = string_iterator(value); !string_iterator_done(&i); ) {
    141163                wchar_t ch;
     
    144166                        return rc;
    145167                if (ch == '"' || ch == '\\') {
    146                         printf("\\%lc", (wint_t) ch);
     168                        state_printf(state, "\\%lc", (wint_t) ch);
    147169                } else if (ch <= 0x1f) {
    148                         printf("\\u%04x", (unsigned int) ch);
     170                        state_printf(state, "\\u%04x", (unsigned int) ch);
    149171                } else {
    150                         printf("%lc", (wint_t) ch);
     172                        state_printf(state, "%lc", (wint_t) ch);
    151173                }
    152174        }
    153         printf("\"");
     175        state_printf(state, "\"");
    154176        return EOK;
    155177}
     
    159181        bithenge_blob_t *blob = bithenge_node_as_blob(node);
    160182        aoff64_t pos = 0;
    161         char buffer[1024];
     183        uint8_t buffer[1024];
    162184        aoff64_t size = sizeof(buffer);
    163185        int rc;
    164         printf(state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
     186        state_printf(state,
     187            state->type == BITHENGE_PRINT_PYTHON ? "b\"" : "\"");
    165188        do {
    166                 rc = bithenge_blob_read(blob, pos, buffer, &size);
     189                rc = bithenge_blob_read(blob, pos, (char *)buffer, &size);
    167190                if (rc != EOK)
    168191                        return rc;
    169192                for (aoff64_t i = 0; i < size; i++)
    170                         printf("\\x%02x", (unsigned int)(uint8_t)buffer[i]);
     193                        state_printf(state, "\\x%02x",
     194                            (unsigned int)buffer[i]);
    171195                pos += size;
    172196        } while (size == sizeof(buffer));
    173         printf("\"");
     197        state_printf(state, "\"");
    174198        return EOK;
    175199}
     
    192216}
    193217
    194 /** Print a tree as text.
     218/** Print a tree as text to stdout.
    195219 * @param type The format to use.
    196220 * @param tree The root node of the tree to print.
     
    198222int bithenge_print_node(bithenge_print_type_t type, bithenge_node_t *tree)
    199223{
    200         state_t state = {type, true, 0};
     224        state_t state = {type, true, 0, NULL, 0};
    201225        return print_node(&state, tree);
    202226}
    203227
     228/** Print a tree as text into a buffer.
     229 * @param[in,out] str Holds a pointer to the buffer; changed to point to the
     230 * null character.
     231 * @param[in,out] size Holds the size of the buffer; changed to hold the
     232 * remaining size.
     233 * @param type The format to use.
     234 * @param tree The root node of the tree to print.
     235 * @return EOK on success or an error code from errno.h. */
     236int bithenge_print_node_to_string(char **str, size_t *size,
     237    bithenge_print_type_t type, bithenge_node_t *tree)
     238{
     239        state_t state = {type, true, 0, *str, *size};
     240        int rc = print_node(&state, tree);
     241        *str = state.buffer;
     242        *size = state.buffer_size;
     243        return rc;
     244}
     245
    204246/** @}
    205247 */
  • uspace/lib/bithenge/print.h

    r0da6c04 r5e718d9  
    5151
    5252int bithenge_print_node(bithenge_print_type_t, bithenge_node_t *);
     53int bithenge_print_node_to_string(char **, size_t *, bithenge_print_type_t,
     54    bithenge_node_t *);
    5355
    5456#endif
  • uspace/lib/bithenge/script.c

    r0da6c04 r5e718d9  
    3838#include <stdio.h>
    3939#include <stdlib.h>
     40#include "compound.h"
    4041#include "expression.h"
    4142#include "os.h"
     
    4546#include "tree.h"
    4647
     48/** @cond internal */
     49#define BUFFER_SIZE 4096
     50/** @endcond */
     51
    4752/** Tokens with more characters than this may be read incorrectly. */
    48 #define MAX_TOKEN_SIZE 256
    49 #define BUFFER_SIZE 4096
    50 
    51 /** Single-character symbols are represented by the character itself. Every
     53static const int MAX_TOKEN_SIZE = 256;
     54
     55/** @cond internal
     56 * Single-character symbols are represented by the character itself. Every
    5257 * other token uses one of these values: */
    5358typedef enum {
    54         TOKEN_EQUALS = -128,
    55         TOKEN_ERROR,
     59        TOKEN_ERROR = -128,
     60
     61        TOKEN_AND,
     62        TOKEN_CONCAT,
     63        TOKEN_EQUALS,
    5664        TOKEN_EOF,
     65        TOKEN_GREATER_THAN_OR_EQUAL,
    5766        TOKEN_IDENTIFIER,
    5867        TOKEN_INTEGER,
     68        TOKEN_INTEGER_DIVIDE,
    5969        TOKEN_LEFT_ARROW,
     70        TOKEN_LESS_THAN_OR_EQUAL,
     71        TOKEN_NOT_EQUAL,
     72        TOKEN_OR,
    6073
    6174        /* Keywords */
     
    6578        TOKEN_IF,
    6679        TOKEN_IN,
     80        TOKEN_PARTIAL,
    6781        TOKEN_REPEAT,
    6882        TOKEN_STRUCT,
     
    7286        TOKEN_WHILE,
    7387} token_type_t;
     88/** @endcond */
    7489
    7590/** Singly-linked list of named transforms. */
     
    232247                        state->token = TOKEN_IN;
    233248                        free(value);
     249                } else if (!str_cmp(value, "partial")) {
     250                        state->token = TOKEN_PARTIAL;
     251                        free(value);
    234252                } else if (!str_cmp(value, "repeat")) {
    235253                        state->token = TOKEN_REPEAT;
     
    267285                        state->buffer_pos++;
    268286                        state->token = TOKEN_LEFT_ARROW;
     287                } else if (state->buffer[state->buffer_pos] == '=') {
     288                        state->buffer_pos++;
     289                        state->token = TOKEN_LESS_THAN_OR_EQUAL;
     290                }
     291        } else if (ch == '>') {
     292                state->token = ch;
     293                state->buffer_pos++;
     294                if (state->buffer[state->buffer_pos] == '=') {
     295                        state->buffer_pos++;
     296                        state->token = TOKEN_GREATER_THAN_OR_EQUAL;
    269297                }
    270298        } else if (ch == '=') {
     
    275303                        state->buffer_pos++;
    276304                }
     305        } else if (ch == '/') {
     306                state->token = ch;
     307                state->buffer_pos++;
     308                if (state->buffer[state->buffer_pos] == '/') {
     309                        state->token = TOKEN_INTEGER_DIVIDE;
     310                        state->buffer_pos++;
     311                }
     312        } else if (ch == '!') {
     313                state->token = ch;
     314                state->buffer_pos++;
     315                if (state->buffer[state->buffer_pos] == '=') {
     316                        state->token = TOKEN_NOT_EQUAL;
     317                        state->buffer_pos++;
     318                }
     319        } else if (ch == '&') {
     320                state->token = ch;
     321                state->buffer_pos++;
     322                if (state->buffer[state->buffer_pos] == '&') {
     323                        state->token = TOKEN_AND;
     324                        state->buffer_pos++;
     325                }
     326        } else if (ch == '|') {
     327                state->token = ch;
     328                state->buffer_pos++;
     329                if (state->buffer[state->buffer_pos] == '|') {
     330                        state->token = TOKEN_OR;
     331                        state->buffer_pos++;
     332                }
     333        } else if (ch == '+') {
     334                state->token = ch;
     335                state->buffer_pos++;
     336                if (state->buffer[state->buffer_pos] == '+') {
     337                        state->token = TOKEN_CONCAT;
     338                        state->buffer_pos++;
     339                }
    277340        } else {
    278341                state->token = ch;
     
    380443/***************** Expressions                               *****************/
    381444
     445/** @cond internal */
    382446typedef enum {
    383447        PRECEDENCE_NONE,
     448        PRECEDENCE_AND,
    384449        PRECEDENCE_EQUALS,
     450        PRECEDENCE_COMPARE,
    385451        PRECEDENCE_ADD,
    386452        PRECEDENCE_MULTIPLY,
    387453} precedence_t;
     454/** @endcond */
    388455
    389456static bithenge_binary_op_t token_as_binary_operator(token_type_t token)
     
    396463        case '*':
    397464                return BITHENGE_EXPRESSION_MULTIPLY;
     465        case TOKEN_INTEGER_DIVIDE:
     466                return BITHENGE_EXPRESSION_INTEGER_DIVIDE;
     467        case '%':
     468                return BITHENGE_EXPRESSION_MODULO;
     469        case '<':
     470                return BITHENGE_EXPRESSION_LESS_THAN;
     471        case TOKEN_LESS_THAN_OR_EQUAL:
     472                return BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL;
     473        case '>':
     474                return BITHENGE_EXPRESSION_GREATER_THAN;
     475        case TOKEN_GREATER_THAN_OR_EQUAL:
     476                return BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL;
    398477        case TOKEN_EQUALS:
    399478                return BITHENGE_EXPRESSION_EQUALS;
     479        case TOKEN_NOT_EQUAL:
     480                return BITHENGE_EXPRESSION_NOT_EQUALS;
     481        case TOKEN_AND:
     482                return BITHENGE_EXPRESSION_AND;
     483        case TOKEN_OR:
     484                return BITHENGE_EXPRESSION_OR;
     485        case TOKEN_CONCAT:
     486                return BITHENGE_EXPRESSION_CONCAT;
    400487        default:
    401488                return BITHENGE_EXPRESSION_INVALID_BINARY_OP;
     
    407494        switch (op) {
    408495        case BITHENGE_EXPRESSION_ADD: /* fallthrough */
    409         case BITHENGE_EXPRESSION_SUBTRACT:
     496        case BITHENGE_EXPRESSION_SUBTRACT: /* fallthrough */
     497        case BITHENGE_EXPRESSION_CONCAT:
    410498                return PRECEDENCE_ADD;
    411         case BITHENGE_EXPRESSION_MULTIPLY:
     499        case BITHENGE_EXPRESSION_MULTIPLY: /* fallthrough */
     500        case BITHENGE_EXPRESSION_INTEGER_DIVIDE: /* fallthrough */
     501        case BITHENGE_EXPRESSION_MODULO:
    412502                return PRECEDENCE_MULTIPLY;
    413         case BITHENGE_EXPRESSION_EQUALS:
     503        case BITHENGE_EXPRESSION_LESS_THAN: /* fallthrough */
     504        case BITHENGE_EXPRESSION_LESS_THAN_OR_EQUAL: /* fallthrough */
     505        case BITHENGE_EXPRESSION_GREATER_THAN: /* fallthrough */
     506        case BITHENGE_EXPRESSION_GREATER_THAN_OR_EQUAL:
     507                return PRECEDENCE_COMPARE;
     508        case BITHENGE_EXPRESSION_EQUALS: /* fallthrough */
     509        case BITHENGE_EXPRESSION_NOT_EQUALS:
    414510                return PRECEDENCE_EQUALS;
     511        case BITHENGE_EXPRESSION_AND: /* fallthrough */
     512        case BITHENGE_EXPRESSION_OR:
     513                return PRECEDENCE_AND;
    415514        default:
    416515                assert(false);
     
    480579                }
    481580
     581                next_token(state);
     582
    482583                bithenge_expression_t *expr;
    483584                rc = bithenge_param_expression(&expr, i);
     
    486587                        return NULL;
    487588                }
    488 
    489                 next_token(state);
    490 
    491589                return expr;
    492590        } else if (state->token == '.') {
     
    530628}
    531629
     630static bithenge_expression_t *parse_postfix_expression(state_t *state)
     631{
     632        int rc;
     633        bithenge_expression_t *expr = parse_term(state);
     634        while (state->error == EOK) {
     635                if (state->token == '.') {
     636                        next_token(state);
     637
     638                        const char *id = expect_identifier(state);
     639
     640                        if (state->error != EOK) {
     641                                free((char *)id);
     642                                bithenge_expression_dec_ref(expr);
     643                                return NULL;
     644                        }
     645
     646                        bithenge_node_t *key = NULL;
     647                        rc = bithenge_new_string_node(&key, id, true);
     648                        if (rc != EOK) {
     649                                error_errno(state, rc);
     650                                bithenge_expression_dec_ref(expr);
     651                                return NULL;
     652                        }
     653
     654                        bithenge_expression_t *key_expr;
     655                        rc = bithenge_const_expression(&key_expr, key);
     656                        if (rc != EOK) {
     657                                error_errno(state, rc);
     658                                bithenge_expression_dec_ref(expr);
     659                                return NULL;
     660                        }
     661
     662                        rc = bithenge_binary_expression(&expr,
     663                            BITHENGE_EXPRESSION_MEMBER, expr, key_expr);
     664                        if (rc != EOK) {
     665                                error_errno(state, rc);
     666                                return NULL;
     667                        }
     668                } else if (state->token == '[') {
     669                        next_token(state);
     670                        bithenge_expression_t *start = parse_expression(state);
     671                        bool absolute_limit = false;
     672                        if (state->token == ',' || state->token == ':') {
     673                                absolute_limit = state->token == ':';
     674                                next_token(state);
     675                                bithenge_expression_t *limit = NULL;
     676                                if (!(state->token == ']' && absolute_limit))
     677                                        limit = parse_expression(state);
     678                                expect(state, ']');
     679
     680                                if (state->error != EOK) {
     681                                        bithenge_expression_dec_ref(expr);
     682                                        bithenge_expression_dec_ref(start);
     683                                        bithenge_expression_dec_ref(limit);
     684                                        return NULL;
     685                                }
     686                                rc = bithenge_subblob_expression(&expr, expr, start,
     687                                    limit, absolute_limit);
     688                                if (rc != EOK) {
     689                                        error_errno(state, rc);
     690                                        return NULL;
     691                                }
     692                        } else if (state->token == ']') {
     693                                next_token(state);
     694
     695                                if (state->error != EOK) {
     696                                        bithenge_expression_dec_ref(expr);
     697                                        bithenge_expression_dec_ref(start);
     698                                        return NULL;
     699                                }
     700                                rc = bithenge_binary_expression(&expr,
     701                                    BITHENGE_EXPRESSION_MEMBER, expr, start);
     702                                if (rc != EOK) {
     703                                        error_errno(state, rc);
     704                                        return NULL;
     705                                }
     706                        } else {
     707                                syntax_error(state, "expected ',', ':', or ']'");
     708                                bithenge_expression_dec_ref(expr);
     709                                bithenge_expression_dec_ref(start);
     710                                return NULL;
     711                        }
     712                } else {
     713                        break;
     714                }
     715        }
     716        return expr;
     717}
     718
    532719static bithenge_expression_t *parse_expression_precedence(state_t *state,
    533720    precedence_t prev_precedence)
    534721{
    535         bithenge_expression_t *expr = parse_term(state);
     722        bithenge_expression_t *expr = parse_postfix_expression(state);
    536723        while (state->error == EOK) {
    537724                bithenge_binary_op_t op =
     
    544731                next_token(state);
    545732
    546                 bithenge_expression_t *expr2 = parse_term(state);
     733                bithenge_expression_t *expr2 =
     734                    parse_expression_precedence(state, precedence);
    547735                if (state->error != EOK) {
    548736                        bithenge_expression_dec_ref(expr2);
     
    550738                }
    551739                int rc = bithenge_binary_expression(&expr, op, expr, expr2);
    552                 if (rc != EOK)
    553                         error_errno(state, rc);
     740                if (rc != EOK) {
     741                        expr = NULL;
     742                        error_errno(state, rc);
     743                }
    554744        }
    555745        if (state->error != EOK) {
     
    759949                int rc = bithenge_if_transform(&switch_xform, exprs[num],
    760950                    xforms[num], switch_xform);
    761                 if (rc != EOK)
    762                         error_errno(state, rc);
     951                if (rc != EOK) {
     952                        switch_xform = NULL;
     953                        error_errno(state, rc);
     954                }
    763955        }
    764956
     
    8271019        }
    8281020        return do_while_xform;
     1021}
     1022
     1023static bithenge_transform_t *parse_partial(state_t *state)
     1024{
     1025        expect(state, TOKEN_PARTIAL);
     1026        bithenge_transform_t *offset_xform = NULL;
     1027        if (state->token == '(') {
     1028                next_token(state);
     1029                bithenge_expression_t *offset = parse_expression(state);
     1030                expect(state, ')');
     1031
     1032                bithenge_expression_t *in_expr;
     1033                int rc = bithenge_in_node_expression(&in_expr);
     1034                if (rc != EOK)
     1035                        error_errno(state, rc);
     1036                if (state->error != EOK) {
     1037                        bithenge_expression_dec_ref(offset);
     1038                        return NULL;
     1039                }
     1040
     1041                rc = bithenge_subblob_expression(&offset, in_expr, offset,
     1042                    NULL, true);
     1043                if (rc != EOK) {
     1044                        error_errno(state, rc);
     1045                        return NULL;
     1046                }
     1047
     1048                rc = bithenge_expression_transform(&offset_xform, offset);
     1049                if (rc != EOK) {
     1050                        error_errno(state, rc);
     1051                        return NULL;
     1052                }
     1053        }
     1054        expect(state, '{');
     1055        bithenge_transform_t *xform = parse_transform(state);
     1056        expect(state, '}');
     1057        if (state->error != EOK) {
     1058                bithenge_transform_dec_ref(offset_xform);
     1059                bithenge_transform_dec_ref(xform);
     1060                return NULL;
     1061        }
     1062
     1063        int rc = bithenge_partial_transform(&xform, xform);
     1064        if (rc != EOK) {
     1065                error_errno(state, rc);
     1066                bithenge_transform_dec_ref(offset_xform);
     1067                return NULL;
     1068        }
     1069
     1070        if (offset_xform) {
     1071                bithenge_transform_t **xforms = malloc(2 * sizeof(*xforms));
     1072                if (!xforms) {
     1073                        error_errno(state, ENOMEM);
     1074                        bithenge_transform_dec_ref(xform);
     1075                        bithenge_transform_dec_ref(offset_xform);
     1076                        return NULL;
     1077                }
     1078                xforms[0] = xform;
     1079                xforms[1] = offset_xform;
     1080                rc = bithenge_new_composed_transform(&xform, xforms, 2);
     1081                if (rc != EOK) {
     1082                        error_errno(state, rc);
     1083                        return NULL;
     1084                }
     1085        }
     1086
     1087        return xform;
    8291088}
    8301089
     
    9101169        } else if (state->token == TOKEN_IF) {
    9111170                return parse_if(state, false);
     1171        } else if (state->token == TOKEN_PARTIAL) {
     1172                return parse_partial(state);
    9121173        } else if (state->token == TOKEN_REPEAT) {
    9131174                return parse_repeat(state);
     
    9391200                if (state->error != EOK)
    9401201                        break;
    941                 xforms[num] = parse_transform_no_compose(state);
    942                 num++;
     1202                xforms[num++] = parse_transform_no_compose(state);
    9431203        }
    9441204        if (state->error != EOK) {
    945                 while (xforms && num--)
    946                         bithenge_transform_dec_ref(xforms[num]);
     1205                while (xforms && num > 1)
     1206                        bithenge_transform_dec_ref(xforms[--num]);
    9471207                free(xforms);
    9481208                bithenge_transform_dec_ref(result);
     
    9821242        }
    9831243
     1244        bithenge_transform_t *barrier = NULL;
     1245        if (state->error == EOK) {
     1246                int rc = bithenge_new_barrier_transform(&barrier,
     1247                    state->num_params);
     1248                if (rc != EOK) {
     1249                        barrier = NULL;
     1250                        error_errno(state, rc);
     1251                }
     1252        }
     1253
     1254        add_named_transform(state, barrier, name);
     1255
    9841256        expect(state, '=');
    9851257        bithenge_transform_t *xform = parse_transform(state);
     
    9871259
    9881260        if (state->error == EOK) {
    989                 int rc = bithenge_new_barrier_transform(&xform, xform,
    990                     state->num_params);
    991                 if (rc != EOK) {
    992                         xform = NULL;
    993                         error_errno(state, rc);
    994                 }
    995         }
    996 
    997         add_named_transform(state, xform, name);
     1261                int rc = bithenge_barrier_transform_set_subtransform(barrier,
     1262                    xform);
     1263                xform = NULL;
     1264                if (rc != EOK)
     1265                        error_errno(state, rc);
     1266        }
     1267
     1268        if (state->error != EOK)
     1269                bithenge_transform_dec_ref(xform);
    9981270
    9991271        for (int i = 0; i < state->num_params; i++)
  • uspace/lib/bithenge/sequence.c

    r0da6c04 r5e718d9  
    418418        struct_node_t *node = node_as_struct(base);
    419419
    420         /* We didn't inc_ref for the scope in struct_transform_make_node, so
    421          * make sure it doesn't try to dec_ref. */
    422         seq_node_scope(struct_as_seq(node))->current_node = NULL;
    423         seq_node_destroy(struct_as_seq(node));
     420        /* Treat the scope carefully because of the circular reference. In
     421         * struct_transform_make_node, things are set up so node owns a
     422         * reference to the scope, but scope doesn't own a reference to node,
     423         * so node's reference count is too low. */
     424        bithenge_scope_t *scope = seq_node_scope(struct_as_seq(node));
     425        if (scope->refs == 1) {
     426                /* Mostly normal destroy, but we didn't inc_ref(node) for the
     427                 * scope in struct_transform_make_node, so make sure it doesn't
     428                 * try to dec_ref. */
     429                scope->current_node = NULL;
     430                seq_node_destroy(struct_as_seq(node));
     431        } else if (scope->refs > 1) {
     432                /* The scope is still needed, but node isn't otherwise needed.
     433                 * Switch things around so scope owns a reference to node, but
     434                 * not vice versa, and scope's reference count is too low. */
     435                bithenge_node_inc_ref(base);
     436                bithenge_scope_dec_ref(scope);
     437                return;
     438        } else {
     439                /* This happens after the previous case, when scope is no
     440                 * longer used and is being destroyed. Since scope is already
     441                 * being destroyed, set it to NULL here so we don't try to
     442                 * destroy it twice. */
     443                struct_as_seq(node)->scope = NULL;
     444                seq_node_destroy(struct_as_seq(node));
     445        }
    424446
    425447        bithenge_transform_dec_ref(struct_as_transform(node->transform));
     
    466488                return rc;
    467489        }
     490
     491        rc = seq_node_init(struct_as_seq(node), &struct_node_seq_ops, inner,
     492            blob, self->num_subtransforms, false);
     493        if (rc != EOK) {
     494                bithenge_scope_dec_ref(inner);
     495                free(node);
     496                return rc;
     497        }
     498
     499        bithenge_transform_inc_ref(struct_as_transform(self));
     500        node->transform = self;
     501        node->prefix = prefix;
     502
    468503        /* We should inc_ref(node) here, but that would make a cycle. Instead,
    469504         * we leave it 1 too low, so that when the only remaining use of node
     
    471506         * struct_node_destroy. */
    472507        bithenge_scope_set_current_node(inner, struct_as_node(node));
    473 
    474         rc = seq_node_init(struct_as_seq(node), &struct_node_seq_ops, inner,
    475             blob, self->num_subtransforms, false);
    476508        bithenge_scope_dec_ref(inner);
    477         if (rc != EOK) {
    478                 free(node);
    479                 return rc;
    480         }
    481 
    482         bithenge_transform_inc_ref(struct_as_transform(self));
    483         node->transform = self;
    484         node->prefix = prefix;
     509
    485510        *out = struct_as_node(node);
    486511
     
    524549                return rc;
    525550
    526         rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
    527             self->num_subtransforms);
    528         if (rc != EOK) {
    529                 bithenge_node_dec_ref(*out_node);
    530                 return rc;
     551        if (out_size) {
     552                rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
     553                    self->num_subtransforms);
     554                if (rc != EOK) {
     555                        bithenge_node_dec_ref(*out_node);
     556                        return rc;
     557                }
    531558        }
    532559
     
    595622/***************** bithenge_repeat_transform                 *****************/
    596623
     624/* TODO: ignore errors */
     625
    597626typedef struct {
    598627        bithenge_transform_t base;
     
    793822                return rc;
    794823
    795         bithenge_int_t count = node_as_repeat(*out_node)->count;
    796         if (count != -1) {
    797                 rc = seq_node_field_offset(node_as_seq(*out_node), out_size, count);
    798                 if (rc != EOK) {
    799                         bithenge_node_dec_ref(*out_node);
    800                         return rc;
    801                 }
    802         } else {
    803                 *out_size = 0;
    804                 for (count = 1; ; count++) {
    805                         aoff64_t size;
     824        if (out_size) {
     825                bithenge_int_t count = node_as_repeat(*out_node)->count;
     826                if (count != -1) {
    806827                        rc = seq_node_field_offset(node_as_seq(*out_node),
    807                             &size, count);
    808                         if (rc != EOK)
    809                                 break;
    810                         *out_size = size;
     828                            out_size, count);
     829                        if (rc != EOK) {
     830                                bithenge_node_dec_ref(*out_node);
     831                                return rc;
     832                        }
     833                } else {
     834                        *out_size = 0;
     835                        for (count = 1; ; count++) {
     836                                aoff64_t size;
     837                                rc = seq_node_field_offset(
     838                                    node_as_seq(*out_node), &size, count);
     839                                if (rc == EINVAL || rc == ENOENT)
     840                                        break;
     841                                if (rc != EOK) {
     842                                        bithenge_node_dec_ref(*out_node);
     843                                        return rc;
     844                                }
     845                                *out_size = size;
     846                        }
    811847                }
    812848        }
     
    886922typedef struct {
    887923        seq_node_t base;
    888         bool prefix;
    889924        bithenge_expression_t *expr;
    890925        bithenge_transform_t *xform;
     
    9661001        }
    9671002
    968         if (!self->prefix) {
    969                 bool complete;
    970                 rc = seq_node_complete(do_while_as_seq(self), &complete);
    971                 if (rc != EOK)
    972                         return rc;
    973                 if (!complete)
    974                         return EINVAL;
    975         }
    976 
    9771003        return rc;
    9781004}
     
    10061032
    10071033static int do_while_transform_make_node(do_while_transform_t *self,
    1008     bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
    1009     bool prefix)
     1034    bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob)
    10101035{
    10111036        do_while_node_t *node = malloc(sizeof(*node));
     
    10311056        bithenge_expression_inc_ref(self->expr);
    10321057        node->expr = self->expr;
    1033         node->prefix = prefix;
    10341058        node->count = -1;
    10351059        *out = do_while_as_node(node);
    10361060        return EOK;
    1037 }
    1038 
    1039 static int do_while_transform_apply(bithenge_transform_t *base,
    1040     bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
    1041 {
    1042         do_while_transform_t *self = transform_as_do_while(base);
    1043         if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
    1044                 return EINVAL;
    1045         return do_while_transform_make_node(self, out, scope,
    1046             bithenge_node_as_blob(in), false);
    10471061}
    10481062
     
    10601074{
    10611075        do_while_transform_t *self = transform_as_do_while(base);
    1062         int rc = do_while_transform_make_node(self, out_node, scope, blob,
    1063             true);
     1076        int rc = do_while_transform_make_node(self, out_node, scope, blob);
    10641077        if (rc != EOK)
    10651078                return rc;
    10661079
    1067         rc = bithenge_node_for_each(*out_node, for_each_noop, NULL);
    1068         if (rc != EOK) {
    1069                 bithenge_node_dec_ref(*out_node);
    1070                 return rc;
    1071         }
    1072 
    1073         rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
    1074             node_as_do_while(*out_node)->count);
    1075         if (rc != EOK) {
    1076                 bithenge_node_dec_ref(*out_node);
    1077                 return rc;
     1080        if (out_size) {
     1081                rc = bithenge_node_for_each(*out_node, for_each_noop, NULL);
     1082                if (rc != EOK) {
     1083                        bithenge_node_dec_ref(*out_node);
     1084                        return rc;
     1085                }
     1086
     1087                rc = seq_node_field_offset(node_as_seq(*out_node), out_size,
     1088                    node_as_do_while(*out_node)->count);
     1089                if (rc != EOK) {
     1090                        bithenge_node_dec_ref(*out_node);
     1091                        return rc;
     1092                }
    10781093        }
    10791094
     
    10901105
    10911106static const bithenge_transform_ops_t do_while_transform_ops = {
    1092         .apply = do_while_transform_apply,
    10931107        .prefix_apply = do_while_transform_prefix_apply,
    10941108        .destroy = do_while_transform_destroy,
  • uspace/lib/bithenge/transform.c

    r0da6c04 r5e718d9  
    3737#include <assert.h>
    3838#include <errno.h>
     39#include <stdarg.h>
    3940#include <stdlib.h>
    4041#include "blob.h"
     42#include "os.h"
     43#include "print.h"
    4144#include "transform.h"
     45
     46
     47
     48/***************** transform                                 *****************/
    4249
    4350/** Initialize a new transform.
     
    5663        assert(ops->apply || ops->prefix_apply);
    5764        assert(ops->destroy);
     65        if (bithenge_should_fail())
     66                return ENOMEM;
    5867        self->ops = ops;
    5968        self->refs = 1;
     
    137146 * @param[out] out_node Holds the result of applying this transform to the
    138147 * prefix.
    139  * @param[out] out_size Holds the size of the prefix.
     148 * @param[out] out_size Holds the size of the prefix. Can be null, in which
     149 * case the size is not determined.
    140150 * @return EOK on success, ENOTSUP if not supported, or another error code from
    141151 * errno.h. */
     
    152162                return ENOTSUP;
    153163
    154         int rc = bithenge_transform_prefix_length(self, scope, blob, out_size);
     164        aoff64_t size;
     165        int rc = bithenge_transform_prefix_length(self, scope, blob, &size);
    155166        if (rc != EOK)
    156167                return rc;
    157168        bithenge_node_t *prefix_blob;
    158169        bithenge_blob_inc_ref(blob);
    159         rc = bithenge_new_subblob(&prefix_blob, blob, 0, *out_size);
     170        rc = bithenge_new_subblob(&prefix_blob, blob, 0, size);
    160171        if (rc != EOK)
    161172                return rc;
    162173        rc = bithenge_transform_apply(self, scope, prefix_blob, out_node);
    163174        bithenge_node_dec_ref(prefix_blob);
     175        if (out_size)
     176                *out_size = size;
    164177        return rc;
    165178}
     179
     180
     181
     182/***************** scope                                     *****************/
    166183
    167184/** Create a transform scope. It must be dereferenced with @a
    168185 * bithenge_scope_dec_ref after it is used. Takes ownership of nothing.
     186 * @memberof bithenge_scope_t
    169187 * @param[out] out Holds the new scope.
    170188 * @param outer The outer scope, or NULL.
     
    179197                bithenge_scope_inc_ref(outer);
    180198        self->outer = outer;
     199        self->error = NULL;
    181200        self->barrier = false;
    182201        self->num_params = 0;
     
    189208
    190209/** Dereference a transform scope.
    191  * @param self The scope to dereference. */
     210 * @memberof bithenge_scope_t
     211 * @param self The scope to dereference, or NULL. */
    192212void bithenge_scope_dec_ref(bithenge_scope_t *self)
    193213{
     
    201221        bithenge_scope_dec_ref(self->outer);
    202222        free(self->params);
     223        free(self->error);
    203224        free(self);
    204225}
    205226
    206227/** Get the outer scope of a scope, which may be NULL.
     228 * @memberof bithenge_scope_t
    207229 * @param self The scope to examine.
    208230 * @return The outer scope, which may be NULL. */
     
    212234}
    213235
     236/** Get the error message stored in the scope, which may be NULL. The error
     237 * message only exists as long as the scope does.
     238 * @memberof bithenge_scope_t
     239 * @param scope The scope to get the error message from.
     240 * @return The error message, or NULL. */
     241const char *bithenge_scope_get_error(bithenge_scope_t *scope)
     242{
     243        return scope->error;
     244}
     245
     246/** Set the error message for the scope. The error message is stored in the
     247 * outermost scope, but if any scope already has an error message this error
     248 * message is ignored.
     249 * @memberof bithenge_scope_t
     250 * @param scope The scope.
     251 * @param format The format string.
     252 * @return EINVAL normally, or another error code from errno.h. */
     253int bithenge_scope_error(bithenge_scope_t *scope, const char *format, ...)
     254{
     255        if (scope->error)
     256                return EINVAL;
     257        while (scope->outer) {
     258                scope = scope->outer;
     259                if (scope->error)
     260                        return EINVAL;
     261        }
     262        size_t space_left = 256;
     263        scope->error = malloc(space_left);
     264        if (!scope->error)
     265                return ENOMEM;
     266        char *out = scope->error;
     267        va_list ap;
     268        va_start(ap, format);
     269
     270        while (*format) {
     271                if (format[0] == '%' && format[1] == 't') {
     272                        format += 2;
     273                        int rc = bithenge_print_node_to_string(&out,
     274                            &space_left, BITHENGE_PRINT_PYTHON,
     275                            va_arg(ap, bithenge_node_t *));
     276                        if (rc != EOK) {
     277                                va_end(ap);
     278                                return rc;
     279                        }
     280                } else {
     281                        const char *end = str_chr(format, '%');
     282                        if (!end)
     283                                end = format + str_length(format);
     284                        size_t size = min((size_t)(end - format),
     285                            space_left - 1);
     286                        memcpy(out, format, size);
     287                        format = end;
     288                        out += size;
     289                        space_left -= size;
     290                }
     291        }
     292        *out = '\0';
     293
     294        va_end(ap);
     295        return EINVAL;
     296}
     297
    214298/** Get the current node being created, which may be NULL.
     299 * @memberof bithenge_scope_t
    215300 * @param scope The scope to get the current node from.
    216301 * @return The node being created, or NULL. */
     
    223308
    224309/** Set the current node being created. Takes a reference to @a node.
     310 * @memberof bithenge_scope_t
    225311 * @param scope The scope to set the current node in.
    226312 * @param node The current node being created, or NULL. */
     
    233319
    234320/** Get the current input node, which may be NULL.
     321 * @memberof bithenge_scope_t
    235322 * @param scope The scope to get the current input node from.
    236323 * @return The input node, or NULL. */
     
    243330
    244331/** Set the current input node. Takes a reference to @a node.
     332 * @memberof bithenge_scope_t
    245333 * @param scope The scope to set the input node in.
    246334 * @param node The input node, or NULL. */
     
    252340
    253341/** Set a scope as a barrier.
     342 * @memberof bithenge_scope_t
    254343 * @param self The scope to change. */
    255344void bithenge_scope_set_barrier(bithenge_scope_t *self)
     
    260349/** Check whether a scope is a barrier, meaning that variable lookup stops at
    261350 * it.
     351 * @memberof bithenge_scope_t
    262352 * @param self The scope to check.
    263353 * @return Whether the scope is a barrier. */
     
    270360 * bithenge_scope_set_param. This must not be called on a scope that already
    271361 * has parameters.
     362 * @memberof bithenge_scope_t
    272363 * @param scope The scope in which to allocate parameters.
    273364 * @param num_params The number of parameters to allocate.
     
    284375}
    285376
    286 /** Set a parameter. Takes a reference to @a value. Note that range checking is
     377/** Set a parameter. Takes a reference to @a node. Note that range checking is
    287378 * not done in release builds.
     379 * @memberof bithenge_scope_t
    288380 * @param scope The scope in which to allocate parameters.
    289381 * @param i The index of the parameter to set.
    290  * @param value The value to store in the parameter.
     382 * @param node The value to store in the parameter.
    291383 * @return EOK on success or an error code from errno.h. */
    292384int bithenge_scope_set_param( bithenge_scope_t *scope, int i,
     
    295387        assert(scope);
    296388        assert(i >= 0 && i < scope->num_params);
     389        if (bithenge_should_fail()) {
     390                bithenge_node_dec_ref(node);
     391                return ENOMEM;
     392        }
    297393        scope->params[i] = node;
    298394        return EOK;
     
    300396
    301397/** Get a parameter. Note that range checking is not done in release builds.
     398 * @memberof bithenge_scope_t
    302399 * @param scope The scope to get the parameter from.
    303400 * @param i The index of the parameter to set.
     
    318415}
    319416
     417
     418
     419/***************** barrier_transform                         *****************/
     420
    320421typedef struct {
    321422        bithenge_transform_t base;
     
    344445                return rc;
    345446        bithenge_scope_set_barrier(inner_scope);
    346         rc = bithenge_transform_apply(self->transform, scope, in, out);
     447        bithenge_scope_set_in_node(inner_scope, in);
     448        rc = bithenge_transform_apply(self->transform, inner_scope, in, out);
    347449        bithenge_scope_dec_ref(inner_scope);
    348450        return rc;
     
    358460                return rc;
    359461        bithenge_scope_set_barrier(inner_scope);
    360         rc = bithenge_transform_prefix_length(self->transform, scope, in, out);
     462        bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in));
     463        rc = bithenge_transform_prefix_length(self->transform, inner_scope, in,
     464            out);
    361465        bithenge_scope_dec_ref(inner_scope);
    362466        return rc;
     
    373477                return rc;
    374478        bithenge_scope_set_barrier(inner_scope);
    375         rc = bithenge_transform_prefix_apply(self->transform, scope, in,
     479        bithenge_scope_set_in_node(inner_scope, bithenge_blob_as_node(in));
     480        rc = bithenge_transform_prefix_apply(self->transform, inner_scope, in,
    376481            out_node, out_length);
    377482        bithenge_scope_dec_ref(inner_scope);
     
    393498};
    394499
     500/** Set the subtransform of a barrier transform. This must be done before the
     501 * barrier transform is used. Takes a reference to @a transform.
     502 * @param base The barrier transform.
     503 * @param transform The subtransform to use for all operations.
     504 * @return EOK on success or an error code from errno.h. */
     505int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *base,
     506    bithenge_transform_t *transform)
     507{
     508        assert(transform);
     509        assert(bithenge_transform_num_params(transform) == 0);
     510
     511        if (bithenge_should_fail()) {
     512                bithenge_transform_dec_ref(transform);
     513                return ENOMEM;
     514        }
     515
     516        barrier_transform_t *self = transform_as_barrier(base);
     517        assert(!self->transform);
     518        self->transform = transform;
     519        return EOK;
     520}
     521
    395522/** Create a wrapper transform that creates a new scope. This ensures nothing
    396523 * from the outer scope is passed in, other than parameters. The wrapper may
    397  * have a different value for num_params. Takes a reference to @a transform,
    398  * which it will use for all operations.
     524 * have a different value for num_params. The subtransform must be set with @a
     525 * bithenge_barrier_transform_set_subtransform before the result is used.
    399526 * @param[out] out Holds the created transform.
    400  * @param transform The transform to wrap.
    401527 * @param num_params The number of parameters to require, which may be 0.
    402528 * @return EOK on success or an error code from errno.h. */
    403 int bithenge_new_barrier_transform(bithenge_transform_t **out,
    404     bithenge_transform_t *transform, int num_params)
    405 {
    406         assert(transform);
    407         assert(bithenge_transform_num_params(transform) == 0);
    408 
     529int bithenge_new_barrier_transform(bithenge_transform_t **out, int num_params)
     530{
    409531        int rc;
    410532        barrier_transform_t *self = malloc(sizeof(*self));
     
    417539        if (rc != EOK)
    418540                goto error;
    419         self->transform = transform;
     541        self->transform = NULL;
    420542        *out = barrier_as_transform(self);
    421543        return EOK;
    422544error:
    423         bithenge_transform_dec_ref(transform);
    424545        free(self);
    425546        return rc;
     
    480601{
    481602        char buffer;
    482         *out_size = 1;
    483         int rc = bithenge_blob_read_bits(blob, 0, &buffer, out_size, true);
    484         if (rc != EOK)
    485                 return rc;
    486         if (*out_size != 1)
    487                 return EINVAL;
     603        aoff64_t size = 1;
     604        int rc = bithenge_blob_read_bits(blob, 0, &buffer, &size, true);
     605        if (rc != EOK)
     606                return rc;
     607        if (size != 1)
     608                return EINVAL;
     609        if (out_size)
     610                *out_size = size;
    488611        return bithenge_new_boolean_node(out_node, (buffer & 1) != 0);
    489612}
     
    758881}
    759882
     883/** @cond internal */
    760884#define MAKE_UINT_TRANSFORM(NAME, TYPE, ENDIAN, PREFIX_LENGTH_FUNC)            \
    761885        static int NAME##_apply(bithenge_transform_t *self,                    \
     
    795919MAKE_UINT_TRANSFORM(uint32le, uint32_t, uint32_t_le2host, prefix_length_4);
    796920MAKE_UINT_TRANSFORM(uint32be, uint32_t, uint32_t_be2host, prefix_length_4);
    797 MAKE_UINT_TRANSFORM(uint64le, uint64_t, uint32_t_le2host, prefix_length_8);
    798 MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint32_t_be2host, prefix_length_8);
     921MAKE_UINT_TRANSFORM(uint64le, uint64_t, uint64_t_le2host, prefix_length_8);
     922MAKE_UINT_TRANSFORM(uint64be, uint64_t, uint64_t_be2host, prefix_length_8);
     923/** @endcond */
    799924
    800925
     
    822947                return EINVAL;
    823948
    824         *out_size = num_bits;
     949        aoff64_t size = num_bits;
    825950        uint8_t buffer[sizeof(bithenge_int_t)];
    826         rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, out_size,
     951        rc = bithenge_blob_read_bits(blob, 0, (char *)buffer, &size,
    827952            little_endian);
    828953        if (rc != EOK)
    829954                return rc;
    830         if (*out_size != (aoff64_t)num_bits)
    831                 return EINVAL;
     955        if (size != (aoff64_t)num_bits)
     956                return EINVAL;
     957        if (out_size)
     958                *out_size = size;
    832959
    833960        bithenge_int_t result = 0;
     
    9481075bithenge_named_transform_t *bithenge_primitive_transforms = primitive_transforms;
    9491076
    950 typedef struct {
    951         bithenge_transform_t base;
    952         bithenge_transform_t **xforms;
    953         size_t num;
    954 } compose_transform_t;
    955 
    956 static bithenge_transform_t *compose_as_transform(compose_transform_t *xform)
    957 {
    958         return &xform->base;
    959 }
    960 
    961 static compose_transform_t *transform_as_compose(bithenge_transform_t *xform)
    962 {
    963         return (compose_transform_t *)xform;
    964 }
    965 
    966 static int compose_apply(bithenge_transform_t *base, bithenge_scope_t *scope,
    967     bithenge_node_t *in, bithenge_node_t **out)
    968 {
    969         int rc;
    970         compose_transform_t *self = transform_as_compose(base);
    971         bithenge_node_inc_ref(in);
    972 
    973         /* i ranges from (self->num - 1) to 0 inside the loop. */
    974         for (size_t i = self->num; i--; ) {
    975                 bithenge_node_t *tmp;
    976                 rc = bithenge_transform_apply(self->xforms[i], scope, in,
    977                     &tmp);
    978                 bithenge_node_dec_ref(in);
    979                 if (rc != EOK)
    980                         return rc;
    981                 in = tmp;
    982         }
    983 
    984         *out = in;
    985         return rc;
    986 }
    987 
    988 static int compose_prefix_length(bithenge_transform_t *base,
    989     bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
    990 {
    991         compose_transform_t *self = transform_as_compose(base);
    992         return bithenge_transform_prefix_length(self->xforms[self->num - 1],
    993             scope, blob, out);
    994 }
    995 
    996 static void compose_destroy(bithenge_transform_t *base)
    997 {
    998         compose_transform_t *self = transform_as_compose(base);
    999         for (size_t i = 0; i < self->num; i++)
    1000                 bithenge_transform_dec_ref(self->xforms[i]);
    1001         free(self->xforms);
    1002         free(self);
    1003 }
    1004 
    1005 static const bithenge_transform_ops_t compose_transform_ops = {
    1006         .apply = compose_apply,
    1007         .prefix_length = compose_prefix_length,
    1008         .destroy = compose_destroy,
    1009 };
    1010 
    1011 /** Create a composition of multiple transforms. When the result is applied to a
    1012  * node, each transform is applied in turn, with the last transform applied
    1013  * first. @a xforms may contain any number of transforms or no transforms at
    1014  * all. This function takes ownership of @a xforms and the references therein.
    1015  * @param[out] out Holds the result.
    1016  * @param[in] xforms The transforms to apply.
    1017  * @param num The number of transforms.
    1018  * @return EOK on success or an error code from errno.h. */
    1019 int bithenge_new_composed_transform(bithenge_transform_t **out,
    1020     bithenge_transform_t **xforms, size_t num)
    1021 {
    1022         if (num == 0) {
    1023                 /* TODO: optimize */
    1024         } else if (num == 1) {
    1025                 *out = xforms[0];
    1026                 free(xforms);
    1027                 return EOK;
    1028         }
    1029 
    1030         int rc;
    1031         compose_transform_t *self = malloc(sizeof(*self));
    1032         if (!self) {
    1033                 rc = ENOMEM;
    1034                 goto error;
    1035         }
    1036         rc = bithenge_init_transform(compose_as_transform(self),
    1037             &compose_transform_ops, 0);
    1038         if (rc != EOK)
    1039                 goto error;
    1040         self->xforms = xforms;
    1041         self->num = num;
    1042         *out = compose_as_transform(self);
    1043         return EOK;
    1044 error:
    1045         for (size_t i = 0; i < num; i++)
    1046                 bithenge_transform_dec_ref(xforms[i]);
    1047         free(xforms);
    1048         free(self);
    1049         return rc;
    1050 }
    1051 
    10521077/** @}
    10531078 */
  • uspace/lib/bithenge/transform.h

    r0da6c04 r5e718d9  
    5454        unsigned int refs;
    5555        struct bithenge_scope *outer;
     56        char *error;
    5657        bool barrier;
    5758        int num_params;
     
    6162} bithenge_scope_t;
    6263
    63 static inline void bithenge_scope_inc_ref(bithenge_scope_t *self) {
     64/** Increment a scope's reference count.
     65 * @memberof bithenge_scope_t
     66 * @param self The scope to reference. */
     67static inline void bithenge_scope_inc_ref(bithenge_scope_t *self)
     68{
     69        assert(self);
    6470        self->refs++;
    6571}
     
    109115                return;
    110116        assert(self->ops);
     117        assert(self->refs > 0);
    111118        if (--self->refs == 0)
    112119                self->ops->destroy(self);
     
    115122/** A transform with a name. */
    116123typedef struct {
     124        /** The transform's name. */
    117125        const char *name;
     126        /** The transform. */
    118127        bithenge_transform_t *transform;
    119128} bithenge_named_transform_t;
    120129
     130/** Transform that decodes an 8-bit unsigned integer */
     131extern bithenge_transform_t bithenge_uint8_transform;
     132/** Transform that decodes a 16-bit little-endian unsigned integer */
     133extern bithenge_transform_t bithenge_uint16le_transform;
     134/** Transform that decodes a 16-bit big-endian unsigned integer */
     135extern bithenge_transform_t bithenge_uint16be_transform;
     136/** Transform that decodes a 32-bit little-endian unsigned integer */
     137extern bithenge_transform_t bithenge_uint32le_transform;
     138/** Transform that decodes a 32-bit big-endian unsigned integer */
     139extern bithenge_transform_t bithenge_uint32be_transform;
     140/** Transform that decodes a 64-bit little-endian unsigned integer */
     141extern bithenge_transform_t bithenge_uint64le_transform;
     142/** Transform that decodes a 64-bit big-endian unsigned integer */
     143extern bithenge_transform_t bithenge_uint64be_transform;
     144
     145/** @cond */
    121146extern bithenge_transform_t bithenge_ascii_transform;
    122147extern bithenge_transform_t bithenge_bit_transform;
     
    126151extern bithenge_transform_t bithenge_known_length_transform;
    127152extern bithenge_transform_t bithenge_nonzero_boolean_transform;
    128 extern bithenge_transform_t bithenge_uint8_transform;
    129 extern bithenge_transform_t bithenge_uint16le_transform;
    130 extern bithenge_transform_t bithenge_uint16be_transform;
    131 extern bithenge_transform_t bithenge_uint32le_transform;
    132 extern bithenge_transform_t bithenge_uint32be_transform;
    133 extern bithenge_transform_t bithenge_uint64le_transform;
    134 extern bithenge_transform_t bithenge_uint64be_transform;
    135153extern bithenge_transform_t bithenge_uint_le_transform;
    136154extern bithenge_transform_t bithenge_uint_be_transform;
    137155extern bithenge_transform_t bithenge_zero_terminated_transform;
    138156extern bithenge_named_transform_t *bithenge_primitive_transforms;
    139 
     157/** @endcond */
     158
     159/** @memberof bithenge_transform_t */
    140160int bithenge_init_transform(bithenge_transform_t *,
    141161    const bithenge_transform_ops_t *, int);
     162/** @memberof bithenge_transform_t */
    142163int bithenge_transform_apply(bithenge_transform_t *, bithenge_scope_t *,
    143164    bithenge_node_t *, bithenge_node_t **);
     165/** @memberof bithenge_transform_t */
    144166int bithenge_transform_prefix_length(bithenge_transform_t *,
    145167    bithenge_scope_t *, bithenge_blob_t *, aoff64_t *);
     168/** @memberof bithenge_transform_t */
    146169int bithenge_transform_prefix_apply(bithenge_transform_t *, bithenge_scope_t *,
    147170    bithenge_blob_t *, bithenge_node_t **, aoff64_t *);
    148 int bithenge_new_barrier_transform(bithenge_transform_t **,
    149     bithenge_transform_t *, int);
    150 int bithenge_new_composed_transform(bithenge_transform_t **,
    151     bithenge_transform_t **, size_t);
    152 
     171int bithenge_new_barrier_transform(bithenge_transform_t **, int);
     172int bithenge_barrier_transform_set_subtransform(bithenge_transform_t *,
     173    bithenge_transform_t *);
     174
     175/** @memberof bithenge_scope_t */
    153176int bithenge_scope_new(bithenge_scope_t **, bithenge_scope_t *);
     177/** @memberof bithenge_scope_t */
    154178void bithenge_scope_dec_ref(bithenge_scope_t *);
     179/** @memberof bithenge_scope_t */
    155180bithenge_scope_t *bithenge_scope_outer(bithenge_scope_t *);
     181/** @memberof bithenge_scope_t */
     182const char *bithenge_scope_get_error(bithenge_scope_t *);
     183/** @memberof bithenge_scope_t */
     184int bithenge_scope_error(bithenge_scope_t *, const char *, ...);
     185/** @memberof bithenge_scope_t */
    156186bithenge_node_t *bithenge_scope_get_current_node(bithenge_scope_t *);
     187/** @memberof bithenge_scope_t */
    157188void bithenge_scope_set_current_node(bithenge_scope_t *, bithenge_node_t *);
     189/** @memberof bithenge_scope_t */
    158190bithenge_node_t *bithenge_scope_in_node(bithenge_scope_t *);
     191/** @memberof bithenge_scope_t */
    159192void bithenge_scope_set_in_node(bithenge_scope_t *, bithenge_node_t *);
     193/** @memberof bithenge_scope_t */
    160194void bithenge_scope_set_barrier(bithenge_scope_t *);
     195/** @memberof bithenge_scope_t */
    161196bool bithenge_scope_is_barrier(bithenge_scope_t *);
     197/** @memberof bithenge_scope_t */
    162198int bithenge_scope_alloc_params(bithenge_scope_t *, int);
     199/** @memberof bithenge_scope_t */
    163200int bithenge_scope_set_param(bithenge_scope_t *, int, bithenge_node_t *);
     201/** @memberof bithenge_scope_t */
    164202int bithenge_scope_get_param(bithenge_scope_t *, int, bithenge_node_t **);
    165203
  • uspace/lib/bithenge/tree.c

    r0da6c04 r5e718d9  
    7676        if (!node)
    7777                return;
     78        assert (node->refs > 0);
    7879        if (--node->refs == 0)
    7980                node_destroy(node);
     
    8990{
    9091        get_for_each_data_t *data = (get_for_each_data_t *)raw_data;
    91         bool equal = bithenge_node_equal(key, data->key);
     92        bool equal;
     93        int rc = bithenge_node_equal(&equal, key, data->key);
    9294        bithenge_node_dec_ref(key);
     95        if (rc != EOK)
     96                return rc;
    9397        if (equal) {
    9498                *data->out = value;
     
    101105/** Get a child of a node. Takes ownership of the key. If the node does not
    102106 * provide this function, for_each will be used as an alternative, which may be
    103  * very slow.
    104  * @memberof bithenge_node_t
    105  * @param self The internal node to find a child of.
     107 * very slow. Also works for blob nodes to find the byte value at a given
     108 * index.
     109 * @memberof bithenge_node_t
     110 * @param self The internal/blob node to find a child of.
    106111 * @param key The key to search for.
    107112 * @param[out] out Holds the found node.
     
    111116    bithenge_node_t **out)
    112117{
     118        if (self->type == BITHENGE_NODE_BLOB) {
     119                if (bithenge_node_type(key) != BITHENGE_NODE_INTEGER) {
     120                        bithenge_node_dec_ref(key);
     121                        return ENOENT;
     122                }
     123                bithenge_int_t offset = bithenge_integer_node_value(key);
     124                bithenge_node_dec_ref(key);
     125                uint8_t byte;
     126                aoff64_t size = 1;
     127                int rc = bithenge_blob_read(bithenge_node_as_blob(self),
     128                    offset, (char *)&byte, &size);
     129                if (rc != EOK)
     130                        return rc;
     131                if (size != 1)
     132                        return ENOENT;
     133
     134                return bithenge_new_integer_node(out, byte);
     135        }
     136
    113137        assert(self->type == BITHENGE_NODE_INTERNAL);
    114138        if (self->internal_ops->get)
     
    174198int bithenge_new_empty_internal_node(bithenge_node_t **out)
    175199{
     200        if (bithenge_should_fail())
     201                return ENOMEM;
    176202        bithenge_node_inc_ref(&empty_internal_node);
    177203        *out = &empty_internal_node;
     
    277303{
    278304        assert(out);
     305        if (bithenge_should_fail())
     306                return ENOMEM;
    279307        *out = value ? &true_node : &false_node;
    280308        (*out)->refs++;
     
    327355 * internal nodes. Takes ownership of nothing.
    328356 * @memberof bithenge_node_t
     357 * @param[out] out Holds whether the nodes are equal.
    329358 * @param a, b Nodes to compare.
    330  * @return Whether the nodes are equal. If an error occurs, returns false.
    331  * @todo Add support for internal nodes.
    332  */
    333 bool bithenge_node_equal(bithenge_node_t *a, bithenge_node_t *b)
    334 {
    335         if (a->type != b->type)
    336                 return false;
     359 * @return EOK on success or an error code from errno.h.
     360 * @todo Add support for internal nodes. */
     361int bithenge_node_equal(bool *out, bithenge_node_t *a, bithenge_node_t *b)
     362{
     363        if (a->type != b->type) {
     364                *out = false;
     365                return EOK;
     366        }
    337367        switch (a->type) {
    338368        case BITHENGE_NODE_INTERNAL:
    339                 return false;
     369                *out = false;
     370                return EOK;
    340371        case BITHENGE_NODE_BOOLEAN:
    341                 return a->boolean_value == b->boolean_value;
     372                *out = a->boolean_value == b->boolean_value;
     373                return EOK;
    342374        case BITHENGE_NODE_INTEGER:
    343                 return a->integer_value == b->integer_value;
     375                *out = a->integer_value == b->integer_value;
     376                return EOK;
    344377        case BITHENGE_NODE_STRING:
    345                 return !str_cmp(a->string_value.ptr, b->string_value.ptr);
     378                *out = !str_cmp(a->string_value.ptr, b->string_value.ptr);
     379                return EOK;
    346380        case BITHENGE_NODE_BLOB:
    347                 return bithenge_blob_equal(bithenge_node_as_blob(a),
     381                return bithenge_blob_equal(out, bithenge_node_as_blob(a),
    348382                    bithenge_node_as_blob(b));
    349383        }
    350         return false;
     384        return EINVAL;
    351385}
    352386
  • uspace/lib/bithenge/tree.h

    r0da6c04 r5e718d9  
    5656} bithenge_node_type_t;
    5757
     58/** A tree node. It can have any of the types in @a bithenge_node_type_t. */
    5859typedef struct bithenge_node_t {
    5960        /** @privatesection */
     
    6162        unsigned int refs;
    6263        union {
     64                /** @privatesection */
    6365                const struct bithenge_internal_node_ops_t *internal_ops;
    6466                bool boolean_value;
    6567                bithenge_int_t integer_value;
    6668                struct {
     69                        /** @privatesection */
    6770                        const char *ptr;
    6871                        bool needs_free;
     
    111114}
    112115
     116/** @memberof bithenge_node_t */
    113117void bithenge_node_dec_ref(bithenge_node_t *node);
    114118
     
    126130}
    127131
     132/** @memberof bithenge_node_t */
    128133int bithenge_node_get(bithenge_node_t *, bithenge_node_t *,
    129134    bithenge_node_t **);
     
    159164}
    160165
     166/** @memberof bithenge_node_t */
    161167int bithenge_init_internal_node(bithenge_node_t *,
    162168    const bithenge_internal_node_ops_t *);
     169/** @memberof bithenge_node_t */
    163170int bithenge_new_empty_internal_node(bithenge_node_t **);
     171/** @memberof bithenge_node_t */
    164172int bithenge_new_simple_internal_node(bithenge_node_t **, bithenge_node_t **,
    165173    bithenge_int_t, bool needs_free);
     174/** @memberof bithenge_node_t */
    166175int bithenge_new_boolean_node(bithenge_node_t **, bool);
     176/** @memberof bithenge_node_t */
    167177int bithenge_new_integer_node(bithenge_node_t **, bithenge_int_t);
     178/** @memberof bithenge_node_t */
    168179int bithenge_new_string_node(bithenge_node_t **, const char *, bool);
    169 bool bithenge_node_equal(bithenge_node_t *, bithenge_node_t *);
     180/** @memberof bithenge_node_t */
     181int bithenge_node_equal(bool *, bithenge_node_t *, bithenge_node_t *);
    170182
    171183#endif
Note: See TracChangeset for help on using the changeset viewer.