2007.
[idzebra-moved-to-github.git] / util / snippet.c
1 /* $Id: snippet.c,v 1.12 2007-01-15 15:10:26 adam Exp $
2    Copyright (C) 1995-2007
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 this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20
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(void)
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     if (window_size == 0)
94         window_size = 1000000;
95
96     while(1)
97     {
98         zint window_start;
99         zint first_seq_no_best_window = 0;
100         zint last_seq_no_best_window = 0;
101         int number_best_window = 0;
102         zebra_snippet_word *hit_w, *doc_w;
103         int min_ord = 0; /* not set yet */
104
105         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
106             if (hit_w->ord > ord &&
107                 (min_ord == 0 || hit_w->ord < min_ord))
108             {
109                 min_ord = hit_w->ord;
110             }
111         if (min_ord == 0)
112             break;
113         ord = min_ord;
114
115         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
116         {
117             if (hit_w->ord == ord)
118             {
119                 zebra_snippet_word *look_w = hit_w;
120                 int number_this = 0;
121                 zint seq_no_last = 0;
122                 while (look_w && look_w->seqno < hit_w->seqno + window_size)
123                 {
124                     if (look_w->ord == ord)
125                     {
126                         seq_no_last = look_w->seqno;
127                         number_this++;
128                     }
129                     look_w = look_w->next;
130                 }
131                 if (number_this > number_best_window)
132                 {
133                     number_best_window = number_this;
134                     first_seq_no_best_window = hit_w->seqno;
135                     last_seq_no_best_window = seq_no_last;
136                 }
137             }
138         }
139         yaz_log(YLOG_DEBUG, "ord=%d", ord);
140         yaz_log(YLOG_DEBUG, "first_seq_no_best_window=" ZINT_FORMAT,
141                 first_seq_no_best_window);
142         yaz_log(YLOG_DEBUG, "last_seq_no_best_window=" ZINT_FORMAT,
143                 last_seq_no_best_window);
144         yaz_log(YLOG_DEBUG, "number_best_window=%d", number_best_window);
145
146         window_start = (first_seq_no_best_window + last_seq_no_best_window -
147                         window_size) / 2;
148         for (doc_w = zebra_snippets_list(doc); doc_w; doc_w = doc_w->next)
149             if (doc_w->ord == ord
150                 && doc_w->seqno >= window_start
151                 && doc_w->seqno < window_start + window_size)
152             {
153                 int match = 0;
154                 for (hit_w = zebra_snippets_list(hit); hit_w;
155                      hit_w = hit_w->next)
156                 {
157                     if (hit_w->ord == ord && hit_w->seqno == doc_w->seqno)
158                         
159                     {
160                         match = 1;
161                         break;
162                     }
163                 }
164                 zebra_snippets_append_match(result, doc_w->seqno,
165                                             ord, doc_w->term, match);
166             }
167     }
168     return result;
169 }
170                          
171 /*
172  * Local variables:
173  * c-basic-offset: 4
174  * indent-tabs-mode: nil
175  * End:
176  * vim: shiftwidth=4 tabstop=8 expandtab
177  */
178