LTP GCOV extension - code coverage report
Current view: directory - src - vstr_del.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 249
Code covered: 99.6 % Executed lines: 248

       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                 : 

Generated by: LTP GCOV extension version 1.1