1*89a07cf8Schristos /* $NetBSD: linear.cpp,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $ */
2*89a07cf8Schristos
3*89a07cf8Schristos // -*- C++ -*-
4*89a07cf8Schristos /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
5*89a07cf8Schristos Free Software Foundation, Inc.
6*89a07cf8Schristos Written by James Clark (jjc@jclark.com)
7*89a07cf8Schristos
8*89a07cf8Schristos This file is part of groff.
9*89a07cf8Schristos
10*89a07cf8Schristos groff is free software; you can redistribute it and/or modify it under
11*89a07cf8Schristos the terms of the GNU General Public License as published by the Free
12*89a07cf8Schristos Software Foundation; either version 2, or (at your option) any later
13*89a07cf8Schristos version.
14*89a07cf8Schristos
15*89a07cf8Schristos groff is distributed in the hope that it will be useful, but WITHOUT ANY
16*89a07cf8Schristos WARRANTY; without even the implied warranty of MERCHANTABILITY or
17*89a07cf8Schristos FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18*89a07cf8Schristos for more details.
19*89a07cf8Schristos
20*89a07cf8Schristos You should have received a copy of the GNU General Public License along
21*89a07cf8Schristos with groff; see the file COPYING. If not, write to the Free Software
22*89a07cf8Schristos Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
23*89a07cf8Schristos
24*89a07cf8Schristos #include "lib.h"
25*89a07cf8Schristos
26*89a07cf8Schristos #include <stdlib.h>
27*89a07cf8Schristos #include <assert.h>
28*89a07cf8Schristos #include <errno.h>
29*89a07cf8Schristos
30*89a07cf8Schristos #include "posix.h"
31*89a07cf8Schristos #include "errarg.h"
32*89a07cf8Schristos #include "error.h"
33*89a07cf8Schristos #include "cset.h"
34*89a07cf8Schristos #include "cmap.h"
35*89a07cf8Schristos #include "nonposix.h"
36*89a07cf8Schristos
37*89a07cf8Schristos #include "refid.h"
38*89a07cf8Schristos #include "search.h"
39*89a07cf8Schristos
40*89a07cf8Schristos class file_buffer {
41*89a07cf8Schristos char *buffer;
42*89a07cf8Schristos char *bufend;
43*89a07cf8Schristos public:
44*89a07cf8Schristos file_buffer();
45*89a07cf8Schristos ~file_buffer();
46*89a07cf8Schristos int load(int fd, const char *filename);
47*89a07cf8Schristos const char *get_start() const;
48*89a07cf8Schristos const char *get_end() const;
49*89a07cf8Schristos };
50*89a07cf8Schristos
51*89a07cf8Schristos typedef unsigned char uchar;
52*89a07cf8Schristos
53*89a07cf8Schristos static uchar map[256];
54*89a07cf8Schristos static uchar inv_map[256][3];
55*89a07cf8Schristos
56*89a07cf8Schristos struct map_init {
57*89a07cf8Schristos map_init();
58*89a07cf8Schristos };
59*89a07cf8Schristos
60*89a07cf8Schristos static map_init the_map_init;
61*89a07cf8Schristos
map_init()62*89a07cf8Schristos map_init::map_init()
63*89a07cf8Schristos {
64*89a07cf8Schristos int i;
65*89a07cf8Schristos for (i = 0; i < 256; i++)
66*89a07cf8Schristos map[i] = csalnum(i) ? cmlower(i) : '\0';
67*89a07cf8Schristos for (i = 0; i < 256; i++) {
68*89a07cf8Schristos if (cslower(i)) {
69*89a07cf8Schristos inv_map[i][0] = i;
70*89a07cf8Schristos inv_map[i][1] = cmupper(i);
71*89a07cf8Schristos inv_map[i][2] = '\0';
72*89a07cf8Schristos }
73*89a07cf8Schristos else if (csdigit(i)) {
74*89a07cf8Schristos inv_map[i][0] = i;
75*89a07cf8Schristos inv_map[i][1] = 0;
76*89a07cf8Schristos }
77*89a07cf8Schristos else
78*89a07cf8Schristos inv_map[i][0] = '\0';
79*89a07cf8Schristos }
80*89a07cf8Schristos }
81*89a07cf8Schristos
82*89a07cf8Schristos
83*89a07cf8Schristos class bmpattern {
84*89a07cf8Schristos char *pat;
85*89a07cf8Schristos int len;
86*89a07cf8Schristos int delta[256];
87*89a07cf8Schristos public:
88*89a07cf8Schristos bmpattern(const char *pattern, int pattern_length);
89*89a07cf8Schristos ~bmpattern();
90*89a07cf8Schristos const char *search(const char *p, const char *end) const;
91*89a07cf8Schristos int length() const;
92*89a07cf8Schristos };
93*89a07cf8Schristos
bmpattern(const char * pattern,int pattern_length)94*89a07cf8Schristos bmpattern::bmpattern(const char *pattern, int pattern_length)
95*89a07cf8Schristos : len(pattern_length)
96*89a07cf8Schristos {
97*89a07cf8Schristos pat = new char[len];
98*89a07cf8Schristos int i;
99*89a07cf8Schristos for (i = 0; i < len; i++)
100*89a07cf8Schristos pat[i] = map[uchar(pattern[i])];
101*89a07cf8Schristos for (i = 0; i < 256; i++)
102*89a07cf8Schristos delta[i] = len;
103*89a07cf8Schristos for (i = 0; i < len; i++)
104*89a07cf8Schristos for (const unsigned char *inv = inv_map[uchar(pat[i])]; *inv; inv++)
105*89a07cf8Schristos delta[*inv] = len - i - 1;
106*89a07cf8Schristos }
107*89a07cf8Schristos
search(const char * buf,const char * end) const108*89a07cf8Schristos const char *bmpattern::search(const char *buf, const char *end) const
109*89a07cf8Schristos {
110*89a07cf8Schristos int buflen = end - buf;
111*89a07cf8Schristos if (len > buflen)
112*89a07cf8Schristos return 0;
113*89a07cf8Schristos const char *strend;
114*89a07cf8Schristos if (buflen > len*4)
115*89a07cf8Schristos strend = end - len*4;
116*89a07cf8Schristos else
117*89a07cf8Schristos strend = buf;
118*89a07cf8Schristos const char *k = buf + len - 1;
119*89a07cf8Schristos const int *del = delta;
120*89a07cf8Schristos const char *pattern = pat;
121*89a07cf8Schristos for (;;) {
122*89a07cf8Schristos while (k < strend) {
123*89a07cf8Schristos int t = del[uchar(*k)];
124*89a07cf8Schristos if (!t)
125*89a07cf8Schristos break;
126*89a07cf8Schristos k += t;
127*89a07cf8Schristos k += del[uchar(*k)];
128*89a07cf8Schristos k += del[uchar(*k)];
129*89a07cf8Schristos }
130*89a07cf8Schristos while (k < end && del[uchar(*k)] != 0)
131*89a07cf8Schristos k++;
132*89a07cf8Schristos if (k == end)
133*89a07cf8Schristos break;
134*89a07cf8Schristos int j = len - 1;
135*89a07cf8Schristos const char *s = k;
136*89a07cf8Schristos for (;;) {
137*89a07cf8Schristos if (j == 0)
138*89a07cf8Schristos return s;
139*89a07cf8Schristos if (map[uchar(*--s)] != uchar(pattern[--j]))
140*89a07cf8Schristos break;
141*89a07cf8Schristos }
142*89a07cf8Schristos k++;
143*89a07cf8Schristos }
144*89a07cf8Schristos return 0;
145*89a07cf8Schristos }
146*89a07cf8Schristos
~bmpattern()147*89a07cf8Schristos bmpattern::~bmpattern()
148*89a07cf8Schristos {
149*89a07cf8Schristos a_delete pat;
150*89a07cf8Schristos }
151*89a07cf8Schristos
length() const152*89a07cf8Schristos inline int bmpattern::length() const
153*89a07cf8Schristos {
154*89a07cf8Schristos return len;
155*89a07cf8Schristos }
156*89a07cf8Schristos
157*89a07cf8Schristos
158*89a07cf8Schristos static const char *find_end(const char *bufend, const char *p);
159*89a07cf8Schristos
search_and_check(const bmpattern * key,const char * buf,const char * bufend,const char ** start) const160*89a07cf8Schristos const char *linear_searcher::search_and_check(const bmpattern *key,
161*89a07cf8Schristos const char *buf, const char *bufend, const char **start) const
162*89a07cf8Schristos {
163*89a07cf8Schristos assert(buf[-1] == '\n');
164*89a07cf8Schristos assert(bufend[-1] == '\n');
165*89a07cf8Schristos const char *ptr = buf;
166*89a07cf8Schristos for (;;) {
167*89a07cf8Schristos const char *found = key->search(ptr, bufend);
168*89a07cf8Schristos if (!found)
169*89a07cf8Schristos break;
170*89a07cf8Schristos if (check_match(buf, bufend, found, key->length(), &ptr, start))
171*89a07cf8Schristos return found;
172*89a07cf8Schristos }
173*89a07cf8Schristos return 0;
174*89a07cf8Schristos }
175*89a07cf8Schristos
skip_field(const char * end,const char * p)176*89a07cf8Schristos static const char *skip_field(const char *end, const char *p)
177*89a07cf8Schristos {
178*89a07cf8Schristos for (;;)
179*89a07cf8Schristos if (*p++ == '\n') {
180*89a07cf8Schristos if (p == end || *p == '%')
181*89a07cf8Schristos break;
182*89a07cf8Schristos const char *q;
183*89a07cf8Schristos for (q = p; *q == ' ' || *q == '\t'; q++)
184*89a07cf8Schristos ;
185*89a07cf8Schristos if (*q == '\n')
186*89a07cf8Schristos break;
187*89a07cf8Schristos p = q + 1;
188*89a07cf8Schristos }
189*89a07cf8Schristos return p;
190*89a07cf8Schristos }
191*89a07cf8Schristos
find_end(const char * bufend,const char * p)192*89a07cf8Schristos static const char *find_end(const char *bufend, const char *p)
193*89a07cf8Schristos {
194*89a07cf8Schristos for (;;)
195*89a07cf8Schristos if (*p++ == '\n') {
196*89a07cf8Schristos if (p == bufend)
197*89a07cf8Schristos break;
198*89a07cf8Schristos const char *q;
199*89a07cf8Schristos for (q = p; *q == ' ' || *q == '\t'; q++)
200*89a07cf8Schristos ;
201*89a07cf8Schristos if (*q == '\n')
202*89a07cf8Schristos break;
203*89a07cf8Schristos p = q + 1;
204*89a07cf8Schristos }
205*89a07cf8Schristos return p;
206*89a07cf8Schristos }
207*89a07cf8Schristos
208*89a07cf8Schristos
check_match(const char * buf,const char * bufend,const char * match,int matchlen,const char ** cont,const char ** start) const209*89a07cf8Schristos int linear_searcher::check_match(const char *buf, const char *bufend,
210*89a07cf8Schristos const char *match, int matchlen,
211*89a07cf8Schristos const char **cont, const char **start) const
212*89a07cf8Schristos {
213*89a07cf8Schristos *cont = match + 1;
214*89a07cf8Schristos // The user is required to supply only the first truncate_len characters
215*89a07cf8Schristos // of the key. If truncate_len <= 0, he must supply all the key.
216*89a07cf8Schristos if ((truncate_len <= 0 || matchlen < truncate_len)
217*89a07cf8Schristos && map[uchar(match[matchlen])] != '\0')
218*89a07cf8Schristos return 0;
219*89a07cf8Schristos
220*89a07cf8Schristos // The character before the match must not be an alphanumeric
221*89a07cf8Schristos // character (unless the alphanumeric character follows one or two
222*89a07cf8Schristos // percent characters at the beginning of the line), nor must it be
223*89a07cf8Schristos // a percent character at the beginning of a line, nor a percent
224*89a07cf8Schristos // character following a percent character at the beginning of a
225*89a07cf8Schristos // line.
226*89a07cf8Schristos
227*89a07cf8Schristos switch (match - buf) {
228*89a07cf8Schristos case 0:
229*89a07cf8Schristos break;
230*89a07cf8Schristos case 1:
231*89a07cf8Schristos if (match[-1] == '%' || map[uchar(match[-1])] != '\0')
232*89a07cf8Schristos return 0;
233*89a07cf8Schristos break;
234*89a07cf8Schristos case 2:
235*89a07cf8Schristos if (map[uchar(match[-1])] != '\0' && match[-2] != '%')
236*89a07cf8Schristos return 0;
237*89a07cf8Schristos if (match[-1] == '%'
238*89a07cf8Schristos && (match[-2] == '\n' || match[-2] == '%'))
239*89a07cf8Schristos return 0;
240*89a07cf8Schristos break;
241*89a07cf8Schristos default:
242*89a07cf8Schristos if (map[uchar(match[-1])] != '\0'
243*89a07cf8Schristos && !(match[-2] == '%'
244*89a07cf8Schristos && (match[-3] == '\n'
245*89a07cf8Schristos || (match[-3] == '%' && match[-4] == '\n'))))
246*89a07cf8Schristos return 0;
247*89a07cf8Schristos if (match[-1] == '%'
248*89a07cf8Schristos && (match[-2] == '\n'
249*89a07cf8Schristos || (match[-2] == '%' && match[-3] == '\n')))
250*89a07cf8Schristos return 0;
251*89a07cf8Schristos }
252*89a07cf8Schristos
253*89a07cf8Schristos const char *p = match;
254*89a07cf8Schristos int had_percent = 0;
255*89a07cf8Schristos for (;;) {
256*89a07cf8Schristos if (*p == '\n') {
257*89a07cf8Schristos if (!had_percent && p[1] == '%') {
258*89a07cf8Schristos if (p[2] != '\0' && strchr(ignore_fields, p[2]) != 0) {
259*89a07cf8Schristos *cont = skip_field(bufend, match + matchlen);
260*89a07cf8Schristos return 0;
261*89a07cf8Schristos }
262*89a07cf8Schristos if (!start)
263*89a07cf8Schristos break;
264*89a07cf8Schristos had_percent = 1;
265*89a07cf8Schristos }
266*89a07cf8Schristos if (p <= buf) {
267*89a07cf8Schristos if (start)
268*89a07cf8Schristos *start = p + 1;
269*89a07cf8Schristos return 1;
270*89a07cf8Schristos }
271*89a07cf8Schristos const char *q;
272*89a07cf8Schristos for (q = p - 1; *q == ' ' || *q == '\t'; q--)
273*89a07cf8Schristos ;
274*89a07cf8Schristos if (*q == '\n') {
275*89a07cf8Schristos if (start)
276*89a07cf8Schristos *start = p + 1;
277*89a07cf8Schristos break;
278*89a07cf8Schristos }
279*89a07cf8Schristos p = q;
280*89a07cf8Schristos }
281*89a07cf8Schristos p--;
282*89a07cf8Schristos }
283*89a07cf8Schristos return 1;
284*89a07cf8Schristos }
285*89a07cf8Schristos
file_buffer()286*89a07cf8Schristos file_buffer::file_buffer()
287*89a07cf8Schristos : buffer(0), bufend(0)
288*89a07cf8Schristos {
289*89a07cf8Schristos }
290*89a07cf8Schristos
~file_buffer()291*89a07cf8Schristos file_buffer::~file_buffer()
292*89a07cf8Schristos {
293*89a07cf8Schristos a_delete buffer;
294*89a07cf8Schristos }
295*89a07cf8Schristos
get_start() const296*89a07cf8Schristos const char *file_buffer::get_start() const
297*89a07cf8Schristos {
298*89a07cf8Schristos return buffer ? buffer + 4 : 0;
299*89a07cf8Schristos }
300*89a07cf8Schristos
get_end() const301*89a07cf8Schristos const char *file_buffer::get_end() const
302*89a07cf8Schristos {
303*89a07cf8Schristos return bufend;
304*89a07cf8Schristos }
305*89a07cf8Schristos
load(int fd,const char * filename)306*89a07cf8Schristos int file_buffer::load(int fd, const char *filename)
307*89a07cf8Schristos {
308*89a07cf8Schristos struct stat sb;
309*89a07cf8Schristos if (fstat(fd, &sb) < 0)
310*89a07cf8Schristos error("can't fstat `%1': %2", filename, strerror(errno));
311*89a07cf8Schristos else if (!S_ISREG(sb.st_mode))
312*89a07cf8Schristos error("`%1' is not a regular file", filename);
313*89a07cf8Schristos else {
314*89a07cf8Schristos // We need one character extra at the beginning for an additional newline
315*89a07cf8Schristos // used as a sentinel. We get 4 instead so that the read buffer will be
316*89a07cf8Schristos // word-aligned. This seems to make the read slightly faster. We also
317*89a07cf8Schristos // need one character at the end also for an additional newline used as a
318*89a07cf8Schristos // sentinel.
319*89a07cf8Schristos int size = int(sb.st_size);
320*89a07cf8Schristos buffer = new char[size + 4 + 1];
321*89a07cf8Schristos int nread = read(fd, buffer + 4, size);
322*89a07cf8Schristos if (nread < 0)
323*89a07cf8Schristos error("error reading `%1': %2", filename, strerror(errno));
324*89a07cf8Schristos else if (nread != size)
325*89a07cf8Schristos error("size of `%1' decreased", filename);
326*89a07cf8Schristos else {
327*89a07cf8Schristos char c;
328*89a07cf8Schristos nread = read(fd, &c, 1);
329*89a07cf8Schristos if (nread != 0)
330*89a07cf8Schristos error("size of `%1' increased", filename);
331*89a07cf8Schristos else if (memchr(buffer + 4, '\0', size < 1024 ? size : 1024) != 0)
332*89a07cf8Schristos error("database `%1' is a binary file", filename);
333*89a07cf8Schristos else {
334*89a07cf8Schristos close(fd);
335*89a07cf8Schristos buffer[3] = '\n';
336*89a07cf8Schristos int sidx = 4, didx = 4;
337*89a07cf8Schristos for ( ; sidx < size + 4; sidx++, didx++)
338*89a07cf8Schristos {
339*89a07cf8Schristos if (buffer[sidx] == '\r')
340*89a07cf8Schristos {
341*89a07cf8Schristos if (buffer[++sidx] != '\n')
342*89a07cf8Schristos buffer[didx++] = '\r';
343*89a07cf8Schristos else
344*89a07cf8Schristos size--;
345*89a07cf8Schristos }
346*89a07cf8Schristos if (sidx != didx)
347*89a07cf8Schristos buffer[didx] = buffer[sidx];
348*89a07cf8Schristos }
349*89a07cf8Schristos bufend = buffer + 4 + size;
350*89a07cf8Schristos if (bufend[-1] != '\n')
351*89a07cf8Schristos *bufend++ = '\n';
352*89a07cf8Schristos return 1;
353*89a07cf8Schristos }
354*89a07cf8Schristos }
355*89a07cf8Schristos a_delete buffer;
356*89a07cf8Schristos buffer = 0;
357*89a07cf8Schristos }
358*89a07cf8Schristos close(fd);
359*89a07cf8Schristos return 0;
360*89a07cf8Schristos }
361*89a07cf8Schristos
linear_searcher(const char * query,int query_len,const char * ign,int trunc)362*89a07cf8Schristos linear_searcher::linear_searcher(const char *query, int query_len,
363*89a07cf8Schristos const char *ign, int trunc)
364*89a07cf8Schristos : ignore_fields(ign), truncate_len(trunc), keys(0), nkeys(0)
365*89a07cf8Schristos {
366*89a07cf8Schristos const char *query_end = query + query_len;
367*89a07cf8Schristos int nk = 0;
368*89a07cf8Schristos const char *p;
369*89a07cf8Schristos for (p = query; p < query_end; p++)
370*89a07cf8Schristos if (map[uchar(*p)] != '\0'
371*89a07cf8Schristos && (p[1] == '\0' || map[uchar(p[1])] == '\0'))
372*89a07cf8Schristos nk++;
373*89a07cf8Schristos if (nk == 0)
374*89a07cf8Schristos return;
375*89a07cf8Schristos keys = new bmpattern*[nk];
376*89a07cf8Schristos p = query;
377*89a07cf8Schristos for (;;) {
378*89a07cf8Schristos while (p < query_end && map[uchar(*p)] == '\0')
379*89a07cf8Schristos p++;
380*89a07cf8Schristos if (p == query_end)
381*89a07cf8Schristos break;
382*89a07cf8Schristos const char *start = p;
383*89a07cf8Schristos while (p < query_end && map[uchar(*p)] != '\0')
384*89a07cf8Schristos p++;
385*89a07cf8Schristos keys[nkeys++] = new bmpattern(start, p - start);
386*89a07cf8Schristos }
387*89a07cf8Schristos assert(nkeys <= nk);
388*89a07cf8Schristos if (nkeys == 0) {
389*89a07cf8Schristos a_delete keys;
390*89a07cf8Schristos keys = 0;
391*89a07cf8Schristos }
392*89a07cf8Schristos }
393*89a07cf8Schristos
~linear_searcher()394*89a07cf8Schristos linear_searcher::~linear_searcher()
395*89a07cf8Schristos {
396*89a07cf8Schristos for (int i = 0; i < nkeys; i++)
397*89a07cf8Schristos delete keys[i];
398*89a07cf8Schristos a_delete keys;
399*89a07cf8Schristos }
400*89a07cf8Schristos
search(const char * buffer,const char * bufend,const char ** startp,int * lengthp) const401*89a07cf8Schristos int linear_searcher::search(const char *buffer, const char *bufend,
402*89a07cf8Schristos const char **startp, int *lengthp) const
403*89a07cf8Schristos {
404*89a07cf8Schristos assert(bufend - buffer > 0);
405*89a07cf8Schristos assert(buffer[-1] == '\n');
406*89a07cf8Schristos assert(bufend[-1] == '\n');
407*89a07cf8Schristos if (nkeys == 0)
408*89a07cf8Schristos return 0;
409*89a07cf8Schristos for (;;) {
410*89a07cf8Schristos const char *refstart;
411*89a07cf8Schristos const char *found = search_and_check(keys[0], buffer, bufend, &refstart);
412*89a07cf8Schristos if (!found)
413*89a07cf8Schristos break;
414*89a07cf8Schristos const char *refend = find_end(bufend, found + keys[0]->length());
415*89a07cf8Schristos int i;
416*89a07cf8Schristos for (i = 1; i < nkeys; i++)
417*89a07cf8Schristos if (!search_and_check(keys[i], refstart, refend))
418*89a07cf8Schristos break;
419*89a07cf8Schristos if (i >= nkeys) {
420*89a07cf8Schristos *startp = refstart;
421*89a07cf8Schristos *lengthp = refend - refstart;
422*89a07cf8Schristos return 1;
423*89a07cf8Schristos }
424*89a07cf8Schristos buffer = refend;
425*89a07cf8Schristos }
426*89a07cf8Schristos return 0;
427*89a07cf8Schristos }
428*89a07cf8Schristos
429*89a07cf8Schristos class linear_search_item : public search_item {
430*89a07cf8Schristos file_buffer fbuf;
431*89a07cf8Schristos public:
432*89a07cf8Schristos linear_search_item(const char *filename, int fid);
433*89a07cf8Schristos ~linear_search_item();
434*89a07cf8Schristos int load(int fd);
435*89a07cf8Schristos search_item_iterator *make_search_item_iterator(const char *);
436*89a07cf8Schristos friend class linear_search_item_iterator;
437*89a07cf8Schristos };
438*89a07cf8Schristos
439*89a07cf8Schristos class linear_search_item_iterator : public search_item_iterator {
440*89a07cf8Schristos linear_search_item *lsi;
441*89a07cf8Schristos int pos;
442*89a07cf8Schristos public:
443*89a07cf8Schristos linear_search_item_iterator(linear_search_item *, const char *query);
444*89a07cf8Schristos ~linear_search_item_iterator();
445*89a07cf8Schristos int next(const linear_searcher &, const char **ptr, int *lenp,
446*89a07cf8Schristos reference_id *ridp);
447*89a07cf8Schristos };
448*89a07cf8Schristos
make_linear_search_item(int fd,const char * filename,int fid)449*89a07cf8Schristos search_item *make_linear_search_item(int fd, const char *filename, int fid)
450*89a07cf8Schristos {
451*89a07cf8Schristos linear_search_item *item = new linear_search_item(filename, fid);
452*89a07cf8Schristos if (!item->load(fd)) {
453*89a07cf8Schristos delete item;
454*89a07cf8Schristos return 0;
455*89a07cf8Schristos }
456*89a07cf8Schristos else
457*89a07cf8Schristos return item;
458*89a07cf8Schristos }
459*89a07cf8Schristos
linear_search_item(const char * filename,int fid)460*89a07cf8Schristos linear_search_item::linear_search_item(const char *filename, int fid)
461*89a07cf8Schristos : search_item(filename, fid)
462*89a07cf8Schristos {
463*89a07cf8Schristos }
464*89a07cf8Schristos
~linear_search_item()465*89a07cf8Schristos linear_search_item::~linear_search_item()
466*89a07cf8Schristos {
467*89a07cf8Schristos }
468*89a07cf8Schristos
load(int fd)469*89a07cf8Schristos int linear_search_item::load(int fd)
470*89a07cf8Schristos {
471*89a07cf8Schristos return fbuf.load(fd, name);
472*89a07cf8Schristos }
473*89a07cf8Schristos
make_search_item_iterator(const char * query)474*89a07cf8Schristos search_item_iterator *linear_search_item::make_search_item_iterator(
475*89a07cf8Schristos const char *query)
476*89a07cf8Schristos {
477*89a07cf8Schristos return new linear_search_item_iterator(this, query);
478*89a07cf8Schristos }
479*89a07cf8Schristos
linear_search_item_iterator(linear_search_item * p,const char *)480*89a07cf8Schristos linear_search_item_iterator::linear_search_item_iterator(
481*89a07cf8Schristos linear_search_item *p, const char *)
482*89a07cf8Schristos : lsi(p), pos(0)
483*89a07cf8Schristos {
484*89a07cf8Schristos }
485*89a07cf8Schristos
~linear_search_item_iterator()486*89a07cf8Schristos linear_search_item_iterator::~linear_search_item_iterator()
487*89a07cf8Schristos {
488*89a07cf8Schristos }
489*89a07cf8Schristos
next(const linear_searcher & searcher,const char ** startp,int * lengthp,reference_id * ridp)490*89a07cf8Schristos int linear_search_item_iterator::next(const linear_searcher &searcher,
491*89a07cf8Schristos const char **startp, int *lengthp,
492*89a07cf8Schristos reference_id *ridp)
493*89a07cf8Schristos {
494*89a07cf8Schristos const char *bufstart = lsi->fbuf.get_start();
495*89a07cf8Schristos const char *bufend = lsi->fbuf.get_end();
496*89a07cf8Schristos const char *ptr = bufstart + pos;
497*89a07cf8Schristos if (ptr < bufend && searcher.search(ptr, bufend, startp, lengthp)) {
498*89a07cf8Schristos pos = *startp + *lengthp - bufstart;
499*89a07cf8Schristos if (ridp)
500*89a07cf8Schristos *ridp = reference_id(lsi->filename_id, *startp - bufstart);
501*89a07cf8Schristos return 1;
502*89a07cf8Schristos }
503*89a07cf8Schristos else
504*89a07cf8Schristos return 0;
505*89a07cf8Schristos }
506