ossp-pkg/cfg/cfg_node.c
1.1
/*
** OSSP cfg - Configuration Parsing
** Copyright (c) 1999-2002 Ralf S. Engelschall <rse@engelschall.com>
** 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 <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#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;
}