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