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