source: mainline/uspace/app/bithenge/tree.c@ d5070ef

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since d5070ef was d5070ef, checked in by Sean Bartell <wingedtachikoma@…>, 13 years ago

Bithenge: transforms and uint32le_transform

  • Property mode set to 100644
File size: 7.4 KB
RevLine 
[11b9ad7]1/*
2 * Copyright (c) 2012 Sean Bartell
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup bithenge
30 * @{
31 */
32/**
33 * @file
34 * Trees and nodes.
35 */
36
37#include <errno.h>
38#include <stdlib.h>
[d5070ef]39#include <str.h>
[5c925ce]40#include "blob.h"
[11b9ad7]41#include "tree.h"
42
[5c925ce]43static int blob_destroy(bithenge_node_t *base)
44{
45 bithenge_blob_t *blob = bithenge_node_as_blob(base);
46 assert(blob->base.blob_ops);
47 return blob->base.blob_ops->destroy(blob);
48}
49
[8375d0eb]50/** Destroy a node.
51 * @memberof bithenge_node_t
52 * @param node The node to destroy.
53 * @return EOK on success or an error code from errno.h. */
[11b9ad7]54int bithenge_node_destroy(bithenge_node_t *node)
55{
56 switch (bithenge_node_type(node)) {
[5c925ce]57 case BITHENGE_NODE_BLOB:
58 return blob_destroy(node);
[11b9ad7]59 case BITHENGE_NODE_STRING:
[5f679702]60 if (node->string_value.needs_free)
61 free(node->string_value.ptr);
[11b9ad7]62 break;
63 case BITHENGE_NODE_INTERNAL:
[5c925ce]64 return node->internal_ops->destroy(node);
[11b9ad7]65 case BITHENGE_NODE_BOOLEAN:
[5f679702]66 return EOK; // the boolean nodes are allocated statically below
[11b9ad7]67 case BITHENGE_NODE_INTEGER: /* pass-through */
68 break;
69 }
70 free(node);
71 return EOK;
72}
73
74typedef struct
75{
[5f679702]76 bithenge_node_t base;
[11b9ad7]77 bithenge_node_t **nodes;
78 bithenge_int_t len;
79 bool needs_free;
80} simple_internal_node_t;
81
[5f679702]82static simple_internal_node_t *node_as_simple(bithenge_node_t *node)
[11b9ad7]83{
84 return (simple_internal_node_t *)node;
85}
86
[8375d0eb]87static int simple_internal_node_for_each(bithenge_node_t *base,
88 bithenge_for_each_func_t func, void *data)
[11b9ad7]89{
90 int rc;
[5f679702]91 simple_internal_node_t *node = node_as_simple(base);
[11b9ad7]92 for (bithenge_int_t i = 0; i < node->len; i++) {
93 rc = func(node->nodes[2*i+0], node->nodes[2*i+1], data);
94 if (rc != EOK)
95 return rc;
96 }
97 return EOK;
98}
99
[5c925ce]100static int simple_internal_node_destroy(bithenge_node_t *base)
101{
102 int rc;
103 simple_internal_node_t *node = node_as_simple(base);
104 for (bithenge_int_t i = 0; i < node->len; i++) {
105 rc = bithenge_node_destroy(node->nodes[2*i+0]);
106 if (rc != EOK)
107 return rc;
108 rc = bithenge_node_destroy(node->nodes[2*i+1]);
109 if (rc != EOK)
110 return rc;
111 }
112 if (node->needs_free)
113 free(node->nodes);
114 free(node);
115 return EOK;
116}
117
[11b9ad7]118static bithenge_internal_node_ops_t simple_internal_node_ops = {
[5c925ce]119 .for_each = simple_internal_node_for_each,
120 .destroy = simple_internal_node_destroy,
[11b9ad7]121};
122
123static bithenge_node_t *simple_internal_as_node(simple_internal_node_t *node)
124{
[5f679702]125 return &node->base;
[11b9ad7]126}
127
[8375d0eb]128/** Create an internal node from a set of keys and values. The node must be
129 * freed with @a bithenge_node_t::bithenge_node_destroy after it is used, which
130 * will also destroy all the key and value nodes.
131 * @memberof bithenge_node_t
132 * @param[out] out Stores the created internal node.
133 * @param nodes The array of key-value pairs. Keys are stored at even indices
134 * and values are stored at odd indices.
135 * @param len The number of key-value pairs in the node array.
136 * @param needs_free If true, when the internal node is destroyed it will free
137 * the nodes array as well as destroying each node inside it.
138 * @return EOK on success or an error code from errno.h. */
139int bithenge_new_simple_internal_node(bithenge_node_t **out,
140 bithenge_node_t **nodes, bithenge_int_t len, bool needs_free)
[11b9ad7]141{
142 assert(out);
143 simple_internal_node_t *node = malloc(sizeof(*node));
144 if (!node)
145 return ENOMEM;
[5f679702]146 node->base.type = BITHENGE_NODE_INTERNAL;
147 node->base.internal_ops = &simple_internal_node_ops;
[11b9ad7]148 node->nodes = nodes;
149 node->len = len;
150 node->needs_free = needs_free;
151 *out = simple_internal_as_node(node);
152 return EOK;
153}
154
[5f679702]155static bithenge_node_t false_node = { BITHENGE_NODE_BOOLEAN, .boolean_value = false };
156static bithenge_node_t true_node = { BITHENGE_NODE_BOOLEAN, .boolean_value = true };
[11b9ad7]157
[8375d0eb]158/** Create a boolean node. The node must be freed with @a
159 * bithenge_node_t::bithenge_node_destroy after it is used.
160 * @memberof bithenge_node_t
161 * @param[out] out Stores the created boolean node.
162 * @param value The value for the node to hold.
163 * @return EOK on success or an error code from errno.h. */
[11b9ad7]164int bithenge_new_boolean_node(bithenge_node_t **out, bool value)
165{
166 assert(out);
[5f679702]167 *out = value ? &true_node : &false_node;
[11b9ad7]168 return EOK;
169}
170
[8375d0eb]171/** Create an integer node. The node must be freed with @a
172 * bithenge_node_t::bithenge_node_destroy after it is used.
173 * @memberof bithenge_node_t
174 * @param[out] out Stores the created integer node.
175 * @param value The value for the node to hold.
176 * @return EOK on success or an error code from errno.h. */
[11b9ad7]177int bithenge_new_integer_node(bithenge_node_t **out, bithenge_int_t value)
178{
179 assert(out);
[5f679702]180 bithenge_node_t *node = malloc(sizeof(*node));
[11b9ad7]181 if (!node)
182 return ENOMEM;
[5f679702]183 node->type = BITHENGE_NODE_INTEGER;
184 node->integer_value = value;
185 *out = node;
[11b9ad7]186 return EOK;
187}
188
[8375d0eb]189/** Create a string node. The node must be freed with @a
190 * bithenge_node_t::bithenge_node_destroy after it is used.
191 * @memberof bithenge_node_t
192 * @param[out] out Stores the created string node.
193 * @param value The value for the node to hold.
194 * @param needs_free Whether the string should be freed when the node is
195 * destroyed.
196 * @return EOK on success or an error code from errno.h. */
[11b9ad7]197int bithenge_new_string_node(bithenge_node_t **out, const char *value, bool needs_free)
198{
199 assert(out);
[5f679702]200 bithenge_node_t *node = malloc(sizeof(*node));
[11b9ad7]201 if (!node)
202 return ENOMEM;
[5f679702]203 node->type = BITHENGE_NODE_STRING;
204 node->string_value.ptr = value;
205 node->string_value.needs_free = needs_free;
206 *out = node;
[11b9ad7]207 return EOK;
208}
[8375d0eb]209
[d5070ef]210/** Check whether the contents of two nodes are equal. Does not yet work for
211 * internal nodes.
212 * @memberof bithenge_node_t
213 * @param a, b Nodes to compare.
214 * @return Whether the nodes are equal. If an error occurs, returns false.
215 * @todo Add support for internal nodes.
216 */
217bool bithenge_node_equal(bithenge_node_t *a, bithenge_node_t *b)
218{
219 if (a->type != b->type)
220 return false;
221 switch (a->type) {
222 case BITHENGE_NODE_INTERNAL:
223 return false;
224 case BITHENGE_NODE_BOOLEAN:
225 return a->boolean_value == b->boolean_value;
226 case BITHENGE_NODE_INTEGER:
227 return a->integer_value == b->integer_value;
228 case BITHENGE_NODE_STRING:
229 return !str_cmp(a->string_value.ptr, b->string_value.ptr);
230 case BITHENGE_NODE_BLOB:
231 return bithenge_blob_equal(bithenge_node_as_blob(a),
232 bithenge_node_as_blob(b));
233 }
234 return false;
235}
236
[8375d0eb]237/** @}
238 */
Note: See TracBrowser for help on using the repository browser.