ossp-pkg/cfg/cfg_main.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_main.c: main API
*/
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include "cfg.h"
#include "cfg_fmt.h"
#include "cfg_main.h"
#include "cfg_data.h"
#include "cfg_node.h"
#include "cfg_syn.h"
#include "cfg_global.h"
#define _CFG_VERS_C_AS_HEADER_
#include "cfg_vers.c"
#undef _CFG_VERS_C_AS_HEADER_
long cfg_version(void)
{
return __cfg_version.v_hex;
}
cfg_rc_t cfg_create(cfg_t **cfg)
{
cfg_rc_t rc;
if (cfg == NULL)
return CFG_ERR_ARG;
if ((*cfg = malloc(sizeof(cfg_t))) == NULL)
return CFG_ERR_SYS;
(*cfg)->root = NULL;
(*cfg)->szError[0] = '\0';
(*cfg)->szErrorInfo[0] = '\0';
(*cfg)->rcErrorInfo = CFG_OK;
if ((rc = cfg_grid_create(&((*cfg)->grid_nodes), sizeof(cfg_node_t), 512)) != CFG_OK) {
free(*cfg);
return rc;
}
if ((rc = cfg_grid_create(&((*cfg)->grid_tokens), 8192, 1)) != CFG_OK) {
free(*cfg);
cfg_grid_destroy((*cfg)->grid_nodes);
return rc;
}
return CFG_OK;
}
static cfg_rc_t cfg_destroy_node(cfg_t *cfg, cfg_node_t *node, void *ctx)
{
cfg_node_destroy(cfg, node);
return CFG_OK;
}
cfg_rc_t cfg_destroy(cfg_t *cfg)
{
if (cfg == NULL)
return CFG_ERR_ARG;
if (cfg->root != NULL)
cfg_node_apply(cfg, cfg->root, NULL, NULL, cfg_destroy_node, NULL);
cfg_grid_destroy(cfg->grid_nodes);
cfg_grid_destroy(cfg->grid_tokens);
free(cfg);
return CFG_OK;
}
cfg_rc_t cfg_error_info(cfg_t *cfg, cfg_rc_t rv, const char *fmt, ...)
{
va_list ap;
/* argument sanity check */
if (cfg == NULL || rv == CFG_OK || fmt == NULL)
return CFG_ERR_ARG;
/* remember error information */
va_start(ap, fmt);
cfg_fmt_vsprintf(cfg->szErrorInfo, sizeof(cfg->szErrorInfo), fmt, ap);
cfg->rcErrorInfo = rv;
va_end(ap);
return CFG_OK;
}
cfg_rc_t cfg_error(cfg_t *cfg, cfg_rc_t rv, char **error)
{
char *sz;
char *cpBuf;
int nBuf;
int n;
/* argument sanity check */
if (cfg == NULL || error == NULL)
return CFG_ERR_ARG;
/* start at begin of buffer */
cpBuf = cfg->szError;
nBuf = sizeof(cfg->szError);
/* translate result value into corresponding string */
if (rv == CFG_OK) sz = "everything ok";
else if (rv == CFG_ERR_ARG) sz = "invalid argument";
else if (rv == CFG_ERR_USE) sz = "invalid use";
else if (rv == CFG_ERR_MEM) sz = "no more memory available";
else if (rv == CFG_ERR_SYS) sz = "operating system error";
else if (rv == CFG_ERR_FMT) sz = "formatting error";
else if (rv == CFG_ERR_INT) sz = "internal error";
else if (rv == CFG_ERR_SYN) sz = "syntax error";
else if (rv == CFG_ERR_NDE) sz = "node reference error";
else sz = "unknown error";
n = cfg_fmt_sprintf(cpBuf, nBuf, "%s", sz);
cpBuf += n;
nBuf -= n;
/* optionally annotate with error information */
if (rv == cfg->rcErrorInfo && cfg->szErrorInfo[0] != '\0') {
n = cfg_fmt_sprintf(cpBuf, nBuf, "; %s", cfg->szErrorInfo);
cpBuf += n;
nBuf -= n;
}
/* optionally annotate with operating system error information */
if (rv == CFG_ERR_SYS) {
n = cfg_fmt_sprintf(cpBuf, nBuf, "; %s (%d)", strerror(errno), errno);
cpBuf += n;
nBuf -= n;
}
/* return pointer to internal buffer */
*error = cfg->szError;
return CFG_OK;
}
cfg_rc_t cfg_import(cfg_t *cfg, cfg_node_t *node, cfg_fmt_t fmt, const char *in_ptr, size_t in_len)
{
cfg_rc_t rv;
char error[1024];
cfg_node_t *root;
if (cfg == NULL || in_ptr == NULL)
return CFG_ERR_ARG;
if (node == NULL)
node = cfg->root;
if (fmt == CFG_FMT_CFG) {
if ((rv = cfg_syn_import(cfg, &root, in_ptr, in_len, error, sizeof(error))) != CFG_OK) {
cfg_error_info(cfg, rv, "%s", error);
return rv;
}
}
/* FIXME: CFG_FMT_XML */
else
return CFG_ERR_INT;
/* FIXME: merge: cfg->root[node] := cfg->root[node] + root */
cfg->root = root;
return CFG_OK;
}
cfg_rc_t cfg_export(cfg_t *cfg, cfg_node_t *node, cfg_fmt_t fmt, char **ex_ptr, size_t ex_len)
{
cfg_rc_t rv;
char *output;
size_t n;
if (cfg == NULL || ex_ptr == NULL)
return CFG_ERR_ARG;
if (node == NULL)
node = cfg->root;
if (fmt == CFG_FMT_CFG) {
if ((rv = cfg_syn_export(cfg, node, &output)) != CFG_OK)
return rv;
}
/* FIXME: CFG_FMT_XML */
else
return CFG_ERR_INT;
/* provide output */
if (ex_len == 0)
*ex_ptr = output;
else {
n = strlen(output);
if (n >= ex_len)
return CFG_ERR_MEM;
memmove(*ex_ptr, output, n+1);
free(output);
}
return CFG_OK;
}