LTP GCOV extension - code coverage report
Current view: directory - work/ustr - ustr-replace-code.h
Test: Ustr coverage
Date: 2008-02-26 Instrumented lines: 179
Code covered: 100.0 % Executed lines: 179

       1                 : /* Copyright (c) 2007 Paul Rosenfeld
       2                 :                       James Antill -- See LICENSE file for terms. */
       3                 : #ifndef USTR_REPLACE_H
       4                 : #error " Include ustr-replace.h before this file."
       5                 : #endif
       6                 : 
       7                 : USTR_CONF_i_PROTO
       8                 : size_t ustrp__replace_inline_buf(struct Ustr_pool *p, struct Ustr **ps1,
       9                 :                                  const void *optr, size_t olen,
      10                 :                                  const void *nptr, size_t nlen, size_t lim)
      11              24 : { /* "fast path" ... we can't fail, so ignore the return values */
      12              24 :   size_t num  = 0;
      13              24 :   size_t pos  = 0;
      14                 :   
      15              12 :   USTR_ASSERT(ustr_owner(*ps1));
      16              14 :   USTR_ASSERT((nlen == olen) || !ustr_alloc(*ps1));
      17                 : 
      18              60 :   while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen)))
      19                 :   {
      20              19 :     USTR_ASSERT((nlen == olen) ||
      21                 :                 (ustr_fixed(*ps1) &&
      22                 :                  (ustr_size(*ps1) >= (ustr_len(*ps1) + (nlen - olen)))));
      23                 :     
      24              32 :     ustrp__sc_sub_buf(p, ps1, pos, olen, nptr, nlen);
      25              32 :     pos += nlen - 1;
      26                 :     
      27              32 :     ++num;
      28              32 :     if (lim && (num == lim))
      29               8 :       break;
      30                 :   }
      31                 :   
      32              24 :   if (!num)
      33               4 :     errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */
      34              24 :   return (num);
      35                 : }
      36                 : 
      37                 : 
      38                 : USTR_CONF_i_PROTO
      39                 : size_t ustrp__replace_buf(struct Ustr_pool *p, struct Ustr **ps1,
      40                 :                           const void *optr, size_t olen,
      41                 :                           const void *nptr, size_t nlen, size_t lim)
      42              97 : {
      43              97 :   size_t num  = 0;
      44              97 :   size_t tlen = 0;
      45              97 :   size_t pos  = 0;
      46              97 :   struct Ustr *ret = USTR_NULL;
      47                 :   const char *rptr;
      48              97 :   size_t lpos = 0;
      49              97 :   size_t roff = 0;
      50                 :   
      51              48 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
      52                 :   
      53              97 :   if ((nlen == olen) && ustr_owner(*ps1))
      54              20 :     return (ustrp__replace_inline_buf(p, ps1, optr, olen, nptr, nlen, lim));
      55                 :   
      56                 :   /* pre-calc size, and do single alloc and then memcpy.
      57                 :    * Using dup()/ustr_sc_sub() is much simpler but very slow
      58                 :    * for large strings. */
      59              77 :   tlen = ustr_len(*ps1);
      60             335 :   while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen)))
      61                 :   {
      62             190 :     pos += olen - 1;
      63                 : 
      64             190 :     if (nlen < olen) /* can go up or down */
      65              48 :       tlen -= (olen - nlen);
      66                 :     else
      67                 :     {
      68             142 :       if (tlen > (tlen + (nlen - olen)))
      69                 :       {
      70               1 :         errno = USTR__ENOMEM;
      71               1 :         return (0);
      72                 :       }
      73             141 :       tlen += (nlen - olen);
      74                 :     }
      75                 : 
      76             189 :     ++num;
      77             189 :     if (lim && (num == lim))
      78               8 :       break;
      79                 :   }
      80                 : 
      81              76 :   if (!num) /* minor speed hack */
      82                 :   {
      83              12 :     errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */
      84              12 :     return (0);
      85                 :   }
      86                 :   
      87              64 :   if (!tlen) /* minor speed hack */
      88               5 :     return (ustrp__del(p, ps1, ustr_len(*ps1)) ? num : 0);
      89                 :   
      90              92 :   if (ustr_fixed(*ps1) && ((num <= 2) || ustr_limited(*ps1)))
      91                 :   { /* if we will have to memmove() a lot, double copy */
      92              12 :     if (tlen <= ustr_size(*ps1))
      93               4 :       return (ustrp__replace_inline_buf(p, ps1, optr, olen, nptr, nlen, lim));
      94              12 :     if (ustr_limited(*ps1))
      95               4 :       goto fail_alloc;
      96                 :   }
      97                 :   
      98             200 :   if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(*ps1), tlen)))
      99               8 :     goto fail_alloc;
     100                 :   
     101              44 :   rptr = ustr_cstr(*ps1);
     102              44 :   lpos = 1;
     103              44 :   roff = 0;
     104              44 :   pos  = 0;
     105              44 :   num  = 0;
     106             212 :   while ((pos = ustr_srch_buf_fwd(*ps1, pos, optr, olen)))
     107                 :   {
     108             132 :     const char *tptr = rptr + roff;
     109             132 :     size_t blen = pos - (roff + 1);
     110                 :     
     111             132 :     pos += olen - 1;
     112              66 :     USTR_ASSERT(pos == (roff + blen + olen));
     113                 :     
     114             132 :     ustrp__sub_buf(p, &ret, lpos, tptr, blen); lpos += blen;
     115             132 :     ustrp__sub_buf(p, &ret, lpos, nptr, nlen); lpos += nlen;
     116                 : 
     117             132 :     roff = pos;
     118                 :     
     119             132 :     ++num;
     120             132 :     if (lim && (num == lim))
     121               8 :       break;
     122                 :   }
     123              55 :   ustrp__sub_buf(p, &ret, lpos, rptr + roff, ustr_len(*ps1) - roff);
     124                 : 
     125             106 :   if (!ustr_fixed(*ps1) || (tlen > ustr_size(*ps1)))
     126              40 :     ustrp__sc_free2(p, ps1, ret);
     127                 :   else
     128                 :   { /* fixed buffer, with multiple replacements ... but fits */
     129               4 :     ustrp__set(p, ps1, ret);
     130               4 :     ustrp__free(p, ret);
     131                 :   }
     132                 :   
     133              44 :   return (num);
     134                 : 
     135              12 :  fail_alloc:
     136              12 :   ustr_setf_enomem_err(*ps1);
     137              12 :   return (0);
     138                 : }
     139                 : 
     140                 : USTR_CONF_I_PROTO
     141                 : size_t ustr_replace_buf(struct Ustr **ps1, const void *optr, size_t olen,
     142                 :                         const void *nptr, size_t nlen, size_t lim)
     143              60 : { return (ustrp__replace_buf(0, ps1, optr, olen, nptr, nlen, lim)); }
     144                 : USTR_CONF_I_PROTO
     145                 : size_t ustrp_replace_buf(struct Ustr_pool *p, struct Ustrp **ps1,
     146                 :                          const void *optr, size_t olen,
     147                 :                          const void *nptr, size_t nlen, size_t lim)
     148              16 : {
     149              16 :   struct Ustr *tmp = &(*ps1)->s;
     150              16 :   int ret = ustrp__replace_buf(p, &tmp, optr, olen, nptr, nlen, lim);
     151              16 :   *ps1 = USTRP(tmp);
     152              16 :   return (ret);
     153                 : }
     154                 : 
     155                 : USTR_CONF_i_PROTO
     156                 : size_t ustrp__replace(struct Ustr_pool *p, struct Ustr **ps1,
     157                 :                       const struct Ustr *srch,
     158                 :                       const struct Ustr *repl, size_t lim)
     159              21 : {
     160              21 :   struct Ustr *t1 = USTR_NULL;
     161              21 :   struct Ustr *t2 = USTR_NULL;
     162              21 :   size_t ret = 0;
     163                 :   
     164              10 :   USTR_ASSERT(ustrp__assert_valid(!!p, srch));
     165              10 :   USTR_ASSERT(ustrp__assert_valid(!!p, repl));
     166                 : 
     167              21 :   if (srch == *ps1) srch = t1 = ustrp__dup(p, *ps1);
     168              21 :   if (repl == *ps1) repl = t2 = ustrp__dup(p, *ps1);
     169                 : 
     170              21 :   if (srch && repl)
     171              21 :     ret = ustrp__replace_buf(p, ps1,
     172                 :                              ustr_cstr(srch), ustr_len(srch),
     173                 :                              ustr_cstr(repl), ustr_len(repl), lim);
     174                 :   
     175              21 :   ustrp__free(p, t1);
     176              21 :   ustrp__free(p, t2);
     177                 :   
     178              21 :   return (ret);
     179                 : }
     180                 : USTR_CONF_I_PROTO
     181                 : size_t ustr_replace(struct Ustr **ps1, const struct Ustr *srch,
     182                 :                     const struct Ustr *repl, size_t lim)
     183              17 : { return (ustrp__replace(0, ps1, srch, repl, lim)); }
     184                 : USTR_CONF_I_PROTO
     185                 : size_t ustrp_replace(struct Ustr_pool *p, struct Ustrp **ps1,
     186                 :                      const struct Ustrp *srch,
     187                 :                      const struct Ustrp *repl, size_t lim)
     188               4 : {
     189               4 :   struct Ustr *tmp = &(*ps1)->s;
     190               4 :   int ret = ustrp__replace(p, &tmp, &srch->s, &repl->s, lim);
     191               4 :   *ps1 = USTRP(tmp);
     192               4 :   return (ret);
     193                 : }
     194                 : 
     195                 : USTR_CONF_i_PROTO
     196                 : size_t ustrp__replace_inline_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
     197                 :                                      char odata, size_t olen, 
     198                 :                                      char ndata, size_t nlen, size_t lim)
     199              24 : { /* "fast path" ... as we can't fail after we are the owner(). In theory
     200                 :    * we can do nlen <= olen, but then we'll spend a lot of time calling
     201                 :    * memmove(). Which might be painful, so let that fall through to dupx(). */
     202              24 :   size_t num  = 0;
     203              24 :   size_t pos  = 0;
     204                 : 
     205              12 :   USTR_ASSERT(ustr_owner(*ps1));
     206              14 :   USTR_ASSERT((nlen == olen) || !ustr_alloc(*ps1));
     207                 : 
     208              68 :   while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen)))
     209                 :   {
     210              21 :     USTR_ASSERT((nlen == olen) ||
     211                 :                 (ustr_fixed(*ps1) &&
     212                 :                  (ustr_size(*ps1) >= (ustr_len(*ps1) + (nlen - olen)))));
     213                 :     
     214              36 :     ustrp__sc_sub_rep_chr(p, ps1, pos, olen, ndata, nlen);
     215              36 :     pos += nlen - 1;
     216                 :     
     217              36 :     ++num;
     218              36 :     if (lim && (num == lim))
     219               4 :       break;
     220                 :   }
     221                 : 
     222              24 :   if (!num)
     223               4 :     errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */
     224              24 :   return (num);
     225                 : }
     226                 : 
     227                 : USTR_CONF_i_PROTO
     228                 : size_t ustrp__replace_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
     229                 :                               char odata, size_t olen, 
     230                 :                               char ndata, size_t nlen, size_t lim)
     231              85 : {
     232              85 :   size_t num  = 0;
     233              85 :   size_t tlen = 0;
     234              85 :   size_t pos  = 0;
     235              85 :   struct Ustr *ret = USTR_NULL;
     236                 :   const char *rptr;
     237              85 :   size_t lpos = 0;
     238              85 :   size_t roff = 0;
     239                 : 
     240              42 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
     241                 :   
     242              85 :   if ((nlen == olen) && ustr_owner(*ps1))
     243              20 :     return (ustrp__replace_inline_rep_chr(p, ps1, odata,olen, ndata,nlen, lim));
     244                 : 
     245                 :   /* pre-calc size, and do single alloc and then memcpy.
     246                 :    * Using dup()/ustr_sc_sub() is much simpler but very slow
     247                 :    * for large strings. */
     248              65 :   tlen = ustr_len(*ps1);
     249             278 :   while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen)))
     250                 :   {
     251             153 :     pos += olen - 1;
     252                 : 
     253             153 :     if (nlen < olen) /* can go up or down */
     254              48 :       tlen -= (olen - nlen);
     255                 :     else
     256                 :     {
     257             105 :       if (tlen > (tlen + (nlen - olen)))
     258                 :       {
     259               1 :         errno = USTR__ENOMEM;
     260               1 :         return (0);
     261                 :       }
     262             104 :       tlen += (nlen - olen);
     263                 :     }
     264                 : 
     265             152 :     ++num;
     266             152 :     if (lim && (num == lim))
     267               4 :       break;
     268                 :   }
     269                 : 
     270              64 :   if (!num) /* minor speed hack */
     271                 :   {
     272               8 :     errno = 0; /* only way to tell between FAILURE and NO REPLACEMENTS */
     273               8 :     return (0);
     274                 :   }
     275                 :   
     276              56 :   if (!tlen) /* minor speed hack */
     277               5 :     return (ustrp__del(p, ps1, ustr_len(*ps1)) ? num : 0);
     278                 :   
     279              80 :   if (ustr_fixed(*ps1) && ((num <= 2) || ustr_limited(*ps1)))
     280                 :   { /* if we will have to memmove() a lot, double copy */
     281               8 :     if (tlen <= ustr_size(*ps1))
     282               4 :       return (ustrp__replace_inline_rep_chr(p, ps1, odata,olen,ndata,nlen,lim));
     283                 :     
     284               6 :     if (ustr_limited(*ps1))
     285               4 :       goto fail_alloc;
     286                 :   }
     287                 :   
     288             162 :   if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(*ps1), tlen)))
     289               8 :     goto fail_alloc;
     290                 :   
     291              36 :   rptr = ustr_cstr(*ps1);
     292              36 :   lpos = 1;
     293              36 :   roff = 0;
     294              36 :   pos  = 0;
     295              36 :   num  = 0;
     296             164 :   while ((pos = ustr_srch_rep_chr_fwd(*ps1, pos, odata, olen)))
     297                 :   {
     298              96 :     const char *tptr = rptr + roff;
     299              96 :     size_t blen = pos - (roff + 1);
     300                 :     
     301              96 :     pos += olen - 1;
     302              48 :     USTR_ASSERT(pos == (roff + blen + olen));
     303                 :     
     304              96 :     ustrp__sub_buf(p, &ret,     lpos, tptr,  blen); lpos += blen;
     305              96 :     ustrp__sub_rep_chr(p, &ret, lpos, ndata, nlen); lpos += nlen;
     306                 : 
     307              96 :     roff = pos;
     308                 :     
     309              96 :     ++num;
     310              96 :     if (lim && (num == lim))
     311               4 :       break;
     312                 :   }
     313              45 :   ustrp__sub_buf(p, &ret, lpos, rptr + roff, ustr_len(*ps1) - roff);
     314                 :   
     315              86 :   if (!ustr_fixed(*ps1) || (tlen > ustr_size(*ps1)))
     316              32 :     ustrp__sc_free2(p, ps1, ret);
     317                 :   else
     318                 :   { /* fixed buffer, with multiple replacements ... but fits */
     319               4 :     ustrp__set(p, ps1, ret);
     320               4 :     ustrp__free(p, ret);
     321                 :   }
     322                 :   
     323              36 :   return (num);
     324                 : 
     325              12 :  fail_alloc:
     326              12 :   ustr_setf_enomem_err(*ps1);
     327              12 :   return (0);
     328                 : }
     329                 : USTR_CONF_I_PROTO
     330                 : size_t ustr_replace_rep_chr(struct Ustr **ps1, char odata, size_t olen, 
     331                 :                             char ndata, size_t nlen, size_t lim)
     332              69 : { return (ustrp__replace_rep_chr(0, ps1, odata, olen, ndata, nlen, lim)); }
     333                 : USTR_CONF_I_PROTO
     334                 : size_t ustrp_replace_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1,
     335                 :                              char odata, size_t olen, 
     336                 :                              char ndata, size_t nlen, size_t lim)
     337              16 : {
     338              16 :   struct Ustr *tmp = &(*ps1)->s;
     339              16 :   int ret = ustrp__replace_rep_chr(p, &tmp, odata, olen, ndata, nlen, lim);
     340              16 :   *ps1 = USTRP(tmp);
     341              16 :   return (ret);
     342                 : }

Generated by: LTP GCOV extension version 1.4