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