blob: fbc7fe5d08f8fdcf85da319b1d1b9938c17eab23 [file] [log] [blame]
/*****************************************************************************\
* data_t parser plugin interface
******************************************************************************
* Copyright (C) SchedMD LLC.
*
* This file is part of Slurm, a resource management program.
* For details, see <https://slurm.schedmd.com/>.
* Please also read the included file: DISCLAIMER.
*
* Slurm is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* In addition, as a special exception, the copyright holders give permission
* to link the code of portions of this program with the OpenSSL library under
* certain conditions as described in each individual source file, and
* distribute linked combinations including the two. You must obey the GNU
* General Public License in all respects for all of the code used other than
* OpenSSL. If you modify file(s) with this exception, you may extend this
* exception to your version of the file(s), but you are not obligated to do
* so. If you do not wish to do so, delete this exception statement from your
* version. If you delete this exception statement from all source files in
* the program, then also delete it here.
*
* Slurm is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along
* with Slurm; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
\*****************************************************************************/
#include "config.h"
#include "src/common/data.h"
#include "src/common/fd.h"
#include "src/common/list.h"
#include "src/common/log.h"
#include "src/common/openapi.h"
#include "src/common/read_config.h"
#include "src/common/timers.h"
#include "src/common/xassert.h"
#include "src/common/xmalloc.h"
#include "src/common/xstring.h"
#include "src/interfaces/data_parser.h"
#include "src/interfaces/serializer.h"
#define PARSE_MAJOR_TYPE "data_parser"
#define PARSE_MAGIC 0x0ea0b1be
#define LATEST_PLUGIN_NAME "latest"
struct data_parser_s {
int magic;
int plugin_offset;
/* arg returned by plugin init() */
void *arg;
const char *plugin_type; /* ptr to plugin plugin_type - do not xfree */
char *params; /* parameters from _new - must xfree */
char *plugin_string; /* plugin_type+params - must xfree */
};
typedef struct {
int (*parse)(void *arg, data_parser_type_t type, void *dst,
ssize_t dst_bytes, data_t *src, data_t *parent_path);
int (*dump)(void *arg, data_parser_type_t type, void *src,
ssize_t src_bytes, data_t *dst);
/* ptr returned to be handed to commands as arg */
void *(*new)(data_parser_on_error_t on_parse_error,
data_parser_on_error_t on_dump_error,
data_parser_on_error_t on_query_error, void *error_arg,
data_parser_on_warn_t on_parse_warn,
data_parser_on_warn_t on_dump_warn,
data_parser_on_warn_t on_query_warn, void *warn,
char *params);
void (*free)(void *arg);
int (*assign)(void *arg, data_parser_attr_type_t type, void *obj);
openapi_type_t (*resolve_openapi_type)(void *arg,
data_parser_type_t type,
const char *field);
const char *(*resolve_type_str)(void *arg, data_parser_type_t type);
int (*inc_ref)(void *arg, data_parser_type_t type,
void **references_ptr);
int (*populate_schema)(void *arg, data_parser_type_t type,
void **references_ptr, data_t *dst, data_t *schemas);
int (*populate_parameters)(void *arg, data_parser_type_t parameter_type,
data_parser_type_t query_type,
void **references_ptr, data_t *dst,
data_t *schemas);
void (*release_refs)(void *arg, void **references_ptr);
bool (*is_complex)(void *arg);
bool (*is_deprecated)(void *arg);
int (*dump_flags)(void *arg, data_t *dst);
} parse_funcs_t;
typedef struct {
char *plugin_type;
char *params;
} plugin_param_t;
/*
* Must be synchronized with parse_funcs_t above.
*/
static const char *parse_syms[] = {
"data_parser_p_parse",
"data_parser_p_dump",
"data_parser_p_new",
"data_parser_p_free",
"data_parser_p_assign",
"data_parser_p_resolve_openapi_type",
"data_parser_p_resolve_type_string",
"data_parser_p_increment_reference",
"data_parser_p_populate_schema",
"data_parser_p_populate_parameters",
"data_parser_p_release_references",
"data_parser_p_is_complex",
"data_parser_p_is_deprecated",
"data_parser_p_dump_flags",
};
static plugins_t *plugins = NULL;
static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER;
static int active_parsers = 0;
static const char *_get_plugin_version(const char *plugin_type);
extern int data_parser_g_parse(data_parser_t *parser, data_parser_type_t type,
void *dst, ssize_t dst_bytes, data_t *src,
data_t *parent_path)
{
const parse_funcs_t *funcs;
DEF_TIMERS;
int rc;
if (!parser)
return ESLURM_DATA_INVALID_PARSER;
funcs = plugins->functions[parser->plugin_offset];
if (!src || (data_get_type(src) == DATA_TYPE_NONE))
return ESLURM_DATA_PARSE_NOTHING;
xassert(type > DATA_PARSER_TYPE_INVALID);
xassert(type < DATA_PARSER_TYPE_MAX);
xassert(parser->magic == PARSE_MAGIC);
xassert(data_get_type(parent_path) == DATA_TYPE_LIST);
xassert(plugins && (plugins->magic == PLUGINS_MAGIC));
xassert(parser->plugin_offset < plugins->count);
xassert(plugins->functions[parser->plugin_offset]);
START_TIMER;
rc = funcs->parse(parser->arg, type, dst, dst_bytes, src, parent_path);
END_TIMER2(__func__);
return rc;
}
extern int data_parser_g_dump(data_parser_t *parser, data_parser_type_t type,
void *src, ssize_t src_bytes, data_t *dst)
{
DEF_TIMERS;
int rc;
const parse_funcs_t *funcs;
if (!parser)
return ESLURM_DATA_INVALID_PARSER;
funcs = plugins->functions[parser->plugin_offset];
xassert(data_get_type(dst));
xassert(type > DATA_PARSER_TYPE_INVALID);
xassert(type < DATA_PARSER_TYPE_MAX);
xassert(parser->magic == PARSE_MAGIC);
xassert(plugins && (plugins->magic == PLUGINS_MAGIC));
xassert(parser->plugin_offset < plugins->count);
xassert(plugins->functions[parser->plugin_offset]);
START_TIMER;
rc = funcs->dump(parser->arg, type, src, src_bytes, dst);
END_TIMER2(__func__);
return rc;
}
/* takes ownership of params */
static data_parser_t *_new_parser(data_parser_on_error_t on_parse_error,
data_parser_on_error_t on_dump_error,
data_parser_on_error_t on_query_error,
void *error_arg,
data_parser_on_warn_t on_parse_warn,
data_parser_on_warn_t on_dump_warn,
data_parser_on_warn_t on_query_warn,
void *warn_arg, int plugin_index,
char *params)
{
DEF_TIMERS;
const parse_funcs_t *funcs;
data_parser_t *parser = xmalloc(sizeof(*parser));
parser->magic = PARSE_MAGIC;
parser->plugin_offset = plugin_index;
parser->plugin_type = plugins->types[plugin_index];
parser->params = params;
START_TIMER;
funcs = plugins->functions[plugin_index];
parser->arg = funcs->new(on_parse_error, on_dump_error, on_query_error,
error_arg, on_parse_warn, on_dump_warn,
on_query_warn, warn_arg, params);
xstrfmtcat(parser->plugin_string, "%s%s", parser->plugin_type,
(parser->params ? parser->params : ""));
END_TIMER2(__func__);
slurm_mutex_lock(&init_mutex);
xassert(active_parsers >= 0);
active_parsers++;
slurm_mutex_unlock(&init_mutex);
return parser;
}
static plugin_param_t *_parse_plugin_type(const char *plugin_type)
{
char *type, *last = NULL, *pl;
plugin_param_t *pparams = NULL;
int count = 0;
if (!plugin_type)
return NULL;
pl = xstrdup(plugin_type);
type = strtok_r(pl, ",", &last);
while (type) {
char *pl;
plugin_param_t *p;
xrecalloc(pparams, (count + 2), sizeof(*pparams));
p = &pparams[count];
if ((pl = xstrstr(type,
SLURM_DATA_PARSER_PLUGIN_PARAMS_CHAR))) {
p->plugin_type = xstrndup(type, (pl - type));
p->params = xstrdup(pl);
} else {
p->plugin_type = xstrdup(type);
}
if (!xstrcasecmp(p->plugin_type, LATEST_PLUGIN_NAME)) {
xfree(p->plugin_type);
p->plugin_type = xstrdup(SLURM_DATA_PARSER_VERSION);
}
log_flag(DATA, "%s: plugin=%s params=%s",
__func__, p->plugin_type, p->params);
count++;
type = strtok_r(NULL, ",", &last);
}
xfree(pl);
return pparams;
}
static int _load_plugins(plugin_param_t *pparams, plugrack_foreach_t listf,
bool skip_loading)
{
int rc = SLURM_SUCCESS;
if (skip_loading)
return rc;
slurm_mutex_lock(&init_mutex);
serializer_required(MIME_TYPE_JSON);
xassert(sizeof(parse_funcs_t) ==
(sizeof(void *) * ARRAY_SIZE(parse_syms)));
if (!pparams) {
rc = load_plugins(&plugins, PARSE_MAJOR_TYPE, NULL, listf,
parse_syms, ARRAY_SIZE(parse_syms));
} else {
for (int i = 0; !rc && pparams[i].plugin_type; i++)
rc = load_plugins(&plugins, PARSE_MAJOR_TYPE,
pparams[i].plugin_type, listf,
parse_syms, ARRAY_SIZE(parse_syms));
}
xassert(rc || plugins);
slurm_mutex_unlock(&init_mutex);
return rc;
}
static int _find_plugin_by_type(const char *plugin_type)
{
if (!plugin_type || !plugins)
return -1;
/* quick match by pointer address */
for (int i = 0; i < plugins->count; i++) {
if (plugin_type == plugins->types[i])
return i;
}
/* match by full string */
for (int i = 0; i < plugins->count; i++) {
if (!xstrcasecmp(plugin_type, plugins->types[i]))
return i;
}
/* match by string without "data_parser/" */
for (int i = 0; i < plugins->count; i++) {
if (!xstrcasecmp(plugin_type,
_get_plugin_version(plugins->types[i])))
return i;
}
return -1;
}
extern data_parser_t *data_parser_g_new(data_parser_on_error_t on_parse_error,
data_parser_on_error_t on_dump_error,
data_parser_on_error_t on_query_error,
void *error_arg,
data_parser_on_warn_t on_parse_warn,
data_parser_on_warn_t on_dump_warn,
data_parser_on_warn_t on_query_warn,
void *warn_arg, const char *plugin_type,
plugrack_foreach_t listf,
bool skip_loading)
{
int rc, index;
char *params = NULL;
data_parser_t *parser = NULL;
plugin_param_t *pparams;
if (!xstrcasecmp(plugin_type, "list")) {
xassert(listf);
load_plugins(&plugins, PARSE_MAJOR_TYPE, plugin_type, listf,
parse_syms, ARRAY_SIZE(parse_syms));
return NULL;
}
pparams = _parse_plugin_type(plugin_type);
if (!pparams || !pparams[0].plugin_type) {
error("%s: invalid plugin %s", __func__, plugin_type);
goto cleanup;
}
if (pparams[1].plugin_type) {
error("%s: rejecting ambiguous plugin %s",
__func__, plugin_type);
goto cleanup;
}
if ((rc = _load_plugins(pparams, listf, skip_loading))) {
error("%s: failure loading plugins: %s",
__func__, slurm_strerror(rc));
goto cleanup;
}
if ((index = _find_plugin_by_type(pparams[0].plugin_type)) < 0) {
error("%s: unable to find plugin %s", __func__,
pparams[0].plugin_type);
goto cleanup;
}
SWAP(params, pparams[0].params);
parser = _new_parser(on_parse_error, on_dump_error, on_query_error,
error_arg, on_parse_warn, on_dump_warn,
on_query_warn, warn_arg, index, params);
cleanup:
if (pparams) {
for (int i = 0; pparams[i].plugin_type; i++) {
xfree(pparams[i].plugin_type);
xfree(pparams[i].params);
}
xfree(pparams);
}
return parser;
}
extern data_parser_t **data_parser_g_new_array(
data_parser_on_error_t on_parse_error,
data_parser_on_error_t on_dump_error,
data_parser_on_error_t on_query_error,
void *error_arg,
data_parser_on_warn_t on_parse_warn,
data_parser_on_warn_t on_dump_warn,
data_parser_on_warn_t on_query_warn,
void *warn_arg,
const char *plugin_type,
plugrack_foreach_t listf,
bool skip_loading)
{
int rc, i = 0;
data_parser_t **parsers = NULL;
plugin_param_t *pparams;
if (!xstrcasecmp(plugin_type, "list")) {
xassert(listf);
load_plugins(&plugins, PARSE_MAJOR_TYPE, plugin_type, listf,
parse_syms, ARRAY_SIZE(parse_syms));
return NULL;
}
pparams = _parse_plugin_type(plugin_type);
if ((rc = _load_plugins(pparams, listf, skip_loading))) {
error("%s: failure loading plugins: %s",
__func__, slurm_strerror(rc));
goto cleanup;
}
/* always allocate for all possible plugins */
parsers = xcalloc((plugins->count + 1), sizeof(*parsers));
if (pparams) {
for (; pparams[i].plugin_type; i++) {
int index =
_find_plugin_by_type(pparams[i].plugin_type);
if (index < 0) {
error("%s: unable to find plugin %s",
__func__, pparams[i].plugin_type);
goto cleanup;
}
parsers[i] = _new_parser(on_parse_error, on_dump_error,
on_query_error, error_arg,
on_parse_warn, on_dump_warn,
on_query_warn, warn_arg, index,
pparams[i].params);
pparams[i].params = NULL;
xfree(pparams[i].plugin_type);
}
} else {
for (; i < plugins->count; i++) {
parsers[i] = _new_parser(on_parse_error, on_dump_error,
on_query_error, error_arg,
on_parse_warn, on_dump_warn,
on_query_warn, warn_arg, i,
NULL);
}
}
xfree(pparams);
return parsers;
cleanup:
if (pparams) {
for (; pparams[i].plugin_type; i++) {
xfree(pparams[i].plugin_type);
xfree(pparams[i].params);
}
xfree(pparams);
}
if (plugins && parsers)
for (int j = 0; j < plugins->count; j++)
FREE_NULL_DATA_PARSER(parsers[j]);
xfree(parsers);
return NULL;
}
extern const char *data_parser_get_plugin(data_parser_t *parser)
{
if (!parser)
return NULL;
xassert(parser->magic == PARSE_MAGIC);
return parser->plugin_string;
}
static const char *_get_plugin_version(const char *plugin_type)
{
static const char prefix[] = PARSE_MAJOR_TYPE "/";
#ifndef NDEBUG
/* catch if the prefix ever changes in an unexpected way */
const char *match;
xassert(plugin_type);
match = xstrstr(plugin_type, prefix);
xassert(match);
#endif
return plugin_type + strlen(prefix);
}
extern const char *data_parser_get_plugin_version(data_parser_t *parser)
{
xassert(!parser || parser->magic == PARSE_MAGIC);
if (!parser)
return NULL;
return _get_plugin_version(parser->plugin_type);
}
extern const char *data_parser_get_plugin_params(data_parser_t *parser)
{
xassert(!parser || parser->magic == PARSE_MAGIC);
if (!parser)
return NULL;
return parser->params;
}
extern void data_parser_g_free(data_parser_t *parser, bool skip_unloading)
{
DEF_TIMERS;
const parse_funcs_t *funcs;
if (!parser)
return;
funcs = plugins->functions[parser->plugin_offset];
if (plugins) {
xassert(plugins->magic == PLUGINS_MAGIC);
xassert(plugins->functions[parser->plugin_offset]);
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
}
START_TIMER;
if (plugins)
funcs->free(parser->arg);
END_TIMER2(__func__);
xfree(parser->params);
xfree(parser->plugin_string);
parser->arg = NULL;
parser->plugin_offset = -1;
parser->magic = ~PARSE_MAGIC;
xfree(parser);
slurm_mutex_lock(&init_mutex);
xassert(active_parsers >= 0);
active_parsers--;
xassert(active_parsers >= 0);
if (!skip_unloading && !active_parsers)
FREE_NULL_PLUGINS(plugins);
slurm_mutex_unlock(&init_mutex);
}
extern void data_parser_g_array_free(data_parser_t **ptr, bool skip_unloading)
{
if (!ptr)
return;
for (int i = 0; ptr[i]; i++)
data_parser_g_free(ptr[i], skip_unloading);
xfree(ptr);
}
extern int data_parser_g_assign(data_parser_t *parser,
data_parser_attr_type_t type, void *obj)
{
int rc;
DEF_TIMERS;
const parse_funcs_t *funcs;
if (!parser)
return ESLURM_DATA_INVALID_PARSER;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser);
xassert(plugins);
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
xassert(type > DATA_PARSER_ATTR_INVALID);
xassert(type < DATA_PARSER_ATTR_MAX);
START_TIMER;
rc = funcs->assign(parser->arg, type, obj);
END_TIMER2(__func__);
return rc;
}
extern openapi_resp_meta_t *data_parser_cli_meta(int argc, char **argv,
const char *mime_type)
{
openapi_resp_meta_t *meta = xmalloc_nz(sizeof(*meta));
int tty;
char **argvnt = NULL;
/* need a new array with a NULL terminator */
if (argc > 0) {
argvnt = xcalloc(argc, sizeof(*argv));
memcpy(argvnt, argv, (sizeof(*argv) * (argc - 1)));
}
if (isatty(STDIN_FILENO))
tty = STDIN_FILENO;
else if (isatty(STDOUT_FILENO))
tty = STDOUT_FILENO;
else if (isatty(STDERR_FILENO))
tty = STDERR_FILENO;
else
tty = -1;
*meta = (openapi_resp_meta_t) {
.plugin = {
.data_parser = NULL,
.accounting_storage =
slurm_conf.accounting_storage_type,
},
.command = argvnt,
.client = {
.source = ((tty != -1) ? fd_resolve_path(tty) :
NULL),
.uid = getuid(),
.gid = getgid(),
},
.slurm = {
.version = {
.major = xstrdup(SLURM_MAJOR),
.micro = xstrdup(SLURM_MICRO),
.minor = xstrdup(SLURM_MINOR),
},
.release = xstrdup(SLURM_VERSION_STRING),
.cluster = xstrdup(slurm_conf.cluster_name),
}
};
return meta;
}
static void _plugrack_foreach_list(const char *full_type, const char *fq_path,
const plugin_handle_t id, void *arg)
{
dprintf(STDOUT_FILENO, "%s\n", full_type);
}
static bool _on_error(void *arg, data_parser_type_t type, int error_code,
const char *source, const char *why, ...)
{
va_list ap;
char *str;
data_parser_dump_cli_ctxt_t *ctxt = arg;
openapi_resp_error_t *e = NULL;
if (ctxt) {
xassert(ctxt->magic == DATA_PARSER_DUMP_CLI_CTXT_MAGIC);
xassert(ctxt->errors);
if (!ctxt->errors)
return false;
e = xmalloc(sizeof(*e));
}
va_start(ap, why);
str = vxstrfmt(why, ap);
va_end(ap);
if (str) {
error("%s: parser=%s rc[%d]=%s -> %s",
(source ? source : __func__),
(!ctxt ? "DEFAULT" : ctxt->data_parser),
error_code, slurm_strerror(error_code), str);
if (e)
e->description = str;
else
xfree(str);
}
if (error_code) {
if (e)
e->num = error_code;
if (ctxt && !ctxt->rc)
ctxt->rc = error_code;
}
/*
* e is always non-NULL is ctxt is non-NULL, but check if e != NULL to
* silence a coverity warning.
*/
if (source && ctxt && e)
e->source = xstrdup(source);
if (ctxt)
list_append(ctxt->errors, e);
return false;
}
static void _on_warn(void *arg, data_parser_type_t type, const char *source,
const char *why, ...)
{
va_list ap;
char *str;
data_parser_dump_cli_ctxt_t *ctxt = arg;
openapi_resp_warning_t *w = NULL;
if (ctxt) {
xassert(ctxt->magic == DATA_PARSER_DUMP_CLI_CTXT_MAGIC);
xassert(ctxt->warnings);
if (!ctxt->warnings)
return;
w = xmalloc(sizeof(*w));
}
va_start(ap, why);
str = vxstrfmt(why, ap);
va_end(ap);
if (str) {
debug("%s: parser=%s WARNING: %s",
(source ? source : __func__),
(!ctxt ? "DEFAULT" : ctxt->data_parser), str);
if (ctxt)
w->description = str;
else
xfree(str);
}
if (source && ctxt)
w->source = xstrdup(source);
if (ctxt)
list_append(ctxt->warnings, w);
}
extern int data_parser_dump_cli_stdout(data_parser_type_t type, void *obj,
int obj_bytes, void *acct_db_conn,
const char *mime_type,
const char *data_parser,
data_parser_dump_cli_ctxt_t *ctxt,
openapi_resp_meta_t *meta)
{
int rc = SLURM_SUCCESS;
data_t *dresp = NULL;
data_parser_t *parser;
char *out = NULL;
if (!xstrcasecmp(data_parser, "list")) {
dprintf(STDERR_FILENO, "Possible data_parser plugins:\n");
parser = data_parser_g_new(NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, "list",
_plugrack_foreach_list, false);
FREE_NULL_DATA_PARSER(parser);
return SLURM_SUCCESS;
}
if (!(parser = data_parser_cli_parser(data_parser, ctxt))) {
rc = ESLURM_DATA_INVALID_PARSER;
error("%s output not supported by %s",
mime_type, SLURM_DATA_PARSER_VERSION);
goto cleanup;
}
if (acct_db_conn)
data_parser_g_assign(parser, DATA_PARSER_ATTR_DBCONN_PTR,
acct_db_conn);
xassert(!meta->plugin.data_parser);
meta->plugin.data_parser = xstrdup(data_parser_get_plugin(parser));
dresp = data_new();
if (!data_parser_g_dump(parser, type, obj, obj_bytes, dresp) &&
(data_get_type(dresp) != DATA_TYPE_NULL)) {
serializer_flags_t sflags = SER_FLAGS_NONE;
if (data_parser_g_is_complex(parser))
sflags |= SER_FLAGS_COMPLEX;
serialize_g_data_to_string(&out, NULL, dresp, mime_type,
sflags);
}
if (out && out[0])
printf("%s\n", out);
else
debug("No output generated");
cleanup:
/*
* This is only called from the CLI just before exiting.
* Skip the explicit free here to improve responsiveness.
*/
#ifdef MEMORY_LEAK_DEBUG
xfree(out);
FREE_NULL_DATA(dresp);
FREE_NULL_DATA_PARSER(parser);
#endif
return rc;
}
extern data_parser_t *data_parser_cli_parser(const char *data_parser, void *arg)
{
char *default_data_parser = (slurm_conf.data_parser_parameters ?
slurm_conf.data_parser_parameters :
SLURM_DATA_PARSER_VERSION);
return data_parser_g_new(_on_error, _on_error, _on_error, arg, _on_warn,
_on_warn, _on_warn, arg,
(data_parser ? data_parser :
default_data_parser), NULL, false);
}
extern openapi_type_t data_parser_g_resolve_openapi_type(
data_parser_t *parser,
data_parser_type_t type,
const char *field)
{
const parse_funcs_t *funcs;
if (!parser)
return OPENAPI_TYPE_INVALID;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser);
xassert(plugins);
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->resolve_openapi_type(parser->arg, type, field);
}
extern const char *data_parser_g_resolve_type_string(data_parser_t *parser,
data_parser_type_t type)
{
const parse_funcs_t *funcs;
if (!parser)
return NULL;
funcs = plugins->functions[parser->plugin_offset];
xassert(plugins);
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->resolve_type_str(parser->arg, type);
}
extern int data_parser_g_increment_reference(data_parser_t *parser,
data_parser_type_t type,
void **references_ptr)
{
const parse_funcs_t *funcs;
if (!parser)
return EINVAL;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->inc_ref(parser->arg, type, references_ptr);
}
extern int data_parser_g_populate_schema(data_parser_t *parser,
data_parser_type_t type,
void **references_ptr, data_t *dst,
data_t *schemas)
{
const parse_funcs_t *funcs;
if (!parser)
return EINVAL;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->populate_schema(parser->arg, type, references_ptr, dst,
schemas);
}
extern int data_parser_g_populate_parameters(data_parser_t *parser,
data_parser_type_t parameter_type,
data_parser_type_t query_type,
void **references_ptr, data_t *dst,
data_t *schemas)
{
const parse_funcs_t *funcs;
if (!parser)
return EINVAL;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->populate_parameters(parser->arg, parameter_type,
query_type, references_ptr, dst,
schemas);
}
extern void data_parser_g_release_references(data_parser_t *parser,
void **references_ptr)
{
const parse_funcs_t *funcs;
if (!parser)
return;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->release_refs(parser->arg, references_ptr);
}
extern bool data_parser_g_is_complex(data_parser_t *parser)
{
const parse_funcs_t *funcs;
if (!parser)
return false;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->is_complex(parser->arg);
}
extern bool data_parser_g_is_deprecated(data_parser_t *parser)
{
const parse_funcs_t *funcs;
if (!parser)
return true;
funcs = plugins->functions[parser->plugin_offset];
xassert(parser->magic == PARSE_MAGIC);
xassert(parser->plugin_offset < plugins->count);
return funcs->is_deprecated(parser->arg);
}
extern int data_parser_g_dump_flags(data_parser_t *parser, data_t *dst)
{
const parse_funcs_t *funcs;
if (!parser)
return EINVAL;
xassert(data_get_type(dst));
xassert(parser->magic == PARSE_MAGIC);
xassert(plugins && (plugins->magic == PLUGINS_MAGIC));
xassert(parser->plugin_offset < plugins->count);
xassert(plugins->functions[parser->plugin_offset]);
funcs = plugins->functions[parser->plugin_offset];
return funcs->dump_flags(parser->arg, dst);
}