LTP GCOV extension - code coverage report
Current view: directory - src - vstr_cache.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 306
Code covered: 100.0 % Executed lines: 306

       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                 : }

Generated by: LTP GCOV extension version 1.1