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

       1                 : #define VSTR_SUB_C
       2                 : /*
       3                 :  *  Copyright (C) 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 substitute data in a vstr */
      22                 : #include "main.h"
      23                 : 
      24                 : #define VSTR__SUB_BUF() do { \
      25                 :   if (tmp > buf_len) \
      26                 :     tmp = buf_len; \
      27                 :   \
      28                 :   vstr_wrap_memcpy((((Vstr_node_buf *)scan)->buf) + pos, buf, tmp); \
      29                 :   buf_len -= tmp; \
      30                 :   buf = ((char *)buf) + tmp; \
      31                 : } while (FALSE)
      32                 : 
      33                 : static int vstr__sub_buf_fast(Vstr_base *base, size_t pos, size_t len,
      34                 :                               const void *buf)
      35           32345 : {
      36           32345 :   Vstr_iter iter[1];
      37           32345 :   size_t buf_len = len;
      38                 : 
      39           32345 :   if (!vstr_iter_fwd_beg(base, pos, len, iter))
      40               8 :     return (FALSE);
      41                 : 
      42           32421 :   do
      43                 :   {
      44           32421 :     const size_t tmp = iter->len;
      45                 : 
      46           32421 :     assert(iter->node->type == VSTR_TYPE_NODE_BUF);
      47                 : 
      48           32421 :     vstr_wrap_memcpy((char *)iter->ptr, buf, tmp);
      49           32421 :     buf = ((char *)buf) + tmp;
      50           32421 :   } while (vstr_iter_fwd_nxt(iter));
      51                 : 
      52           32337 :   vstr_cache_cb_sub(base, pos, buf_len);
      53                 : 
      54           32337 :   return (TRUE);
      55                 : }
      56                 : 
      57                 : static int vstr__sub_buf_slow(Vstr_base *base, size_t pos, size_t len,
      58                 :                               const void *buf, size_t buf_len)
      59           22441 : {
      60           22441 :   Vstr_iter iter[1];
      61           22441 :   size_t orig_pos = pos;
      62           22441 :   size_t orig_buf_len = buf_len;
      63           22441 :   size_t sub_add_len = 0;
      64           22441 :   size_t add_len = 0;
      65           22441 :   size_t del_len = 0;
      66           22441 :   size_t real_pos = 0;
      67           22441 :   int ret = FALSE;
      68                 :   
      69           22441 :   assert(vstr__check_spare_nodes(base->conf));
      70           22441 :   assert(vstr__check_real_nodes(base));
      71                 : 
      72           22441 :   if (len > buf_len)
      73                 :   {
      74             184 :     del_len = len - buf_len;
      75             184 :     len = buf_len;
      76                 :   }
      77                 :   else
      78           22257 :     add_len = buf_len - len;
      79                 : 
      80           22441 :   ret = vstr_iter_fwd_beg(base, pos, len, iter);
      81           22441 :   ASSERT_RET(ret, FALSE);
      82                 : 
      83           22490 :   do
      84                 :   {
      85           22490 :     size_t tmp = iter->len;
      86                 : 
      87           22490 :     ASSERT(tmp <= buf_len); /* iter is capped to buffer length */
      88                 : 
      89           22490 :     if (iter->node->type != VSTR_TYPE_NODE_BUF)
      90           13850 :       sub_add_len += tmp;
      91                 : 
      92           22490 :     buf_len -= tmp;
      93           22490 :   } while (buf_len && vstr_iter_fwd_nxt(iter));
      94                 : 
      95           22441 :   buf_len = orig_buf_len;
      96                 : 
      97           22441 :   if ((sub_add_len == buf_len) || (sub_add_len == len))
      98                 :   { /* no _BUF nodes, so we can't optimise it anyway ... */
      99           13826 :     ret = vstr_add_buf(base, pos - 1, buf, buf_len);
     100                 : 
     101           13826 :     if (!ret)
     102               4 :       return (FALSE);
     103                 : 
     104           13822 :     ret = vstr_del(base, pos + buf_len, len + del_len);
     105           13822 :     ASSERT(ret || !buf_len); /* if stuff added, then split happened ... so
     106                 :                               * can't fail */
     107                 : 
     108           13822 :     return (ret);
     109                 :   }
     110                 : 
     111            8615 :   add_len += sub_add_len;
     112                 : 
     113            8615 :   if (add_len)
     114                 :   {
     115                 :     /* allocate extra _BUF nodes needed, all other are ok -- no splits will
     116                 :      * happen on non _BUF nodes */
     117             151 :     unsigned int num = (add_len / base->conf->buf_sz) + 2;
     118             151 :     if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF,
     119                 :                         num, UINT_MAX))
     120               2 :       return (FALSE);
     121                 :   }
     122                 :   
     123            8613 :   if (sub_add_len)
     124                 :   { /* loop again removing any non _BUF nodes */
     125              10 :     int nxt_iter = FALSE;
     126                 : 
     127              10 :     ret = vstr_iter_fwd_beg(base, pos, len, iter);
     128              10 :     ASSERT_RET(ret, FALSE);
     129                 : 
     130              20 :     do
     131                 :     {
     132              20 :       size_t tmp_len        = iter->len;
     133              20 :       unsigned int tmp_type = iter->node->type;
     134                 : 
     135              20 :       nxt_iter = vstr_iter_fwd_nxt(iter);
     136                 : 
     137              20 :       if (tmp_type != VSTR_TYPE_NODE_BUF)
     138                 :       {
     139              10 :         vstr_del(base, pos, tmp_len);
     140              10 :         len -= tmp_len;
     141                 :       }
     142                 : 
     143              20 :       pos += tmp_len;
     144              20 :     } while (buf_len && nxt_iter);
     145                 :   }
     146                 : 
     147            8613 :   vstr__sub_buf_fast(base, orig_pos, len, buf);
     148                 : 
     149            8613 :   real_pos = orig_pos + len;
     150            8613 :   buf_len -= len;
     151            8613 :   buf = ((char *)buf) + len;
     152                 : 
     153            8613 :   if (del_len)
     154             140 :     vstr_del(base, real_pos, del_len);
     155                 : 
     156            8613 :   if (buf_len)
     157             149 :     vstr_add_buf(base, real_pos - 1, buf, buf_len);
     158                 : 
     159            8613 :   assert(vstr__check_spare_nodes(base->conf));
     160            8613 :   assert(vstr__check_real_nodes(base));
     161                 : 
     162            8613 :   return (TRUE);
     163                 : }
     164                 : 
     165                 : int vstr_sub_buf(Vstr_base *base, size_t pos, size_t len,
     166                 :                  const void *buf, size_t buf_len)
     167           46192 : {
     168           46192 :   ASSERT_RET(base, FALSE);
     169                 :   
     170           46188 :   if (!len)
     171              10 :     return (vstr_add_buf(base, pos - 1, buf, buf_len));
     172                 : 
     173           46178 :   if (!buf_len)
     174               5 :     return (vstr_del(base, pos, len));
     175                 :   
     176           46173 :   if ((len == buf_len) &&
     177                 :       !base->node_non_used &&
     178                 :       !base->node_ptr_used &&
     179                 :       !base->node_ref_used)
     180           23732 :     return (vstr__sub_buf_fast(base, pos, len, buf));
     181                 : 
     182           22441 :   return (vstr__sub_buf_slow(base, pos, len, buf, buf_len));
     183                 : }
     184                 : 
     185                 : int vstr_sub_non(Vstr_base *base, size_t pos, size_t len, size_t non_len)
     186             120 : {
     187             120 :   int ret = vstr_add_non(base, pos - 1, non_len);
     188                 : 
     189             120 :   if (!ret)
     190               2 :     return (FALSE);
     191                 : 
     192             118 :   ret = vstr_del(base, pos + non_len, len);
     193             118 :   ASSERT(ret || !non_len); /* if stuff added, then split happened ... so
     194                 :                             * can't fail */
     195                 : 
     196             118 :   return (ret);
     197                 : }
     198                 : 
     199                 : int vstr_sub_ptr(Vstr_base *base, size_t pos, size_t len,
     200                 :                  const void *ptr, size_t ptr_len)
     201              79 : {
     202              79 :   int ret = FALSE;
     203              79 :   Vstr_iter iter[1];
     204                 : 
     205              79 :   if (!len || !ptr_len)
     206               5 :     goto simple_sub;
     207                 : 
     208              60 :   if (!(ret = vstr_iter_fwd_beg(base, pos, len, iter)))
     209               8 :     return (FALSE);
     210                 : 
     211              52 :   if ((ptr_len <= VSTR_MAX_NODE_ALL) && VSTR__ITER_EQ_ALL_NODE(base, iter))
     212                 :   {
     213              42 :     Vstr_node_ptr *ptr_node = NULL;
     214                 : 
     215              42 :     if (iter->node->type == VSTR_TYPE_NODE_PTR)
     216              21 :       ptr_node = (Vstr_node_ptr *)iter->node;
     217                 :     else
     218                 :     {
     219              21 :       if (!vstr_cntl_conf(base->conf,
     220                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR, 1, UINT_MAX))
     221               1 :         return (FALSE);
     222              20 :       --base->conf->spare_ptr_num;
     223              20 :       ptr_node = base->conf->spare_ptr_beg;
     224              20 :       base->conf->spare_ptr_beg = (Vstr_node_ptr *)ptr_node->s.next;
     225                 :     }
     226                 : 
     227              41 :     if (ptr_len < len)
     228                 :     {
     229               5 :       size_t diff_len = len - ptr_len;
     230                 : 
     231               5 :       len             -= diff_len;
     232               5 :       iter->node->len -= diff_len;
     233               5 :       base->len       -= diff_len;
     234               5 :       vstr__cache_del(base, pos, diff_len);
     235                 :     }
     236                 : 
     237              41 :     ptr_node->s.len = len;
     238              41 :     ptr_node->ptr = (void *)ptr;
     239                 : 
     240              41 :     if (iter->node->type == VSTR_TYPE_NODE_PTR)
     241              21 :       vstr__cache_iovec_reset_node(base, &ptr_node->s, iter->num);
     242                 :     else
     243              20 :       vstr__swap_node_X_X(base, pos, &ptr_node->s);
     244                 : 
     245              41 :     vstr_cache_cb_sub(base, pos, ptr_len);
     246                 : 
     247              41 :     if (ptr_len > len)
     248                 :     {
     249              10 :       size_t diff_len = ptr_len - len;
     250                 : 
     251              10 :       ptr_node->s.len += diff_len;
     252              10 :       base->len     += diff_len;
     253                 : 
     254              10 :       vstr__cache_iovec_reset_node(base, &ptr_node->s, iter->num);
     255              10 :       vstr__cache_add(base, pos, diff_len);
     256                 :     }
     257                 : 
     258              41 :     assert(vstr__check_spare_nodes(base->conf));
     259              41 :     assert(vstr__check_real_nodes(base));
     260              41 :     return (TRUE);
     261                 :   }
     262                 : 
     263                 :  simple_sub:
     264              29 :   ret = vstr_add_ptr(base, pos - 1, ptr, ptr_len);
     265                 : 
     266              29 :   if (!ret)
     267               4 :     return (FALSE);
     268                 : 
     269              25 :   ret = vstr_del(base, pos + ptr_len, len);
     270              25 :   ASSERT(ret || !ptr_len); /* if stuff added, then split happened ... so
     271                 :                             * can't fail */
     272                 : 
     273              25 :   return (ret);
     274                 : }
     275                 : 
     276                 : int vstr_sub_ref(Vstr_base *base, size_t pos, size_t len,
     277                 :                  Vstr_ref *ref, size_t off, size_t ref_len)
     278              51 : {
     279              51 :   int ret = FALSE;
     280              51 :   Vstr_iter iter[1];
     281                 : 
     282              51 :   if (!len || !ref_len)
     283               5 :     goto simple_sub;
     284                 : 
     285              46 :   if (!(ret = vstr_iter_fwd_beg(base, pos, len, iter)))
     286              12 :     return (FALSE);
     287                 : 
     288              34 :   if ((ref_len <= VSTR_MAX_NODE_ALL) && VSTR__ITER_EQ_ALL_NODE(base, iter))
     289                 :   {
     290              25 :     Vstr_node_ref *ref_node = NULL;
     291                 : 
     292              25 :     vstr_ref_add(ref);
     293                 : 
     294              25 :     if (iter->node->type == VSTR_TYPE_NODE_REF)
     295              11 :       ref_node = (Vstr_node_ref *)iter->node;
     296                 :     else
     297                 :     {
     298              14 :       if (!vstr_cntl_conf(base->conf,
     299                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF, 1, UINT_MAX))
     300               4 :         return (FALSE);
     301              10 :       --base->conf->spare_ref_num;
     302              10 :       ref_node = base->conf->spare_ref_beg;
     303              10 :       base->conf->spare_ref_beg = (Vstr_node_ref *)ref_node->s.next;
     304              10 :       ref_node->ref = NULL;
     305                 :     }
     306                 : 
     307              21 :     if (ref_len < len)
     308                 :     {
     309               5 :       size_t diff_len = len - ref_len;
     310                 : 
     311               5 :       len             -= diff_len;
     312               5 :       iter->node->len -= diff_len;
     313               5 :       base->len       -= diff_len;
     314               5 :       vstr__cache_del(base, pos, diff_len);
     315                 :     }
     316                 : 
     317              21 :     vstr_ref_del(ref_node->ref);
     318                 : 
     319              21 :     ref_node->s.len = len;
     320              21 :     ref_node->ref = ref;
     321              21 :     ref_node->off = off;
     322                 : 
     323              21 :     if (iter->node->type == VSTR_TYPE_NODE_REF)
     324              11 :       vstr__cache_iovec_reset_node(base, &ref_node->s, iter->num);
     325                 :     else
     326              10 :       vstr__swap_node_X_X(base, pos, &ref_node->s);
     327                 : 
     328              21 :     vstr_cache_cb_sub(base, pos, ref_len);
     329                 : 
     330              21 :     if (ref_len > len)
     331                 :     {
     332              10 :       size_t diff_len = ref_len - len;
     333                 : 
     334              10 :       ref_node->s.len += diff_len;
     335              10 :       base->len     += diff_len;
     336                 : 
     337              10 :       vstr__cache_iovec_reset_node(base, &ref_node->s, iter->num);
     338              10 :       vstr__cache_add(base, pos, diff_len);
     339                 :     }
     340                 : 
     341              21 :     assert(vstr__check_spare_nodes(base->conf));
     342              21 :     assert(vstr__check_real_nodes(base));
     343              21 :     return (TRUE);
     344                 :   }
     345                 : 
     346                 :  simple_sub:
     347              14 :   ret = vstr_add_ref(base, pos - 1, ref, off, ref_len);
     348                 : 
     349              14 :   if (!ret)
     350               5 :     return (FALSE);
     351                 : 
     352               9 :   ret = vstr_del(base, pos + ref_len, len);
     353               9 :   ASSERT(ret || !ref_len); /* if stuff added, then split happened ... so
     354                 :                             * can't fail */
     355                 : 
     356               9 :   return (ret);
     357                 : }
     358                 : 
     359                 : int vstr_sub_vstr(Vstr_base *base, size_t pos, size_t len,
     360                 :                   const Vstr_base *from_base,
     361                 :                   size_t from_pos, size_t from_len, unsigned int type)
     362              67 : { /* TODO: this is inefficient compared to vstr_sub_buf() because of atomic
     363                 :    * guarantees - could be made to work with _ALL_BUF */
     364              67 :   int ret = TRUE;
     365                 : 
     366              67 :   assert(pos && from_pos);
     367                 : 
     368              67 :   ret = vstr_add_vstr(base, pos - 1, from_base, from_pos, from_len, type);
     369                 : 
     370              67 :   if (!ret)
     371               2 :     return (FALSE);
     372                 : 
     373              65 :   ret = vstr_del(base, pos + from_len, len);
     374              65 :   ASSERT(ret || !from_len); /* if stuff added, then split happened ... so
     375                 :                              * can't fail */
     376                 : 
     377              65 :   return (ret);
     378                 : }
     379                 : 
     380                 : int vstr_sub_rep_chr(Vstr_base *base, size_t pos, size_t len,
     381                 :                      char chr, size_t rep_len)
     382              61 : {
     383              61 :   int ret = TRUE;
     384                 :   
     385              61 :   ASSERT_RET(ret, FALSE);
     386                 :   
     387              61 :   if (!len && !rep_len)
     388               5 :     return (TRUE);
     389                 : 
     390              56 :   if (rep_len == 1)
     391              10 :     return (vstr_sub_buf(base, pos, len, &chr, 1));
     392                 :   
     393                 :   /* TODO: this is a simple opt. */
     394              46 :   if ((len == rep_len) &&
     395                 :       !base->node_non_used &&
     396                 :       !base->node_ptr_used &&
     397                 :       !base->node_ref_used)
     398                 :   {
     399              13 :     Vstr_iter iter[1];
     400                 : 
     401              13 :     if (!(ret = vstr_iter_fwd_beg(base, pos, len, iter)))
     402               8 :       return (FALSE);
     403                 : 
     404               5 :     do
     405                 :     {
     406               5 :       const size_t tmp = iter->len;
     407                 : 
     408               5 :       assert(iter->node->type == VSTR_TYPE_NODE_BUF);
     409                 : 
     410               5 :       vstr_wrap_memset((char *)iter->ptr, chr, tmp);
     411               5 :     } while (vstr_iter_fwd_nxt(iter));
     412                 : 
     413               5 :     vstr_cache_cb_sub(base, pos, rep_len);
     414                 : 
     415               5 :     return (TRUE);
     416                 :   }
     417                 :   /* need something like vstr_sub_buf() so mostly _BUF strings can
     418                 :    * be quick here */
     419                 :      
     420              33 :   ret = vstr_add_rep_chr(base, pos - 1, chr, rep_len);
     421                 : 
     422              33 :   if (!ret)
     423               5 :     return (FALSE);
     424                 : 
     425              28 :   ret = vstr_del(base, pos + rep_len, len);
     426              28 :   ASSERT(ret || !rep_len); /* if stuff added, then split happened ... so
     427                 :                             * can't fail */
     428                 : 
     429              28 :   return (ret);
     430                 : }

Generated by: LTP GCOV extension version 1.1