diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-12-15 20:57:55 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2012-12-15 20:57:55 +0200 |
commit | e60288d595ec405c5d416e5da54b516e65f8a8c5 (patch) | |
tree | d88aaa4352658be717b463ca60c05d85b41d1cd0 /lib/filemap.c | |
parent | 00110918072f77e0e5705e93ad91207f1bd0d873 (diff) | |
download | eclat-e60288d595ec405c5d416e5da54b516e65f8a8c5.tar.gz eclat-e60288d595ec405c5d416e5da54b516e65f8a8c5.tar.bz2 |
Implement direct and reverse map lookups.
Not all maps support reverse lookups generically (for
example, gdbm does not), therefore introduce a new
"bidi" (bi-directional) map, which is a compound of
two maps, each one used for a particular lookup direction.
* lib/Makefile.am (maps): List all maps here.
* lib/bidimap.c: New file. Implementation of a
bi-directional map.
* lib/filemap.c: Update to the changes in API.
Implement reverse lookup.
* lib/gdbmmap.c: Update to the changes in API.
* lib/nullmap.c: Likewise.
* lib/seqmap.c: Likewise.
* lib/ldapmap.c: Update to the changes in API.
Implement reverse lookup.
New configuration keywords: reverse-filter, reverse-attr.
* lib/libeclat.h (eclat_map_drv) <map_get>: Change signature,
take search direction as a new argument.
(eclat_map_get): Likewise.
(eclat_map) <eclat_map_bad_dir>: New status code.
(MAP_DIR, MAP_REV): New macros.
(eclat_map_name_split): New function.
(eclat_map_drv_bidi): New extern.
* lib/map.c (eclat_map_get): Change signature,
take search direction as a new argument.
Pass new keyword to the "key" translation: "dir".
(eclat_map_strerror): Handle new status code.
(eclat_map_name_split): New function.
* src/eclat.c (main): Register eclat_map_drv_bidi.
* src/util.c (translate_ids): Use eclat_map_name_split
to obtain direction code from the map name.
(translate_resource_ids): Use direct lookups.
* tests/Makefile.am: Add new testcases.
* tests/testsuite.at: Likewise.
* tests/bidimap.at: New testcase.
* tests/filemap.at: Test reverse lookups.
Diffstat (limited to 'lib/filemap.c')
-rw-r--r-- | lib/filemap.c | 66 |
1 files changed, 65 insertions, 1 deletions
diff --git a/lib/filemap.c b/lib/filemap.c index c43ba35..e797169 100644 --- a/lib/filemap.c +++ b/lib/filemap.c @@ -111,7 +111,7 @@ skipline(FILE *fp) } static int -filemap_get(int dbg, void *data, const char *key, char **return_value) +filemap_get_0(int dbg, void *data, const char *key, char **return_value) { struct filemap *filemap = data; FILE *fp = filemap->fp; @@ -161,6 +161,70 @@ filemap_get(int dbg, void *data, const char *key, char **return_value) return rc; } +static int +filemap_get_1(int dbg, void *data, const char *key, char **return_value) +{ + struct filemap *filemap = data; + FILE *fp = filemap->fp; + int line = 0; + int rc, c; + const char *p; + size_t len; + + rewind(fp); + while ((c = getc(fp)) != EOF) { + line++; + while (c != EOF && (c == ' ' || c == '\t')) + c = getc(fp); + if (c == '\n') + continue; + if (c == '#') { + skipline(fp); + continue; + } + if (c == EOF) + break; + for (len = 0; c != EOF && c != ':'; len++) + c = getc(fp); + if (c == EOF) + break; + if (c == '\n') + continue; + if (c == ':') { + for (p = key, c = getc(fp), len++; + c != EOF && c != '\n' && *p == c; + p++, len++, c = getc(fp)); + if (c == EOF || c == '\n') + break; + skipline(fp); + } + } + + if (c == '\n') { + struct grecs_txtacc *acc; + + debug(dbg, 2, ("%s:%d: found key", filemap->name, line)); + fseek(fp, - (len + 1), SEEK_CUR); + acc = grecs_txtacc_create(); + while ((c = getc(fp)) != EOF && c != ':') + grecs_txtacc_grow_char(acc, c); + grecs_txtacc_grow_char(acc, 0); + *return_value = grecs_txtacc_finish(acc, 1); + grecs_txtacc_free(acc); + rc = eclat_map_ok; + } else + rc = eclat_map_not_found; + + return rc; +} + +static int +filemap_get(int dbg, int dir, void *data, const char *key, char **return_value) +{ + return (dir ? filemap_get_1 : filemap_get_0)(dbg, data, key, + return_value); +} + struct eclat_map_drv eclat_map_drv_file = { "file", filemap_config, |