LTP GCOV extension - code coverage report
Current view: directory - src - vstr_sect.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 198
Code covered: 99.5 % Executed lines: 197

       1                 : #define VSTR_SECT_C
       2                 : /*
       3                 :  *  Copyright (C) 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 manage a Vstr section */
      22                 : #include "main.h"
      23                 : 
      24                 : Vstr_sects *vstr_sects_make(unsigned int beg_num)
      25           13828 : {
      26           13828 :   Vstr_sects *sects = VSTR__MK(sizeof(Vstr_sects));
      27           13828 :   Vstr_sect_node *ptr = NULL;
      28           13828 :   if (!sects)
      29               2 :     return (NULL);
      30                 : 
      31           13826 :   if (beg_num && !(ptr = VSTR__MK(sizeof(Vstr_sect_node) * beg_num)))
      32                 :   {
      33               2 :     VSTR__F(sects);
      34               2 :     return (NULL);
      35                 :   }
      36                 : 
      37           13824 :   VSTR_SECTS_INIT(sects, beg_num, ptr, TRUE);
      38                 : 
      39           13824 :   return (sects);
      40                 : }
      41                 : 
      42                 : void vstr_sects_free(Vstr_sects *sects)
      43           13830 : {
      44           13830 :   if (!sects)
      45              10 :     return;
      46                 : 
      47           13820 :   if (sects->free_ptr)
      48           13820 :     VSTR__F(sects->ptr);
      49                 : 
      50           13820 :   VSTR__F(sects);
      51                 : }
      52                 : 
      53                 : static int vstr__sects_mv(Vstr_sects *sects, unsigned int sz)
      54             452 : {
      55             452 :   struct Vstr_sect_node *tmp_ptr = NULL;
      56                 : 
      57             452 :   if (!VSTR__MV(sects->ptr, tmp_ptr, sizeof(Vstr_sect_node) * sz))
      58                 :   {
      59              18 :     sects->malloc_bad = TRUE;
      60              18 :     return (FALSE);
      61                 :   }
      62             434 :   sects->sz = sz;
      63                 : 
      64             434 :   return (TRUE);
      65                 : }
      66                 : 
      67                 : static int vstr__sects_add(Vstr_sects *sects)
      68             453 : {
      69             453 :   unsigned int sz = sects->sz;
      70                 : 
      71             453 :   if (!sz)
      72                 :   {
      73               6 :     if (!(sects->ptr = VSTR__MK(sizeof(Vstr_sect_node) * 1)))
      74               1 :       goto malloc_fail;
      75                 : 
      76               5 :     sects->sz = 1;
      77               5 :     return (TRUE);
      78                 :   }
      79                 :   
      80             447 :   if (sects->alloc_double)
      81             432 :     sz <<= 1;
      82                 :     
      83             447 :   if (sz <= sects->sz)
      84              20 :     sz = sects->sz + 1;
      85                 :   
      86             447 :   if (sz <= sects->sz)
      87               5 :     goto malloc_fail;
      88                 :   
      89             442 :   return (vstr__sects_mv(sects, sz));
      90                 :   
      91                 :  malloc_fail:
      92               6 :   sects->malloc_bad = TRUE;
      93               6 :   return (FALSE);
      94                 : }
      95                 : 
      96                 : static int vstr__sects_del(Vstr_sects *sects)
      97              10 : {
      98              10 :   unsigned int sz = sects->sz;
      99                 : 
     100              10 :   sz >>= 1;
     101              10 :   assert(sz >= sects->num);
     102                 : 
     103              10 :   return (vstr__sects_mv(sects, sz));
     104                 : }
     105                 : 
     106                 : int vstr_extern_inline_sects_add(Vstr_sects *sects,
     107                 :                                  size_t VSTR__ATTR_UNUSED(pos),
     108                 :                                  size_t VSTR__ATTR_UNUSED(len))
     109             453 : {
     110                 :   /* see vstr-extern.h for why */
     111             453 :   assert(sizeof(struct Vstr_sects) >= sizeof(struct Vstr_sect_node));
     112                 : 
     113             453 :   return (vstr__sects_add(sects));
     114                 : }
     115                 : 
     116                 : int vstr_sects_del(Vstr_sects *sects, unsigned int num)
     117              30 : {
     118              30 :   ASSERT_RET((sects->sz && num), FALSE);
     119              30 :   ASSERT_RET((sects->num >= num), FALSE);
     120                 : 
     121              30 :   if (!sects->ptr[num - 1].pos)
     122               5 :     return (FALSE);
     123                 : 
     124              25 :   sects->ptr[num - 1].pos = 0;
     125                 : 
     126              40 :   while (sects->num && !sects->ptr[sects->num - 1].pos)
     127              15 :     --sects->num;
     128                 : 
     129              25 :   if (sects->can_del_sz && (sects->num < (sects->sz / 2)))
     130               5 :     vstr__sects_del(sects); /* can't return this error */
     131                 : 
     132              25 :   return (TRUE);
     133                 : }
     134                 : 
     135                 : unsigned int vstr_sects_srch(Vstr_sects *sects, size_t pos, size_t len)
     136              45 : {
     137              45 :   unsigned int count = 0;
     138                 : 
     139              45 :   if (!sects->sz)
     140               5 :     return (0);
     141                 : 
     142             145 :   while (count++ < sects->num)
     143                 :   {
     144             140 :     size_t scan_pos = VSTR_SECTS_NUM(sects, count)->pos;
     145             140 :     size_t scan_len = VSTR_SECTS_NUM(sects, count)->len;
     146                 : 
     147             140 :     if ((scan_pos == pos) && (scan_len == len))
     148              35 :       return (count);
     149                 :   }
     150                 : 
     151               5 :   return (0);
     152                 : }
     153                 : 
     154                 : int vstr_sects_foreach(const Vstr_base *base,
     155                 :                        Vstr_sects *sects, const unsigned int flags,
     156                 :                        unsigned int (*foreach_func)(const Vstr_base *,
     157                 :                                                     size_t, size_t, void *),
     158                 :                        void *data)
     159              30 : {
     160              30 :   unsigned int count = 0;
     161              30 :   unsigned int scan = 0;
     162                 : 
     163              30 :   if (!sects->sz)
     164               5 :     return (0);
     165                 : 
     166              25 :   if (flags & VSTR_FLAG_SECTS_FOREACH_BACKWARD)
     167               5 :     scan = sects->num;
     168                 : 
     169             180 :   while ((!(flags & VSTR_FLAG_SECTS_FOREACH_BACKWARD) &&
     170                 :           (scan < sects->num)) ||
     171                 :          ((flags & VSTR_FLAG_SECTS_FOREACH_BACKWARD) && scan))
     172                 :   {
     173             160 :     size_t pos = 0;
     174             160 :     size_t len = 0;
     175                 : 
     176             160 :     if (flags & VSTR_FLAG_SECTS_FOREACH_BACKWARD)
     177               5 :       --scan;
     178                 : 
     179             160 :     pos = sects->ptr[scan].pos;
     180             160 :     len = sects->ptr[scan].len;
     181                 : 
     182             160 :     if (pos && (len || (flags & VSTR_FLAG_SECTS_FOREACH_ALLOW_NULL)))
     183                 :     {
     184             155 :       ++count;
     185                 : 
     186             155 :       switch ((*foreach_func)(base, pos, len, data))
     187                 :       {
     188                 :         case VSTR_TYPE_SECTS_FOREACH_RET:
     189              50 :           goto shorten_and_return;
     190                 : 
     191                 :         case VSTR_TYPE_SECTS_FOREACH_DEL:
     192              50 :           sects->ptr[scan].pos = 0;
     193                 :           /* FALL THROUGH */
     194                 :         case VSTR_TYPE_SECTS_FOREACH_DEF:
     195                 :           
     196              10 :           ASSERT_NO_SWITCH_DEF();
     197                 :       }
     198                 :     }
     199                 : 
     200             155 :     if (!(flags & VSTR_FLAG_SECTS_FOREACH_BACKWARD))
     201             155 :       ++scan;
     202                 :   }
     203                 : 
     204                 :  shorten_and_return:
     205              75 :   while (sects->num && !sects->ptr[sects->num - 1].pos)
     206              50 :     --sects->num;
     207                 : 
     208              25 :   if (sects->can_del_sz && (sects->num < (sects->sz / 2)))
     209               5 :     vstr__sects_del(sects); /* can't return this error */
     210                 : 
     211              25 :   return (count);
     212                 : }
     213                 : 
     214                 : typedef struct Vstr__sects_cache_data
     215                 : {
     216                 :  unsigned int sz;
     217                 :  unsigned int len;
     218                 :  Vstr_sects *VSTR__STRUCT_HACK_ARRAY(updates);
     219                 : } Vstr__sects_cache_data;
     220                 : 
     221                 : static void *vstr__sects_update_cb(const Vstr_base *base,size_t pos, size_t len,
     222                 :                                    unsigned int type, void *passed_data)
     223              55 : {
     224              55 :   Vstr__sects_cache_data *data = passed_data;
     225              55 :   unsigned int count = 0;
     226                 : 
     227              55 :   ASSERT(base->conf->cache_pos_cb_sects);
     228              55 :   ASSERT(data == vstr_cache_get(base, base->conf->cache_pos_cb_sects));
     229                 : 
     230              55 :   if (type == VSTR_TYPE_CACHE_FREE)
     231                 :   {
     232               5 :     VSTR__F(data);
     233               5 :     return (NULL);
     234                 :   }
     235                 : 
     236              50 :   if (type == VSTR_TYPE_CACHE_SUB) /* do nothing for substitutions ... */
     237               5 :     return (data);
     238                 : 
     239              90 :   while (count < data->len)
     240                 :   {
     241              45 :     Vstr_sects *sects = data->updates[count];
     242              45 :     unsigned int scan = 0;
     243                 : 
     244              45 :     switch (type)
     245                 :     {
     246                 :       case VSTR_TYPE_CACHE_ADD:
     247              30 :         while (scan < sects->num)
     248                 :         {
     249              20 :           if (sects->ptr[scan].pos && sects->ptr[scan].len)
     250                 :           {
     251              20 :             if (pos < sects->ptr[scan].pos)
     252              15 :               sects->ptr[scan].pos += len;
     253              20 :             if ((pos >= sects->ptr[scan].pos) &&
     254                 :                 (pos < (sects->ptr[scan].pos + sects->ptr[scan].len - 1)))
     255               5 :               sects->ptr[scan].len += len;
     256                 :           }
     257                 : 
     258              20 :           ++scan;
     259                 :         }
     260              35 :         break;
     261                 : 
     262                 :       case VSTR_TYPE_CACHE_DEL:
     263             105 :         while (scan < sects->num)
     264                 :         {
     265              70 :           if (sects->ptr[scan].pos && sects->ptr[scan].len)
     266                 :           {
     267              65 :             if (pos <= sects->ptr[scan].pos)
     268                 :             {
     269              30 :               size_t tmp = sects->ptr[scan].pos - pos;
     270                 : 
     271              30 :               if (tmp >= len)
     272              10 :                 sects->ptr[scan].pos -= len;
     273                 :               else
     274                 :               {
     275              20 :                 len -= tmp;
     276              20 :                 if (len >= sects->ptr[scan].len)
     277               5 :                   sects->ptr[scan].pos = 0;
     278                 :                 else
     279                 :                 {
     280              15 :                   sects->ptr[scan].pos -= tmp;
     281              15 :                   sects->ptr[scan].len -= len;
     282                 :                 }
     283                 :               }
     284                 :             }
     285              35 :             else if ((pos > sects->ptr[scan].pos) &&
     286                 :                      (pos <= (sects->ptr[scan].pos + sects->ptr[scan].len - 1)))
     287                 :             {
     288              25 :               size_t tmp = pos - sects->ptr[scan].pos;
     289                 : 
     290              25 :               if (len >= (sects->ptr[scan].len - tmp))
     291              20 :                 sects->ptr[scan].len = tmp;
     292                 :               else
     293               5 :                 sects->ptr[scan].len -= len;
     294                 :             }
     295                 :           }
     296                 : 
     297              70 :           ++scan;
     298                 :         }
     299              36 :         ASSERT_NO_SWITCH_DEF();
     300                 :     }
     301                 : 
     302              45 :     ++count;
     303                 :   }
     304                 : 
     305              45 :   return (data);
     306                 : }
     307                 : 
     308                 : static Vstr_sects **vstr__sects_update_srch(Vstr__sects_cache_data *data,
     309                 :                                             Vstr_sects *sects)
     310              31 : {
     311              31 :   unsigned int count = 0;
     312                 : 
     313              56 :   while (count < data->len)
     314                 :   {
     315              44 :     if (data->updates[count] == sects)
     316              19 :       return (&data->updates[count]);
     317                 : 
     318              25 :     ++count;
     319                 :   }
     320                 : 
     321              12 :   return (NULL);
     322                 : }
     323                 : 
     324                 : static void vstr__sects_update_del(Vstr__sects_cache_data *data,
     325                 :                                    Vstr_sects **sects)
     326              19 : {
     327              19 :   Vstr_sects **end = (data->updates + (data->len - 1));
     328                 : 
     329              19 :   --data->len;
     330                 : 
     331              19 :   if (sects != end)
     332               5 :     vstr_wrap_memmove(sects, sects + 1,
     333                 :                       (end - sects) * sizeof(Vstr_sects *));
     334                 : }
     335                 : 
     336                 : int vstr_sects_update_add(const Vstr_base *base,
     337                 :                           Vstr_sects *sects)
     338              38 : {
     339              38 :   Vstr__sects_cache_data *data = NULL;
     340              38 :   unsigned int sz = 1;
     341                 : 
     342              38 :   if (!base->conf->cache_pos_cb_sects)
     343                 :   {
     344              18 :     unsigned int tmp = 0;
     345                 : 
     346              18 :     tmp = vstr_cache_add(base->conf, "/vstr__/sects/update",
     347                 :                          vstr__sects_update_cb);
     348                 : 
     349              18 :     if (!tmp)
     350               4 :       goto malloc_bad;
     351                 : 
     352              14 :     base->conf->cache_pos_cb_sects = tmp;
     353                 :   }
     354                 : 
     355              34 :   if (!(data = vstr_cache_get(base, base->conf->cache_pos_cb_sects)))
     356                 :   {
     357              16 :     if (!vstr_cache_set(base, base->conf->cache_pos_cb_sects, NULL))
     358               1 :       goto malloc_bad;
     359                 : 
     360              15 :     data = VSTR__MK(sizeof(Vstr__sects_cache_data) +
     361                 :                     (sz * sizeof(Vstr_sects *)));
     362              15 :     if (!data)
     363               1 :       goto malloc_bad;
     364                 : 
     365              14 :     data->sz = 1;
     366              14 :     data->len = 0;
     367                 : 
     368              14 :     vstr_cache_set(base, base->conf->cache_pos_cb_sects, data);
     369                 :   }
     370                 : 
     371                 :   /* it can't be valid to have the same sects twice */
     372              32 :   ASSERT(!vstr__sects_update_srch(data, sects));
     373                 :   
     374              32 :   sz = data->len + 1;
     375                 : 
     376                 :   /* this is basically impossible to test (size overflow)...
     377                 :    * done this way for coverage */
     378              32 :   ASSERT_RET((sz > data->len) || !(base->conf->malloc_bad = TRUE), FALSE);
     379                 :   
     380              32 :   ASSERT(data->sz);
     381              32 :   ASSERT(data->len <= data->sz);
     382                 :   
     383              32 :   if (data->len >= data->sz)
     384                 :   {
     385              18 :     Vstr__sects_cache_data *tmp_data = NULL;
     386                 : 
     387              18 :     if (!(VSTR__MV(data, tmp_data, sizeof(Vstr__sects_cache_data) +
     388                 :                    (sz * sizeof(Vstr_sects *)))))
     389               0 :       goto malloc_bad;
     390                 : 
     391              10 :     data->sz = data->len + 1;
     392                 : 
     393              10 :     vstr_cache_set(base, base->conf->cache_pos_cb_sects, data);
     394                 :   }
     395                 : 
     396              24 :   data->updates[data->len] = sects;
     397              24 :   ++data->len;
     398                 : 
     399              24 :   return (TRUE);
     400                 : 
     401                 :  malloc_bad:
     402              14 :   base->conf->malloc_bad = TRUE;
     403              14 :   return (FALSE);
     404                 : }
     405                 : 
     406                 : int vstr_sects_update_del(const Vstr_base *base,
     407                 :                           Vstr_sects *sects)
     408              33 : {
     409              33 :   Vstr__sects_cache_data *data = NULL;
     410              33 :   Vstr_sects **srch = NULL;
     411                 : 
     412              33 :   if (!sects)
     413              10 :     return (FALSE);
     414                 :   
     415              23 :   ASSERT_RET(base->conf->cache_pos_cb_sects, FALSE);
     416                 : 
     417              23 :   data = vstr_cache_get(base, base->conf->cache_pos_cb_sects);
     418              23 :   ASSERT_RET(data, FALSE);
     419                 : 
     420              19 :   srch = vstr__sects_update_srch(data, sects);
     421              19 :   ASSERT_RET(srch, FALSE);
     422                 : 
     423              19 :   vstr__sects_update_del(data, srch);
     424                 : 
     425              19 :   if (!data->len)
     426                 :   {
     427               9 :     VSTR__F(data);
     428               9 :     vstr_cache_set(base, base->conf->cache_pos_cb_sects, NULL);
     429                 :   }
     430                 : 
     431              19 :   return (TRUE);
     432                 : }

Generated by: LTP GCOV extension version 1.1