ossp-pkg/cfg/cfg_data.c
/*
** OSSP cfg - Configuration Parsing
** Copyright (c) 2002-2006 Ralf S. Engelschall <rse@engelschall.com>
** Copyright (c) 2002-2006 The OSSP Project (http://www.ossp.org/)
**
** 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 CONTRACT, 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_data.c: configuration annotational data
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "cfg.h"
#include "cfg_data.h"
#include "cfg_global.h"
cfg_rc_t cfg_data_create(cfg_data_t **data)
{
cfg_rc_t rc;
if (data == NULL)
return CFG_ERR_ARG;
if ((*data = (cfg_data_t *)malloc(sizeof(cfg_data_t))) == NULL)
return CFG_ERR_SYS;
if ((rc = cfg_data_init(*data)) != CFG_OK) {
free(*data);
return rc;
}
return CFG_OK;
}
cfg_rc_t cfg_data_init(cfg_data_t *data)
{
if (data == NULL)
return CFG_ERR_ARG;
data->type = CFG_DATA_TYPE_INT;
data->value.i = 0;
data->ctrl = cfg_data_ctrl;
return CFG_OK;
}
cfg_rc_t cfg_data_kill(cfg_data_t *data)
{
cfg_rc_t rc;
if (data == NULL)
return CFG_ERR_ARG;
if (data->ctrl != NULL)
if ((rc = data->ctrl(data, CFG_DATA_CTRL_DESTROY)) != CFG_OK)
return rc;
return CFG_OK;
}
cfg_rc_t cfg_data_destroy(cfg_data_t *data)
{
cfg_rc_t rc;
if (data == NULL)
return CFG_ERR_ARG;
if ((rc = cfg_data_kill(data)) != CFG_OK)
return rc;
free(data);
return CFG_OK;
}
cfg_rc_t cfg_data_copy(cfg_data_t *data, cfg_data_t *copy)
{
cfg_rc_t rc;
if (data == NULL || copy == NULL)
return CFG_ERR_ARG;
copy->type = data->type;
copy->ctrl = data->ctrl;
if ((rc = data->ctrl(data, CFG_DATA_CTRL_CLONE, copy)) != CFG_OK)
return rc;
return CFG_OK;
}
cfg_rc_t cfg_data_clone(cfg_data_t *data, cfg_data_t **clone)
{
cfg_rc_t rc;
if (data == NULL || clone == NULL)
return CFG_ERR_ARG;
if ((*clone = (cfg_data_t *)malloc(sizeof(cfg_data_t))) == NULL)
return CFG_ERR_SYS;
if ((rc = cfg_data_copy(data, *clone)) != CFG_OK)
return rc;
return CFG_OK;
}
cfg_rc_t cfg_data_ctrl(cfg_data_t *data, cfg_data_ctrl_t ctrl, ...)
{
cfg_data_t *data2;
va_list ap;
va_start(ap, ctrl);
if (data == NULL)
return CFG_ERR_ARG;
if (ctrl == CFG_DATA_CTRL_CLONE) {
if ((data2 = (cfg_data_t *)va_arg(ap, void *)) == NULL)
return CFG_ERR_ARG;
if (data->type == CFG_DATA_TYPE_STR) {
if (data->value.s != NULL)
data2->value.s = strdup(data->value.s);
else
data2->value.s = NULL;
}
else {
memcpy((void *)&(data2->value),
(void *)&(data->value), sizeof(cfg_data_value_t));
}
}
else if (ctrl == CFG_DATA_CTRL_DESTROY) {
if (data->type == CFG_DATA_TYPE_STR)
if (data->value.s != NULL)
free(data->value.s);
}
va_end(ap);
return CFG_OK;
}
cfg_rc_t cfg_data_set(cfg_data_t *data, cfg_data_attr_t id, ...)
{
va_list ap;
if (data == NULL)
return CFG_ERR_ARG;
va_start(ap, id);
switch (id) {
case CFG_DATA_ATTR_TYPE: {
cfg_data_type_t t = (cfg_data_type_t)va_arg(ap, int);
if (!( t == CFG_DATA_TYPE_PTR
|| t == CFG_DATA_TYPE_STR
|| t == CFG_DATA_TYPE_INT
|| t == CFG_DATA_TYPE_FLT))
return CFG_ERR_ARG;
data->type = t;
break;
}
case CFG_DATA_ATTR_VALUE: {
switch (data->type) {
case CFG_DATA_TYPE_PTR: {
data->value.p = (void *)va_arg(ap, void *);
break;
}
case CFG_DATA_TYPE_STR: {
char *s = (char *)va_arg(ap, void *);
if (data->value.s != NULL)
free(data->value.s);
if (s != NULL)
s = strdup(s);
data->value.s = s;
break;
}
case CFG_DATA_TYPE_INT: {
data->value.i = (int)va_arg(ap, int);
break;
}
case CFG_DATA_TYPE_FLT: {
data->value.f = (double)va_arg(ap, double);
break;
}
}
break;
}
case CFG_DATA_ATTR_CTRL: {
cfg_data_cb_t ctrl = (cfg_data_cb_t)va_arg(ap, cfg_data_cb_t);
data->ctrl = ctrl;
break;
}
}
va_end(ap);
return CFG_OK;
}
cfg_rc_t cfg_data_get(cfg_data_t *data, cfg_data_attr_t id, ...)
{
va_list ap;
if (data == NULL)
return CFG_ERR_ARG;
va_start(ap, id);
switch (id) {
case CFG_DATA_ATTR_TYPE: {
cfg_data_type_t *pt = (cfg_data_type_t *)va_arg(ap, int *);
if (pt == NULL)
return CFG_ERR_ARG;
*pt = data->type;
break;
}
case CFG_DATA_ATTR_VALUE: {
switch (data->type) {
case CFG_DATA_TYPE_PTR: {
void **p = (void **)va_arg(ap, void *);
if (p == NULL)
return CFG_ERR_ARG;
*p = data->value.p;
break;
}
case CFG_DATA_TYPE_STR: {
char **p = (char **)va_arg(ap, void *);
if (p == NULL)
return CFG_ERR_ARG;
*p = data->value.s;
break;
}
case CFG_DATA_TYPE_INT: {
int *p = (int *)va_arg(ap, void *);
if (p == NULL)
return CFG_ERR_ARG;
*p = data->value.i;
break;
}
case CFG_DATA_TYPE_FLT: {
double *p = (double *)va_arg(ap, void *);
if (p == NULL)
return CFG_ERR_ARG;
*p = data->value.f;
break;
}
}
break;
}
case CFG_DATA_ATTR_CTRL: {
cfg_data_cb_t *pcb = (cfg_data_cb_t *)va_arg(ap, void *);
if (pcb == NULL)
return CFG_ERR_ARG;
*pcb = data->ctrl;
break;
}
}
va_end(ap);
return CFG_OK;
}