From 75f2669bf1b62b441002ac361e245254e9ad7330 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Fri, 12 Oct 2012 17:29:14 +0300 Subject: Implement sequence map. * doc/eclat.conf.5: Document sequence maps. * lib/Makefile.am: Add new files. * lib/libeclat.h (eclat_map_drv_seq): New extern. * lib/seqmap.c: New file. * src/eclat.c: Minor fixes. * tests/Makefile.am: Add new testcase. * tests/testsuite.at: Likewise. * tests/seqmap.at: New file. --- lib/Makefile.am | 1 + lib/libeclat.h | 2 +- lib/seqmap.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 lib/seqmap.c (limited to 'lib') diff --git a/lib/Makefile.am b/lib/Makefile.am index ede2b7b..7b2cb11 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -49,6 +49,7 @@ libeclat_a_SOURCES=\ qencode.c\ qfree.c\ reqsign.c\ + seqmap.c\ sha1.c\ sha1.h\ urlencode.c\ diff --git a/lib/libeclat.h b/lib/libeclat.h index 0843fb1..ee94345 100644 --- a/lib/libeclat.h +++ b/lib/libeclat.h @@ -155,4 +155,4 @@ extern struct eclat_map_drv eclat_map_drv_file; extern struct eclat_map_drv eclat_map_drv_gdbm; extern struct eclat_map_drv eclat_map_drv_ldap; extern struct eclat_map_drv eclat_map_drv_null; - +extern struct eclat_map_drv eclat_map_drv_seq; diff --git a/lib/seqmap.c b/lib/seqmap.c new file mode 100644 index 0000000..777bbd7 --- /dev/null +++ b/lib/seqmap.c @@ -0,0 +1,161 @@ +/* This file is part of Eclat. + Copyright (C) 2012 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, 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], 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 +}; + -- cgit v1.2.1