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

Changeset 0f8062a4 in mainline


Ignore:
Timestamp:
2012-08-02T22:08:59Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
ee7cc3c
Parents:
b8d45e9e
Message:

Bithenge: move struct code to sequence.c; factor out non-struct-specific code

Location:
uspace/app/bithenge
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bithenge/Makefile

    rb8d45e9e r0f8062a4  
    3939        print.c \
    4040        script.c \
     41        sequence.c \
    4142        source.c \
    4243        test.c \
  • uspace/app/bithenge/Makefile.linux

    rb8d45e9e r0f8062a4  
    4040        print.c \
    4141        script.c \
     42        sequence.c \
    4243        source.c \
    4344        test.c \
  • uspace/app/bithenge/script.c

    rb8d45e9e r0f8062a4  
    4141#include "os.h"
    4242#include "script.h"
     43#include "sequence.h"
    4344#include "transform.h"
    4445#include "tree.h"
  • uspace/app/bithenge/transform.c

    rb8d45e9e r0f8062a4  
    618618typedef struct {
    619619        bithenge_transform_t base;
    620         bithenge_named_transform_t *subtransforms;
    621         size_t num_subtransforms;
    622 } struct_transform_t;
    623 
    624 typedef struct {
    625         bithenge_node_t base;
    626         bithenge_scope_t scope;
    627         struct_transform_t *transform;
    628         bithenge_blob_t *blob;
    629         aoff64_t *ends;
    630         size_t num_ends;
    631         bool prefix;
    632 } struct_node_t;
    633 
    634 static bithenge_node_t *struct_as_node(struct_node_t *node)
    635 {
    636         return &node->base;
    637 }
    638 
    639 static struct_node_t *node_as_struct(bithenge_node_t *node)
    640 {
    641         return (struct_node_t *)node;
    642 }
    643 
    644 static bithenge_transform_t *struct_as_transform(struct_transform_t *xform)
    645 {
    646         return &xform->base;
    647 }
    648 
    649 static struct_transform_t *transform_as_struct(bithenge_transform_t *xform)
    650 {
    651         return (struct_transform_t *)xform;
    652 }
    653 
    654 static int struct_node_field_offset(struct_node_t *self, aoff64_t *out,
    655     size_t index)
    656 {
    657         if (index == 0) {
    658                 *out = 0;
    659                 return EOK;
    660         }
    661         index--;
    662         aoff64_t prev_offset =
    663             self->num_ends ? self->ends[self->num_ends - 1] : 0;
    664         for (; self->num_ends <= index; self->num_ends++) {
    665                 bithenge_node_t *subblob_node;
    666                 bithenge_blob_inc_ref(self->blob);
    667                 int rc = bithenge_new_offset_blob(&subblob_node, self->blob,
    668                     prev_offset);
    669                 if (rc != EOK)
    670                         return rc;
    671 
    672                 bithenge_blob_t *subblob = bithenge_node_as_blob(subblob_node);
    673                 aoff64_t field_size;
    674                 rc = bithenge_transform_prefix_length(
    675                     self->transform->subtransforms[self->num_ends].transform,
    676                     &self->scope, subblob, &field_size);
    677                 bithenge_node_dec_ref(subblob_node);
    678                 if (rc != EOK)
    679                         return rc;
    680 
    681                 prev_offset = self->ends[self->num_ends] =
    682                     prev_offset + field_size;
    683         }
    684         *out = self->ends[index];
    685         return EOK;
    686 }
    687 
    688 static int struct_node_subtransform(struct_node_t *self, bithenge_node_t **out,
    689     size_t index)
    690 {
    691         aoff64_t start_pos;
    692         int rc = struct_node_field_offset(self, &start_pos, index);
    693         if (rc != EOK)
    694                 return rc;
    695 
    696         if (index == self->num_ends) {
    697                 /* We can apply the subtransform and cache its prefix length at
    698                  * the same time. */
    699                 bithenge_node_t *blob_node;
    700                 bithenge_blob_inc_ref(self->blob);
    701                 rc = bithenge_new_offset_blob(&blob_node, self->blob,
    702                     start_pos);
    703                 if (rc != EOK)
    704                         return rc;
    705 
    706                 aoff64_t size;
    707                 rc = bithenge_transform_prefix_apply(
    708                     self->transform->subtransforms[index].transform,
    709                     &self->scope, bithenge_node_as_blob(blob_node), out,
    710                     &size);
    711                 bithenge_node_dec_ref(blob_node);
    712                 if (rc != EOK)
    713                         return rc;
    714 
    715                 self->ends[self->num_ends++] = start_pos + size;
    716         } else {
    717                 aoff64_t end_pos;
    718                 int rc = struct_node_field_offset(self, &end_pos, index + 1);
    719                 if (rc != EOK)
    720                         return rc;
    721 
    722                 bithenge_node_t *blob_node;
    723                 bithenge_blob_inc_ref(self->blob);
    724                 rc = bithenge_new_subblob(&blob_node, self->blob, start_pos,
    725                     end_pos - start_pos);
    726                 if (rc != EOK)
    727                         return rc;
    728 
    729                 rc = bithenge_transform_apply(
    730                     self->transform->subtransforms[index].transform,
    731                     &self->scope, blob_node, out);
    732                 bithenge_node_dec_ref(blob_node);
    733                 if (rc != EOK)
    734                         return rc;
    735         }
    736 
    737         return EOK;
    738 }
    739 
    740 static int struct_node_for_each(bithenge_node_t *base,
    741     bithenge_for_each_func_t func, void *data)
    742 {
    743         int rc = EOK;
    744         struct_node_t *self = node_as_struct(base);
    745         bithenge_named_transform_t *subxforms =
    746             self->transform->subtransforms;
    747 
    748         for (size_t i = 0; subxforms[i].transform; i++) {
    749                 bithenge_node_t *subxform_result;
    750                 rc = struct_node_subtransform(self, &subxform_result, i);
    751                 if (rc != EOK)
    752                         return rc;
    753 
    754                 if (subxforms[i].name) {
    755                         bithenge_node_t *name_node;
    756                         rc = bithenge_new_string_node(&name_node,
    757                             subxforms[i].name, false);
    758                         if (rc == EOK) {
    759                                 rc = func(name_node, subxform_result, data);
    760                                 subxform_result = NULL;
    761                         }
    762                 } else {
    763                         if (bithenge_node_type(subxform_result) !=
    764                             BITHENGE_NODE_INTERNAL) {
    765                                 rc = EINVAL;
    766                         } else {
    767                                 rc = bithenge_node_for_each(subxform_result,
    768                                     func, data);
    769                         }
    770                 }
    771                 bithenge_node_dec_ref(subxform_result);
    772                 if (rc != EOK)
    773                         return rc;
    774         }
    775 
    776         if (!self->prefix) {
    777                 aoff64_t blob_size, end_pos;
    778                 rc = bithenge_blob_size(self->blob, &blob_size);
    779                 if (rc != EOK)
    780                         return rc;
    781                 rc = struct_node_field_offset(self, &end_pos,
    782                     self->transform->num_subtransforms);
    783                 if (rc != EOK)
    784                         return rc;
    785                 if (blob_size != end_pos) {
    786                         rc = EINVAL;
    787                         return rc;
    788                 }
    789         }
    790 
    791         return rc;
    792 }
    793 
    794 static int struct_node_get(bithenge_node_t *base, bithenge_node_t *key,
    795     bithenge_node_t **out)
    796 {
    797         struct_node_t *self = node_as_struct(base);
    798 
    799         if (bithenge_node_type(key) != BITHENGE_NODE_STRING) {
    800                 bithenge_node_dec_ref(key);
    801                 return ENOENT;
    802         }
    803         const char *name = bithenge_string_node_value(key);
    804 
    805         for (size_t i = 0; self->transform->subtransforms[i].transform; i++) {
    806                 if (self->transform->subtransforms[i].name
    807                     && !str_cmp(name, self->transform->subtransforms[i].name)) {
    808                         bithenge_node_dec_ref(key);
    809                         return struct_node_subtransform(self, out, i);
    810                 }
    811         }
    812 
    813         for (size_t i = 0; self->transform->subtransforms[i].transform; i++) {
    814                 if (self->transform->subtransforms[i].name)
    815                         continue;
    816                 bithenge_node_t *subxform_result;
    817                 int rc = struct_node_subtransform(self, &subxform_result, i);
    818                 if (rc != EOK) {
    819                         bithenge_node_dec_ref(key);
    820                         return rc;
    821                 }
    822                 if (bithenge_node_type(subxform_result) !=
    823                     BITHENGE_NODE_INTERNAL) {
    824                         bithenge_node_dec_ref(subxform_result);
    825                         bithenge_node_dec_ref(key);
    826                         return EINVAL;
    827                 }
    828                 bithenge_node_inc_ref(key);
    829                 rc = bithenge_node_get(subxform_result, key, out);
    830                 bithenge_node_dec_ref(subxform_result);
    831                 if (rc != ENOENT) {
    832                         bithenge_node_dec_ref(key);
    833                         return rc;
    834                 }
    835         }
    836 
    837         bithenge_node_dec_ref(key);
    838         return ENOENT;
    839 }
    840 
    841 static void struct_node_destroy(bithenge_node_t *base)
    842 {
    843         struct_node_t *node = node_as_struct(base);
    844 
    845         /* We didn't inc_ref for the scope in struct_transform_make_node, so
    846          * make sure it doesn't try to dec_ref. */
    847         node->scope.current_node = NULL;
    848         bithenge_scope_destroy(&node->scope);
    849 
    850         bithenge_transform_dec_ref(struct_as_transform(node->transform));
    851         bithenge_blob_dec_ref(node->blob);
    852         free(node->ends);
    853         free(node);
    854 }
    855 
    856 static const bithenge_internal_node_ops_t struct_node_ops = {
    857         .for_each = struct_node_for_each,
    858         .get = struct_node_get,
    859         .destroy = struct_node_destroy,
    860 };
    861 
    862 static int struct_transform_make_node(struct_transform_t *self,
    863     bithenge_node_t **out, bithenge_scope_t *scope, bithenge_blob_t *blob,
    864     bool prefix)
    865 {
    866         struct_node_t *node = malloc(sizeof(*node));
    867         if (!node)
    868                 return ENOMEM;
    869 
    870         bithenge_scope_init(&node->scope);
    871         int rc = bithenge_scope_copy(&node->scope, scope);
    872         if (rc != EOK) {
    873                 free(node);
    874                 return rc;
    875         }
    876 
    877         node->ends = malloc(sizeof(*node->ends) * self->num_subtransforms);
    878         if (!node->ends) {
    879                 bithenge_scope_destroy(&node->scope);
    880                 free(node);
    881                 return ENOMEM;
    882         }
    883 
    884         rc = bithenge_init_internal_node(struct_as_node(node),
    885             &struct_node_ops);
    886         if (rc != EOK) {
    887                 bithenge_scope_destroy(&node->scope);
    888                 free(node->ends);
    889                 free(node);
    890                 return rc;
    891         }
    892 
    893         bithenge_transform_inc_ref(struct_as_transform(self));
    894         bithenge_blob_inc_ref(blob);
    895         node->transform = self;
    896         node->blob = blob;
    897         node->prefix = prefix;
    898         node->num_ends = 0;
    899         *out = struct_as_node(node);
    900 
    901         /* We should inc_ref(*out) here, but that would make a cycle. Instead,
    902          * we leave it 1 too low, so that when the only remaining use of *out
    903          * is the scope, *out will be destroyed. Also see the comment in
    904          * struct_node_destroy. */
    905         bithenge_scope_set_current_node(&node->scope, *out);
    906 
    907         return EOK;
    908 }
    909 
    910 static int struct_transform_apply(bithenge_transform_t *base,
    911     bithenge_scope_t *scope, bithenge_node_t *in, bithenge_node_t **out)
    912 {
    913         struct_transform_t *self = transform_as_struct(base);
    914         if (bithenge_node_type(in) != BITHENGE_NODE_BLOB)
    915                 return EINVAL;
    916         return struct_transform_make_node(self, out, scope,
    917             bithenge_node_as_blob(in), false);
    918 }
    919 
    920 static int struct_transform_prefix_length(bithenge_transform_t *base,
    921     bithenge_scope_t *scope, bithenge_blob_t *blob, aoff64_t *out)
    922 {
    923         struct_transform_t *self = transform_as_struct(base);
    924         bithenge_node_t *struct_node;
    925         int rc = struct_transform_make_node(self, &struct_node, scope, blob,
    926             true);
    927         if (rc != EOK)
    928                 return rc;
    929 
    930         rc = struct_node_field_offset(node_as_struct(struct_node), out,
    931             self->num_subtransforms);
    932         bithenge_node_dec_ref(struct_node);
    933         return rc;
    934 }
    935 
    936 static int struct_transform_prefix_apply(bithenge_transform_t *base,
    937     bithenge_scope_t *scope, bithenge_blob_t *blob, bithenge_node_t **out_node,
    938     aoff64_t *out_size)
    939 {
    940         struct_transform_t *self = transform_as_struct(base);
    941         int rc = struct_transform_make_node(self, out_node, scope, blob,
    942             true);
    943         if (rc != EOK)
    944                 return rc;
    945 
    946         rc = struct_node_field_offset(node_as_struct(*out_node), out_size,
    947             self->num_subtransforms);
    948         if (rc != EOK) {
    949                 bithenge_node_dec_ref(*out_node);
    950                 return rc;
    951         }
    952 
    953         return EOK;
    954 }
    955 
    956 static void free_subtransforms(bithenge_named_transform_t *subtransforms)
    957 {
    958         for (size_t i = 0; subtransforms[i].transform; i++) {
    959                 free((void *)subtransforms[i].name);
    960                 bithenge_transform_dec_ref(subtransforms[i].transform);
    961         }
    962         free(subtransforms);
    963 }
    964 
    965 static void struct_transform_destroy(bithenge_transform_t *base)
    966 {
    967         struct_transform_t *self = transform_as_struct(base);
    968         free_subtransforms(self->subtransforms);
    969         free(self);
    970 }
    971 
    972 static bithenge_transform_ops_t struct_transform_ops = {
    973         .apply = struct_transform_apply,
    974         .prefix_length = struct_transform_prefix_length,
    975         .prefix_apply = struct_transform_prefix_apply,
    976         .destroy = struct_transform_destroy,
    977 };
    978 
    979 /** Create a struct transform. The transform will apply its subtransforms
    980  * sequentially to a blob to create an internal node. Each result is either
    981  * given a key from @a subtransforms or, if the name is NULL, the result's keys
    982  * and values are merged into the struct transform's result. This function
    983  * takes ownership of @a subtransforms and the names and references therein.
    984  * @param[out] out Stores the created transform.
    985  * @param subtransforms The subtransforms and field names.
    986  * @return EOK on success or an error code from errno.h. */
    987 int bithenge_new_struct(bithenge_transform_t **out,
    988     bithenge_named_transform_t *subtransforms)
    989 {
    990         int rc;
    991         struct_transform_t *self = malloc(sizeof(*self));
    992         if (!self) {
    993                 rc = ENOMEM;
    994                 goto error;
    995         }
    996         rc = bithenge_init_transform(struct_as_transform(self),
    997             &struct_transform_ops, 0);
    998         if (rc != EOK)
    999                 goto error;
    1000         self->subtransforms = subtransforms;
    1001         self->num_subtransforms = 0;
    1002         for (self->num_subtransforms = 0;
    1003             subtransforms[self->num_subtransforms].transform;
    1004             self->num_subtransforms++);
    1005         *out = struct_as_transform(self);
    1006         return EOK;
    1007 error:
    1008         free_subtransforms(subtransforms);
    1009         free(self);
    1010         return rc;
    1011 }
    1012 
    1013 typedef struct {
    1014         bithenge_transform_t base;
    1015620        bithenge_transform_t **xforms;
    1016621        size_t num;
  • uspace/app/bithenge/transform.h

    rb8d45e9e r0f8062a4  
    134134int bithenge_new_scope_transform(bithenge_transform_t **,
    135135    bithenge_transform_t *, int);
    136 int bithenge_new_struct(bithenge_transform_t **,
    137     bithenge_named_transform_t *);
    138136int bithenge_new_composed_transform(bithenge_transform_t **,
    139137    bithenge_transform_t **, size_t);
Note: See TracChangeset for help on using the changeset viewer.