1 : #define VSTR_DEL_C
2 : /*
3 : * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 James Antill
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU Lesser General Public
7 : * License as published by the Free Software Foundation; either
8 : * version 2 of the License, or (at your option) any later version.
9 : *
10 : * This library is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 : * Lesser General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU Lesser General Public
16 : * License along with this library; if not, write to the Free Software
17 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 : *
19 : * email: james@and.org
20 : */
21 : /* function to delete data from a vstr */
22 : #include "main.h"
23 :
24 :
25 : static void vstr__cache_iovec_reset(Vstr_base *base)
26 186052 : {
27 186052 : ASSERT(!base->num);
28 186052 : ASSERT(!base->len);
29 :
30 186052 : if (!(base->cache_available && VSTR__CACHE(base) &&
31 : VSTR__CACHE(base)->vec && VSTR__CACHE(base)->vec->sz))
32 0 : return;
33 :
34 104009 : base->iovec_upto_date = TRUE;
35 :
36 104009 : if (VSTR__CACHE(base)->vec->sz > base->conf->iov_min_offset)
37 104004 : VSTR__CACHE(base)->vec->off = base->conf->iov_min_offset;
38 : else
39 5 : VSTR__CACHE(base)->vec->off = 0;
40 : }
41 :
42 : static void vstr__cache_iovec_del_node_end(Vstr_base *base, unsigned int num,
43 : unsigned int len)
44 15976 : { /* done by hand in vstr-inline.h -- for del */
45 15976 : if (!base->iovec_upto_date)
46 13904 : return;
47 :
48 2072 : num += VSTR__CACHE(base)->vec->off;
49 2072 : VSTR__CACHE(base)->vec->v[num - 1].iov_len -= len;
50 : }
51 :
52 : static void vstr__cache_iovec_del_node_beg(Vstr_base *base, Vstr_node *node,
53 : unsigned int num, unsigned int len)
54 16159 : {
55 16159 : if (!base->iovec_upto_date)
56 1461 : return;
57 :
58 14698 : num += VSTR__CACHE(base)->vec->off;
59 14698 : --num;
60 :
61 14698 : if (node->type != VSTR_TYPE_NODE_NON)
62 : {
63 14698 : char *tmp = VSTR__CACHE(base)->vec->v[num].iov_base;
64 14698 : tmp += len;
65 14698 : VSTR__CACHE(base)->vec->v[num].iov_base = tmp;
66 : }
67 :
68 14698 : VSTR__CACHE(base)->vec->v[num].iov_len -= len;
69 :
70 15861 : assert((node->len == VSTR__CACHE(base)->vec->v[num].iov_len) ||
71 : ((base->beg == node) &&
72 : (node->len == (VSTR__CACHE(base)->vec->v[num].iov_len + base->used))));
73 : }
74 :
75 : static void vstr__cache_iovec_del_beg(Vstr_base *base, unsigned int num)
76 119869 : {
77 119869 : if (!base->iovec_upto_date)
78 11777 : return;
79 :
80 108092 : VSTR__CACHE(base)->vec->off += num;
81 :
82 117469 : assert(VSTR__CACHE(base)->vec->sz > VSTR__CACHE(base)->vec->off);
83 117469 : assert((VSTR__CACHE(base)->vec->sz - VSTR__CACHE(base)->vec->off) >= base->num);
84 : }
85 :
86 : static void vstr__del_beg_cleanup(Vstr_base *base, Vstr_node **scan,
87 : unsigned int num, int base_update)
88 750481 : {
89 750481 : if (num)
90 : {
91 749649 : Vstr_node *tmp = *scan;
92 :
93 749649 : vstr__relink_nodes(base->conf, base->beg, scan, num);
94 :
95 749649 : base->beg = tmp;
96 :
97 749649 : if (base_update)
98 : {
99 119869 : base->num -= num;
100 :
101 119869 : ASSERT(base->beg); /* if == NULL: then
102 : * should be del_all, not del_beg */
103 :
104 119869 : vstr__cache_iovec_del_beg(base, num);
105 : }
106 : }
107 : }
108 :
109 : static void vstr__del_node(Vstr_node *node)
110 2094248 : { /* free resources of a node ... just ref atm. */
111 2094248 : if (node->type == VSTR_TYPE_NODE_REF)
112 187502 : vstr_ref_del(((Vstr_node_ref *)node)->ref);
113 : }
114 :
115 : static void vstr__del_all(Vstr_base *base)
116 186052 : {
117 186052 : size_t orig_len = base->len;
118 186052 : unsigned int num = 0;
119 186052 : unsigned int type;
120 186052 : Vstr_node **scan = NULL;
121 :
122 186052 : assert(vstr__check_spare_nodes(base->conf));
123 186052 : assert(vstr__check_real_nodes(base));
124 :
125 186052 : scan = &base->beg;
126 186052 : type = (*scan)->type;
127 :
128 186052 : base->len = 0;
129 :
130 2061633 : while (*scan)
131 : {
132 1875581 : if ((*scan)->type != type)
133 : {
134 443728 : vstr__del_beg_cleanup(base, scan, num, FALSE);
135 443728 : type = base->beg->type;
136 443728 : scan = &base->beg;
137 443728 : num = 0;
138 : }
139 :
140 1875581 : ++num;
141 :
142 1875581 : vstr__del_node(*scan);
143 :
144 1875581 : scan = &(*scan)->next;
145 : }
146 186052 : vstr__del_beg_cleanup(base, scan, num, FALSE);
147 :
148 186052 : base->used = 0;
149 186052 : base->num = 0;
150 186052 : ASSERT(!base->beg);
151 186052 : base->end = NULL;
152 :
153 186052 : base->node_buf_used = FALSE;
154 186052 : base->node_non_used = FALSE;
155 186052 : base->node_ptr_used = FALSE;
156 186052 : base->node_ref_used = FALSE;
157 :
158 186052 : vstr__cache_iovec_reset(base);
159 :
160 186052 : vstr__cache_del(base, 1, orig_len);
161 :
162 53435 : assert(vstr__check_spare_nodes(base->conf));
163 53435 : assert(vstr__check_real_nodes(base));
164 : }
165 :
166 : static void vstr__del_beg(Vstr_base *base, size_t len)
167 104129 : {
168 104129 : size_t orig_len = len;
169 104129 : unsigned int num = 0;
170 104129 : unsigned int type;
171 104129 : Vstr_node **scan = NULL;
172 :
173 104129 : assert(len && base->beg);
174 :
175 104129 : assert(vstr__check_spare_nodes(base->conf));
176 104129 : assert(vstr__check_real_nodes(base));
177 :
178 104129 : scan = &base->beg;
179 104129 : type = (*scan)->type;
180 :
181 104129 : base->len -= len;
182 :
183 104129 : if (base->used)
184 : {
185 75569 : assert((*scan)->len > base->used);
186 75569 : assert((*scan)->type == VSTR_TYPE_NODE_BUF);
187 :
188 75569 : if (len < (size_t)((*scan)->len - base->used))
189 : {
190 660 : base->used += len;
191 :
192 660 : vstr__cache_iovec_del_node_beg(base, *scan, 1, len);
193 :
194 660 : vstr__cache_del(base, 1, orig_len);
195 :
196 660 : assert(vstr__check_real_nodes(base));
197 16657 : return;
198 : }
199 :
200 74909 : num = 1;
201 :
202 74909 : len -= ((*scan)->len - base->used);
203 : /* vstr_ref_del(((Vstr_node_ref *)(*scan))->ref); */
204 74909 : type = VSTR_TYPE_NODE_BUF;
205 :
206 74909 : scan = &(*scan)->next;
207 :
208 74909 : base->used = 0;
209 :
210 96897 : ASSERT(*scan || !len);
211 : }
212 :
213 286967 : while (len > 0)
214 : {
215 198997 : if ((*scan)->type != type)
216 : {
217 17232 : vstr__del_beg_cleanup(base, scan, num, TRUE);
218 17232 : type = base->beg->type;
219 17232 : scan = &base->beg;
220 17232 : num = 0;
221 : }
222 :
223 198997 : if (len < (*scan)->len)
224 : {
225 15499 : switch ((*scan)->type)
226 : {
227 : case VSTR_TYPE_NODE_BUF:
228 5602 : base->used = len;
229 5602 : break;
230 : case VSTR_TYPE_NODE_NON:
231 10 : (*scan)->len -= len;
232 10 : break;
233 : case VSTR_TYPE_NODE_PTR:
234 : {
235 640 : char *tmp = ((Vstr_node_ptr *)(*scan))->ptr;
236 640 : ((Vstr_node_ptr *)(*scan))->ptr = tmp + len;
237 640 : (*scan)->len -= len;
238 : }
239 640 : break;
240 : case VSTR_TYPE_NODE_REF:
241 9247 : ((Vstr_node_ref *)(*scan))->off += len;
242 9247 : (*scan)->len -= len;
243 9247 : break;
244 : default:
245 120721 : assert(FALSE);
246 : }
247 :
248 183498 : break;
249 : }
250 :
251 183498 : ++num;
252 183498 : len -= (*scan)->len;
253 :
254 183498 : vstr__del_node(*scan);
255 :
256 183498 : scan = &(*scan)->next;
257 : }
258 :
259 103469 : vstr__del_beg_cleanup(base, scan, num, TRUE);
260 :
261 103469 : if (len)
262 15499 : vstr__cache_iovec_del_node_beg(base, base->beg, 1, len);
263 :
264 103469 : vstr__cache_del(base, 1, orig_len);
265 :
266 103997 : assert(vstr__check_spare_nodes(base->conf));
267 103997 : assert(vstr__check_real_nodes(base));
268 : }
269 :
270 : static Vstr_node *vstr__del_end_cleanup(Vstr_conf *conf,
271 : Vstr_node *beg, Vstr_node **end,
272 : unsigned int num)
273 11067 : {
274 11067 : Vstr_node *ret = *end;
275 :
276 11067 : vstr__relink_nodes(conf, beg, end, num);
277 :
278 11067 : return (ret);
279 : }
280 :
281 : int vstr_extern_inline_del(Vstr_base *base, size_t pos, size_t len)
282 326362 : {
283 326362 : unsigned int num = 0;
284 326362 : size_t orig_pos = pos;
285 326362 : size_t orig_len = len;
286 326362 : Vstr_node *scan = NULL;
287 326362 : Vstr_node **pscan = NULL;
288 326362 : Vstr_node *beg = NULL;
289 326362 : int type;
290 326362 : Vstr_node *saved_beg = NULL;
291 326362 : unsigned int saved_num = 0;
292 326362 : unsigned int del_nodes = 0;
293 :
294 326362 : ASSERT(len); /* inline version deals with !len */
295 326362 : ASSERT_RET(base && pos &&
296 : ((pos <= base->len) &&
297 : (vstr_sc_poslast(pos, len) <= base->len)), FALSE);
298 :
299 326358 : assert(pos);
300 :
301 326358 : if (pos <= 1)
302 : {
303 290181 : if (len >= base->len)
304 : {
305 186052 : vstr__del_all(base);
306 :
307 186052 : return (TRUE);
308 : }
309 :
310 104129 : vstr__del_beg(base, len);
311 104129 : return (TRUE);
312 : }
313 :
314 36177 : ASSERT(vstr__check_spare_nodes(base->conf));
315 36177 : ASSERT(vstr__check_real_nodes(base));
316 :
317 36177 : --pos; /* pos == ammount of chars ok from begining */
318 :
319 36177 : if ((pos + len) >= base->len)
320 10214 : len = base->len - pos;
321 :
322 36177 : scan = vstr_base__pos(base, &pos, &num, FALSE);
323 :
324 36177 : base->len -= len;
325 :
326 36177 : if (pos != scan->len)
327 : { /* need to del some data from this node ... */
328 15978 : size_t tmp = scan->len - pos;
329 :
330 15978 : if (len >= tmp)
331 : {
332 8386 : vstr__cache_iovec_del_node_end(base, num, tmp);
333 8386 : scan->len = pos;
334 8386 : len -= tmp;
335 : }
336 : else
337 : { /* delete from the middle of a single node */
338 7592 : switch (scan->type)
339 : {
340 : default:
341 5325 : ASSERT(FALSE);
342 : case VSTR_TYPE_NODE_NON:
343 7061 : break;
344 :
345 : case VSTR_TYPE_NODE_BUF:
346 7061 : if (!base->conf->split_buf_del)
347 : {
348 7055 : vstr_wrap_memmove(((Vstr_node_buf *)scan)->buf + pos,
349 : ((Vstr_node_buf *)scan)->buf + pos + len,
350 : scan->len - (pos + len));
351 7055 : break;
352 : }
353 : /* else FALLTHROUGH */
354 :
355 : case VSTR_TYPE_NODE_PTR:
356 : case VSTR_TYPE_NODE_REF:
357 537 : scan = vstr__base_split_node(base, scan, pos + len);
358 537 : if (!scan)
359 : {
360 2 : base->len += len; /* make sure nothing changed */
361 :
362 2 : assert(vstr__check_spare_nodes(base->conf));
363 2 : assert(vstr__check_real_nodes(base));
364 :
365 2 : return (FALSE);
366 : }
367 7590 : break;
368 : }
369 7590 : scan->len -= len;
370 7590 : vstr__cache_iovec_del_node_end(base, num, len);
371 :
372 7590 : vstr__cache_del(base, orig_pos, orig_len);
373 :
374 7590 : assert(vstr__check_spare_nodes(base->conf));
375 7590 : assert(vstr__check_real_nodes(base));
376 :
377 7590 : return (TRUE);
378 : }
379 : }
380 :
381 28585 : saved_beg = scan;
382 28585 : saved_num = num;
383 28585 : del_nodes = 0;
384 :
385 28585 : if (!len)
386 : {
387 1059 : vstr__cache_del(base, orig_pos, orig_len);
388 :
389 1059 : assert(vstr__check_spare_nodes(base->conf));
390 1059 : assert(vstr__check_real_nodes(base));
391 :
392 1059 : return (TRUE);
393 : }
394 :
395 27526 : scan = scan->next;
396 27526 : assert(scan);
397 :
398 27526 : if (len < scan->len)
399 16689 : goto fix_last_node;
400 :
401 10837 : len -= scan->len;
402 10837 : type = scan->type;
403 10837 : beg = scan;
404 10837 : vstr__del_node(scan);
405 10837 : pscan = &scan->next;
406 10837 : num = 1;
407 35169 : while (*pscan && (len >= (*pscan)->len))
408 : {
409 24332 : vstr__del_node(*pscan);
410 :
411 24332 : len -= (*pscan)->len;
412 :
413 24332 : if ((*pscan)->type != type)
414 : {
415 230 : del_nodes += num;
416 :
417 230 : scan = vstr__del_end_cleanup(base->conf, beg, pscan, num);
418 230 : type = scan->type;
419 230 : pscan = &scan->next;
420 230 : num = 1;
421 230 : beg = scan;
422 230 : continue;
423 : }
424 :
425 24102 : ++num;
426 24102 : pscan = &(*pscan)->next;
427 : }
428 :
429 10837 : scan = vstr__del_end_cleanup(base->conf, beg, pscan, num);
430 10837 : del_nodes += num;
431 :
432 10837 : if (base->iovec_upto_date)
433 : {
434 384 : size_t rebeg_num = saved_num + del_nodes;
435 384 : Vstr__cache_data_iovec *vec = VSTR__CACHE(base)->vec;
436 384 : struct iovec *vec_v = (vec->v + vec->off);
437 384 : unsigned char *vec_t = (vec->t + vec->off);
438 :
439 384 : vstr_wrap_memmove(vec_v + saved_num, vec_v + rebeg_num,
440 : (base->num - rebeg_num) * sizeof(struct iovec));
441 384 : vstr_wrap_memmove(vec_t + saved_num, vec_t + rebeg_num,
442 : (base->num - rebeg_num));
443 : }
444 10837 : base->num -= del_nodes;
445 :
446 10837 : saved_beg->next = scan;
447 10837 : if (!scan)
448 10189 : base->end = saved_beg;
449 648 : else if (len)
450 : {
451 : fix_last_node:
452 17002 : assert(len < scan->len);
453 :
454 17002 : switch (scan->type)
455 : {
456 : case VSTR_TYPE_NODE_BUF:
457 : /* if (!base->conf->split_buf_del) */
458 : /* no point in splitting */
459 1499 : vstr_wrap_memmove(((Vstr_node_buf *)scan)->buf,
460 : ((Vstr_node_buf *)scan)->buf + len,
461 : scan->len - len);
462 1499 : break;
463 : case VSTR_TYPE_NODE_NON:
464 13935 : break;
465 : case VSTR_TYPE_NODE_PTR:
466 13935 : ((Vstr_node_ptr *)scan)->ptr =
467 : ((char *)((Vstr_node_ptr *)scan)->ptr) + len;
468 13935 : break;
469 : case VSTR_TYPE_NODE_REF:
470 1498 : ((Vstr_node_ref *)scan)->off += len;
471 364 : break;
472 : default:
473 13533 : assert(FALSE);
474 : }
475 17002 : scan->len -= len;
476 :
477 17002 : vstr__cache_iovec_reset_node(base, scan, saved_num + 1);
478 : }
479 :
480 27526 : vstr__cache_del(base, orig_pos, orig_len);
481 :
482 27526 : assert(vstr__check_spare_nodes(base->conf));
483 27526 : assert(vstr__check_real_nodes(base));
484 :
485 27526 : return (TRUE);
486 : }
487 :
|