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

       1                 : #define VSTR_MOV_C
       2                 : /*
       3                 :  *  Copyright (C) 2001, 2002, 2003  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 move data from one vstr to another */
      22                 : #include "main.h"
      23                 : 
      24                 : static int vstr__mov_slow(Vstr_base *base, size_t pos,
      25                 :                           Vstr_base *from_base, size_t from_pos, size_t len)
      26              29 : {
      27              29 :   int ret = 0;
      28                 : 
      29              29 :   assert(base != from_base);
      30                 : 
      31              29 :   ret = vstr_add_vstr(base, pos,
      32                 :                       from_base, from_pos, len, VSTR_TYPE_ADD_DEF);
      33              29 :   if (!ret)
      34               3 :     return (FALSE);
      35                 : 
      36              26 :   ret = vstr_del(from_base, from_pos, len);
      37              26 :   if (!ret)
      38                 :   {
      39               1 :     ret = vstr_del(base, pos + 1, len);
      40               1 :     assert(ret); /* this must work as a split can't happen */
      41               1 :     return (FALSE);
      42                 :   }
      43                 : 
      44              25 :   return (ret);
      45                 : }
      46                 : 
      47                 : static int vstr__mov_single_node(Vstr_base *base, size_t pos,
      48                 :                                  size_t from_pos, size_t len)
      49            3170 : {
      50            3170 :   Vstr_node *scan = NULL;
      51            3170 :   char tbuf[VSTR__STACK_BUF_SZ];
      52            3170 :   unsigned int num = 0;
      53                 : 
      54            3170 :   if (len > sizeof(tbuf))
      55               5 :     return (FALSE);
      56                 : 
      57                 :   /* XX>XXXFFX = cp T, F1, FL; mv P1+FL, P1, F1-P1; cp P1, T, FL */
      58                 :   /* 123456789 */
      59                 :   /* XXFFXX>XX = cp T, F1, FL; mv F1, F1+FL, P1-F1; cp P1, T, FL */
      60                 : 
      61            3165 :   scan = vstr_base__pos(base, &pos, &num, TRUE);
      62            3165 :   if ((scan->type == VSTR_TYPE_NODE_BUF) &&
      63                 :       (vstr_base__pos(base, &from_pos, &num, TRUE) == scan) &&
      64                 :       (scan->len > len) &&
      65                 :       ((scan->len - len) >= from_pos))
      66                 :   {
      67            1837 :     char *ptr = vstr_export__node_ptr(scan);
      68                 : 
      69            1837 :     vstr_wrap_memcpy(tbuf, ptr + from_pos - 1, len);
      70            1837 :     if (pos > from_pos)
      71              15 :       vstr_wrap_memmove(ptr + from_pos + len - 1,
      72                 :                         ptr + from_pos - 1, (pos + 1) - from_pos); /* POSDIFF */
      73                 :     else
      74            1822 :       vstr_wrap_memmove(ptr + pos + len,
      75                 :                         ptr + pos, from_pos - (pos + 1));
      76            1837 :     vstr_wrap_memcpy(ptr + pos, tbuf, len);
      77                 : 
      78            1837 :     return (TRUE);
      79                 :   }
      80                 : 
      81            1328 :   return (FALSE);
      82                 : }
      83                 : 
      84                 : /* *ret == start of data */
      85                 : static Vstr_node **vstr__mov_setup_beg(Vstr_base *base, size_t pos,
      86                 :                                        unsigned int *num, Vstr_node **prev)
      87            5342 : {
      88            5342 :   Vstr_node *scan = NULL;
      89                 : 
      90            5342 :   assert(num && pos && prev);
      91            5342 :   --pos;
      92            5342 :   if (!pos)
      93                 :   {
      94            4008 :     *num = 1;
      95            4008 :     vstr__base_zero_used(base);
      96            4008 :     *prev = NULL;
      97            4008 :     return (&base->beg);
      98                 :   }
      99                 : 
     100            1334 :   scan = vstr_base__pos(base, &pos, num, TRUE);
     101                 : 
     102            1334 :   if ((pos != scan->len) && !(scan = vstr__base_split_node(base, scan, pos)))
     103              42 :     return (NULL);
     104                 : 
     105            1292 :   ++*num;
     106                 : 
     107            1292 :   *prev = scan;
     108            1292 :   return (&scan->next);
     109                 : }
     110                 : 
     111                 : /* *ret == after end of data */
     112                 : static Vstr_node **vstr__mov_setup_end(Vstr_base *base, size_t pos,
     113                 :                                        unsigned int *num)
     114           10647 : {
     115           10647 :   Vstr_node *scan = NULL;
     116           10647 :   unsigned int dummy_num;
     117                 : 
     118           10647 :   if (!num)
     119            5347 :     num = &dummy_num;
     120                 : 
     121           10647 :   if (!pos)
     122                 :   {
     123            1132 :     *num = 0;
     124            1132 :     vstr__base_zero_used(base);
     125            1132 :     return (&base->beg);
     126                 :   }
     127                 : 
     128            9515 :   scan = vstr_base__pos(base, &pos, num, TRUE);
     129                 : 
     130            9515 :   if ((pos != scan->len) && !(scan = vstr__base_split_node(base, scan, pos)))
     131               9 :     return (NULL);
     132                 : 
     133            9506 :   return (&scan->next);
     134                 : }
     135                 : 
     136                 : static void vstr__mov_iovec_kill(Vstr_base *base)
     137           10592 : {
     138           10592 :   if (!base->cache_available)
     139            2045 :     return;
     140                 : 
     141            8547 :   assert(VSTR__CACHE(base));
     142                 : 
     143            8547 :   base->iovec_upto_date = FALSE;
     144                 : }
     145                 : 
     146                 : int vstr_mov(Vstr_base *base, size_t pos,
     147                 :              Vstr_base *from_base, size_t from_pos, size_t len)
     148            7243 : {
     149            7243 :   Vstr_node *from_prev = NULL;
     150            7243 :   Vstr_node **beg = NULL;
     151            7243 :   Vstr_node **end = NULL;
     152            7243 :   Vstr_node **con = NULL;
     153            7243 :   Vstr_node *tmp = NULL;
     154            7243 :   unsigned int beg_num = 0;
     155            7243 :   unsigned int end_num = 0;
     156            7243 :   unsigned int num = 0;
     157            7243 :   unsigned int from_node_buf_used = FALSE;
     158            7243 :   unsigned int from_node_non_used = FALSE;
     159            7243 :   unsigned int from_node_ptr_used = FALSE;
     160            7243 :   unsigned int from_node_ref_used = FALSE;
     161            7243 :   unsigned int count = 0;
     162                 : 
     163            7243 :   if (!len)
     164              20 :     return (TRUE);
     165                 : 
     166            7223 :   assert(!(!base || (pos > base->len) ||
     167                 :            !from_base || (from_pos > from_base->len)));
     168                 : 
     169            7223 :   if ((base->conf->buf_sz != from_base->conf->buf_sz) &&
     170                 :       from_base->node_buf_used)
     171              29 :     return (vstr__mov_slow(base, pos, from_base, from_pos, len));
     172                 : 
     173            7194 :   if (base == from_base)
     174                 :   {
     175            3180 :     if ((pos >= (from_pos - 1)) && (pos < (from_pos + len)))
     176              10 :       return (TRUE); /* move a string anywhere into itself -- nop */
     177                 : 
     178            3170 :     if (vstr__mov_single_node(base, pos, from_pos, len))
     179            1837 :       return (TRUE);
     180                 :   }
     181                 : 
     182            5347 :   assert(vstr__check_real_nodes(base));
     183            5347 :   assert((from_base == base) || vstr__check_real_nodes(from_base));
     184                 : 
     185                 :   /* have to aquire the pointers in the right order,
     186                 :    * depending on which is first */
     187            5347 :   if (pos > from_pos)
     188            3095 :     goto move_up;
     189                 : 
     190            7548 :   while (count < 2)
     191                 :   {
     192            5347 :     if (!(con = vstr__mov_setup_end(base, pos, NULL)))
     193               5 :       return (FALSE);
     194            5342 :     ++count;
     195                 : 
     196            5342 :     if (count >= 2)
     197            3095 :       break;
     198                 :     
     199                 :    move_up:
     200            5342 :     if (!(beg = vstr__mov_setup_beg(from_base, from_pos, &beg_num, &from_prev)))
     201              42 :       return (FALSE);
     202                 : 
     203            5300 :     if (!(end = vstr__mov_setup_end(from_base, from_pos + len - 1, &end_num)))
     204               4 :       return (FALSE);
     205            5296 :     ++count;
     206                 :   }
     207            5296 :   assert(count == 2);
     208                 : 
     209            5296 :   from_node_buf_used = from_base->node_buf_used;
     210            5296 :   from_node_non_used = from_base->node_non_used;
     211            5296 :   from_node_ptr_used = from_base->node_ptr_used;
     212            5296 :   from_node_ref_used = from_base->node_ref_used;
     213                 : 
     214                 :   /* NOTE: the numbers might be off by one if con is before beg,
     215                 :    * but that doesn't matter as we just need the difference */
     216            5296 :   num = end_num - beg_num + 1;
     217                 : 
     218            5296 :   tmp = *beg;
     219            5296 :   if (!(*beg = *end))
     220            4252 :     from_base->end = from_prev;
     221                 : 
     222            5296 :   ASSERT(!!from_base->beg == !!from_base->end);
     223                 : 
     224            5296 :   from_base->len -= len;
     225            5296 :   from_base->num -= num;
     226            5296 :   vstr__cache_del(from_base, from_pos, len);
     227            5296 :   vstr__mov_iovec_kill(from_base);
     228                 : 
     229            5296 :   if (!from_base->len)
     230                 :   {
     231            3972 :     from_base->node_buf_used = FALSE;
     232            3972 :     from_base->node_non_used = FALSE;
     233            3972 :     from_base->node_ptr_used = FALSE;
     234            3972 :     from_base->node_ref_used = FALSE;
     235                 :   }
     236                 : 
     237            5296 :   beg = &tmp;
     238                 : 
     239            5296 :   *end = *con;
     240            5296 :   *con = *beg;
     241                 : 
     242            5296 :   if (!*end)
     243            4013 :     base->end = VSTR__CONV_PTR_NEXT_PREV(end);
     244                 : 
     245            5296 :   base->len += len;
     246            5296 :   base->num += num;
     247                 : 
     248            5296 :   base->node_buf_used |= from_node_buf_used;
     249            5296 :   base->node_non_used |= from_node_non_used;
     250            5296 :   base->node_ptr_used |= from_node_ptr_used;
     251            5296 :   base->node_ref_used |= from_node_ref_used;
     252                 : 
     253            5296 :   vstr__cache_add(base, pos, len);
     254            5296 :   vstr__mov_iovec_kill(base); /* This is easy to rm, if they append */
     255                 : 
     256            5296 :   assert(vstr__check_real_nodes(base));
     257            5296 :   assert((from_base == base) || vstr__check_real_nodes(from_base));
     258                 : 
     259            5296 :   return (TRUE);
     260                 : }

Generated by: LTP GCOV extension version 1.1