From: Heikki Levanto Date: Tue, 9 Apr 2002 15:24:13 +0000 (+0000) Subject: rsbetween.[ch] - new result set type X-Git-Tag: CHANGELOG X-Git-Url: http://jsfdemo.indexdata.com/cgi-bin?a=commitdiff_plain;h=71e41c3f5146a6f783fbae7e59776bcdd4e3c4c8;p=idzebra-moved-to-github.git rsbetween.[ch] - new result set type --- diff --git a/include/Makefile.am b/include/Makefile.am index 52baf65..2e9ccdd 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -2,4 +2,5 @@ noinst_HEADERS = bfile.h bset.h charmap.h dfa.h dict.h direntz.h isam.h \ isamc.h isamd.h isams.h mfile.h passwddb.h recctrl.h res.h rsbool.h rset.h \ rsisam.h rsisamc.h rsisams.h rsisamd.h rsm_or.h rsnull.h rstemp.h set.h \ - sortidx.h str.h zebra-lock.h zebramap.h zebrautl.h zebraver.h isamb.h + sortidx.h str.h zebra-lock.h zebramap.h zebrautl.h zebraver.h isamb.h \ + rsbetween.h diff --git a/include/rsbetween.h b/include/rsbetween.h new file mode 100644 index 0000000..39a5e50 --- /dev/null +++ b/include/rsbetween.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 1994-2002, Index Data + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss, Heikki Levanto + * + * $Id: rsbetween.h,v 1.1 2002-04-09 15:24:13 heikki Exp $ + * + * Result set that returns anything in between two things, + * typically start-tag, stuff, end-tag. + * + */ + +#ifndef RSET_BETWEEN_H +#define RSET_BETWEEN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct rset_control *rset_kind_between; + +typedef struct rset_between_parms +{ + int key_size; + RSET rset_l; + RSET rset_m; + RSET rset_r; + int (*cmp)(const void *p1, const void *p2); +} rset_between_parms; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/rset/Makefile.am b/rset/Makefile.am index e7fb2a5..f35adce 100644 --- a/rset/Makefile.am +++ b/rset/Makefile.am @@ -1,7 +1,7 @@ -## $Id: Makefile.am,v 1.2 2001-01-16 16:56:15 heikki Exp $ +## $Id: Makefile.am,v 1.3 2002-04-09 15:24:13 heikki Exp $ noinst_LIBRARIES = librset.a -librset_a_SOURCES = rset.c rstemp.c rsisam.c rsnull.c rsbool.c \ +librset_a_SOURCES = rset.c rstemp.c rsisam.c rsnull.c rsbool.c rsbetween.c \ rsisamc.c rsm_or.c rsisams.c rsisamd.c INCLUDES = -I$(srcdir)/../include @YAZINC@ diff --git a/rset/rsbetween.c b/rset/rsbetween.c new file mode 100644 index 0000000..17b26b5 --- /dev/null +++ b/rset/rsbetween.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 1994-2002, Index Data + * All rights reserved. + * Sebastian Hammer, Adam Dickmeiss, Heikki Levanto + * + * $Id: rsbetween.c,v 1.1 2002-04-09 15:24:13 heikki Exp $ + */ + +#include +#include +#include +#include + +#include +#include + +static void *r_create(RSET ct, const struct rset_control *sel, void *parms); +static RSFD r_open (RSET ct, int flag); +static void r_close (RSFD rfd); +static void r_delete (RSET ct); +static void r_rewind (RSFD rfd); +static int r_count (RSET ct); +static int r_read (RSFD rfd, void *buf, int *term_index); +static int r_write (RSFD rfd, const void *buf); + +static const struct rset_control control_between = +{ + "between", + r_create, + r_open, + r_close, + r_delete, + r_rewind, + r_count, + r_read, + r_write, +}; + + +const struct rset_control *rset_kind_between = &control_between; + +struct rset_between_info { + int key_size; + RSET rset_l; + RSET rset_m; + RSET rset_r; + int term_index_s; + int (*cmp)(const void *p1, const void *p2); + struct rset_between_rfd *rfd_list; +}; + +struct rset_between_rfd { + RSFD rfd_l; + RSFD rfd_m; + RSFD rfd_r; + int more_l; + int more_m; + int more_r; + int term_index_l; + int term_index_m; + int term_index_r; + void *buf_l; + void *buf_m; + void *buf_r; + int level; + struct rset_between_rfd *next; + struct rset_between_info *info; +}; + +static void *r_create (RSET ct, const struct rset_control *sel, void *parms) +{ + rset_between_parms *between_parms = (rset_between_parms *) parms; + struct rset_between_info *info; + + info = (struct rset_between_info *) xmalloc (sizeof(*info)); + info->key_size = between_parms->key_size; + info->rset_l = between_parms->rset_l; + info->rset_m = between_parms->rset_m; + info->rset_r = between_parms->rset_r; + if (rset_is_volatile(info->rset_l) || + rset_is_volatile(info->rset_m) || + rset_is_volatile(info->rset_r)) + ct->flags |= RSET_FLAG_VOLATILE; + info->cmp = between_parms->cmp; + info->rfd_list = NULL; + + info->term_index_s = info->rset_l->no_rset_terms; + ct->no_rset_terms = + info->rset_l->no_rset_terms + + info->rset_m->no_rset_terms + + info->rset_r->no_rset_terms; + ct->rset_terms = (RSET_TERM *) + xmalloc (sizeof (*ct->rset_terms) * ct->no_rset_terms); + + memcpy (ct->rset_terms, info->rset_l->rset_terms, + info->rset_l->no_rset_terms * sizeof(*ct->rset_terms)); + memcpy (ct->rset_terms + info->rset_l->no_rset_terms, + info->rset_m->rset_terms, + info->rset_m->no_rset_terms * sizeof(*ct->rset_terms)); + memcpy (ct->rset_terms + info->rset_l->no_rset_terms + + info->rset_m->no_rset_terms, + info->rset_r->rset_terms, + info->rset_r->no_rset_terms * sizeof(*ct->rset_terms)); + return info; +} + +static RSFD r_open (RSET ct, int flag) +{ + struct rset_between_info *info = (struct rset_between_info *) ct->buf; + struct rset_between_rfd *rfd; + + if (flag & RSETF_WRITE) + { + logf (LOG_FATAL, "between set type is read-only"); + return NULL; + } + rfd = (struct rset_between_rfd *) xmalloc (sizeof(*rfd)); + rfd->next = info->rfd_list; + info->rfd_list = rfd; + rfd->info = info; + + rfd->buf_l = xmalloc (info->key_size); + rfd->buf_m = xmalloc (info->key_size); + rfd->buf_r = xmalloc (info->key_size); + rfd->rfd_l = rset_open (info->rset_l, RSETF_READ); + rfd->rfd_m = rset_open (info->rset_m, RSETF_READ); + rfd->rfd_r = rset_open (info->rset_r, RSETF_READ); + rfd->more_l = rset_read (info->rset_l, rfd->rfd_l, rfd->buf_l, + &rfd->term_index_l); + rfd->more_m = rset_read (info->rset_m, rfd->rfd_m, rfd->buf_m, + &rfd->term_index_m); + rfd->more_r = rset_read (info->rset_r, rfd->rfd_r, rfd->buf_r, + &rfd->term_index_r); + rfd->level=0; + return rfd; +} + +static void r_close (RSFD rfd) +{ + struct rset_between_info *info = ((struct rset_between_rfd*)rfd)->info; + struct rset_between_rfd **rfdp; + + for (rfdp = &info->rfd_list; *rfdp; rfdp = &(*rfdp)->next) + if (*rfdp == rfd) + { + xfree ((*rfdp)->buf_l); + xfree ((*rfdp)->buf_m); + xfree ((*rfdp)->buf_r); + rset_close (info->rset_l, (*rfdp)->rfd_l); + rset_close (info->rset_m, (*rfdp)->rfd_m); + rset_close (info->rset_r, (*rfdp)->rfd_r); + *rfdp = (*rfdp)->next; + xfree (rfd); + return; + } + logf (LOG_FATAL, "r_close but no rfd match!"); + assert (0); +} + +static void r_delete (RSET ct) +{ + struct rset_between_info *info = (struct rset_between_info *) ct->buf; + + assert (info->rfd_list == NULL); + xfree (ct->rset_terms); + rset_delete (info->rset_l); + rset_delete (info->rset_m); + rset_delete (info->rset_r); + xfree (info); +} + +static void r_rewind (RSFD rfd) +{ + struct rset_between_info *info = ((struct rset_between_rfd*)rfd)->info; + struct rset_between_rfd *p = (struct rset_between_rfd *) rfd; + + logf (LOG_DEBUG, "rsbetween_rewind"); + rset_rewind (info->rset_l, p->rfd_l); + rset_rewind (info->rset_m, p->rfd_m); + rset_rewind (info->rset_r, p->rfd_r); + p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l, &p->term_index_l); + p->more_m = rset_read (info->rset_m, p->rfd_m, p->buf_m, &p->term_index_m); + p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r, &p->term_index_r); + p->level=0; +} + +static int r_count (RSET ct) +{ + return 0; +} + +static int r_read (RSFD rfd, void *buf, int *term_index) +{ + struct rset_between_rfd *p = (struct rset_between_rfd *) rfd; + struct rset_between_info *info = p->info; + int cmp_l; + int cmp_r; + + + while (p->more_m) + { + + /* forward L until past m, count levels, note rec boundaries */ + if (p->more_l) + cmp_l= (*info->cmp)(p->buf_l, p->buf_m); + else + cmp_l=2; /* past this record */ + while (cmp_l < 0) /* l before m */ + { + if (cmp_l == -2) + p->level=0; /* earlier record */ + if (cmp_l == -1) + p->level++; /* relevant start tag */ + if (p->more_l) + { + p->more_l = rset_read (info->rset_l, p->rfd_l, p->buf_l, + &p->term_index_l); + cmp_l= (*info->cmp)(p->buf_l, p->buf_m); + } + else + cmp_l=2; + } /* forward L */ + + /* forward R until past m, count levels */ + if (p->more_r) + cmp_r= (*info->cmp)(p->buf_r, p->buf_m); + else + cmp_r=2; + while (cmp_r < 0) /* r before m */ + { + /* -2, earlier record, doesn't matter */ + if (cmp_r == -1) + p->level--; /* relevant end tag */ + if (p->more_r) + { + p->more_r = rset_read (info->rset_r, p->rfd_r, p->buf_r, + &p->term_index_r); + cmp_r= (*info->cmp)(p->buf_r, p->buf_m); + } + else + cmp_r=2; + } /* forward R */ + + if ( ( p->level <= 0 ) && ! p->more_l) + return 0; /* no more start tags, nothing more to find */ + + if ( p->level > 0) /* within a tag pair (or deeper) */ + { + memcpy (buf, p->buf_m, info->key_size); + *term_index = p->term_index_m; + return 1; + } + else + if ( ! p->more_l ) /* not in data, no more starts */ + return 0; /* ergo, nothing can be found. stop scanning */ + + p->more_m = rset_read (info->rset_m, p->rfd_m, p->buf_m, + &p->term_index_m); + } /* while more_m */ + + return 0; /* no more data possible */ + +} /* r_read */ + + +static int r_write (RSFD rfd, const void *buf) +{ + logf (LOG_FATAL, "between set type is read-only"); + return -1; +} +