/* ** OSSP cfg - Configuration Parsing ** Copyright (c) 2002-2006 Ralf S. Engelschall ** 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 #include #include #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; }