groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / libs / libbib / search.cpp
CommitLineData
92d0a6a6 1// -*- C++ -*-
4d3e9548 2/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2009
92d0a6a6
JR
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
5
6This file is part of groff.
7
8groff is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
4d3e9548
JL
10Software Foundation, either version 3 of the License, or
11(at your option) any later version.
92d0a6a6
JR
12
13groff is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
4d3e9548
JL
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
92d0a6a6
JR
20
21#include "lib.h"
22
23#include <stdlib.h>
24#include <assert.h>
25#include <errno.h>
26
27#include "posix.h"
28#include "errarg.h"
29#include "error.h"
30#include "nonposix.h"
31
32#include "refid.h"
33#include "search.h"
34
35int linear_truncate_len = 6;
36const char *linear_ignore_fields = "XYZ";
37
38search_list::search_list()
39: list(0), niterators(0), next_fid(1)
40{
41}
42
43search_list::~search_list()
44{
45 assert(niterators == 0);
46 while (list) {
47 search_item *tem = list->next;
48 delete list;
49 list = tem;
50 }
51}
52
53void search_list::add_file(const char *filename, int silent)
54{
55 search_item *p = make_index_search_item(filename, next_fid);
56 if (!p) {
57 int fd = open(filename, O_RDONLY | O_BINARY);
58 if (fd < 0) {
59 if (!silent)
60 error("can't open `%1': %2", filename, strerror(errno));
61 }
62 else
63 p = make_linear_search_item(fd, filename, next_fid);
64 }
65 if (p) {
66 search_item **pp;
67 for (pp = &list; *pp; pp = &(*pp)->next)
68 ;
69 *pp = p;
70 next_fid = p->next_filename_id();
71 }
72}
73
74int search_list::nfiles() const
75{
76 int n = 0;
77 for (search_item *ptr = list; ptr; ptr = ptr->next)
78 n++;
79 return n;
80}
81
82search_list_iterator::search_list_iterator(search_list *p, const char *q)
83: list(p), ptr(p->list), iter(0), query(strsave(q)),
84 searcher(q, strlen(q), linear_ignore_fields, linear_truncate_len)
85{
86 list->niterators += 1;
87}
88
89search_list_iterator::~search_list_iterator()
90{
91 list->niterators -= 1;
92 a_delete query;
93 delete iter;
94}
95
96int search_list_iterator::next(const char **pp, int *lenp, reference_id *ridp)
97{
98 while (ptr) {
99 if (iter == 0)
100 iter = ptr->make_search_item_iterator(query);
101 if (iter->next(searcher, pp, lenp, ridp))
102 return 1;
103 delete iter;
104 iter = 0;
105 ptr = ptr->next;
106 }
107 return 0;
108}
109
110search_item::search_item(const char *nm, int fid)
111: name(strsave(nm)), filename_id(fid), next(0)
112{
113}
114
115search_item::~search_item()
116{
117 a_delete name;
118}
119
120int search_item::is_named(const char *nm) const
121{
122 return strcmp(name, nm) == 0;
123}
124
125int search_item::next_filename_id() const
126{
127 return filename_id + 1;
128}
129
130search_item_iterator::~search_item_iterator()
131{
132}