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

       1                 : #define VSTR_ADD_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 add data to a vstr */
      22                 : #include "main.h"
      23                 : 
      24                 : static void vstr__cache_iovec_add_end(Vstr_base *base, Vstr_node *node,
      25                 :                                       unsigned int len)
      26          459626 : {
      27          459626 :   char *tmp = NULL;
      28          459626 :   unsigned int num = 0;
      29                 : 
      30          459626 :   tmp = vstr_export__node_ptr(node);
      31          459626 :   ASSERT((node != base->beg) || !base->used);
      32                 : 
      33          459626 :   num = VSTR__CACHE(base)->vec->off + base->num - 1;
      34                 :   
      35          459626 :   ASSERT(num < VSTR__CACHE(base)->vec->sz);
      36                 :   
      37          459626 :   VSTR__CACHE(base)->vec->v[num].iov_len  = len;
      38          459626 :   VSTR__CACHE(base)->vec->v[num].iov_base = tmp;
      39          459626 :   VSTR__CACHE(base)->vec->t[num]          = node->type;
      40                 : }
      41                 : 
      42                 : static void vstr__cache_iovec_add_beg(Vstr_base *base, Vstr_node *node,
      43                 :                                       unsigned int len)
      44              45 : {
      45              45 :   char *tmp = NULL;
      46              45 :   unsigned int num = 0;
      47                 : 
      48              45 :   tmp = vstr_export__node_ptr(node);
      49                 : 
      50              45 :   ASSERT(VSTR__CACHE(base)->vec->off);
      51              45 :   num = --VSTR__CACHE(base)->vec->off;
      52                 : 
      53              45 :   VSTR__CACHE(base)->vec->v[num].iov_len  = len;
      54              45 :   VSTR__CACHE(base)->vec->v[num].iov_base = tmp;
      55              45 :   VSTR__CACHE(base)->vec->t[num]          = node->type;
      56                 : }
      57                 : 
      58                 : void vstr__cache_iovec_add_node_end(Vstr_base *base, unsigned int num,
      59                 :                                     unsigned int len)
      60          751413 : { /* done by hand in vstr-inline.h -- for add_buf and add_rep_chr */
      61          751413 :   if (!base->iovec_upto_date)
      62          312152 :     return;
      63                 : 
      64          439261 :   num += VSTR__CACHE(base)->vec->off;
      65          439261 :   VSTR__CACHE(base)->vec->v[num - 1].iov_len += len;
      66                 : }
      67                 : 
      68                 : static void vstr__cache_iovec_maybe_add(Vstr_base *base, Vstr_node *node,
      69                 :                                         int at_end, unsigned int len)
      70         1288943 : {
      71         1288943 :   if (!base->iovec_upto_date)
      72          787623 :     return;
      73                 :   
      74          501320 :   if (at_end &&
      75                 :       (base->num <= (VSTR__CACHE(base)->vec->sz - VSTR__CACHE(base)->vec->off)))
      76          459626 :     vstr__cache_iovec_add_end(base, node, len);
      77           41694 :   else if (!at_end && VSTR__CACHE(base)->vec->off)
      78              45 :     vstr__cache_iovec_add_beg(base, node, len);
      79                 :   else
      80           41649 :     base->iovec_upto_date = FALSE;
      81                 : }
      82                 : 
      83                 : Vstr_node *vstr__add_setup_pos(Vstr_base *base, size_t *pos, unsigned int *num,
      84                 :                                size_t *orig_scan_len)
      85         1413535 : {
      86         1413535 :   Vstr_node *scan = NULL;
      87                 : 
      88         1413535 :   assert(base && pos && num && *pos);
      89                 : 
      90         1413535 :   scan = vstr_base__pos(base, pos, num, TRUE);;
      91                 : 
      92         1413535 :   if (orig_scan_len)
      93          267151 :     *orig_scan_len = scan->len;
      94                 : 
      95         1413535 :   if ((*pos != scan->len) && !(scan = vstr__base_split_node(base, scan, *pos)))
      96              25 :     return (NULL);
      97         1413510 :   assert(*pos == scan->len);
      98                 : 
      99         1413510 :   return (scan);
     100                 : }
     101                 : 
     102                 : /* add 2: one for setup_pos -> split_node ; one for rouding error in divide */
     103                 : #define VSTR__ADD_BEG(max, int_type, o_p_s_l) do { \
     104                 :  assert(vstr__check_spare_nodes(base->conf)); \
     105                 :  assert(vstr__check_real_nodes(base)); \
     106                 :  \
     107                 :  if (pos && base->len) \
     108                 :  { \
     109                 :    scan = vstr__add_setup_pos(base, &pos, &num, o_p_s_l); \
     110                 :    if (!scan) \
     111                 :      return (FALSE); \
     112                 :  } \
     113                 :  \
     114                 :  if (((VSTR_TYPE_NODE_ ## int_type) != VSTR_TYPE_NODE_BUF) || !scan || \
     115                 :      (scan->type != VSTR_TYPE_NODE_BUF) || (pos != scan->len) || \
     116                 :      (len > (base->conf->buf_sz - scan->len))) \
     117                 :  { \
     118                 :    unsigned int alloc_num = (len / max) + !!(len % max); \
     119                 :    \
     120                 :    if (!vstr_cntl_conf(base->conf, \
     121                 :                        VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_ ## int_type, \
     122                 :                        alloc_num, UINT_MAX)) \
     123                 :      return (FALSE); \
     124                 :  } \
     125                 :  \
     126                 :  if (pos && base->len) \
     127                 :  { \
     128                 :   pos_scan = scan; \
     129                 :   pos_scan_next = scan->next \
     130                 : 
     131                 : #define VSTR__ADD_MID(max, node_type) \
     132                 :   if (scan != base->end) \
     133                 :     base->iovec_upto_date = FALSE; \
     134                 :  } \
     135                 :  else if (base->len) \
     136                 :  { \
     137                 :    pos_scan_next = base->beg; \
     138                 :    assert(!pos); \
     139                 :    vstr__base_zero_used(base); \
     140                 :  } else if (!pos && !base->len) pos = 1; \
     141                 :  \
     142                 :  scan = (Vstr_node *)base->conf-> spare_ ## node_type ## _beg; \
     143                 :  if (pos_scan) \
     144                 :  { \
     145                 :   assert(base->len); \
     146                 :   pos_scan->next = scan; \
     147                 :  } \
     148                 :  else \
     149                 :    base->beg = scan; \
     150                 :  \
     151                 :  num = 0; \
     152                 :  base->len += len; \
     153                 :  \
     154                 :  while (len > 0) \
     155                 :  { \
     156                 :   size_t tmp = (max); \
     157                 :   \
     158                 :   if (tmp > len) \
     159                 :     tmp = len; \
     160                 :   \
     161                 :   base-> node_ ## node_type ## _used = TRUE; \
     162                 :   ++num; \
     163                 :   ++base->num; \
     164                 : 
     165                 : #define VSTR__ADD_END(node_type, int_type, o_p_s_l) \
     166                 :   scan->len = tmp; \
     167                 :   \
     168                 :   vstr__cache_iovec_maybe_add(base, scan, pos, tmp); \
     169                 :   \
     170                 :   len -= tmp; \
     171                 :   \
     172                 :   if (!len) \
     173                 :     break; \
     174                 :   \
     175                 :   scan = scan->next; \
     176                 :  } \
     177                 :  \
     178                 :  base->conf-> spare_ ## node_type ## _beg = \
     179                 :    (Vstr_node_ ## node_type *)scan->next; \
     180                 :  base->conf-> spare_ ## node_type ## _num -= num; \
     181                 :  \
     182                 :  assert(!scan || (scan->type == (VSTR_TYPE_NODE_ ## int_type))); \
     183                 :  \
     184                 :  if (!(scan->next = pos_scan_next)) \
     185                 :    base->end = scan; \
     186                 :  \
     187                 :  vstr__cache_add(base, orig_pos, orig_len); \
     188                 :  \
     189                 :  ASSERT(vstr__check_spare_nodes(base->conf)); \
     190                 :  ASSERT(vstr__check_real_nodes(base)); \
     191                 : } while (FALSE)
     192                 : 
     193                 : int vstr_extern_inline_add_buf(Vstr_base *base, size_t pos,
     194                 :                                const void *buffer, size_t len)
     195          309703 : {
     196          309703 :   unsigned int num = 0;
     197          309703 :   size_t orig_pos = pos;
     198          309703 :   size_t orig_len = len;
     199          309703 :   Vstr_node *scan = NULL;
     200          309703 :   Vstr_node *pos_scan = NULL;
     201          309703 :   Vstr_node *pos_scan_next = NULL;
     202          309703 :   size_t orig_pos_scan_len = 0;
     203                 : 
     204          309703 :   ASSERT_RET(!(!base || !buffer || !len || (pos > base->len)), FALSE);
     205                 : 
     206          309703 :   VSTR__ADD_BEG(base->conf->buf_sz, BUF, &orig_pos_scan_len);
     207                 : 
     208          197863 :   if ((scan->type == VSTR_TYPE_NODE_BUF) && (pos == scan->len) &&
     209                 :       (scan->len < base->conf->buf_sz))
     210                 :   {
     211           97024 :     size_t tmp = (base->conf->buf_sz - scan->len);
     212                 : 
     213           97024 :     assert(base->node_buf_used);
     214                 : 
     215           97024 :     if (tmp > len)
     216           14293 :       tmp = len;
     217                 : 
     218           97024 :     vstr_wrap_memcpy(((Vstr_node_buf *)scan)->buf + scan->len, buffer, tmp);
     219           97024 :     scan->len += tmp;
     220           97024 :     buffer = ((char *)buffer) + tmp;
     221                 : 
     222           97024 :     vstr__cache_iovec_add_node_end(base, num, tmp);
     223                 : 
     224           97024 :     base->len += tmp;
     225           97024 :     len       -= tmp;
     226                 : 
     227           97024 :     if (!len)
     228                 :     {
     229           14458 :       vstr__cache_add(base, orig_pos, orig_len);
     230                 : 
     231           14458 :       assert(vstr__check_real_nodes(base));
     232           14458 :       return (TRUE);
     233                 :     }
     234                 :   }
     235                 : 
     236          183405 :   VSTR__ADD_MID(base->conf->buf_sz, buf);
     237                 : 
     238          345191 :   vstr_wrap_memcpy(((Vstr_node_buf *)scan)->buf, buffer, tmp);
     239          345191 :   buffer = ((char *)buffer) + tmp;
     240                 : 
     241          345191 :   VSTR__ADD_END(buf, BUF, orig_pos_scan_len);
     242                 : 
     243          275390 :   return (TRUE);
     244                 : }
     245                 : 
     246                 : int vstr_add_ptr(Vstr_base *base, size_t pos,
     247                 :                  const void *pass_ptr, size_t len)
     248          443894 : {
     249          443894 :   unsigned int num = 0;
     250          443894 :   size_t orig_pos = pos;
     251          443894 :   size_t orig_len = len;
     252          443894 :   char *ptr = (char *)pass_ptr; /* store as a char *, but _don't_ alter it */
     253          443894 :   Vstr_node *scan = NULL;
     254          443894 :   Vstr_node *pos_scan = NULL;
     255          443894 :   Vstr_node *pos_scan_next = NULL;
     256                 : 
     257          443894 :   ASSERT_RET(!(!base || (pos > base->len)), FALSE);
     258                 : 
     259          443882 :   if (!len)
     260              40 :     return (TRUE);
     261                 : 
     262          443842 :   VSTR__ADD_BEG(VSTR_MAX_NODE_ALL, PTR, NULL);
     263                 : 
     264          326910 :   if ((scan->type == VSTR_TYPE_NODE_PTR) &&
     265                 :       ((((char *)((Vstr_node_ptr *)scan)->ptr) + scan->len) == ptr) &&
     266                 :       (pos == scan->len) && (scan->len < VSTR_MAX_NODE_ALL))
     267                 :   {
     268              36 :     size_t tmp = VSTR_MAX_NODE_ALL - scan->len;
     269                 : 
     270              36 :     assert(base->node_ptr_used);
     271                 : 
     272              36 :     if (tmp > len)
     273              36 :       tmp = len;
     274                 : 
     275              36 :     scan->len += tmp;
     276                 : 
     277              36 :     vstr__cache_iovec_add_node_end(base, num, tmp);
     278                 : 
     279              36 :     base->len += tmp;
     280              36 :     len       -= tmp;
     281                 : 
     282              36 :     if (!len)
     283                 :     {
     284              36 :       vstr__cache_add(base, orig_pos, orig_len);
     285                 : 
     286              36 :       assert(vstr__check_real_nodes(base));
     287              36 :       return (TRUE);
     288                 :     }
     289                 :   }
     290                 : 
     291          326874 :   VSTR__ADD_MID(VSTR_MAX_NODE_ALL, ptr);
     292                 : 
     293          443605 :   base->node_ptr_used = TRUE;
     294          443605 :   ((Vstr_node_ptr *)scan)->ptr = ptr;
     295          443605 :   ptr += tmp;
     296                 : 
     297          443605 :   VSTR__ADD_END(ptr, PTR, pos_scan->len);
     298                 : 
     299          443605 :   return (TRUE);
     300                 : }
     301                 : 
     302                 : int vstr_add_non(Vstr_base *base, size_t pos, size_t len)
     303            1614 : {
     304            1614 :   unsigned int num = 0;
     305            1614 :   size_t orig_pos = pos;
     306            1614 :   size_t orig_len = len;
     307            1614 :   Vstr_node *scan = NULL;
     308            1614 :   Vstr_node *pos_scan = NULL;
     309            1614 :   Vstr_node *pos_scan_next = NULL;
     310            1614 :   size_t orig_pos_scan_len = 0;
     311                 : 
     312            1614 :   ASSERT_RET(!(!base || (pos > base->len)), FALSE);
     313                 : 
     314            1606 :   if (!len)
     315              15 :     return (TRUE);
     316                 : 
     317            1591 :   VSTR__ADD_BEG(VSTR_MAX_NODE_ALL, NON, &orig_pos_scan_len);
     318                 : 
     319            1221 :   if ((scan->type == VSTR_TYPE_NODE_NON) && (scan->len < VSTR_MAX_NODE_ALL))
     320                 :   {
     321               9 :     size_t tmp = VSTR_MAX_NODE_ALL - scan->len;
     322                 : 
     323               9 :     assert(base->node_non_used);
     324                 : 
     325               9 :     if (tmp > len)
     326               9 :       tmp = len;
     327                 : 
     328               9 :     scan->len += tmp;
     329                 : 
     330               9 :     vstr__cache_iovec_add_node_end(base, num, tmp);
     331                 : 
     332               9 :     base->len += tmp;
     333               9 :     len       -= tmp;
     334                 : 
     335               9 :     if (!len)
     336                 :     {
     337               9 :       vstr__cache_add(base, orig_pos, orig_len);
     338                 : 
     339               9 :       assert(vstr__check_real_nodes(base));
     340               9 :       return (TRUE);
     341                 :     }
     342                 :   }
     343                 : 
     344            1212 :   VSTR__ADD_MID(VSTR_MAX_NODE_ALL, non);
     345            1705 :   VSTR__ADD_END(non, NON, orig_pos_scan_len);
     346                 : 
     347            1561 :   return (TRUE);
     348                 : }
     349                 : 
     350                 : int vstr_add_ref(Vstr_base *base, size_t pos,
     351                 :                  Vstr_ref *ref, size_t off, size_t len)
     352          797745 : {
     353          797745 :   unsigned int num = 0;
     354          797745 :   size_t orig_pos = pos;
     355          797745 :   size_t orig_len = len;
     356          797745 :   Vstr_node *scan = NULL;
     357          797745 :   Vstr_node *pos_scan = NULL;
     358          797745 :   Vstr_node *pos_scan_next = NULL;
     359                 : 
     360          797745 :   ASSERT_RET(!(!base || !ref || (pos > base->len)), FALSE);
     361                 : 
     362          797733 :   if (!len)
     363              40 :     return (TRUE);
     364                 : 
     365          797693 :   VSTR__ADD_BEG(VSTR_MAX_NODE_ALL, REF, NULL);
     366                 : 
     367          792356 :   if ((scan->type == VSTR_TYPE_NODE_REF) &&
     368                 :       (((Vstr_node_ref *)scan)->ref == ref) &&
     369                 :       ((((Vstr_node_ref *)scan)->off + scan->len) == off) &&
     370                 :       (pos == scan->len) && (scan->len < VSTR_MAX_NODE_ALL))
     371                 :   {
     372          628653 :     size_t tmp = VSTR_MAX_NODE_ALL - scan->len;
     373                 : 
     374          628653 :     assert(base->node_ref_used);
     375                 : 
     376          628653 :     if (tmp > len)
     377          628653 :       tmp = len;
     378                 : 
     379          628653 :     scan->len += tmp;
     380                 : 
     381          628653 :     vstr__cache_iovec_add_node_end(base, num, tmp);
     382                 : 
     383          628653 :     base->len += tmp;
     384          628653 :     len       -= tmp;
     385                 : 
     386          628653 :     if (!len)
     387                 :     {
     388          628653 :       vstr__cache_add(base, orig_pos, orig_len);
     389                 : 
     390          628653 :       assert(vstr__check_real_nodes(base));
     391          628653 :       return (TRUE);
     392                 :     }
     393                 :   }
     394                 : 
     395          163703 :   VSTR__ADD_MID(VSTR_MAX_NODE_ALL, ref);
     396                 : 
     397          168879 :   ((Vstr_node_ref *)scan)->ref = vstr_ref_add(ref);
     398          168879 :   ((Vstr_node_ref *)scan)->off = off;
     399          168879 :   off += len;
     400                 : 
     401          168879 :   VSTR__ADD_END(ref, REF, pos_scan->len);
     402                 : 
     403          168879 :   return (TRUE);
     404                 : }
     405                 : 
     406                 : /* replace all buf nodes with ref nodes, we don't need to change the
     407                 :  * vectors if they are there */
     408                 : static int vstr__convert_buf_ref(Vstr_base *base, size_t pos, size_t len)
     409          780809 : {
     410          780809 :   Vstr_node **scan = NULL;
     411          780809 :   unsigned int num = 0;
     412                 : 
     413          780809 :   scan = vstr__base_ptr_pos(base, &pos, &num);
     414          780809 :   --pos;
     415                 : 
     416          780809 :   len += pos;
     417          780809 :   len -= base->used;
     418                 : 
     419          793040 :   while (*scan)
     420                 :   {
     421          793040 :     if ((*scan)->type == VSTR_TYPE_NODE_BUF)
     422                 :     {
     423           18175 :       if (!vstr__chg_node_buf_ref(base, scan, num))
     424              29 :         return (FALSE);
     425                 :     }
     426                 : 
     427          793011 :     if (len <= (*scan)->len)
     428          780780 :       break;
     429           12231 :     len -= (*scan)->len;
     430                 : 
     431           12231 :     scan = &(*scan)->next;
     432           12231 :     ++num;
     433                 :   }
     434          780780 :   assert(!len || (*scan && ((*scan)->len >= len)));
     435                 : 
     436          780780 :   return (TRUE);
     437                 : }
     438                 : 
     439                 : static int vstr__add_all_ref(Vstr_base *base, size_t pos,
     440                 :                              Vstr_base *from_base, size_t from_pos, size_t len)
     441             599 : {
     442             599 :   Vstr_ref *ref = NULL;
     443             599 :   size_t off = 0;
     444                 : 
     445             599 :   if (!(ref = vstr_export_ref(from_base, from_pos, len, &off)))
     446                 :   {
     447              43 :     base->conf->malloc_bad = TRUE;
     448              43 :     goto add_all_ref_fail;
     449                 :   }
     450                 : 
     451             556 :   if (!vstr_add_ref(base, pos, ref, off, len))
     452              16 :     goto add_ref_all_ref_fail;
     453                 : 
     454             540 :   vstr_ref_del(ref);
     455                 : 
     456             540 :   return (TRUE);
     457                 : 
     458                 :  add_ref_all_ref_fail:
     459              16 :   vstr_ref_del(ref);
     460                 : 
     461                 :  add_all_ref_fail:
     462                 : 
     463              59 :   from_base->conf->malloc_bad = TRUE;
     464              59 :   return (FALSE);
     465                 : }
     466                 : 
     467                 : static int vstr__add_vstr_node(Vstr_base *base, size_t pos,
     468                 :                                Vstr_node *scan, size_t off, size_t len,
     469                 :                                unsigned int add_type)
     470          912187 : {
     471          912187 :   switch (scan->type)
     472                 :   {
     473                 :     case VSTR_TYPE_NODE_BUF:
     474                 :       /* all bufs should now be refs */
     475          115192 :       assert(add_type != VSTR_TYPE_ADD_BUF_REF);
     476                 : 
     477          115192 :       if (add_type == VSTR_TYPE_ADD_BUF_PTR)
     478                 :       {
     479           70205 :         if (!vstr_add_ptr(base, pos,
     480                 :                           ((Vstr_node_buf *)scan)->buf + off, len))
     481              57 :           return (FALSE);
     482           44987 :         break;
     483                 :       }
     484                 : 
     485           44987 :       if (!vstr_add_buf(base, pos, ((Vstr_node_buf *)scan)->buf + off, len))
     486             242 :         return (FALSE);
     487             666 :       break;
     488                 : 
     489                 :     case VSTR_TYPE_NODE_NON:
     490             666 :       if (!vstr_add_non(base, pos, len))
     491              16 :         return (FALSE);
     492            2932 :       break;
     493                 : 
     494                 :     case VSTR_TYPE_NODE_PTR:
     495                 :     {
     496            2932 :       char *ptr = ((Vstr_node_ptr *)scan)->ptr;
     497                 : 
     498            2932 :       if (add_type == VSTR_TYPE_ADD_ALL_BUF)
     499                 :       {
     500             440 :         if (!vstr_add_buf(base, pos, ptr + off, len))
     501              99 :           return (FALSE);
     502            2492 :         break;
     503                 :       }
     504                 : 
     505            2492 :       if (!vstr_add_ptr(base, pos, ptr + off, len))
     506             133 :         return (FALSE);
     507                 :     }
     508          793397 :     break;
     509                 : 
     510                 :     case VSTR_TYPE_NODE_REF:
     511          793397 :       off += ((Vstr_node_ref *)scan)->off;
     512          793397 :       if (add_type == VSTR_TYPE_ADD_ALL_BUF)
     513                 :       {
     514             347 :         char *ptr = ((Vstr_node_ref *)scan)->ref->ptr;
     515             347 :         if (!vstr_add_buf(base, pos, ptr + off, len))
     516              21 :           return (FALSE);
     517          793050 :         break;
     518                 :       }
     519                 : 
     520          793050 :       if (!vstr_add_ref(base, pos, ((Vstr_node_ref *)scan)->ref, off, len))
     521             119 :         return (FALSE);
     522                 : 
     523          688009 :       ASSERT_NO_SWITCH_DEF();
     524                 :   }
     525                 : 
     526          911500 :   return (TRUE);
     527                 : }
     528                 : 
     529                 : # define DO_CP_LOOP_BEG(x) size_t tmp = scan->len; \
     530                 :     tmp -= (x); \
     531                 :     if (tmp > len) tmp = len
     532                 : 
     533                 : # define DO_CP_LOOP_END() do { \
     534                 :     pos += tmp; \
     535                 :     len -= tmp; \
     536                 :     \
     537                 :     scan = scan->next; \
     538                 : } while (FALSE)
     539                 : 
     540                 : static size_t vstr__add_vstr_nodes(Vstr_base *base, size_t pos,
     541                 :                                    Vstr_node *scan, size_t from_pos, size_t len,
     542                 :                                    unsigned int add_type)
     543          881528 : {
     544          881528 :   if (len > 0)
     545                 :   {
     546          881528 :     size_t off = from_pos - 1;
     547          881528 :     DO_CP_LOOP_BEG(off);
     548                 : 
     549          881528 :     if (!vstr__add_vstr_node(base, pos, scan, off, tmp, add_type))
     550             247 :       return (0);
     551                 : 
     552          881281 :     DO_CP_LOOP_END();
     553                 :   }
     554                 : 
     555          911500 :   while (len > 0)
     556                 :   {
     557           30659 :     DO_CP_LOOP_BEG(0);
     558                 : 
     559           30659 :     if (!vstr__add_vstr_node(base, pos, scan, 0, tmp, add_type))
     560             440 :       return (0);
     561                 : 
     562           30219 :     DO_CP_LOOP_END();
     563                 :   }
     564                 : 
     565          880841 :   return (pos);
     566                 : }
     567                 : 
     568                 : # undef DO_CP_LOOP_BEG
     569                 : # undef DO_CP_LOOP_END
     570                 : 
     571                 : /* it's so big it looks cluncky, so wrap in a define */
     572                 : # define DO_VALID_CHK() do { \
     573                 :     assert(vstr__check_spare_nodes(base->conf)); \
     574                 :     assert(vstr__check_real_nodes(base)); \
     575                 :     assert(vstr__check_spare_nodes(from_base->conf)); \
     576                 :     assert(vstr__check_real_nodes((Vstr_base *)from_base)); \
     577                 : } while (FALSE)
     578                 : 
     579                 : int vstr_add_vstr(Vstr_base *base, size_t pos,
     580                 :                   const Vstr_base *from_base, size_t from_pos, size_t len,
     581                 :                   unsigned int add_type)
     582         1285958 : {
     583         1285958 :   Vstr_base *nonconst_from_base = (Vstr_base *)from_base;
     584         1285958 :   size_t orig_pos = pos;
     585         1285958 :   size_t orig_from_pos = from_pos;
     586         1285958 :   size_t orig_len = len;
     587         1285958 :   size_t orig_base_len = 0;
     588         1285958 :   Vstr_node *scan = NULL;
     589         1285958 :   unsigned int dummy_num = 0;
     590                 : 
     591         1285958 :   ASSERT_RET(!(!base || (pos > base->len) ||
     592                 :                !from_base || ((from_pos > from_base->len) && len)), FALSE);
     593                 : 
     594         1285942 :   orig_base_len = base->len;
     595                 :   
     596         1285942 :   if (!len)
     597          403863 :     return (TRUE);
     598                 : 
     599          882079 :   DO_VALID_CHK();
     600                 : 
     601                 :   /* quick short cut instead of using export_cstr_ref() also doesn't change
     602                 :    * from_base in certain cases */
     603          882079 :   if (add_type == VSTR_TYPE_ADD_ALL_REF)
     604                 :   {
     605             599 :     if (!vstr__add_all_ref(base, pos, nonconst_from_base, from_pos, len))
     606              59 :       goto fail_beg;
     607                 : 
     608             540 :     DO_VALID_CHK();
     609                 : 
     610             540 :     return (TRUE);
     611                 :   }
     612                 : 
     613                 :   /* make sure there are no buf nodes */
     614          881480 :   if (add_type == VSTR_TYPE_ADD_BUF_REF)
     615                 :   {
     616          780809 :     if (!vstr__convert_buf_ref(nonconst_from_base, from_pos, len))
     617              29 :       goto fail_beg;
     618                 : 
     619          860493 :     DO_VALID_CHK();
     620                 :   }
     621                 : 
     622          881451 :   scan = vstr_base__pos(from_base, &from_pos, &dummy_num, TRUE);
     623                 :   
     624                 :   /* do an initial split where it's comming from, if needed (Ie. not a buffer,
     625                 :    * or it's at the start of the buffer), this is just so we don't call
     626                 :    * memcpy() on overlapping data... however with split poisoning it'll do
     627                 :    * bad things */
     628          881451 :   if ((from_base == base) && (scan->type == VSTR_TYPE_NODE_BUF) &&
     629                 :       (from_pos != (((scan == base->beg) ? base->used : 0U) + 1)))
     630                 :   {
     631              83 :     if (!(scan = vstr__base_split_node(nonconst_from_base, scan, from_pos - 1)))
     632               8 :       goto fail_beg;
     633                 :     
     634              75 :     ASSERT((from_pos - 1) == scan->len);
     635              75 :     ASSERT(scan->next);
     636              75 :     scan = scan->next;
     637              75 :     from_pos = 1;
     638                 :   }
     639                 :   
     640          881443 :   if ((from_base == base) && (orig_from_pos <= orig_pos) &&
     641                 :       ((orig_from_pos + orig_len - 1) > orig_pos))
     642                 :   { /* ok the vstr has to be copied inside itself, Ie.
     643                 :      *
     644                 :      * aaXXXXaa
     645                 :      *
     646                 :      * Where a is the From vstr data, and X is the To vstr data,
     647                 :      * so we have to copy the first part, skip the middle and copy the
     648                 :      * second part */
     649              89 :     size_t before = vstr_sc_posdiff(orig_from_pos, orig_pos);
     650                 :     //    size_t before = orig_pos - orig_from_pos;
     651                 : 
     652              89 :     assert(before < len);
     653                 : 
     654              89 :     if (!(pos = vstr__add_vstr_nodes(base, pos,
     655                 :                                      scan, from_pos, before, add_type)))
     656               4 :       goto fail_end;
     657                 : 
     658              85 :     len -= before;
     659              85 :     from_pos = orig_from_pos + (before * 2);
     660              85 :     scan = vstr_base__pos(from_base, &from_pos, &dummy_num, TRUE);
     661                 :   }
     662                 : 
     663          881439 :   if (!vstr__add_vstr_nodes(base, pos, scan, from_pos, len, add_type))
     664             683 :     goto fail_end;
     665                 : 
     666          880756 :   vstr__cache_cstr_cpy(base, orig_pos, orig_len,
     667                 :                        nonconst_from_base, orig_from_pos);
     668                 : 
     669          880756 :   DO_VALID_CHK();
     670                 : 
     671          880756 :   return (TRUE);
     672                 : 
     673                 :  fail_end:
     674                 :   /* must work as orig_pos must now be at the begining of a node */
     675             687 :   vstr_del(base, orig_pos + 1, base->len - orig_base_len);
     676             687 :   assert(base->len == orig_base_len);
     677                 : 
     678                 :  fail_beg:
     679             783 :   from_base->conf->malloc_bad = TRUE;
     680             783 :   base->conf->malloc_bad = TRUE;
     681             783 :   DO_VALID_CHK();
     682                 : 
     683             783 :   return (FALSE);
     684                 : }
     685                 : # undef DO_VALID_CHK
     686                 : 
     687                 : size_t vstr_add_iovec_buf_beg(Vstr_base *base, size_t pos,
     688                 :                               unsigned int min, unsigned int max,
     689                 :                               struct iovec **ret_iovs,
     690                 :                               unsigned int *num)
     691           70905 : {
     692           70905 :   unsigned int sz = max;
     693           70905 :   struct iovec *iovs = NULL;
     694           70905 :   unsigned char *types = NULL;
     695           70905 :   size_t bytes = 0;
     696           70905 :   Vstr_node *scan = NULL;
     697                 : 
     698           70905 :   ASSERT(base && ret_iovs && num);
     699           70905 :   ASSERT_RET(max && (max >= min), 0);
     700                 : 
     701           70905 :   ASSERT(vstr__check_spare_nodes(base->conf));
     702           70905 :   ASSERT(vstr__check_real_nodes(base));
     703                 : 
     704           70905 :   if (pos != base->len)
     705              63 :     ++min;
     706                 : 
     707           70905 :   if (!vstr_cntl_conf(base->conf,
     708                 :                       VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF, min, UINT_MAX))
     709              68 :     return (0);
     710                 : 
     711           70837 :   ASSERT(sz == max); /* max to write to at once */
     712           70837 :   if (sz > base->conf->spare_buf_num)
     713           13474 :     sz = base->conf->spare_buf_num;
     714                 : 
     715           70837 :   ASSERT(sz);
     716                 : 
     717           70837 :   if (!vstr__cache_iovec_alloc(base, base->num + sz))
     718               5 :     return (0);
     719                 : 
     720           70832 :   if (!vstr__cache_iovec_valid(base))
     721           47327 :     assert(FALSE);
     722                 : 
     723           70832 :   iovs  = VSTR__CACHE(base)->vec->v + VSTR__CACHE(base)->vec->off;
     724           70832 :   types = VSTR__CACHE(base)->vec->t + VSTR__CACHE(base)->vec->off;
     725           70832 :   *num = 0;
     726                 : 
     727           70832 :   if (pos)
     728                 :   {
     729           26856 :     unsigned int scan_num = 0;
     730                 : 
     731           26856 :     ASSERT(base);
     732           26856 :     ASSERT_RET((pos <= base->len), 0);
     733                 :     
     734           26856 :     if (!(scan = vstr__add_setup_pos(base, &pos, &scan_num, NULL)))
     735               1 :       return (0);
     736                 : 
     737           26855 :     if ((scan->type == VSTR_TYPE_NODE_BUF) && (base->conf->buf_sz > scan->len))
     738                 :     {
     739           12432 :       if (sz < max)
     740            2851 :         ++sz;
     741                 : 
     742           12432 :       iovs  += scan_num - 1;
     743           12432 :       types += scan_num - 1;
     744                 : 
     745           12432 :       iovs[0].iov_len  = (base->conf->buf_sz - pos);
     746           12432 :       iovs[0].iov_base = (((Vstr_node_buf *)scan)->buf + pos);
     747                 : 
     748           12432 :       base->iovec_upto_date = FALSE;
     749                 : 
     750           12432 :       bytes = iovs[0].iov_len;
     751           12432 :       *num = 1;
     752                 :     }
     753                 :     else
     754                 :     {
     755           14423 :       iovs  += scan_num;
     756           14423 :       types += scan_num;
     757                 : 
     758           14423 :       if (scan != base->end)
     759                 :         /* if we are adding into the middle of the Vstr then we don't keep
     760                 :          * the vec valid for after the point where we are adding.
     761                 :          * This is then updated again in the _end() func */
     762              10 :         base->iovec_upto_date = FALSE;
     763                 :     }
     764                 :   }
     765           43976 :   else if (base->len)
     766                 :     /* TODO: maybe work with offset to not damage iovec cache
     767                 :      * non trivial though */
     768              12 :     base->iovec_upto_date = FALSE;
     769                 : 
     770           70831 :   scan = (Vstr_node *)base->conf->spare_buf_beg;
     771         1416812 :   assert(scan);
     772                 : 
     773         2311403 :   while (*num < sz)
     774                 :   {
     775         2240572 :     assert(scan->type == VSTR_TYPE_NODE_BUF);
     776                 : 
     777         2240572 :     iovs[*num].iov_len  = base->conf->buf_sz;
     778         2240572 :     iovs[*num].iov_base = ((Vstr_node_buf *)scan)->buf;
     779         2240572 :     types[*num] = VSTR_TYPE_NODE_BUF;
     780                 : 
     781         2240572 :     bytes += iovs[*num].iov_len;
     782         2240572 :     ++*num;
     783                 : 
     784         2240572 :     scan = scan->next;
     785                 :   }
     786                 : 
     787           70831 :   *ret_iovs = iovs;
     788           70831 :   return (bytes);
     789                 : }
     790                 : 
     791                 : void vstr_add_iovec_buf_end(Vstr_base *base, size_t pos, size_t bytes)
     792           70831 : {
     793           70831 :   size_t orig_pos = pos;
     794           70831 :   size_t orig_bytes = bytes;
     795           70831 :   struct iovec *iovs = NULL;
     796           70831 :   unsigned char *types = NULL;
     797           70831 :   unsigned int count = 0;
     798           70831 :   Vstr_node *scan = NULL;
     799           70831 :   Vstr_node **adder = NULL;
     800                 : 
     801           70831 :   base->node_buf_used |= !!bytes;
     802                 : 
     803           70831 :   iovs  = VSTR__CACHE(base)->vec->v + VSTR__CACHE(base)->vec->off;
     804           70831 :   types = VSTR__CACHE(base)->vec->t + VSTR__CACHE(base)->vec->off;
     805           70831 :   if (pos)
     806                 :   {
     807           26855 :     unsigned int scan_num = 0;
     808                 : 
     809           26855 :     scan = vstr_base__pos(base, &pos, &scan_num, TRUE);
     810           26855 :     iovs  += scan_num - 1;
     811           26855 :     types += scan_num - 1;
     812                 : 
     813           26855 :     assert(pos == scan->len);
     814                 : 
     815           26855 :     if ((scan->type == VSTR_TYPE_NODE_BUF) && (base->conf->buf_sz > scan->len))
     816                 :     {
     817           12432 :       size_t first_iov_len = 0;
     818                 : 
     819                 :       /* normally the first case is true ... but it's possible the user could
     820                 :        * lowered the value for some reason -- As in vstr__sc_read_len_fd() */
     821           12432 :       assert(((base->conf->buf_sz - scan->len) == iovs[0].iov_len) ||
     822                 :              (((base->conf->buf_sz - scan->len) >  iovs[0].iov_len) &&
     823                 :               (bytes <= iovs[0].iov_len)));
     824           12432 :       assert((((Vstr_node_buf *)scan)->buf + scan->len) == iovs[0].iov_base);
     825                 : 
     826           12432 :       first_iov_len = iovs[0].iov_len;
     827           12432 :       if (first_iov_len > bytes)
     828            9857 :         first_iov_len = bytes;
     829                 : 
     830           12432 :       assert(!base->iovec_upto_date);
     831           12432 :       if (scan == base->end)
     832                 :       {
     833           12427 :         base->end = NULL;
     834           12427 :         base->iovec_upto_date = TRUE;
     835                 :       }
     836                 : 
     837           12432 :       scan->len += first_iov_len;
     838                 : 
     839           12432 :       vstr__cache_iovec_reset_node(base, scan, scan_num);
     840                 : 
     841           12432 :       bytes -= first_iov_len;
     842                 :     }
     843           14423 :     else if (scan == base->end)
     844                 :     {
     845           14413 :       base->end = NULL;
     846           24993 :       assert(base->iovec_upto_date);
     847                 :     }
     848                 : 
     849           26855 :     ++iovs;
     850           26855 :     ++types;
     851                 : 
     852           26855 :     adder = &scan->next;
     853                 :   }
     854                 :   else
     855           43976 :     adder = &base->beg;
     856                 : 
     857           70831 :   base->len += orig_bytes;
     858                 : 
     859           70831 :   if (!bytes)
     860                 :   {
     861           16676 :     if (!base->end)
     862                 :     {
     863           16656 :       assert(!*adder);
     864           16656 :       base->end = scan;
     865                 :     }
     866                 : 
     867           16676 :     if (!base->iovec_upto_date && base->len)
     868                 :     {
     869              20 :       count = 0;
     870              20 :       scan = *adder;
     871             160 :       while (scan)
     872                 :       {
     873             140 :         iovs[count].iov_len = scan->len;
     874                 : 
     875             140 :         if (scan == base->beg)
     876              10 :           iovs[count].iov_base = vstr_export__node_ptr(scan) + base->used;
     877                 :         else
     878             130 :           iovs[count].iov_base = vstr_export__node_ptr(scan);
     879                 : 
     880             140 :         types[count] = scan->type;
     881                 : 
     882             140 :         ++count;
     883             140 :         scan = scan->next;
     884                 :       }
     885                 :     }
     886                 : 
     887           16676 :     if (orig_bytes)
     888            7658 :       vstr__cache_add(base, orig_pos, orig_bytes);
     889                 : 
     890            9919 :     assert(vstr__check_spare_nodes(base->conf));
     891            9919 :     assert(vstr__check_real_nodes(base));
     892                 : 
     893           27239 :     return;
     894                 :   }
     895                 : 
     896           54155 :   scan = (Vstr_node *)base->conf->spare_buf_beg;
     897           54155 :   count = 0;
     898          930642 :   while (bytes > 0)
     899                 :   {
     900          876487 :     Vstr_node *scan_next = NULL;
     901          876487 :     size_t tmp = iovs[count].iov_len;
     902                 : 
     903          876487 :     assert(scan);
     904          876487 :     scan_next = scan->next;
     905                 : 
     906          876487 :     if (tmp > bytes)
     907           15358 :       tmp = bytes;
     908                 : 
     909          876487 :     assert(((Vstr_node_buf *)scan)->buf == iovs[count].iov_base);
     910          876487 :     assert((tmp == base->conf->buf_sz) || (tmp == bytes));
     911                 : 
     912          876487 :     scan->len = tmp;
     913                 : 
     914          876487 :     bytes -= tmp;
     915                 : 
     916          876487 :     if (!bytes)
     917                 :     {
     918           54155 :       if (!(scan->next = *adder))
     919                 :       {
     920           54148 :         assert(base->iovec_upto_date);
     921           54148 :         base->end = scan;
     922                 :       }
     923                 : 
     924           54155 :       iovs[count].iov_len = tmp;
     925                 :     }
     926                 : 
     927          876487 :     scan = scan_next;
     928                 : 
     929          876487 :     ++count;
     930                 :   }
     931           54155 :   assert(base->conf->spare_buf_num >= count);
     932                 : 
     933           54155 :   base->num += count;
     934           54155 :   base->conf->spare_buf_num -= count;
     935                 : 
     936           54155 :   assert(base->len);
     937                 : 
     938           54155 :   if (!base->iovec_upto_date)
     939                 :   {
     940               7 :     Vstr_node *tmp = *adder;
     941                 : 
     942              40 :     while (tmp)
     943                 :     {
     944              33 :       iovs[count].iov_len  = tmp->len;
     945              33 :       iovs[count].iov_base = vstr_export__node_ptr(tmp);
     946              33 :       types[count] = tmp->type;
     947                 : 
     948              33 :       ++count;
     949              33 :       tmp = tmp->next;
     950                 :     }
     951                 : 
     952               7 :     base->iovec_upto_date = TRUE;
     953                 :   }
     954                 :   else
     955           54152 :     assert(!*adder);
     956                 : 
     957           54155 :   assert(base->end);
     958                 : 
     959           54155 :   *adder = (Vstr_node *)base->conf->spare_buf_beg;
     960           54155 :   base->conf->spare_buf_beg = (Vstr_node_buf *)scan;
     961                 : 
     962           54155 :   if (orig_bytes)
     963           54155 :     vstr__cache_add(base, orig_pos, orig_bytes);
     964                 : 
     965           67739 :   assert(vstr__check_spare_nodes(base->conf));
     966           67739 :   assert(vstr__check_real_nodes(base));
     967                 : }
     968                 : 
     969                 : int vstr_extern_inline_add_rep_chr(Vstr_base *base, size_t pos,
     970                 :                                    char chr, size_t len)
     971          102370 : { /* almost embarassingly similar to add_buf */
     972          102370 :   unsigned int num = 0;
     973          102370 :   size_t orig_pos = pos;
     974          102370 :   size_t orig_len = len;
     975          102370 :   Vstr_node *scan = NULL;
     976          102370 :   Vstr_node *pos_scan = NULL;
     977          102370 :   Vstr_node *pos_scan_next = NULL;
     978          102370 :   size_t orig_pos_scan_len = 0;
     979                 : 
     980          102370 :   ASSERT_RET(!(!base || !len || (pos > base->len)), FALSE);
     981                 : 
     982          102370 :   VSTR__ADD_BEG(base->conf->buf_sz, BUF, &orig_pos_scan_len);
     983                 : 
     984           41113 :   if ((scan->type == VSTR_TYPE_NODE_BUF) && (pos == scan->len) &&
     985                 :       (scan->len < base->conf->buf_sz))
     986                 :   {
     987           25691 :     size_t tmp = (base->conf->buf_sz - scan->len);
     988                 : 
     989           25691 :     assert(base->node_buf_used);
     990                 : 
     991           25691 :     if (tmp > len)
     992              23 :       tmp = len;
     993                 : 
     994           25691 :     vstr_wrap_memset(((Vstr_node_buf *)scan)->buf + scan->len, chr, tmp);
     995           25691 :     scan->len += tmp;
     996                 : 
     997           25691 :     vstr__cache_iovec_add_node_end(base, num, tmp);
     998                 : 
     999           25691 :     base->len += tmp;
    1000           25691 :     len       -= tmp;
    1001                 : 
    1002           25691 :     if (!len)
    1003                 :     {
    1004              23 :       vstr__cache_add(base, orig_pos, orig_len);
    1005                 : 
    1006              23 :       assert(vstr__check_real_nodes(base));
    1007              23 :       return (TRUE);
    1008                 :     }
    1009                 :   }
    1010                 : 
    1011           41090 :   VSTR__ADD_MID(base->conf->buf_sz, buf);
    1012                 : 
    1013                 :   /* always do memset -- don't do above */
    1014          329563 :   vstr_wrap_memset(((Vstr_node_buf *)scan)->buf, chr, tmp);
    1015                 : 
    1016          329563 :   VSTR__ADD_END(buf, BUF, orig_pos_scan_len);
    1017                 : 
    1018           90273 :   return (TRUE);
    1019                 : }

Generated by: LTP GCOV extension version 1.1