/* This file is part of Eclat.
Copyright (C) 2012-2014 Sergey Poznyakoff.
Eclat 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 3, or (at your option)
any later version.
Eclat 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 Eclat. If not, see . */
#include "libeclat.h"
#include
struct seqmap {
struct grecs_list *namelist;
size_t nmaps;
struct eclat_map **maps;
};
static struct grecs_keyword seqmap_kw[] = {
{ "type", "'sequence", "Set sequence map type", grecs_type_null },
{ "key", "", "key expression", grecs_type_null },
{ "sequence", "arg", "list of maps to use",
grecs_type_string, GRECS_LIST,
NULL, offsetof(struct seqmap, namelist) },
{ NULL }
};
static void
seqmap_confhelp()
{
static struct grecs_keyword seqmap_top[] = {
{ "map", "name: string",
"Configuration for a sequence map",
grecs_type_section, GRECS_INAC, NULL, 0, NULL, NULL,
seqmap_kw },
{ NULL }
};
grecs_print_statement_array(seqmap_top, 1, 0, stdout);
}
static void
seqmap_free(int dbg, void *data)
{
struct seqmap *seqmap = data;
grecs_list_free(seqmap->namelist);
if (seqmap->maps) {
#if 0
size_t i;
/* FIXME: Uncomment this when reference
counters are implemented */
for (i = 0; i < seqmap->nmaps; i++)
if (seqmap->maps[i])
eclat_map_free(seqmap->maps[i]);
#endif
free(seqmap->maps);
}
free(seqmap);
}
static int
seqmap_config(int dbg, struct grecs_node *node, void *data)
{
struct seqmap *seqmap, **return_seqmap = data;
int i;
seqmap = grecs_malloc(sizeof(*seqmap));
for (i = 0; seqmap_kw[i].ident; i++)
seqmap_kw[i].varptr = seqmap;
if (grecs_tree_process(node->down, seqmap_kw)) {
seqmap_free(dbg, seqmap);
return eclat_map_failure;
}
if (!seqmap->namelist ||
(seqmap->nmaps = grecs_list_size(seqmap->namelist)) == 0) {
grecs_error(&node->locus, 0, "sequence empty");
seqmap_free(dbg, seqmap);
return eclat_map_failure;
}
seqmap->maps = grecs_calloc(seqmap->nmaps, sizeof(seqmap->maps[0]));
*return_seqmap = seqmap;
return eclat_map_ok;
}
static int
seqmap_open(int dbg, void *data)
{
struct seqmap *seqmap = data;
struct grecs_list_entry *ep;
size_t i;
int rc;
for (ep = seqmap->namelist->head, i = 0; ep; ep = ep->next, i++) {
struct eclat_map *map;
map = eclat_map_lookup(ep->data);
if (!map) {
err("no such map: %s", ep->data);
return eclat_map_failure;
}
if ((rc = eclat_map_open(map)) != eclat_map_ok)
return rc;
seqmap->maps[i] = map;
}
return eclat_map_ok;
}
static int
seqmap_close(int dbg, void *data)
{
struct seqmap *seqmap = data;
size_t i;
for (i = 0; i < seqmap->nmaps; i++) {
if (seqmap->maps[i])
eclat_map_close(seqmap->maps[i]);
}
return eclat_map_ok;
}
static int
seqmap_get(int dbg, int dir, void *data, const char *key, char **return_value)
{
struct seqmap *seqmap = data;
size_t i;
char *p = grecs_strdup(key);
char *v;
for (i = 0; i < seqmap->nmaps; i++) {
int rc = eclat_map_get(seqmap->maps[i], dir, p, &v);
free(p);
if (rc != eclat_map_ok) {
debug(dbg, 1, ("map %s returned %s",
seqmap->maps[i]->name,
eclat_map_strerror(rc)));
return rc;
}
p = v;
}
*return_value = v;
return eclat_map_ok;
}
struct eclat_map_drv eclat_map_drv_seq = {
"sequence",
seqmap_config,
seqmap_open,
seqmap_close,
seqmap_get,
seqmap_free,
seqmap_confhelp
};