/*
**  OSSP cfg - Configuration Parsing
**  Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002-2003 The OSSP Project (http://www.ossp.org/)
**  Copyright (c) 2002-2003 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 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.h: master API
*/

#ifndef __CFG_H__
#define __CFG_H__

#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

/* general return codes */
typedef enum {
    CFG_OK = 0,               /* everything ok */
    CFG_ERR_ARG,              /* invalid argument */
    CFG_ERR_USE,              /* invalid use */
    CFG_ERR_MEM,              /* no more memory available */
    CFG_ERR_SYS,              /* operating system error */
    CFG_ERR_FMT,              /* formatting error */
    CFG_ERR_INT,              /* internal error */
    CFG_ERR_SYN,              /* syntax error */
    CFG_ERR_NDE               /* node reference error */
} cfg_rc_t;

/* configuration format */
typedef enum {
    CFG_FMT_CFG,
    CFG_FMT_XML
} cfg_fmt_t;

/* list of node types */
typedef enum {
    CFG_NODE_TYPE_SEQ,        /* node represents a sequence */
    CFG_NODE_TYPE_DIR,        /* node represents a directive */
    CFG_NODE_TYPE_OPT,        /* node represents a option */
    CFG_NODE_TYPE_ARG         /* node represents a argument */
} cfg_node_type_t;

/* list of node attributes */
typedef enum {
    CFG_NODE_ATTR_PARENT,     /* RW: (cfg_node_t *)    pointer to parent node */
    CFG_NODE_ATTR_LBROTH,     /* RW: (cfg_node_t *)    pointer to left brother node */
    CFG_NODE_ATTR_RBROTH,     /* RW: (cfg_node_t *)    pointer to right brother node */
    CFG_NODE_ATTR_CHILD1,     /* RW: (cfg_node_t *)    pointer to first child node */
    CFG_NODE_ATTR_CHILDL,     /* RO: (cfg_node_t *)    pointer to last child */
    CFG_NODE_ATTR_CHILDS,     /* RO: (int)             number of child nodes */
    CFG_NODE_ATTR_NODES,      /* RO: (int)             number of total nodes (recursive) */
    CFG_NODE_ATTR_DEPTH,      /* RO: (int)             number of nodes back to root node */
    CFG_NODE_ATTR_SRCNAME,    /* RW: (char *)          pointer to the source name */
    CFG_NODE_ATTR_SRCPOS,     /* RW: (int)             position offset into source */
    CFG_NODE_ATTR_TYPE,       /* RW: (cfg_node_type_t) type of node */
    CFG_NODE_ATTR_TOKEN,      /* RW: (char *)          pointer to the node token string */
    CFG_NODE_ATTR_DATA        /* RW: (cfg_data_t *)    pointer to the node annotation data */
} cfg_node_attr_t;

/* list of data types */
typedef enum {
    CFG_DATA_TYPE_PTR,        /* "void *" */
    CFG_DATA_TYPE_STR,        /* "char *" */
    CFG_DATA_TYPE_INT,        /* "int"    */
    CFG_DATA_TYPE_FLT         /* "double" */
} cfg_data_type_t;

/* list of data control operations */
typedef enum {
    CFG_DATA_CTRL_CLONE,      /* clone data */
    CFG_DATA_CTRL_DESTROY     /* destroy data */
} cfg_data_ctrl_t;

/* list of data attributes */
typedef enum {
    CFG_DATA_ATTR_TYPE,       /* RW: type of data value */
    CFG_DATA_ATTR_VALUE,      /* RW: pointer to data value */
    CFG_DATA_ATTR_CTRL        /* RW: pointer to data control callback */
} cfg_data_attr_t;

/* configuration handle type (opaque) */
struct cfg_st;
typedef struct cfg_st cfg_t;

/* configuration node type (opaque) */
struct cfg_node_st;
typedef struct cfg_node_st cfg_node_t;

/* configuration data type */
struct cfg_data_st;
typedef struct cfg_data_st cfg_data_t;

/* configuration data control callback type */
typedef cfg_rc_t (*cfg_data_cb_t)(cfg_data_t *, cfg_data_ctrl_t, ...);

/* configuration handling */
cfg_rc_t   cfg_create      (cfg_t **cfg);
cfg_rc_t   cfg_destroy     (cfg_t  *cfg);
cfg_rc_t   cfg_error       (cfg_t  *cfg, cfg_rc_t rc, char **error);
long       cfg_version     (void);

/* configuration import/export */
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   cfg_export      (cfg_t  *cfg, cfg_node_t  *node, cfg_fmt_t fmt,      char **ex_ptr, size_t ex_len);

/* node handling */
cfg_rc_t   cfg_node_create (cfg_t  *cfg, cfg_node_t **node);
cfg_rc_t   cfg_node_destroy(cfg_t  *cfg, cfg_node_t  *node);
cfg_rc_t   cfg_node_clone  (cfg_t  *cfg, cfg_node_t  *node, cfg_node_t **node2);

/* node attribution */
cfg_rc_t   cfg_node_set    (cfg_t  *cfg, cfg_node_t  *node, cfg_node_attr_t attr, ...);
cfg_rc_t   cfg_node_get    (cfg_t  *cfg, cfg_node_t  *node, cfg_node_attr_t attr, ...);

/* node traversing/locating */
cfg_rc_t   cfg_node_root   (cfg_t  *cfg, cfg_node_t **node);
cfg_rc_t   cfg_node_select (cfg_t  *cfg, cfg_node_t  *node, cfg_node_t ***result, const char *spec, ...);
cfg_rc_t   cfg_node_find   (cfg_t  *cfg, cfg_node_t  *node, cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cmp, cfg_node_t **cont);
cfg_rc_t   cfg_node_apply  (cfg_t  *cfg, cfg_node_t  *node, cfg_rc_t (*cb_fct_cmp)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cmp, cfg_rc_t (*cb_fct_cb)(cfg_t *, cfg_node_t *, void *), void *cb_ctx_cb);
cfg_rc_t   cfg_node_cmp    (cfg_t  *cfg, cfg_node_t  *node, void *token);

/* node linking */
cfg_rc_t   cfg_node_link   (cfg_t  *cfg, cfg_node_t  *node, cfg_node_attr_t id, cfg_node_t *node2);
cfg_rc_t   cfg_node_unlink (cfg_t  *cfg, cfg_node_t  *node);

/* data attribution */
cfg_rc_t   cfg_data_set    (cfg_data_t *data, cfg_data_attr_t attr, ...);
cfg_rc_t   cfg_data_get    (cfg_data_t *data, cfg_data_attr_t attr, ...);
cfg_rc_t   cfg_data_ctrl   (cfg_data_t *data, cfg_data_ctrl_t ctrl, ...);

#endif /* __CFG_H__ */

