IDZEBRA 2.2.8
scan.c
Go to the documentation of this file.
1/* This file is part of the Zebra server.
2 Copyright (C) Index Data
3
4 Zebra is free software; you can redistribute it and/or modify it under
5 the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2, or (at your option) any later
7 version.
8
9 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
10 WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18*/
19
20
21#if HAVE_CONFIG_H
22#include <config.h>
23#endif
24#include <stdlib.h>
25#include <string.h>
26#include <stdio.h>
27#include <assert.h>
28
29#include "dict-p.h"
30
31static void scan_direction(Dict dict, Dict_ptr ptr, int pos, Dict_char *str,
32 int start, int *count, void *client,
33 int (*userfunc)(char *, const char *, int, void *),
34 int dir)
35{
36 int lo, hi, j;
37 void *p;
38 short *indxp;
39 char *info;
40
41 dict_bf_readp(dict->dbf, ptr, &p);
42 hi = DICT_nodir(p)-1;
43 if (start != -1)
44 lo = start;
45 else
46 {
47 if (dir == -1)
48 lo = hi;
49 else
50 lo = 0;
51 }
52 indxp = (short*) ((char*) p+DICT_bsize(p)-sizeof(short));
53
54 while (lo <= hi && lo >= 0 && *count > 0)
55 {
56 if (indxp[-lo] > 0)
57 {
58 /* string (Dict_char *) DICT_EOS terminated */
59 /* unsigned char length of information */
60 /* char * information */
61
62 info = (char*)p + indxp[-lo];
63 for (j = 0; info[j] != DICT_EOS; j++)
64 str[pos+j] = info[j];
65 str[pos+j] = DICT_EOS;
66 if ((*userfunc)((char*) str, info+(j+1)*sizeof(Dict_char),
67 *count * dir, client))
68 {
69 *count = 0;
70 }
71 else
72 --(*count);
73 }
74 else
75 {
76 Dict_char dc;
77 Dict_ptr subptr;
78
79 /* Dict_ptr subptr */
80 /* Dict_char sub char */
81 /* unsigned char length of information */
82 /* char * information */
83
84 info = (char*)p - indxp[-lo];
85 memcpy(&dc, info+sizeof(Dict_ptr), sizeof(Dict_char));
86 str[pos] = dc;
87 memcpy(&subptr, info, sizeof(Dict_ptr));
88 if (dir>0 && info[sizeof(Dict_ptr)+sizeof(Dict_char)])
89 {
90 str[pos+1] = DICT_EOS;
91 if ((*userfunc)((char*) str,
92 info+sizeof(Dict_ptr)+sizeof(Dict_char),
93 *count * dir, client))
94 {
95 *count = 0;
96 }
97 else
98 --(*count);
99 }
100 if (*count>0 && subptr)
101 {
102 scan_direction(dict, subptr, pos+1, str, -1, count,
103 client, userfunc, dir);
104 dict_bf_readp(dict->dbf, ptr, &p);
105 indxp = (short*) ((char*) p+DICT_bsize(p)-sizeof(short));
106 }
107 if (*count>0 && dir<0 && info[sizeof(Dict_ptr)+sizeof(Dict_char)])
108 {
109 str[pos+1] = DICT_EOS;
110 if ((*userfunc)((char*) str,
111 info+sizeof(Dict_ptr)+sizeof(Dict_char),
112 *count * dir, client))
113 {
114 *count = 0;
115 }
116 else
117 --(*count);
118 }
119 }
120 lo += dir;
121 }
122}
123
124void dict_scan_r(Dict dict, Dict_ptr ptr, int pos, Dict_char *str,
125 int *before, int *after, void *client,
126 int (*userfunc)(char *, const char *, int, void *))
127{
128 int cmp = 0, mid, lo, hi;
129 void *p;
130 short *indxp;
131 char *info;
132
133 dict_bf_readp(dict->dbf, ptr, &p);
134 if (!p)
135 return;
136 mid = lo = 0;
137 hi = DICT_nodir(p)-1;
138 indxp = (short*) ((char*) p+DICT_bsize(p)-sizeof(short));
139 while (lo <= hi)
140 {
141 mid = (lo+hi)/2;
142 if (indxp[-mid] > 0)
143 {
144 /* string (Dict_char *) DICT_EOS terminated */
145 /* unsigned char length of information */
146 /* char * information */
147 info = (char*)p + indxp[-mid];
148 cmp = dict_strcmp((Dict_char*) info, str + pos);
149 if (!cmp)
150 {
151 if (*after)
152 {
153 if ((*userfunc)((char *) str, info+
154 (dict_strlen((Dict_char*) info)+1)
155 *sizeof(Dict_char),
156 *after, client))
157 {
158 *after = 0;
159 }
160 else
161 --(*after);
162 }
163 break;
164 }
165 }
166 else
167 {
168 Dict_char dc;
169 Dict_ptr subptr;
170
171 /* Dict_ptr subptr */
172 /* Dict_char sub char */
173 /* unsigned char length of information */
174 /* char * information */
175 info = (char*)p - indxp[-mid];
176 memcpy(&dc, info+sizeof(Dict_ptr), sizeof(Dict_char));
177 cmp = dc - str[pos];
178 if (!cmp)
179 {
180 memcpy(&subptr, info, sizeof(Dict_ptr));
181 if (str[pos+1] == DICT_EOS)
182 {
183 if (info[sizeof(Dict_ptr)+sizeof(Dict_char)])
184 {
185 if (*after)
186 {
187 if ((*userfunc)((char*) str,
188 info+sizeof(Dict_ptr)+
189 sizeof(Dict_char),
190 *after, client))
191 {
192 *after = 0;
193 }
194 else
195 --(*after);
196 }
197 }
198 if (*after && subptr)
199 scan_direction(dict, subptr, pos+1, str, -1,
200 after, client, userfunc, 1);
201 }
202 else
203 {
204 if (subptr)
205 dict_scan_r(dict, subptr, pos+1, str, before, after,
206 client, userfunc);
207 if (info[sizeof(Dict_ptr)+sizeof(Dict_char)])
208 {
209 if (*before)
210 {
211 str[pos+1] = DICT_EOS;
212 if ((*userfunc)((char*) str,
213 info+sizeof(Dict_ptr)+
214 sizeof(Dict_char),
215 - *before, client))
216 {
217 *before = 0;
218 }
219 else
220 --(*before);
221 }
222 }
223 }
224 break;
225 }
226 }
227 if (cmp < 0)
228 lo = mid+1;
229 else
230 hi = mid-1;
231 }
232 if (lo>hi && cmp < 0)
233 ++mid;
234 if (*after)
235 scan_direction(dict, ptr, pos, str, cmp ? mid : mid+1, after,
236 client, userfunc, 1);
237 if (*before && mid > 0)
238 scan_direction(dict, ptr, pos, str, mid-1, before,
239 client, userfunc, -1);
240}
241
242int dict_scan(Dict dict, char *str, int *before, int *after, void *client,
243 int (*f)(char *name, const char *info, int pos, void *client))
244{
245 int i;
246
247 yaz_log(YLOG_DEBUG, "dict_scan");
248 for (i = 0; str[i]; i++)
249 {
250 yaz_log(YLOG_DEBUG, "start_term pos %d %3d %c", i, str[i],
251 (str[i] > ' ' && str[i] < 127) ? str[i] : '?');
252 }
253 if (!dict->head.root)
254 return 0;
255 dict_scan_r(dict, dict->head.root, 0, (Dict_char *) str,
256 before, after, client, f);
257 return 0;
258}
259/*
260 * Local variables:
261 * c-basic-offset: 4
262 * c-file-style: "Stroustrup"
263 * indent-tabs-mode: nil
264 * End:
265 * vim: shiftwidth=4 tabstop=8 expandtab
266 */
267
unsigned Dict_ptr
Definition dict-p.h:34
#define DICT_EOS
Definition dict-p.h:102
int dict_bf_readp(Dict_BFile bf, int no, void **bufp)
Definition drdwr.c:188
int dict_strlen(const Dict_char *s)
Definition open.c:118
int dict_strcmp(const Dict_char *s1, const Dict_char *s2)
Definition open.c:108
#define DICT_bsize(x)
Definition dict-p.h:105
unsigned char Dict_char
Definition dict-p.h:33
#define DICT_nodir(x)
Definition dict-p.h:106
static Dict dict
Definition dicttest.c:35
void dict_scan_r(Dict dict, Dict_ptr ptr, int pos, Dict_char *str, int *before, int *after, void *client, int(*userfunc)(char *, const char *, int, void *))
Definition scan.c:124
static void scan_direction(Dict dict, Dict_ptr ptr, int pos, Dict_char *str, int start, int *count, void *client, int(*userfunc)(char *, const char *, int, void *), int dir)
Definition scan.c:31
int dict_scan(Dict dict, char *str, int *before, int *after, void *client, int(*f)(char *name, const char *info, int pos, void *client))
dictionary scan
Definition scan.c:242
Dict_ptr root
Definition dict-p.h:40
struct Dict_head head
Definition dict-p.h:83
Dict_BFile dbf
Definition dict-p.h:74