ossp-pkg/cfg/perl/cfg.xs
/*
** 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.xs: Perl Binding (Perl/XS part)
*/
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "cfg.h"
/* find/apply callback context */
typedef struct {
SV *fct;
SV *ctx;
} cb_ctx_t;
/* find/apply callback wrapper */
static cfg_rc_t cb_fct(cfg_t *cfg, cfg_node_t *node, void *_ctx)
{
cb_ctx_t *ctx = (cb_ctx_t *)ctx;
cfg_rc_t rc;
dSP;
ENTER; SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSViv(PTR2IV(cfg))));
XPUSHs(sv_2mortal(newSViv(PTR2IV(node))));
XPUSHs(ctx->ctx);
PUTBACK;
if (call_sv(ctx->fct, G_SCALAR) != 1)
croak("cfg_node_find: expected single scalar as return value from callback");
SPAGAIN;
rc = (cfg_rc_t)SvIV(POPs);
FREETMPS; LEAVE;
return rc;
}
MODULE = OSSP::cfg PACKAGE = OSSP::cfg
void
constant(sv)
PREINIT:
dXSTARG;
STRLEN len;
int i;
static struct {
const char *name;
int value;
} constant_table[] = {
{ "CFG_OK", CFG_OK },
{ "CFG_ERR_ARG", CFG_ERR_ARG },
{ "CFG_ERR_USE", CFG_ERR_USE },
{ "CFG_ERR_MEM", CFG_ERR_MEM },
{ "CFG_ERR_SYS", CFG_ERR_SYS },
{ "CFG_ERR_FMT", CFG_ERR_FMT },
{ "CFG_ERR_INT", CFG_ERR_INT },
{ "CFG_ERR_SYN", CFG_ERR_SYN },
{ "CFG_ERR_NDE", CFG_ERR_NDE },
{ "CFG_FMT_CFG", CFG_FMT_CFG },
{ "CFG_FMT_XML", CFG_FMT_XML },
{ "CFG_NODE_TYPE_SEQ", CFG_NODE_TYPE_SEQ },
{ "CFG_NODE_TYPE_DIR", CFG_NODE_TYPE_DIR },
{ "CFG_NODE_TYPE_OPT", CFG_NODE_TYPE_OPT },
{ "CFG_NODE_TYPE_ARG", CFG_NODE_TYPE_ARG },
{ "CFG_NODE_ATTR_PARENT", CFG_NODE_ATTR_PARENT },
{ "CFG_NODE_ATTR_LBROTH", CFG_NODE_ATTR_LBROTH },
{ "CFG_NODE_ATTR_RBROTH", CFG_NODE_ATTR_RBROTH },
{ "CFG_NODE_ATTR_CHILD1", CFG_NODE_ATTR_CHILD1 },
{ "CFG_NODE_ATTR_CHILDL", CFG_NODE_ATTR_CHILDL },
{ "CFG_NODE_ATTR_CHILDS", CFG_NODE_ATTR_CHILDS },
{ "CFG_NODE_ATTR_NODES", CFG_NODE_ATTR_NODES },
{ "CFG_NODE_ATTR_DEPTH", CFG_NODE_ATTR_DEPTH },
{ "CFG_NODE_ATTR_SRCNAME", CFG_NODE_ATTR_SRCNAME },
{ "CFG_NODE_ATTR_SRCPOS", CFG_NODE_ATTR_SRCPOS },
{ "CFG_NODE_ATTR_TYPE", CFG_NODE_ATTR_TYPE },
{ "CFG_NODE_ATTR_TOKEN", CFG_NODE_ATTR_TOKEN },
{ "CFG_NODE_ATTR_DATA", CFG_NODE_ATTR_DATA },
{ "CFG_DATA_TYPE_PTR", CFG_DATA_TYPE_PTR },
{ "CFG_DATA_TYPE_STR", CFG_DATA_TYPE_STR },
{ "CFG_DATA_TYPE_INT", CFG_DATA_TYPE_INT },
{ "CFG_DATA_TYPE_FLT", CFG_DATA_TYPE_FLT },
{ "CFG_DATA_CTRL_CLONE", CFG_DATA_CTRL_CLONE },
{ "CFG_DATA_CTRL_DESTROY", CFG_DATA_CTRL_DESTROY },
{ "CFG_DATA_ATTR_TYPE", CFG_DATA_ATTR_TYPE },
{ "CFG_DATA_ATTR_VALUE", CFG_DATA_ATTR_VALUE },
{ "CFG_DATA_ATTR_CTRL", CFG_DATA_ATTR_CTRL }
};
INPUT:
SV *sv;
const char *s = SvPV(sv, len);
PPCODE:
for (i = 0; i < sizeof(constant_table)/sizeof(constant_table[0]); i++) {
if (strcmp(s, constant_table[i].name) == 0) {
EXTEND(SP, 1);
PUSHs(&PL_sv_undef);
PUSHi(constant_table[i].value);
break;
}
}
if (i == sizeof(constant_table)/sizeof(constant_table[0])) {
sv = sv_2mortal(newSVpvf("unknown contant OSSP::cfg::%s", s));
PUSHs(sv);
}
cfg_rc_t
cfg_create(cfg)
PROTOTYPE:
$
INPUT:
cfg_t *&cfg = NO_INIT
CODE:
RETVAL = cfg_create(&cfg);
OUTPUT:
cfg
RETVAL
cfg_rc_t
cfg_destroy(cfg)
PROTOTYPE:
$
INPUT:
cfg_t *cfg
CODE:
RETVAL = cfg_destroy(cfg);
OUTPUT:
RETVAL
cfg_rc_t
cfg_error(cfg,rc,error)
PROTOTYPE:
$$$
INPUT:
cfg_t *cfg
cfg_rc_t rc
char *&error = NO_INIT
CODE:
RETVAL = cfg_error(cfg, rc, &error);
OUTPUT:
error
RETVAL
long
cfg_version()
PROTOTYPE:
INPUT:
CODE:
RETVAL = cfg_version();
OUTPUT:
RETVAL
cfg_rc_t
cfg_import(cfg,node,fmt,in_ptr,in_len)
PROTOTYPE:
$$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_fmt_t fmt
const char *in_ptr
size_t in_len
CODE:
if (ST(4) == &PL_sv_undef)
in_len = sv_len(ST(3));
RETVAL = cfg_import(cfg, node, fmt, in_ptr, in_len);
OUTPUT:
RETVAL
cfg_rc_t
cfg_export(cfg,node,fmt,ex_ptr,ex_len)
PROTOTYPE:
$$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_fmt_t fmt
char *&ex_ptr = NO_INIT
size_t ex_len
CODE:
RETVAL = cfg_export(cfg, node, fmt, &ex_ptr, ex_len);
OUTPUT:
ex_ptr
RETVAL
cfg_rc_t
cfg_node_create(cfg,node)
PROTOTYPE:
$$
INPUT:
cfg_t *cfg
cfg_node_t *&node = NO_INIT
CODE:
RETVAL = cfg_node_create(cfg, &node);
OUTPUT:
node
RETVAL
cfg_rc_t
cfg_node_destroy(cfg,node)
PROTOTYPE:
$$
INPUT:
cfg_t *cfg
cfg_node_t *node
CODE:
RETVAL = cfg_node_destroy(cfg, node);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_clone(cfg,node,node2)
PROTOTYPE:
$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_t *&node2 = NO_INIT
CODE:
RETVAL = cfg_node_clone(cfg, node, &node2);
OUTPUT:
node2
RETVAL
cfg_rc_t
cfg_node_set(cfg,node,attr,va_arg1)
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_PARENT \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_LBROTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_RBROTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILD1 \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDL )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_node_t *va_arg1
CODE:
RETVAL = cfg_node_set(cfg, node, attr, va_arg1);
OUTPUT:
RETVAL
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDS \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_NODES \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DEPTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCPOS )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
int va_arg1
CODE:
RETVAL = cfg_node_set(cfg, node, attr, va_arg1);
OUTPUT:
RETVAL
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCNAME \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TOKEN )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
char *va_arg1
CODE:
RETVAL = cfg_node_set(cfg, node, attr|CFG_ATTR_COPY, va_arg1);
OUTPUT:
RETVAL
CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TYPE)
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_node_type_t va_arg1
CODE:
RETVAL = cfg_node_set(cfg, node, attr, va_arg1);
OUTPUT:
RETVAL
CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DATA)
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_data_t *va_arg1
CODE:
RETVAL = cfg_node_set(cfg, node, attr, va_arg1);
OUTPUT:
RETVAL
CASE:
PROTOTYPE:
$$$;$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
CODE:
RETVAL = cfg_node_set(cfg, node, attr);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_get(cfg,node,attr,va_arg1)
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_PARENT \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_LBROTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_RBROTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILD1 \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDL )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_node_t *&va_arg1 = NO_INIT
CODE:
RETVAL = cfg_node_get(cfg, node, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_CHILDS \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_NODES \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DEPTH \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCPOS )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
int &va_arg1 = NO_INIT
CODE:
RETVAL = cfg_node_get(cfg, node, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: ( (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_SRCNAME \
|| (cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TOKEN )
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
char *&va_arg1 = NO_INIT
CODE:
RETVAL = cfg_node_get(cfg, node, attr|CFG_ATTR_COPY, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_TYPE)
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_node_type_t &va_arg1 = NO_INIT
CODE:
RETVAL = cfg_node_get(cfg, node, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: ((cfg_node_attr_t)SvIV(ST(2)) == CFG_NODE_ATTR_DATA)
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
cfg_data_t *&va_arg1 = NO_INIT
CODE:
RETVAL = cfg_node_get(cfg, node, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE:
PROTOTYPE:
$$$;$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t attr
CODE:
RETVAL = cfg_node_get(cfg, node, attr);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_root(cfg,node,node_old)
PROTOTYPE:
$$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_t *&node_old = NO_INIT
CODE:
RETVAL = cfg_node_root(cfg, node, &node_old);
OUTPUT:
node_old
RETVAL
cfg_rc_t
cfg_node_select(cfg,node,result,spec)
PROTOTYPE:
$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
SV *&result = NO_INIT
const char *spec
PREINIT:
cfg_node_t **r;
CODE:
/* FIXME: perhaps use sv_vsetpvfn() to fully emulate C API? */
RETVAL = cfg_node_select(cfg, node, &r, "%s", spec);
if (RETVAL == CFG_OK) {
/* translate C array into Perl array */
int i;
AV *av = newAV();
for (i = 0; r[i] != NULL; i++)
av_push(av, newSV(PTR2IV(r[i])));
free(r);
result = newRV_noinc((SV *)av);
}
else
result = &PL_sv_undef;
OUTPUT:
result
RETVAL
cfg_rc_t
cfg_node_find(cfg,node,cb_fct_cmp,cb_ctx_cmp,cont)
PROTOTYPE:
$$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
SV *cb_fct_cmp
SV *cb_ctx_cmp
cfg_node_t *&cont = NO_INIT
PREINIT:
cb_ctx_t ctx_cmp;
CODE:
ctx_cmp.fct = cb_fct_cmp;
ctx_cmp.ctx = cb_ctx_cmp;
RETVAL = cfg_node_find(cfg, node, cb_fct, &ctx_cmp, &cont);
OUTPUT:
cont
RETVAL
cfg_rc_t
cfg_node_apply(cfg,node,cb_fct_cmp,cb_ctx_cmp,cb_fct_cb,cb_ctx_cb)
PROTOTYPE:
$$$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
SV *cb_fct_cmp
SV *cb_ctx_cmp
SV *cb_fct_cb
SV *cb_ctx_cb
PREINIT:
cb_ctx_t ctx_cmp;
cb_ctx_t ctx_cb;
CODE:
ctx_cmp.fct = cb_fct_cmp;
ctx_cmp.ctx = cb_ctx_cmp;
ctx_cb.fct = cb_fct_cb;
ctx_cb.ctx = cb_ctx_cb;
RETVAL = cfg_node_apply(cfg, node, cb_fct, &ctx_cmp, cb_fct, &ctx_cb);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_cmp(cfg,node,token)
PROTOTYPE:
$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
char *token
CODE:
RETVAL = cfg_node_cmp(cfg, node, (void *)token);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_link(cfg,node,id,node2)
PROTOTYPE:
$$$$
INPUT:
cfg_t *cfg
cfg_node_t *node
cfg_node_attr_t id
cfg_node_t *node2
CODE:
RETVAL = cfg_node_link(cfg, node, id, node2);
OUTPUT:
RETVAL
cfg_rc_t
cfg_node_unlink(cfg,node)
PROTOTYPE:
$$
INPUT:
cfg_t *cfg
cfg_node_t *node
CODE:
RETVAL = cfg_node_unlink(cfg, node);
OUTPUT:
RETVAL
cfg_rc_t
cfg_data_set(data,attr,va_arg1)
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_TYPE
PROTOTYPE:
$$$
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
cfg_data_type_t va_arg1
CODE:
RETVAL = cfg_data_set(data, attr, va_arg1);
OUTPUT:
RETVAL
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_VALUE
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
PREINIT:
cfg_data_type_t type;
CODE:
if ((RETVAL = cfg_data_get(data, CFG_DATA_ATTR_TYPE, &type)) == CFG_OK) {
switch (type) {
case CFG_DATA_TYPE_PTR: {
void *va_arg1 = INT2PTR(cfg_node_t *, SvIV((SV*)SvRV(ST(2))));
RETVAL = cfg_data_set(data, attr, va_arg1);
break;
}
case CFG_DATA_TYPE_STR: {
char *va_arg1 = SvPV_nolen(ST(2));
RETVAL = cfg_data_set(data, attr, va_arg1);
break;
}
case CFG_DATA_TYPE_INT: {
int va_arg1 = SvIV(ST(2));
RETVAL = cfg_data_set(data, attr, va_arg1);
break;
}
case CFG_DATA_TYPE_FLT: {
double va_arg1 = SvNV(ST(2));
RETVAL = cfg_data_set(data, attr, va_arg1);
break;
}
}
}
OUTPUT:
RETVAL
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_CTRL
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
cfg_data_cb_t va_arg1
CODE:
RETVAL = cfg_data_set(data, attr, va_arg1);
OUTPUT:
RETVAL
cfg_rc_t
cfg_data_get(data,attr,va_arg1)
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_TYPE
PROTOTYPE:
$$$
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
cfg_data_type_t &va_arg1 = NO_INIT
CODE:
RETVAL = cfg_data_get(data, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_VALUE
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
SV *va_arg1
PREINIT:
cfg_data_type_t type;
CODE:
if ((RETVAL = cfg_data_get(data, CFG_DATA_ATTR_TYPE, &type)) == CFG_OK) {
switch (type) {
case CFG_DATA_TYPE_PTR: {
void *arg;
RETVAL = cfg_data_get(data, attr, &arg);
sv_setiv(va_arg1, PTR2IV(arg));
break;
}
case CFG_DATA_TYPE_STR: {
char *arg;
RETVAL = cfg_data_set(data, attr, &arg);
sv_setpv(va_arg1, arg);
break;
}
case CFG_DATA_TYPE_INT: {
int arg;
RETVAL = cfg_data_set(data, attr, &arg);
sv_setiv(va_arg1, arg);
break;
}
case CFG_DATA_TYPE_FLT: {
double arg;
RETVAL = cfg_data_set(data, attr, &arg);
sv_setnv(va_arg1, arg);
break;
}
}
}
OUTPUT:
va_arg1
RETVAL
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_ATTR_CTRL
INPUT:
cfg_data_t *data
cfg_data_attr_t attr
cfg_data_cb_t &va_arg1 = NO_INIT
CODE:
RETVAL = cfg_data_set(data, attr, &va_arg1);
OUTPUT:
va_arg1
RETVAL
cfg_rc_t
cfg_data_ctrl(data,ctrl,va_arg1)
CASE: (cfg_data_ctrl_t)SvIV(ST(1)) == CFG_DATA_CTRL_CLONE
PROTOTYPE:
$$;$
INPUT:
cfg_data_t *data
cfg_data_ctrl_t ctrl
cfg_data_t *&va_arg1 = NO_INIT
CODE:
RETVAL = cfg_data_ctrl(data, ctrl, &va_arg1);
OUTPUT:
va_arg1
RETVAL
CASE: (cfg_data_attr_t)SvIV(ST(1)) == CFG_DATA_CTRL_DESTROY
INPUT:
cfg_data_t *data
cfg_data_ctrl_t ctrl
CODE:
RETVAL = cfg_data_ctrl(data, ctrl);
OUTPUT:
RETVAL
CASE:
INPUT:
cfg_data_t *data
cfg_data_ctrl_t ctrl
CODE:
RETVAL = cfg_data_set(data, ctrl);
OUTPUT:
RETVAL