1 : #define VSTR_CACHE_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 : /* Functions to allow things to be cached for the string */
22 : #include "main.h"
23 : /* NOTE: some assert stuff is in vstr.c also vstr_add.c and vstr_del.c
24 : * know a bit about the internals of this file as well */
25 :
26 :
27 : /* we don't call the cb is it's grpallocated, we do that by always having a
28 : * NULL data */
29 : #define ASSERT_VALID_IOVEC_POS(base) \
30 : assert((base->conf->cache_pos_cb_iovec == 2) && \
31 : ((VSTR__CACHE(base)->vec == vstr_cache_get(base, 2)) || \
32 : ((base->grpalloc_cache >= VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC) && \
33 : VSTR__CACHE(base)->vec && !vstr_cache_get(base, 2))))
34 :
35 :
36 :
37 : static void vstr__cache_cbs(const Vstr_base *base, size_t pos, size_t len,
38 : unsigned int type, unsigned int skip_internal)
39 2032292 : {
40 2032292 : unsigned int scan = 0;
41 2032292 : unsigned int last = 0;
42 :
43 2032292 : ASSERT(!skip_internal ||
44 : (type == VSTR_TYPE_CACHE_FREE) || (type == VSTR_TYPE_CACHE_NOTHING));
45 :
46 2032292 : if (skip_internal)
47 36 : switch (base->grpalloc_cache)
48 : {
49 26 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_POS: scan = 1; break;
50 5 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC: scan = 2; break;
51 5 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR: scan = 3;
52 1 : ASSERT_NO_SWITCH_DEF();
53 : }
54 :
55 5680145 : while (scan < VSTR__CACHE(base)->sz)
56 : {
57 3647853 : void *data = VSTR__CACHE(base)->data[scan];
58 :
59 3647853 : if (data)
60 : {
61 3342999 : if (type != VSTR_TYPE_CACHE_NOTHING)
62 : {
63 : void *(*cb_func)(const struct Vstr_base *, size_t, size_t,
64 3342999 : unsigned int, void *);
65 3342999 : cb_func = base->conf->cache_cbs_ents[scan].cb_func;
66 3342999 : VSTR__CACHE(base)->data[scan] = (*cb_func)(base, pos, len, type, data);
67 : }
68 :
69 3342999 : assert((type != VSTR_TYPE_CACHE_FREE) || !VSTR__CACHE(base)->data[scan]);
70 :
71 3342999 : if (VSTR__CACHE(base)->data[scan])
72 3305230 : last = scan;
73 : }
74 :
75 3647853 : ++scan;
76 : }
77 :
78 2032292 : if (last < VSTR__CACHE_INTERNAL_POS_MAX) /* last is one less than the pos */
79 1741549 : ((Vstr_base *)base)->cache_internal = TRUE;
80 : }
81 :
82 : void vstr__cache_del(const Vstr_base *base, size_t pos, size_t len)
83 331662 : {
84 331662 : if (!base->cache_available)
85 18255 : return;
86 :
87 313407 : assert(VSTR__CACHE(base));
88 :
89 313407 : vstr__cache_cbs(base, pos, len, VSTR_TYPE_CACHE_DEL, FALSE);
90 : }
91 :
92 : void vstr__cache_add(const Vstr_base *base, size_t pos, size_t len)
93 1690016 : {
94 1690016 : if (!base->cache_available)
95 25594 : return;
96 :
97 1664422 : assert(VSTR__CACHE(base));
98 :
99 1664422 : vstr__cache_cbs(base, pos, len, VSTR_TYPE_CACHE_ADD, FALSE);
100 : }
101 :
102 : void vstr_cache_cb_sub(const Vstr_base *base, size_t pos, size_t len)
103 32444 : {
104 32444 : if (!base->cache_available)
105 5 : return;
106 :
107 32439 : assert(VSTR__CACHE(base));
108 :
109 32439 : vstr__cache_cbs(base, pos, len, VSTR_TYPE_CACHE_SUB, FALSE);
110 : }
111 :
112 : void vstr_cache_cb_free(const Vstr_base *base, unsigned int num)
113 121 : {
114 121 : if (!base->cache_available)
115 5 : return;
116 :
117 116 : assert(VSTR__CACHE(base));
118 :
119 116 : switch (base->grpalloc_cache)
120 : {
121 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR:
122 25 : if (num == 3)
123 : {
124 10 : struct Vstr__cache_data_cstr *data = NULL;
125 :
126 10 : data = vstr_cache_get(base, base->conf->cache_pos_cb_cstr);
127 10 : vstr_ref_del(data->ref);
128 10 : data->ref = NULL;
129 10 : return;
130 : }
131 35 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC: if (num == 2) return;
132 96 : case VSTR_TYPE_CNTL_CONF_GRPALLOC_POS: if (num == 1) return;
133 56 : ASSERT_NO_SWITCH_DEF();
134 : }
135 :
136 71 : if (num && (--num < VSTR__CACHE(base)->sz))
137 : { /* free'ing a single callbacks data ... */
138 40 : void *data = VSTR__CACHE(base)->data[num];
139 :
140 40 : if (data)
141 : {
142 : void *(*cb_func)(const struct Vstr_base *, size_t, size_t,
143 5 : unsigned int, void *);
144 :
145 5 : cb_func = base->conf->cache_cbs_ents[num].cb_func;
146 5 : VSTR__CACHE(base)->data[num] = (*cb_func)(base, 0, 0,
147 : VSTR_TYPE_CACHE_FREE, data);
148 :
149 5 : vstr__cache_cbs(base, 0, 0, VSTR_TYPE_CACHE_NOTHING, TRUE);
150 : }
151 :
152 5 : return;
153 : }
154 :
155 : /* free all */
156 31 : vstr__cache_cbs(base, 0, 0, VSTR_TYPE_CACHE_FREE, TRUE);
157 : }
158 :
159 : void vstr__cache_cstr_cpy(const Vstr_base *base, size_t pos, size_t len,
160 : const Vstr_base *from_base, size_t from_pos)
161 880756 : {
162 880756 : Vstr__cache_data_cstr *data = NULL;
163 880756 : Vstr__cache_data_cstr *from_data = NULL;
164 880756 : unsigned int off = 3;
165 880756 : unsigned int from_off = 3;
166 :
167 880756 : ASSERT(off == base->conf->cache_pos_cb_cstr);
168 880756 : ASSERT(from_off == from_base->conf->cache_pos_cb_cstr);
169 :
170 880756 : if (!base->cache_available)
171 120 : return;
172 :
173 880636 : assert(VSTR__CACHE(base));
174 :
175 880636 : if (!(data = vstr_cache_get(base, off)))
176 838967 : return;
177 :
178 41669 : if (!(from_data = vstr_cache_get(from_base, from_off)))
179 17 : return;
180 :
181 41652 : if ((data->ref && data->len) || (!from_data->ref || !from_data->len))
182 1072 : return;
183 :
184 35 : if ((from_pos <= vstr_sc_poslast(from_data->pos, from_data->len)) &&
185 : (vstr_sc_poslast(from_pos, len) >=
186 : vstr_sc_poslast(from_data->pos, from_data->len)))
187 : {
188 30 : size_t overlap = from_data->len;
189 30 : size_t begskip = 0;
190 30 : size_t offskip = 0;
191 :
192 30 : if (from_pos < from_data->pos)
193 5 : begskip = (from_data->pos - from_pos);
194 : else
195 : {
196 25 : overlap -= (from_pos - from_data->pos);
197 25 : offskip = (from_pos - from_data->pos);
198 : }
199 :
200 30 : if (data->ref)
201 25 : vstr_ref_del(data->ref);
202 :
203 30 : data->ref = vstr_ref_add(from_data->ref);
204 30 : data->pos = pos + 1 + begskip;
205 30 : data->len = overlap;
206 30 : data->sz = from_data->sz;
207 30 : data->off = from_data->off + offskip;
208 : }
209 : }
210 :
211 : static void vstr__cache_iovec_memmove(const Vstr_base *base)
212 1663 : {
213 1663 : Vstr__cache_data_iovec *vec = VSTR__CACHE(base)->vec;
214 1663 : size_t sz = sizeof(struct iovec) * base->num;
215 1663 : unsigned int off = base->conf->iov_min_offset;
216 :
217 1663 : ASSERT((off + base->num) <= vec->sz);
218 :
219 1663 : vstr_wrap_memmove(vec->v + off, vec->v + vec->off, sz);
220 1663 : vstr_wrap_memmove(vec->t + off, vec->t + vec->off, base->num);
221 :
222 1663 : vec->off = off;
223 : }
224 :
225 : int vstr__cache_iovec_alloc(const Vstr_base *base, unsigned int sz)
226 104819 : {
227 104819 : Vstr__cache_data_iovec *vec = NULL;
228 104819 : size_t alloc_sz = sz + base->conf->iov_min_alloc + base->conf->iov_min_offset;
229 104819 : Vstr_conf *conf = base->conf;
230 :
231 104819 : if (!base->cache_available)
232 15 : return (FALSE);
233 :
234 104804 : assert(VSTR__CACHE(base));
235 :
236 104804 : vec = VSTR__CACHE(base)->vec;
237 104804 : if (!vec)
238 : {
239 2964 : if (!(vec = VSTR__MK(sizeof(Vstr__cache_data_iovec))))
240 10 : goto malloc_bad;
241 2954 : if (!vstr_cache_set(base, conf->cache_pos_cb_iovec, vec))
242 9 : goto cache_vec_malloc_bad;
243 :
244 2945 : VSTR__CACHE(base)->vec = vec;
245 :
246 2945 : if (!(vec->v = VSTR__MK(sizeof(struct iovec) * alloc_sz)))
247 3 : goto vec_v_malloc_bad;
248 :
249 2942 : if (!(vec->t = VSTR__MK(alloc_sz)))
250 6 : goto vec_t_malloc_bad;
251 :
252 2936 : vec->sz = alloc_sz;
253 2936 : vec->off = 0;
254 : }
255 104776 : ASSERT_VALID_IOVEC_POS(base);
256 104776 : ASSERT(vec->v);
257 :
258 104776 : if (!base->iovec_upto_date)
259 36272 : vec->off = base->conf->iov_min_offset;
260 68504 : else if ((vec->off > base->conf->iov_min_offset) &&
261 : (sz > (vec->sz - vec->off)))
262 1663 : vstr__cache_iovec_memmove(base);
263 :
264 104776 : if (sz > (vec->sz - vec->off))
265 : {
266 7733 : struct iovec *vec_v = NULL;
267 7733 : unsigned char *vec_t = NULL;
268 :
269 7733 : alloc_sz = sz + base->conf->iov_min_offset;
270 :
271 7733 : if (!VSTR__MV(vec->v, vec_v, sizeof(struct iovec) * alloc_sz))
272 : {
273 21 : ASSERT(!vec_v);
274 21 : ASSERT(vec->v);
275 21 : conf->malloc_bad = TRUE;
276 21 : return (FALSE);
277 : }
278 :
279 7712 : if (!VSTR__MV(vec->t, vec_t, alloc_sz))
280 : {
281 21 : ASSERT(!vec_t);
282 21 : ASSERT(vec->t);
283 21 : conf->malloc_bad = TRUE;
284 21 : return (FALSE);
285 : }
286 :
287 7691 : vec->sz = alloc_sz;
288 : }
289 :
290 104734 : return (TRUE);
291 :
292 : vec_t_malloc_bad:
293 6 : VSTR__F(vec->v);
294 : vec_v_malloc_bad:
295 9 : VSTR__CACHE(base)->vec = NULL;
296 9 : conf->malloc_bad = FALSE;
297 9 : vstr_cache_set(base, conf->cache_pos_cb_iovec, NULL); /* must work */
298 9 : ASSERT(!conf->malloc_bad);
299 : cache_vec_malloc_bad:
300 18 : VSTR__F(vec);
301 : malloc_bad:
302 28 : conf->malloc_bad = TRUE;
303 28 : return (FALSE);
304 : }
305 :
306 : void vstr__free_cache(const Vstr_base *base)
307 23057 : {
308 23057 : if (!base->cache_available)
309 1069 : return;
310 :
311 21988 : assert(VSTR__CACHE(base));
312 :
313 21988 : ASSERT_VALID_IOVEC_POS(base);
314 :
315 21988 : vstr__cache_cbs(base, 0, 0, VSTR_TYPE_CACHE_FREE, FALSE);
316 :
317 21988 : ((Vstr_base *)base)->iovec_upto_date = FALSE;
318 : }
319 :
320 : static int vstr__resize_cache(const Vstr_base *base, unsigned int sz)
321 3098 : {
322 3098 : Vstr__cache *cache = NULL;
323 :
324 3098 : assert(base->cache_available && VSTR__CACHE(base));
325 3098 : assert(VSTR__CACHE(base)->sz < sz);
326 :
327 3098 : if (!VSTR__MV(VSTR__CACHE(base), cache,
328 : sizeof(Vstr__cache) + (sizeof(void *) * sz)))
329 : {
330 10 : base->conf->malloc_bad = TRUE;
331 10 : return (FALSE);
332 : }
333 3088 : cache = VSTR__CACHE(base);
334 :
335 3088 : vstr_wrap_memset(cache->data + cache->sz, 0,
336 : sizeof(void *) * (sz - cache->sz));
337 3088 : cache->sz = sz;
338 :
339 3088 : return (TRUE);
340 : }
341 :
342 : static void *vstr__cache_pos_cb(const Vstr_base *base,
343 : size_t pos, size_t VSTR__ATTR_UNUSED(len),
344 : unsigned int type, void *passed_data)
345 2028744 : {
346 2028744 : Vstr__cache_data_pos *data = passed_data;
347 :
348 2028744 : (void)base; /* no warnings when arsserts are off */
349 2028744 : ASSERT(base->grpalloc_cache >= VSTR_TYPE_CNTL_CONF_GRPALLOC_POS);
350 :
351 2028744 : if (type == VSTR_TYPE_CACHE_FREE)
352 21988 : return (NULL);
353 :
354 2006756 : if (!data->node)
355 1925066 : return (data);
356 :
357 81690 : if ((type == VSTR_TYPE_CACHE_ADD) && (pos >= data->pos))
358 20147 : return (data);
359 :
360 61543 : if ((type == VSTR_TYPE_CACHE_DEL) && (pos > data->pos))
361 16389 : return (data);
362 :
363 45154 : if (type == VSTR_TYPE_CACHE_SUB)
364 14372 : return (data);
365 :
366 : /* can't update data->num properly */
367 30782 : data->node = NULL;
368 30782 : return (data);
369 : }
370 :
371 : static void *vstr__cache_iovec_cb(const Vstr_base *base,
372 : size_t VSTR__ATTR_UNUSED(pos),
373 : size_t VSTR__ATTR_UNUSED(len),
374 : unsigned int type, void *passed_data)
375 1009157 : {
376 1009157 : Vstr__cache_data_iovec *data = passed_data;
377 :
378 1009157 : (void)base; /* no warnings when arsserts are off */
379 1009157 : assert(VSTR__CACHE(base)->vec == data);
380 1009157 : ASSERT(base->grpalloc_cache < VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC);
381 :
382 1009157 : if (type == VSTR_TYPE_CACHE_FREE)
383 : {
384 2936 : assert(VSTR__DEBUG_MALLOC_CHECK_MEM(data));
385 2936 : VSTR__F(data->v);
386 2936 : VSTR__F(data->t);
387 2936 : VSTR__F(data);
388 2936 : VSTR__CACHE(base)->vec = NULL;
389 :
390 2936 : return (NULL);
391 : }
392 :
393 : /* NOTE: add/del/sub/etc. handled by hand in the code, as we can do a lot more
394 : * optimizations there ... :O */
395 :
396 1006221 : return (data);
397 : }
398 :
399 : static void *vstr__cache_cstr_cb(const Vstr_base *base,
400 : size_t pos, size_t len,
401 : unsigned int type, void *passed_data)
402 303418 : {
403 303418 : Vstr__cache_data_cstr *data = passed_data;
404 303418 : const size_t end_pos = vstr_sc_poslast(pos, len);
405 303418 : const size_t data_end_pos = vstr_sc_poslast(data->pos, data->len);
406 :
407 303418 : ASSERT(passed_data);
408 :
409 303418 : if (type == VSTR_TYPE_CACHE_FREE)
410 : {
411 12805 : vstr_ref_del(data->ref);
412 12805 : data->ref = NULL;
413 12805 : if (base->grpalloc_cache < VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR)
414 166 : VSTR__F(data);
415 12805 : return (NULL);
416 : }
417 :
418 290613 : if (!data->ref || !data->len)
419 273664 : return (data);
420 :
421 16949 : if (data_end_pos < pos)
422 1010 : return (data);
423 :
424 15939 : if (type == VSTR_TYPE_CACHE_ADD)
425 : {
426 1082 : if (data_end_pos == pos)
427 917 : return (data);
428 :
429 165 : if (data->pos > pos)
430 : {
431 165 : data->pos += len;
432 165 : return (data);
433 : }
434 : }
435 14857 : else if (data->pos > end_pos)
436 : {
437 155 : if (type == VSTR_TYPE_CACHE_DEL)
438 155 : data->pos -= len;
439 :
440 155 : return (data);
441 : }
442 14702 : else if ((type == VSTR_TYPE_CACHE_DEL) && (data_end_pos > end_pos))
443 : { /* delete some of the begining of the cache cstr */
444 1625 : data->len -= vstr_sc_posdiff(data->pos, end_pos);
445 1625 : data->off += vstr_sc_posdiff(data->pos, end_pos);
446 :
447 1625 : data->pos = pos;
448 :
449 1625 : return (data);
450 : }
451 :
452 13077 : data->len = 0;
453 :
454 13077 : return (data);
455 : }
456 :
457 : int vstr__cache_conf_init(Vstr_conf *conf)
458 6273 : {
459 6273 : if (!(conf->cache_cbs_ents = VSTR__MK(sizeof(Vstr_cache_cb) * 3)))
460 1 : return (FALSE);
461 :
462 6272 : conf->cache_cbs_sz = 3;
463 :
464 6272 : conf->cache_pos_cb_sects = 0; /* NOTE: should really be in vstr_sects.c ...
465 : * but it's not a big problem */
466 :
467 6272 : conf->cache_cbs_ents[0].name = "/vstr__/pos";
468 6272 : conf->cache_cbs_ents[0].cb_func = vstr__cache_pos_cb;
469 6272 : conf->cache_pos_cb_pos = 1;
470 :
471 6272 : conf->cache_cbs_ents[1].name = "/vstr__/iovec";
472 6272 : conf->cache_cbs_ents[1].cb_func = vstr__cache_iovec_cb;
473 6272 : conf->cache_pos_cb_iovec = 2;
474 :
475 6272 : conf->cache_cbs_ents[2].name = "/vstr__/cstr";
476 6272 : conf->cache_cbs_ents[2].cb_func = vstr__cache_cstr_cb;
477 6272 : conf->cache_pos_cb_cstr = 3;
478 :
479 6272 : assert(VSTR__CACHE_INTERNAL_POS_MAX == 2);
480 :
481 6272 : return (TRUE);
482 : }
483 :
484 : /* initial stuff done in vstr.c */
485 : unsigned int vstr_cache_srch(Vstr_conf *passed_conf, const char *name)
486 133 : {
487 133 : Vstr_conf *conf = passed_conf ? passed_conf : vstr__options.def;
488 133 : unsigned int pos = 0;
489 :
490 413 : ASSERT(name);
491 :
492 571 : while (pos < conf->cache_cbs_sz)
493 : {
494 510 : if (!strcmp(name, conf->cache_cbs_ents[pos++].name))
495 72 : return (pos);
496 : }
497 :
498 61 : return (0);
499 : }
500 :
501 : unsigned int vstr_cache_add(Vstr_conf *passed_conf, const char *name,
502 : void *(*func)(const Vstr_base *, size_t, size_t,
503 : unsigned int, void *))
504 68 : {
505 68 : Vstr_conf *conf = passed_conf ? passed_conf : vstr__options.def;
506 68 : unsigned int sz = conf->cache_cbs_sz + 1;
507 68 : struct Vstr_cache_cb *ents = NULL;
508 :
509 68 : ASSERT(!vstr_cache_srch(conf, name));
510 :
511 68 : if (!VSTR__MV(conf->cache_cbs_ents, ents, sizeof(Vstr_cache_cb) * sz))
512 : {
513 4 : conf->malloc_bad = TRUE;
514 4 : return (0);
515 : }
516 64 : conf->cache_cbs_sz = sz;
517 :
518 64 : conf->cache_cbs_ents[sz - 1].name = name;
519 64 : conf->cache_cbs_ents[sz - 1].cb_func = func;
520 :
521 64 : ASSERT(vstr_cache_srch(conf, name));
522 :
523 64 : return (sz);
524 : }
525 :
526 : int vstr_cache_set(const Vstr_base *base, unsigned int pos, void *data)
527 38246 : {
528 38246 : ASSERT_RET(pos, FALSE);
529 :
530 38246 : if (!base->cache_available)
531 45 : return (FALSE);
532 :
533 38201 : assert(VSTR__CACHE(base));
534 :
535 38201 : if (pos-- > VSTR__CACHE(base)->sz)
536 : {
537 3098 : if (!vstr__resize_cache(base, pos + 1))
538 10 : return (FALSE);
539 : }
540 :
541 : /* we've set data for a user cache */
542 38191 : if ((pos > VSTR__CACHE_INTERNAL_POS_MAX) && data)
543 64 : ((Vstr_base *)base)->cache_internal = FALSE;
544 :
545 38191 : VSTR__CACHE(base)->data[pos] = data;
546 :
547 38191 : return (TRUE);
548 : }
549 :
550 : int vstr__cache_subset_cbs(Vstr_conf *ful_conf, Vstr_conf *sub_conf)
551 51 : {
552 51 : unsigned int scan = 0;
553 51 : struct Vstr_cache_cb *sub_cbs_ents = sub_conf->cache_cbs_ents;
554 51 : struct Vstr_cache_cb *ful_cbs_ents = ful_conf->cache_cbs_ents;
555 :
556 51 : if (sub_conf->cache_cbs_sz < ful_conf->cache_cbs_sz)
557 11 : return (FALSE);
558 :
559 165 : while (scan < ful_conf->cache_cbs_sz)
560 : {
561 130 : if (strcmp(ful_cbs_ents[scan].name, sub_cbs_ents[scan].name))
562 5 : return (FALSE); /* different ... so bad */
563 :
564 : /* NOTE: While "possible" this is crack if this isn't valid and is
565 : * bound to cause untracable bugs */
566 125 : ASSERT(ful_cbs_ents[scan].cb_func == sub_cbs_ents[scan].cb_func);
567 :
568 125 : ++scan;
569 : }
570 :
571 35 : return (TRUE);
572 : }
573 :
574 : int vstr__cache_dup_cbs(Vstr_conf *conf, Vstr_conf *dupconf)
575 11 : {
576 11 : Vstr_cache_cb *ents = conf->cache_cbs_ents;
577 11 : unsigned int scan = 0;
578 :
579 11 : if (conf->cache_cbs_sz < dupconf->cache_cbs_sz)
580 : {
581 6 : if (!VSTR__MV(conf->cache_cbs_ents, ents,
582 : sizeof(Vstr_cache_cb) * dupconf->cache_cbs_sz))
583 : {
584 1 : conf->malloc_bad = TRUE;
585 1 : return (FALSE);
586 : }
587 5 : conf->cache_cbs_sz = dupconf->cache_cbs_sz;
588 : }
589 :
590 55 : while (scan < dupconf->cache_cbs_sz)
591 : {
592 45 : ents[scan] = dupconf->cache_cbs_ents[scan];
593 45 : ++scan;
594 : }
595 :
596 10 : return (TRUE);
597 : }
598 :
599 : /* FIXME: changed in 1.0.10 --
600 : * always allocated now ... needed for ABI compat. however it can't be called */
601 : extern struct Vstr__cache_data_pos *
602 : vstr_extern_inline_make_cache_pos(const Vstr_base *);
603 : struct Vstr__cache_data_pos *
604 : vstr_extern_inline_make_cache_pos(const Vstr_base *base)
605 4 : {
606 4 : (void)base;
607 4 : ASSERT(FALSE);
608 4 : return (NULL);
609 : }
|