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