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