Save register type for TERMIDs and snippets.
[idzebra-moved-to-github.git] / util / snippet.c
1 /* $Id: snippet.c,v 1.3 2005-06-07 14:53:39 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 reg_type, int ord, const char *term)
51 {
52     zebra_snippets_append_match(l, seqno, reg_type, ord, term, 0);
53 }
54
55 void zebra_snippets_append_match(zebra_snippets *l,
56                                  zint seqno, int reg_type, 
57                                  int ord, const char *term, 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->reg_type = reg_type;
70     w->ord = ord;
71     w->term = nmem_strdup(l->nmem, term);
72     w->match = match;
73 }
74
75 zebra_snippet_word *zebra_snippets_list(zebra_snippets *l)
76 {
77     return l->front;
78 }
79
80 void zebra_snippets_log(zebra_snippets *l, int log_level)
81 {
82     zebra_snippet_word *w;
83     for (w = l->front; w; w = w->next)
84         yaz_log(log_level, "term=%s%s seqno=" ZINT_FORMAT " reg_type=%c "
85                 "ord=%d",
86                 w->term, (w->match ? "*" : ""), w->seqno, w->reg_type, w->ord);
87 }
88
89 zebra_snippets *zebra_snippets_window(zebra_snippets *doc, zebra_snippets *hit,
90                                       int window_size)
91 {
92     int ord = -1;
93
94     zebra_snippets *result = zebra_snippets_create();
95     if (window_size == 0)
96         window_size = 1000000;
97
98     while(1)
99     {
100         int window_start;
101         int reg_type;
102         zebra_snippet_word *hit_w, *doc_w;
103         int min_ord = 0; /* not set yet */
104         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
105             if (hit_w->ord > ord &&
106                 (min_ord == 0 || 
107                  (hit_w->ord < min_ord && hit_w->reg_type == reg_type)))
108             {
109                 min_ord = hit_w->ord;
110                 reg_type = hit_w->reg_type;
111             }
112         if (min_ord == 0)
113             break;
114         ord = min_ord;
115
116         int first_seq_no_best_window = 0;
117         int last_seq_no_best_window = 0;
118         int number_best_window = 0;
119
120         for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
121         {
122             if (hit_w->ord == ord)
123             {
124                 zebra_snippet_word *look_w = hit_w;
125                 int number_this = 0;
126                 int seq_no_last = 0;
127                 while (look_w && look_w->seqno < hit_w->seqno + window_size)
128                 {
129                     if (look_w->ord == ord && look_w->reg_type == reg_type)
130                     {
131                         seq_no_last = look_w->seqno;
132                         number_this++;
133                     }
134                     look_w = look_w->next;
135                 }
136                 if (number_this > number_best_window)
137                 {
138                     number_best_window = number_this;
139                     first_seq_no_best_window = hit_w->seqno;
140                     last_seq_no_best_window = seq_no_last;
141                 }
142             }
143         }
144         yaz_log(YLOG_DEBUG, "ord=%d", ord);
145         yaz_log(YLOG_DEBUG, "first_seq_no_best_window=%d", first_seq_no_best_window);
146         yaz_log(YLOG_DEBUG, "last_seq_no_best_window=%d", last_seq_no_best_window);
147         yaz_log(YLOG_DEBUG, "number_best_window=%d", number_best_window);
148
149         window_start = (first_seq_no_best_window + last_seq_no_best_window -
150                         window_size) / 2;
151         for (doc_w = zebra_snippets_list(doc); doc_w; doc_w = doc_w->next)
152             if (doc_w->ord == ord && doc_w->reg_type == reg_type
153                 && doc_w->seqno >= window_start
154                 && doc_w->seqno < window_start + window_size)
155             {
156                 int match = 0;
157                 for (hit_w = zebra_snippets_list(hit); hit_w; hit_w = hit_w->next)
158                 {
159                     if (hit_w->ord == ord && hit_w->reg_type == reg_type &&
160                         hit_w->seqno == doc_w->seqno)
161                         
162                     {
163                         match = 1;
164                         break;
165                     }
166                 }
167                 zebra_snippets_append_match(result, doc_w->seqno,
168                                             doc_w->reg_type, ord,
169                                             doc_w->term, match);
170             }
171     }
172     return result;
173 }
174