Added snippet utilities and snippet window implementation.
[idzebra-moved-to-github.git] / util / snippet.c
1 /* $Id: snippet.c,v 1.1 2005-06-07 11:36:43 adam Exp $
2    Copyright (C) 1995-2005
3    Index Data ApS
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23 #include <stddef.h>
24 #include <yaz/nmem.h>
25 #include <yaz/log.h>
26 #include <idzebra/snippet.h>
27
28 struct zebra_snippets {
29     NMEM nmem;
30     zebra_snippet_word *front;
31     zebra_snippet_word *tail;
32 };
33
34 zebra_snippets *zebra_snippets_create()
35 {
36     NMEM nmem = nmem_create();
37     zebra_snippets *l = nmem_malloc(nmem, sizeof(*l));
38     l->nmem = nmem;
39     l->front = l->tail = 0;
40     return l;
41 }
42
43 void zebra_snippets_destroy(zebra_snippets *l)
44 {
45     if (l)
46         nmem_destroy(l->nmem);
47 }
48
49 void zebra_snippets_append(zebra_snippets *l,
50                            zint seqno, int ord, const char *term)
51 {
52     zebra_snippets_append_match(l, seqno, ord, term, 0);
53 }
54
55 void zebra_snippets_append_match(zebra_snippets *l,
56                                  zint seqno, int ord, const char *term,
57                                  int match)
58 {
59     struct zebra_snippet_word *w = nmem_malloc(l->nmem, sizeof(*w));
60
61     w->next = 0;
62     if (l->tail)
63         l->tail->next = w;
64     else
65         l->front = w;
66     l->tail = w;
67
68     w->seqno = seqno;
69     w->ord = ord;
70     w->term = nmem_strdup(l->nmem, term);
71     w->match = match;
72 }
73
74 zebra_snippet_word *zebra_snippets_list(zebra_snippets *l)
75 {
76     return l->front;
77 }
78
79 void zebra_snippets_log(zebra_snippets *l, int log_level)
80 {
81     zebra_snippet_word *w;
82     for (w = l->front; w; w = w->next)
83         yaz_log(log_level, "term=%s%s seqno=" ZINT_FORMAT " ord=%d",
84                 w->term, (w->match ? "*" : ""), w->seqno, w->ord);
85 }
86
87 zebra_snippets *zebra_snippets_window(zebra_snippets *doc, zebra_snippets *hit,
88                                       int window_size)
89 {
90     int ord = -1;
91
92     zebra_snippets *result = zebra_snippets_create();
93
94     while(1)
95     {
96         int window_start;
97         zebra_snippet_word *hit_w, *doc_w;
98         int min_ord = 0; /* not set yet */
99         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
100             if (hit_w->ord > ord &&
101                 (min_ord == 0 || hit_w->ord < min_ord))
102                 min_ord = hit_w->ord;
103         if (min_ord == 0)
104             break;
105         ord = min_ord;
106
107         int first_seq_no_best_window = 0;
108         int last_seq_no_best_window = 0;
109         int number_best_window = 0;
110
111         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
112         {
113             if (hit_w->ord == ord)
114             {
115                 zebra_snippet_word *look_w = hit_w;
116                 int number_this = 0;
117                 int seq_no_last = 0;
118                 while (look_w && look_w->seqno < hit_w->seqno + window_size)
119                 {
120                     if (look_w->ord == ord)
121                     {
122                         seq_no_last = look_w->seqno;
123                         number_this++;
124                     }
125                     look_w = look_w->next;
126                 }
127                 if (number_this > number_best_window)
128                 {
129                     number_best_window = number_this;
130                     first_seq_no_best_window = hit_w->seqno;
131                     last_seq_no_best_window = seq_no_last;
132                 }
133             }
134         }
135         yaz_log(YLOG_LOG, "ord=%d", ord);
136         yaz_log(YLOG_LOG, "first_seq_no_best_window=%d", first_seq_no_best_window);
137         yaz_log(YLOG_LOG, "last_seq_no_best_window=%d", last_seq_no_best_window);
138         yaz_log(YLOG_LOG, "number_best_window=%d", number_best_window);
139
140         window_start = (first_seq_no_best_window + last_seq_no_best_window -
141                         window_size) / 2;
142         for (doc_w = zebra_snippets_list(doc); doc_w; doc_w = doc_w->next)
143             if (doc_w->ord == ord 
144                 && doc_w->seqno >= window_start
145                 && doc_w->seqno < window_start + window_size)
146             {
147                 int match = 0;
148                 for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
149                 {
150                     if (hit_w->ord == ord && hit_w->seqno == doc_w->seqno)
151                         
152                     {
153                         match = 1;
154                         break;
155                     }
156                 }
157                 zebra_snippets_append_match(result, doc_w->seqno, ord,
158                                             doc_w->term, match);
159             }
160     }
161     return result;
162 }
163