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