/* ** OSSP cfg - Configuration Parsing ** Copyright (c) 1999-2002 Ralf S. Engelschall ** Copyright (c) 1999-2002 The OSSP Project (http://www.ossp.org/) ** Copyright (c) 2001-2002 Cable & Wireless Deutschland (http://www.cw.com/de/) ** ** This file is part of OSSP cfg, a configuration parsing ** library which can be found at http://www.ossp.org/pkg/lib/cfg/. ** ** Permission to use, copy, modify, and distribute this software for ** any purpose with or without fee is hereby granted, provided that ** the above copyright notice and this permission notice appear in all ** copies. ** ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ** WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ** IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ** USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRCFG, STRICT LIABILITY, ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ** OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ** SUCH DAMAGE. ** ** cfg_node.c: configuration nodes */ #include #include #include #include #include "cfg_node.h" cfg_rc_t cfg_node_create(cfg_node_t **node) { cfg_node_t *n; if ((n = malloc(sizeof(cfg_node_t))) == NULL) return CFG_ERR_SYS; n->type = CFG_NODE_TYPE_NN; n->parent = NULL; n->rbroth = NULL; n->child1 = NULL; n->token = NULL; n->data.t = CFG_DATA_TYPE_LONG; n->data.u.l = 0; *node = n; return CFG_OK; } cfg_rc_t cfg_node_set(cfg_node_t *node, cfg_node_attr_t attr, ...) { va_list ap; if (node == NULL) return CFG_ERR_ARG; va_start(ap, attr); switch (attr) { case CFG_NODE_ATTR_TYPE: { node->type = (cfg_node_type_t)va_arg(ap, cfg_node_type_t); break; } case CFG_NODE_ATTR_PARENT: { node->parent = (cfg_node_t *)va_arg(ap, cfg_node_t *); break; } case CFG_NODE_ATTR_RBROTH: { node->rbroth = (cfg_node_t *)va_arg(ap, cfg_node_t *); break; } case CFG_NODE_ATTR_CHILD1: { node->child1 = (cfg_node_t *)va_arg(ap, cfg_node_t *); break; } case CFG_NODE_ATTR_TOKEN: { node->token = (char *)va_arg(ap, char *); break; } case CFG_NODE_ATTR_DATA: { node->data.t = (cfg_data_type_t)va_arg(ap, cfg_data_type_t); switch (node->data.t) { case CFG_DATA_TYPE_PTR: node->data.u.p = (void *)va_arg(ap, void *); break; case CFG_DATA_TYPE_CHAR: node->data.u.c = (char )va_arg(ap, int ); break; case CFG_DATA_TYPE_INT: node->data.u.i = (int )va_arg(ap, int ); break; case CFG_DATA_TYPE_LONG: node->data.u.l = (long )va_arg(ap, long ); break; case CFG_DATA_TYPE_FLOAT: node->data.u.f = (float )va_arg(ap, double); break; case CFG_DATA_TYPE_DOUBLE: node->data.u.d = (double)va_arg(ap, double); break; default: return CFG_ERR_ARG; } } default: return CFG_ERR_ARG; } va_end(ap); return CFG_OK; } cfg_rc_t cfg_node_get(cfg_node_t *node, cfg_node_attr_t attr, ...) { va_list ap; if (node == NULL) return CFG_ERR_ARG; va_start(ap, attr); switch (attr) { case CFG_NODE_ATTR_TYPE: { cfg_node_type_t *type = (cfg_node_type_t *)va_arg(ap, cfg_node_type_t *); *type = node->type; break; } case CFG_NODE_ATTR_PARENT: { cfg_node_t **n = (cfg_node_t **)va_arg(ap, cfg_node_t **); *n = node->parent; break; } case CFG_NODE_ATTR_RBROTH: { cfg_node_t **n = (cfg_node_t **)va_arg(ap, cfg_node_t **); *n = node->rbroth; break; } case CFG_NODE_ATTR_CHILD1: { cfg_node_t **n = (cfg_node_t **)va_arg(ap, cfg_node_t **); *n = node->child1; break; } case CFG_NODE_ATTR_TOKEN: { char **token = (char **)va_arg(ap, char **); *token = node->token; break; } case CFG_NODE_ATTR_DATA: { cfg_data_type_t *type = (cfg_data_type_t *)va_arg(ap, cfg_data_type_t *); *type = node->data.t; switch (node->data.t) { case CFG_DATA_TYPE_PTR: *((void **)va_arg(ap, void **)) = node->data.u.p; break; case CFG_DATA_TYPE_CHAR: *((char *)va_arg(ap, int *)) = node->data.u.c; break; case CFG_DATA_TYPE_INT: *((int *)va_arg(ap, int *)) = node->data.u.i; break; case CFG_DATA_TYPE_LONG: *((long *)va_arg(ap, long *)) = node->data.u.l; break; case CFG_DATA_TYPE_DOUBLE: *((double *)va_arg(ap, double *)) = node->data.u.d; break; case CFG_DATA_TYPE_FLOAT: *((float *)va_arg(ap, double *)) = node->data.u.f; break; default: return CFG_ERR_ARG; } } default: return CFG_ERR_ARG; } va_end(ap); return CFG_OK; } cfg_rc_t cfg_node_link(cfg_node_t *node, cfg_node_link_t id, cfg_node_t *node2) { cfg_node_t *n; if (node == NULL || node2 == NULL) return CFG_ERR_ARG; if (id == CFG_NODE_LINK_RBROTH) { /* make node a rbroth */ n = node2; n->parent = node->parent; while (n->rbroth != NULL) { n->parent = node->parent; n = n->rbroth; } n->rbroth = node->rbroth; node->rbroth = node2; } else if (id == CFG_NODE_LINK_CHILD1) { /* make node a child1 */ n = node2; n->parent = node; while (n->rbroth != NULL) { n->parent = node; n = n->rbroth; } n->rbroth = node->child1; node->child1 = node2; } return CFG_OK; } cfg_rc_t cfg_node_unlink(cfg_node_t *node) { cfg_node_t *n; if (node == NULL) return CFG_ERR_ARG; if (node->parent == NULL) return CFG_OK; if (node->parent->child1 == node) { /* node was a child1 */ node->parent->child1 = node->rbroth; } else { /* node was a rbroth */ n = node->parent->child1; while (n->rbroth != node) n = n->rbroth; n->rbroth = node->rbroth; } return CFG_OK; } cfg_rc_t cfg_node_apply(cfg_node_t *node, void (*cb_fct)(void *, cfg_node_t *), void *cb_ctx) { cfg_rc_t rc; if (cb_fct == NULL) return CFG_ERR_ARG; if (node != NULL) { cb_fct(cb_ctx, node); if (node->child1 != NULL) if ((rc = cfg_node_apply(node->child1, cb_fct, cb_ctx)) != CFG_OK) return rc; if (node->rbroth != NULL) if ((rc = cfg_node_apply(node->rbroth, cb_fct, cb_ctx)) != CFG_OK) return rc; } return CFG_OK; } cfg_rc_t cfg_node_destroy(cfg_node_t *node) { if (node == NULL) return CFG_ERR_ARG; free(node); return CFG_OK; }