Implemented automatic EXPLAIN database maintenance.
[idzebra-moved-to-github.git] / recctrl / rectext.c
1 /*
2  * Copyright (C) 1994-1998, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: rectext.c,v $
7  * Revision 1.8  1998-05-20 10:12:27  adam
8  * Implemented automatic EXPLAIN database maintenance.
9  * Modified Zebra to work with ASN.1 compiled version of YAZ.
10  *
11  * Revision 1.7  1998/03/11 11:19:05  adam
12  * Changed the way sequence numbers are generated.
13  *
14  * Revision 1.6  1998/02/10 12:03:06  adam
15  * Implemented Sort.
16  *
17  * Revision 1.5  1997/10/27 14:33:06  adam
18  * Moved towards generic character mapping depending on "structure"
19  * field in abstract syntax file. Fixed a few memory leaks. Fixed
20  * bug with negative integers when doing searches with relational
21  * operators.
22  *
23  * Revision 1.4  1996/11/04 14:09:16  adam
24  * Minor changes.
25  *
26  * Revision 1.3  1996/11/01 09:00:33  adam
27  * This simple "text" format now supports element specs B and M.
28  *
29  * Revision 1.2  1996/10/29 14:02:45  adam
30  * Uses buffered read to speed up things.
31  *
32  * Revision 1.1  1996/10/11 10:57:28  adam
33  * New module recctrl. Used to manage records (extract/retrieval).
34  *
35  * Revision 1.7  1996/01/17 14:57:55  adam
36  * Prototype changed for reader functions in extract/retrieve. File
37  *  is identified by 'void *' instead of 'int.
38  *
39  * Revision 1.6  1995/10/10  13:59:24  adam
40  * Function rset_open changed its wflag parameter to general flags.
41  *
42  * Revision 1.5  1995/10/02  16:24:39  adam
43  * Use attribute actually used in search requests.
44  *
45  * Revision 1.4  1995/10/02  15:42:55  adam
46  * Extract uses file descriptors instead of FILE pointers.
47  *
48  * Revision 1.3  1995/09/28  09:19:45  adam
49  * xfree/xmalloc used everywhere.
50  * Extract/retrieve method seems to work for text records.
51  *
52  * Revision 1.2  1995/09/15  14:45:21  adam
53  * Retrieve control.
54  * Work on truncation.
55  *
56  * Revision 1.1  1995/09/14  07:48:25  adam
57  * Record control management.
58  *
59  */
60 #include <stdio.h>
61 #include <assert.h>
62 #include <ctype.h>
63
64 #include <zebrautl.h>
65 #include "rectext.h"
66
67 static void text_init (void)
68 {
69 }
70
71 struct buf_info {
72     struct recExtractCtrl *p;
73     char *buf;
74     int offset;
75     int max;
76 };
77
78 struct buf_info *buf_open (struct recExtractCtrl *p)
79 {
80     struct buf_info *fi = xmalloc (sizeof(*fi));
81
82     fi->p = p;
83     fi->buf = xmalloc (4096);
84     fi->offset = 1;
85     fi->max = 1;
86     return fi;
87 }
88
89 int buf_read (struct buf_info *fi, char *dst)
90 {
91     if (fi->offset >= fi->max)
92     {
93         if (fi->max <= 0)
94             return 0;
95         fi->max = (*fi->p->readf)(fi->p->fh, fi->buf, 4096);
96         fi->offset = 0;
97         if (fi->max <= 0)
98             return 0;
99     }
100     *dst = fi->buf[(fi->offset)++];
101     return 1;
102 }
103
104 void buf_close (struct buf_info *fi)
105 {
106     xfree (fi->buf);
107     xfree (fi);
108 }
109
110 static int text_extract (struct recExtractCtrl *p)
111 {
112     char w[512];
113     RecWord recWord;
114     int r;
115     struct buf_info *fi = buf_open (p);
116
117     (*p->init)(p, &recWord);
118     recWord.reg_type = 'w';
119     do
120     {
121         int i = 0;
122             
123         r = buf_read (fi, w);
124         while (r > 0 && i < 511 && w[i] != '\n' && w[i] != '\r')
125         {
126             i++;
127             r = buf_read (fi, w + i);
128         }
129         if (i)
130         {
131             recWord.string = w;
132             recWord.length = i;
133             (*p->addWord)(&recWord);
134         }
135     } while (r > 0);
136     buf_close (fi);
137     return 0;
138 }
139
140 static int text_retrieve (struct recRetrieveCtrl *p)
141 {
142     int r, text_ptr = 0;
143     static char *text_buf = NULL;
144     static int text_size = 0;
145     int start_flag = 1;
146     const char *elementSetName = NULL;
147     int no_lines = 0;
148
149     if (p->comp && p->comp->which == Z_RecordComp_simple &&
150         p->comp->u.simple->which == Z_ElementSetNames_generic)
151         elementSetName = p->comp->u.simple->u.generic;
152
153     while (1)
154     {
155         if (text_ptr + 4096 >= text_size)
156         {
157             char *nb;
158
159             text_size = 2*text_size + 8192;
160             nb = xmalloc (text_size);
161             if (text_buf)
162             {
163                 memcpy (nb, text_buf, text_ptr);
164                 xfree (text_buf);
165             }
166             text_buf = nb;
167         }
168         if (start_flag)
169         {
170             start_flag = 0;
171             if (p->score >= 0)
172             {
173                 sprintf (text_buf, "Rank: %d\n", p->score);
174                 text_ptr = strlen(text_buf);
175             }
176             sprintf (text_buf + text_ptr, "Local Number: %d\n", p->localno);
177             text_ptr = strlen(text_buf);
178         }
179         r = (*p->readf)(p->fh, text_buf + text_ptr, 4096);
180         if (r <= 0)
181             break;
182         text_ptr += r;
183     }
184     text_buf[text_ptr] = '\0';
185     if (elementSetName)
186     {
187         if (!strcmp (elementSetName, "B"))
188             no_lines = 4;
189         if (!strcmp (elementSetName, "M"))
190             no_lines = 20;
191     }
192     if (no_lines)
193     {
194         char *p = text_buf;
195         int i = 0;
196
197         while (++i <= no_lines && (p = strchr (p, '\n')))
198             p++;
199         if (p)
200         {
201             p[1] = '\0';
202             text_ptr = p-text_buf;
203         }
204     }
205     p->output_format = VAL_SUTRS;
206     p->rec_buf = text_buf;
207     p->rec_len = text_ptr; 
208     return 0;
209 }
210
211 static struct recType text_type = {
212     "text",
213     text_init,
214     text_extract,
215     text_retrieve
216 };
217
218 RecType recTypeText = &text_type;