LTP GCOV extension - code coverage report
Current view: directory - src - vstr.c
Test: Vstr coverage
Date: 2005-01-10 Instrumented lines: 816
Code covered: 99.9 % Executed lines: 815

       1                 : #define VSTR_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                 : /* master file, contains most of the base functions */
      22                 : #include "main.h"
      23                 : 
      24                 : 
      25                 : /* validity checking function... only called from asserts */
      26                 : #ifndef NDEBUG
      27                 : static void vstr__cache_iovec_check(const Vstr_base *base)
      28         5810910 : {
      29         5810910 :   unsigned int count = 0;
      30         5810910 :   Vstr_node *scan = NULL;
      31                 : 
      32         5810910 :   if (!base->iovec_upto_date || !base->beg)
      33           65414 :     return;
      34                 : 
      35         4173576 :   count = VSTR__CACHE(base)->vec->off;
      36         4173576 :   scan = base->beg;
      37                 : 
      38         4173576 :   assert(scan->len > base->used);
      39         4173576 :   assert(VSTR__CACHE(base)->vec->sz >= base->num);
      40         4173576 :   assert(VSTR__CACHE(base)->vec->v[count].iov_len == (size_t)(scan->len - base->used));
      41         4173576 :   if (scan->type == VSTR_TYPE_NODE_NON)
      42              89 :     assert(!VSTR__CACHE(base)->vec->v[count].iov_base);
      43                 :   else
      44         4173487 :     assert(VSTR__CACHE(base)->vec->v[count].iov_base ==
      45                 :            (vstr_export__node_ptr(scan) + base->used));
      46         4173576 :   assert(VSTR__CACHE(base)->vec->t[count] == scan->type);
      47                 : 
      48         4173576 :   if (!(scan = scan->next))
      49          351338 :     ASSERT(base->beg == base->end);
      50                 : 
      51         4173576 :   ++count;
      52       334756699 :   while (scan)
      53                 :   {
      54       330583123 :     assert(VSTR__CACHE(base)->vec->t[count] == scan->type);
      55       330583123 :     assert(VSTR__CACHE(base)->vec->v[count].iov_len == scan->len);
      56       330583123 :     assert(VSTR__CACHE(base)->vec->v[count].iov_base ==
      57                 :            vstr_export__node_ptr(scan));
      58                 : 
      59       330583123 :     ++count;
      60                 : 
      61       330583123 :     if (!scan->next)
      62         3822238 :       assert(scan == base->end);
      63                 : 
      64       330583123 :     scan = scan->next;
      65                 :   }
      66                 : }
      67                 : 
      68                 : static void vstr__cache_cstr_check(const Vstr_base *base)
      69         5810910 : {
      70         5810910 :   Vstr__cache_data_cstr *data = NULL;
      71         5810910 :   const char *ptr = NULL;
      72                 : 
      73         5810910 :   ASSERT(base->conf->cache_pos_cb_cstr == 3);
      74                 : 
      75         5810910 :   if (!(data = vstr_cache_get(base, base->conf->cache_pos_cb_cstr)))
      76         3490496 :     return;
      77         2320414 :   if (!data->ref || !data->len)
      78           46250 :     return;
      79                 :   
      80            9638 :   ASSERT(data->len < data->sz);
      81                 : 
      82            9638 :   ptr  = data->ref->ptr;
      83            9638 :   ptr += data->off;
      84                 : 
      85                 :   { /* special case vstr_cmp_buf_eq() ... works with _NON data */
      86            9638 :     Vstr_iter iter[1];
      87                 : 
      88            9638 :     ASSERT(vstr_iter_fwd_beg(base, data->pos, data->len, iter));
      89                 : 
      90          108567 :     do
      91                 :     {
      92          108567 :       if (iter->node->type != VSTR_TYPE_NODE_NON)
      93          108525 :         ASSERT(!memcmp(iter->ptr, ptr, iter->len));
      94          108567 :       ptr += iter->len;
      95          108567 :     } while (vstr_iter_fwd_nxt(iter));
      96                 :   }
      97                 : }
      98                 : 
      99                 : int vstr__check_real_nodes(const Vstr_base *base)
     100         5810910 : {
     101         5810910 :   size_t len = 0;
     102         5810910 :   size_t num = 0;
     103         5810910 :   unsigned int node_buf_used = FALSE;
     104         5810910 :   unsigned int node_non_used = FALSE;
     105         5810910 :   unsigned int node_ptr_used = FALSE;
     106         5810910 :   unsigned int node_ref_used = FALSE;
     107         5810910 :   Vstr_node *scan = base->beg;
     108                 : 
     109         5810910 :   vstr__debug_malloc_check_mem(base);
     110                 : 
     111         5810910 :   ASSERT(!base->used || (base->used < base->beg->len));
     112         5810910 :   ASSERT(!base->used || (base->beg->type == VSTR_TYPE_NODE_BUF));
     113         5810910 :   ASSERT((base->beg == base->end) || (base->num > 1));
     114                 :   
     115       539517071 :   while (scan)
     116                 :   {
     117       533706161 :     ASSERT(scan->len);
     118                 : 
     119       533706161 :     switch (scan->type)
     120                 :     {
     121        88333785 :       case VSTR_TYPE_NODE_BUF: node_buf_used = TRUE; break;
     122          159167 :       case VSTR_TYPE_NODE_NON: node_non_used = TRUE; break;
     123       269207323 :       case VSTR_TYPE_NODE_PTR: node_ptr_used = TRUE; break;
     124       176005886 :       case VSTR_TYPE_NODE_REF: node_ref_used = TRUE;
     125                 :         
     126       176005886 :         ASSERT_NO_SWITCH_DEF();
     127                 :     }
     128                 : 
     129       533706161 :     len += scan->len;
     130                 : 
     131       533706161 :     ++num;
     132                 : 
     133       533706161 :     scan = scan->next;
     134                 :   }
     135                 : 
     136                 :   /* it can be TRUE in the base and FALSE in reallity */
     137         5810910 :   assert(!node_buf_used || base->node_buf_used);
     138         5810910 :   assert(!node_non_used || base->node_non_used);
     139         5810910 :   assert(!node_ptr_used || base->node_ptr_used);
     140         5810910 :   assert(!node_ref_used || base->node_ref_used);
     141                 : 
     142         5810910 :   assert(!!base->beg == !!base->end);
     143         5810910 :   assert(((len - base->used) == base->len) && (num == base->num));
     144                 : 
     145         5810910 :   vstr__cache_iovec_check(base);
     146         5810910 :   vstr__cache_cstr_check(base);
     147                 : 
     148         5810910 :   return (TRUE);
     149                 : }
     150                 : 
     151                 : int vstr__check_spare_nodes(const Vstr_conf *conf)
     152         5989311 : {
     153         5989311 :   unsigned int num = 0;
     154         5989311 :   Vstr_node *scan = NULL;
     155                 : 
     156         5989311 :   vstr__debug_malloc_check_mem(conf);
     157                 :   
     158         5989311 :   num = 0;
     159         5989311 :   scan = (Vstr_node *)conf->spare_buf_beg;
     160      1508852309 :   while (scan)
     161                 :   {
     162      1502862998 :     ++num;
     163                 : 
     164      1502862998 :     assert(scan->type == VSTR_TYPE_NODE_BUF);
     165                 : 
     166      1502862998 :     scan = scan->next;
     167                 :   }
     168         5989311 :   assert(conf->spare_buf_num == num);
     169                 : 
     170         5989311 :   num = 0;
     171         5989311 :   scan = (Vstr_node *)conf->spare_non_beg;
     172         6121767 :   while (scan)
     173                 :   {
     174          132456 :     ++num;
     175                 : 
     176          132456 :     assert(scan->type == VSTR_TYPE_NODE_NON);
     177                 : 
     178          132456 :     scan = scan->next;
     179                 :   }
     180         5989311 :   assert(conf->spare_non_num == num);
     181                 : 
     182         5989311 :   num = 0;
     183         5989311 :   scan = (Vstr_node *)conf->spare_ptr_beg;
     184       461647735 :   while (scan)
     185                 :   {
     186       455658424 :     ++num;
     187                 : 
     188       455658424 :     assert(scan->type == VSTR_TYPE_NODE_PTR);
     189                 : 
     190       455658424 :     scan = scan->next;
     191                 :   }
     192         5989311 :   assert(conf->spare_ptr_num == num);
     193                 : 
     194         5989311 :   num = 0;
     195         5989311 :   scan = (Vstr_node *)conf->spare_ref_beg;
     196       294328826 :   while (scan)
     197                 :   {
     198       288339515 :     ++num;
     199                 : 
     200       288339515 :     assert(scan->type == VSTR_TYPE_NODE_REF);
     201                 : 
     202       288339515 :     scan = scan->next;
     203                 :   }
     204         5989311 :   assert(conf->spare_ref_num == num);
     205                 : 
     206         5989311 :   return (TRUE);
     207                 : }
     208                 : 
     209                 : static int vstr__check_spare_base(const Vstr_conf *conf)
     210           22393 : {
     211           22393 :   Vstr_base *scan = NULL;
     212           22393 :   unsigned int num = 0;
     213                 :   
     214           22393 :   ASSERT(conf);
     215                 : 
     216           22393 :   scan = conf->spare_base_beg;
     217           86813 :   while (scan)
     218                 :   { /* FIXME: ... BIG HACK */
     219           64420 :     ++num;
     220                 :     
     221           64420 :     scan = (Vstr_base *)scan->beg;
     222                 :   }  
     223                 : 
     224           22393 :   ASSERT(num == conf->spare_base_num);
     225                 :   
     226           22393 :   return (TRUE);
     227                 : }
     228                 : #endif
     229                 : 
     230                 : /* real functions... */
     231                 : 
     232                 : 
     233                 : size_t vstr__loc_thou_grp_strlen(const char *passed_str)
     234            1077 : {
     235            1077 :   const unsigned char *str = (const unsigned char *)passed_str;
     236            1077 :   size_t len = 0;
     237                 : 
     238            3026 :   while (*str && (*str < SCHAR_MAX))
     239                 :   {
     240            1949 :     ++len;
     241            1949 :     ++str;
     242                 :   }
     243                 : 
     244            1077 :   if (*str)
     245              15 :     ++len;
     246                 : 
     247            1077 :   return (len);
     248                 : }
     249                 : 
     250                 : Vstr_locale_num_base *
     251                 : vstr__loc_num_srch(Vstr_locale *loc, unsigned int num_base, int clone)
     252         2593305 : {
     253         2593305 :   Vstr_locale_num_base *scan = loc->num_beg;
     254         2593305 :   Vstr_locale_num_base *def = NULL;
     255                 : 
     256         3889759 :   while (scan)
     257                 :   {
     258         2593936 :     if (scan->num_base == num_base)
     259         1297482 :       return (scan);
     260                 :     
     261         1296454 :     scan = scan->next;
     262                 :   }
     263                 : 
     264         1295823 :   ASSERT(num_base);
     265                 : 
     266         1295823 :   def = vstr__loc_num_srch(loc, 0, FALSE);
     267                 :   
     268         1295823 :   if (clone)
     269                 :   {
     270              41 :     if (!(scan = VSTR__MK(sizeof(Vstr_locale_num_base))))
     271               1 :       return (NULL);
     272                 : 
     273              40 :     scan->next              = loc->num_beg;
     274                 : 
     275              40 :     scan->num_base          = num_base;
     276              40 :     scan->grouping          = vstr_ref_add(def->grouping);
     277              40 :     scan->thousands_sep_ref = vstr_ref_add(def->thousands_sep_ref);
     278              40 :     scan->thousands_sep_len =              def->thousands_sep_len;
     279              40 :     scan->decimal_point_ref = vstr_ref_add(def->decimal_point_ref);
     280              40 :     scan->decimal_point_len =              def->decimal_point_len;
     281                 :     
     282              40 :     loc->num_beg            = scan;
     283                 : 
     284              40 :     return (scan);
     285                 :   }
     286                 :   
     287         1295782 :   return (def);
     288                 : }
     289                 : 
     290                 : static int vstr__make_conf_loc_def_numeric(Vstr_conf *conf)
     291            6269 : {
     292            6269 :   Vstr_ref *ref = NULL;
     293                 :   
     294            6269 :   ASSERT(conf);
     295            6269 :   ASSERT(conf->loc);
     296            6269 :   ASSERT(conf->loc->num_beg);
     297                 :   
     298            6269 :   conf->loc->num_beg->num_base                = 0;
     299            6269 :   conf->loc->num_beg->next                    = NULL;
     300                 : 
     301            6269 :   if (!(conf->loc->name_lc_numeric_ref        = vstr_ref_make_strdup("C")))
     302               1 :     goto fail_numeric;
     303                 : 
     304            6268 :   if (!(ref = conf->loc->num_beg->grouping    = vstr_ref_make_strdup("")))
     305               1 :     goto fail_grp;
     306                 : 
     307            6267 :   conf->loc->num_beg->thousands_sep_ref       = vstr_ref_add(ref);
     308                 : 
     309            6267 :   if (!(conf->loc->num_beg->decimal_point_ref = vstr_ref_make_strdup(".")))
     310               1 :     goto fail_deci;
     311                 : 
     312            6266 :   if (!(conf->loc->null_ref                   = vstr_ref_make_strdup("(null)")))
     313               1 :     goto fail_null;
     314                 : 
     315            6265 :   conf->loc->name_lc_numeric_len              = 1;
     316            6265 :   conf->loc->num_beg->thousands_sep_len       = 0;
     317            6265 :   conf->loc->num_beg->decimal_point_len       = 1;
     318            6265 :   conf->loc->null_len                         = strlen("(null)");
     319                 : 
     320            6265 :   return (TRUE);
     321                 : 
     322                 :   /* vstr_ref_del(conf->loc->null_ref); */
     323                 :  fail_null:
     324               1 :   vstr_ref_del(conf->loc->num_beg->decimal_point_ref);
     325                 :  fail_deci:
     326               2 :   vstr_ref_del(conf->loc->num_beg->thousands_sep_ref);
     327               2 :   vstr_ref_del(conf->loc->num_beg->grouping);
     328                 :  fail_grp:
     329               3 :   vstr_ref_del(conf->loc->name_lc_numeric_ref);
     330                 :  fail_numeric:
     331                 : 
     332               4 :   return (FALSE);
     333                 : }
     334                 : 
     335                 : int vstr__make_conf_loc_numeric(Vstr_conf *conf, const char *name)
     336            1035 : {
     337            1035 :   struct lconv *sys_loc = NULL;
     338            1035 :   const char *tmp = NULL;
     339            1035 :   Vstr_locale loc[1];
     340            1035 :   Vstr_locale_num_base num_beg[1];
     341                 : 
     342            1035 :   ASSERT(conf);
     343            1035 :   ASSERT(conf->loc);
     344            1035 :   ASSERT(conf->loc->num_beg);
     345                 :   
     346            1035 :   loc->num_beg = num_beg;
     347                 :   
     348            1035 :   if (name)
     349            1035 :     tmp = setlocale(LC_NUMERIC, name);
     350                 : 
     351            1035 :   if (!(sys_loc = localeconv()))
     352             224 :     return (FALSE);
     353                 :   else
     354                 :   {
     355            1035 :     const char *name_numeric = NULL;
     356            1035 :     size_t numeric_len = 0;
     357            1035 :     size_t grp_len  = vstr__loc_thou_grp_strlen(SYS_LOC(grouping));
     358            1035 :     size_t thou_len =                    strlen(SYS_LOC(thousands_sep));
     359            1035 :     size_t deci_len =                    strlen(SYS_LOC(decimal_point));
     360            1035 :     Vstr_ref *ref = NULL;
     361                 :     
     362            1035 :     if (VSTR__DEBUG_MALLOC_TST() ||
     363                 :         !(name_numeric = setlocale(LC_NUMERIC, NULL))) /* name for "name" */
     364             355 :       name_numeric = "C";
     365            1035 :     numeric_len = strlen(name_numeric);
     366                 :     
     367            1035 :     if (!(ref = vstr_ref_make_strdup(name_numeric)))
     368             225 :       goto fail_numeric;
     369            1034 :     loc->name_lc_numeric_ref        = ref;
     370                 :     
     371                 :     
     372            1034 :     if (!(ref = vstr_ref_make_malloc(grp_len + 1)))
     373             225 :       goto fail_grp;
     374            1033 :     loc->num_beg->grouping          = ref;
     375                 : 
     376            1033 :     if (!(ref = vstr_ref_make_strdup(SYS_LOC(thousands_sep))))
     377             225 :       goto fail_thou;
     378            1032 :     loc->num_beg->thousands_sep_ref = ref;
     379                 : 
     380            1032 :     if (!(ref = vstr_ref_make_strdup(SYS_LOC(decimal_point))))
     381             225 :       goto fail_deci;
     382            1031 :     loc->num_beg->decimal_point_ref = ref;
     383                 : 
     384            1031 :     loc->name_lc_numeric_len = numeric_len;
     385                 : 
     386                 :     /* Grouping is different we have to make sure it is 0 terminated */
     387            1031 :     if (grp_len)
     388            1031 :       vstr_wrap_memcpy(loc->num_beg->grouping->ptr, SYS_LOC(grouping), grp_len);
     389            1031 :     ((char *)loc->num_beg->grouping->ptr)[grp_len] = 0;
     390                 : 
     391            1031 :     loc->num_beg->thousands_sep_len = thou_len;
     392            1031 :     loc->num_beg->decimal_point_len = deci_len;
     393                 :   }
     394                 : 
     395            1043 :   while (TRUE)
     396                 :   {
     397            1043 :     Vstr_locale_num_base *next = conf->loc->num_beg->next;
     398                 :     
     399            1043 :     vstr_ref_del(conf->loc->num_beg->grouping);
     400            1043 :     vstr_ref_del(conf->loc->num_beg->thousands_sep_ref);
     401            1043 :     vstr_ref_del(conf->loc->num_beg->decimal_point_ref);
     402                 : 
     403            1043 :     if (!next)
     404            1031 :       break;
     405                 : 
     406             236 :     VSTR__F(conf->loc->num_beg);
     407             236 :     conf->loc->num_beg = next;
     408                 :   }
     409                 : 
     410            1031 :   vstr_ref_del(conf->loc->name_lc_numeric_ref);
     411            1031 :   conf->loc->name_lc_numeric_ref        = loc->name_lc_numeric_ref;
     412            1031 :   conf->loc->name_lc_numeric_len        = loc->name_lc_numeric_len;
     413                 : 
     414            1031 :   conf->loc->num_beg->num_base          = 0;
     415            1031 :   conf->loc->num_beg->grouping          = loc->num_beg->grouping;
     416                 : 
     417            1031 :   conf->loc->num_beg->thousands_sep_ref = loc->num_beg->thousands_sep_ref;
     418            1031 :   conf->loc->num_beg->thousands_sep_len = loc->num_beg->thousands_sep_len;
     419                 : 
     420            1031 :   conf->loc->num_beg->decimal_point_ref = loc->num_beg->decimal_point_ref;
     421            1031 :   conf->loc->num_beg->decimal_point_len = loc->num_beg->decimal_point_len;
     422                 : 
     423            1031 :   if (tmp)
     424            1031 :     setlocale(LC_NUMERIC, tmp);
     425                 : 
     426            1031 :   return (TRUE);
     427                 : 
     428                 :  fail_deci:
     429             225 :   vstr_ref_del(loc->num_beg->thousands_sep_ref);
     430                 :  fail_thou:
     431             226 :   vstr_ref_del(loc->num_beg->grouping);
     432                 :  fail_grp:
     433             227 :   vstr_ref_del(loc->name_lc_numeric_ref);
     434                 :  fail_numeric:
     435                 : 
     436             228 :   if (tmp)
     437             228 :     setlocale(LC_NUMERIC, tmp);
     438                 : 
     439             228 :   return (FALSE);
     440                 : }
     441                 : 
     442                 : Vstr_conf *vstr_make_conf(void)
     443            6275 : {
     444            6275 :   Vstr_conf *conf = VSTR__MK(sizeof(Vstr_conf));
     445                 : 
     446            6275 :   if (!conf)
     447               2 :     goto fail_conf;
     448                 : 
     449            6273 :   if (!vstr__cache_conf_init(conf))
     450               1 :     goto fail_cache;
     451                 : 
     452            6272 :   if (!vstr__data_conf_init(conf))
     453               1 :     goto fail_data;
     454                 : 
     455            6271 :   if (!(conf->loc = VSTR__MK(sizeof(Vstr_locale))))
     456               1 :     goto fail_loc;
     457                 : 
     458            6270 :   if (!(conf->loc->num_beg = VSTR__MK(sizeof(Vstr_locale_num_base))))
     459               1 :     goto fail_loc_num;
     460                 : 
     461            6269 :   if (!vstr__make_conf_loc_def_numeric(conf))
     462               4 :     goto fail_numeric;
     463                 : 
     464            6265 :   conf->spare_buf_num = 0;
     465            6265 :   conf->spare_buf_beg = NULL;
     466                 : 
     467            6265 :   conf->spare_non_num = 0;
     468            6265 :   conf->spare_non_beg = NULL;
     469                 : 
     470            6265 :   conf->spare_ptr_num = 0;
     471            6265 :   conf->spare_ptr_beg = NULL;
     472                 : 
     473            6265 :   conf->spare_ref_num = 0;
     474            6265 :   conf->spare_ref_beg = NULL;
     475                 : 
     476            6265 :   conf->iov_min_alloc = 0;
     477            6265 :   conf->iov_min_offset = 0;
     478                 : 
     479            6265 :   conf->buf_sz = 64 - (sizeof(Vstr_node_buf) + 8);
     480                 : 
     481            6265 :   conf->fmt_usr_names = 0;
     482            6265 :   conf->fmt_usr_escape = 0;
     483                 : 
     484            6265 :   conf->vstr__fmt_spec_make = NULL;
     485            6265 :   conf->vstr__fmt_spec_list_beg = NULL;
     486            6265 :   conf->vstr__fmt_spec_list_end = NULL;
     487                 : 
     488            6265 :   conf->ref = 1;
     489                 : 
     490            6265 :   conf->ref_link = NULL;
     491                 : 
     492            6265 :   conf->ref_grp_ptr     = NULL;
     493            6265 :   conf->ref_grp_buf2ref = NULL;
     494                 : 
     495            6265 :   conf->free_do = TRUE;
     496            6265 :   conf->malloc_bad = FALSE;
     497            6265 :   conf->iovec_auto_update = TRUE;
     498            6265 :   conf->split_buf_del = FALSE;
     499                 : 
     500            6265 :   conf->user_ref = 1;
     501                 : 
     502            6265 :   conf->no_cache = FALSE;
     503            6265 :   conf->fmt_usr_curly_braces = TRUE;
     504            6265 :   conf->atomic_ops = TRUE;
     505                 : 
     506            6265 :   conf->grpalloc_cache = VSTR_TYPE_CNTL_CONF_GRPALLOC_POS;
     507                 :   
     508            6265 :   conf->spare_base_num = 0;
     509            6265 :   conf->spare_base_beg = NULL;
     510                 :   
     511            6265 :   return (conf);
     512                 : 
     513                 :  fail_numeric:
     514               4 :   VSTR__F(conf->loc->num_beg);
     515                 :  fail_loc_num:
     516               5 :   VSTR__F(conf->loc);
     517                 :  fail_loc:
     518               6 :   VSTR__F(conf->data_usr_ents);
     519                 :  fail_data:
     520               7 :   VSTR__F(conf->cache_cbs_ents);
     521                 :  fail_cache:
     522               8 :   VSTR__F(conf);
     523                 :  fail_conf:
     524                 : 
     525              10 :   return (NULL);
     526                 : }
     527                 : 
     528                 : static void vstr__add_conf(Vstr_conf *conf)
     529           23293 : {
     530           23293 :   ++conf->ref;
     531                 : }
     532                 : 
     533                 : void vstr__add_user_conf(Vstr_conf *conf)
     534              45 : {
     535              45 :   assert(conf);
     536              45 :   assert(conf->user_ref <= conf->ref);
     537                 : 
     538              45 :   ++conf->user_ref;
     539                 : 
     540              45 :   vstr__add_conf(conf);
     541                 : }
     542                 : 
     543                 : /* NOTE: magic also exists in vstr_add..c (vstr__convert_buf_ref_add)
     544                 :  * for linked references */
     545                 : 
     546                 : void vstr__add_base_conf(Vstr_base *base, Vstr_conf *conf)
     547           23248 : {
     548           23248 :   assert(conf->user_ref <= conf->ref);
     549                 : 
     550           23248 :   base->conf = conf;
     551           23248 :   vstr__add_conf(conf);
     552                 : }
     553                 : 
     554                 : void vstr__del_grpalloc(Vstr_conf *conf, unsigned int num)
     555            7419 : {
     556            7419 :   Vstr_base *scan = conf->spare_base_beg;
     557                 :   
     558           13579 :   ASSERT(vstr__check_spare_base(conf));
     559                 :   
     560           15107 :   while (scan && num)
     561                 :   { /* FIXME: ... BIG HACK */
     562            7688 :     conf->spare_base_beg = (Vstr_base *)scan->beg;
     563                 : 
     564            7688 :     if (scan->cache_available)
     565                 :     {
     566            6658 :       if (VSTR__CACHE(scan)->vec)
     567                 :       {
     568             267 :         VSTR__F(VSTR__CACHE(scan)->vec->v);
     569             267 :         VSTR__F(VSTR__CACHE(scan)->vec->t);          
     570                 :       }
     571            6658 :       VSTR__F(VSTR__CACHE(scan));
     572                 :     }
     573            7688 :     VSTR__F(scan);
     574                 : 
     575            7688 :     --conf->spare_base_num;
     576            7688 :     --num;
     577                 :     
     578            7688 :     scan = conf->spare_base_beg;
     579                 :   }
     580                 : 
     581            7419 :   ASSERT(vstr__check_spare_base(conf));
     582                 : }
     583                 : 
     584                 : void vstr__del_conf(Vstr_conf *conf)
     585           32030 : {
     586           32030 :   assert(conf->ref > 0);
     587                 : 
     588           32030 :   if (!--conf->ref)
     589                 :   {
     590            6057 :     ASSERT(!conf->ref_link);
     591                 : 
     592            6057 :     vstr__ref_grp_free(conf->ref_grp_ptr);
     593            6057 :     vstr__ref_grp_free(conf->ref_grp_buf2ref);
     594                 :     
     595            6057 :     vstr_free_spare_nodes(conf, VSTR_TYPE_NODE_BUF, conf->spare_buf_num);
     596            6057 :     vstr_free_spare_nodes(conf, VSTR_TYPE_NODE_NON, conf->spare_non_num);
     597            6057 :     vstr_free_spare_nodes(conf, VSTR_TYPE_NODE_PTR, conf->spare_ptr_num);
     598            6057 :     vstr_free_spare_nodes(conf, VSTR_TYPE_NODE_REF, conf->spare_ref_num);
     599                 : 
     600            6057 :     VSTR__DEBUG_MALLOC_CHECK_MEM(conf->loc->name_lc_numeric_ref);
     601            6057 :     vstr_ref_del(conf->loc->name_lc_numeric_ref);
     602                 :     
     603           12142 :     while (conf->loc->num_beg)
     604                 :     {
     605            6085 :       Vstr_locale_num_base *next = conf->loc->num_beg->next;
     606                 :       
     607            6085 :       VSTR__DEBUG_MALLOC_CHECK_MEM(conf->loc->num_beg);
     608                 :       
     609            6085 :       vstr_ref_del(conf->loc->num_beg->grouping);
     610            6085 :       vstr_ref_del(conf->loc->num_beg->thousands_sep_ref);
     611            6085 :       vstr_ref_del(conf->loc->num_beg->decimal_point_ref);
     612                 :       
     613            6085 :       VSTR__F(conf->loc->num_beg);
     614            6085 :       conf->loc->num_beg = next;
     615                 :     }
     616                 : 
     617            6057 :     vstr_ref_del(conf->loc->null_ref);
     618                 : 
     619            6057 :     VSTR__F(conf->loc);
     620                 : 
     621            6057 :     vstr__data_conf_free(conf);
     622                 :     
     623            6057 :     VSTR__F(conf->cache_cbs_ents);
     624                 : 
     625            6057 :     vstr__add_fmt_free_conf(conf);
     626                 : 
     627            6057 :     vstr__del_grpalloc(conf, conf->spare_base_num);
     628                 :     
     629            6057 :     if (conf->free_do)
     630            6057 :       VSTR__F(conf);
     631                 :   }
     632                 : }
     633                 : 
     634                 : int vstr_swap_conf(Vstr_base *base, Vstr_conf **conf)
     635              46 : {
     636              46 :   int can_change_conf = FALSE;
     637                 :   
     638              46 :   assert(conf && *conf);
     639              46 :   assert((*conf)->user_ref > 0);
     640              46 :   assert((*conf)->user_ref <= (*conf)->ref);
     641                 : 
     642              46 :   if (base->conf == *conf)
     643               5 :     return (TRUE);
     644                 : 
     645                 :   /* there are base string object using this configuration,
     646                 :    * so we can't change it */
     647              41 :   if ((*conf)->user_ref == (*conf)->ref)
     648              31 :     can_change_conf = TRUE;
     649                 :   
     650              41 :   if (base->conf->buf_sz != (*conf)->buf_sz)
     651                 :   {
     652              15 :     if (!can_change_conf)
     653               5 :       return (FALSE);
     654                 : 
     655              10 :     vstr_free_spare_nodes(*conf, VSTR_TYPE_NODE_BUF, (*conf)->spare_buf_num);
     656              10 :     (*conf)->buf_sz = base->conf->buf_sz;
     657                 :   }
     658                 : 
     659              36 :   if (!vstr__cache_subset_cbs(base->conf, *conf))
     660                 :   {
     661              16 :     if (!can_change_conf)
     662               5 :       return (FALSE);
     663                 : 
     664              11 :     if (!vstr__cache_dup_cbs(*conf, base->conf))
     665               1 :       return (FALSE);
     666                 :   }
     667                 : 
     668              30 :   --(*conf)->user_ref;
     669              30 :   ++base->conf->user_ref;
     670                 : 
     671              30 :   SWAP_TYPE(*conf, base->conf, Vstr_conf *);
     672                 : 
     673              30 :   return (TRUE);
     674                 : }
     675                 : 
     676                 : void vstr_free_conf(Vstr_conf *conf)
     677            6170 : {
     678            6170 :   if (!conf)
     679               5 :     return;
     680                 : 
     681            6165 :   assert(conf->user_ref > 0);
     682            6165 :   assert(conf->user_ref <= conf->ref);
     683                 : 
     684            6165 :   --conf->user_ref;
     685                 : 
     686            6165 :   vstr__del_conf(conf);
     687                 : }
     688                 : 
     689                 : int vstr_init(void)
     690            3007 : {
     691            3007 :   if (!vstr__options.def)
     692                 :   {
     693            3007 :     vstr__options.mmap_count = 0;
     694                 :     
     695            3007 :     vstr__options.fd_count = 0;
     696                 : 
     697            3007 :     vstr__options.mem_sz = 0;
     698            3007 :     vstr__options.mem_num = 0;
     699            3007 :     vstr__options.mem_vals = NULL;
     700                 : 
     701                 :     /* NOTE: don't set fail nums */
     702                 :     
     703            3007 :     if (!(vstr__options.def = vstr_make_conf()))
     704               1 :       return (FALSE);
     705                 :   }
     706                 : 
     707            3006 :   return (TRUE);
     708                 : }
     709                 : 
     710                 : void vstr_exit(void)
     711            2925 : {
     712            2925 :   ASSERT((vstr__options.def->user_ref == 1) &&
     713                 :          (vstr__options.def->ref == 1));
     714                 : 
     715            2925 :   vstr_free_conf(vstr__options.def);
     716            2925 :   vstr__options.def = NULL;
     717                 : 
     718             607 :   ASSERT(!vstr__options.mmap_count);
     719             607 :   ASSERT(!vstr__options.fd_count);
     720                 :   
     721             607 :   VSTR__DEBUG_MALLOC_CHECK_EMPTY();
     722                 : }
     723                 : 
     724                 : int vstr__cache_iovec_valid(Vstr_base *base)
     725          167655 : {
     726          167655 :   unsigned int count = 0;
     727          167655 :   Vstr_node *scan = NULL;
     728                 : 
     729          167655 :   if (base->iovec_upto_date)
     730          131776 :     return (TRUE);
     731                 : 
     732           35879 :   if (!base->beg)
     733                 :   {
     734            1897 :     if (base->cache_available && VSTR__CACHE(base) && VSTR__CACHE(base)->vec &&
     735                 :         VSTR__CACHE(base)->vec->sz)
     736            1897 :       base->iovec_upto_date = TRUE;
     737                 : 
     738            1897 :     return (TRUE);
     739                 :   }
     740                 : 
     741           33982 :   if (!vstr__cache_iovec_alloc(base, base->num))
     742              80 :     return (FALSE);
     743                 : 
     744           33902 :   assert(VSTR__CACHE(base)->vec->off == base->conf->iov_min_offset);
     745                 : 
     746           33902 :   count = base->conf->iov_min_offset;
     747           33902 :   scan = base->beg;
     748                 : 
     749           33902 :   VSTR__CACHE(base)->vec->v[count].iov_len = scan->len - base->used;
     750           33902 :   if (scan->type == VSTR_TYPE_NODE_NON)
     751               9 :     VSTR__CACHE(base)->vec->v[count].iov_base = NULL;
     752                 :   else
     753           33893 :     VSTR__CACHE(base)->vec->v[count].iov_base = (vstr_export__node_ptr(scan) +
     754                 :                                                  base->used);
     755           33902 :   VSTR__CACHE(base)->vec->t[count] = scan->type;
     756                 : 
     757           33902 :   scan = scan->next;
     758           33902 :   ++count;
     759          483969 :   while (scan)
     760                 :   {
     761          450067 :     VSTR__CACHE(base)->vec->t[count] = scan->type;
     762          450067 :     VSTR__CACHE(base)->vec->v[count].iov_len = scan->len;
     763          450067 :     VSTR__CACHE(base)->vec->v[count].iov_base = vstr_export__node_ptr(scan);
     764                 : 
     765          450067 :     ++count;
     766          450067 :     scan = scan->next;
     767                 :   }
     768                 : 
     769           33902 :   base->iovec_upto_date = TRUE;
     770                 : 
     771           33902 :   return (TRUE);
     772                 : }
     773                 : 
     774                 : static void vstr__init_base(Vstr_conf *conf, Vstr_base *base)
     775           23233 : {
     776           23233 :   base->beg = NULL;
     777           23233 :   base->end = NULL;
     778                 : 
     779           23233 :   base->len = 0;
     780           23233 :   base->num = 0;
     781                 : 
     782           23233 :   vstr__add_base_conf(base, conf);
     783                 : 
     784           23233 :   base->used = 0;
     785           23233 :   base->free_do = FALSE;
     786           23233 :   base->iovec_upto_date = FALSE;
     787                 : 
     788           23233 :   base->node_buf_used = FALSE;
     789           23233 :   base->node_non_used = FALSE;
     790           23233 :   base->node_ptr_used = FALSE;
     791           23233 :   base->node_ref_used = FALSE;
     792                 : 
     793           23233 :   if (base->cache_available &&
     794                 :       (base->grpalloc_cache >= VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC))
     795                 :   {
     796           13036 :     VSTR__CACHE(base)->vec->off = base->conf->iov_min_offset;
     797           13036 :     base->iovec_upto_date = TRUE;
     798                 :   }
     799                 : }
     800                 : 
     801                 : void vstr_free_base(Vstr_base *base)
     802           24107 : {
     803           24107 :   Vstr_conf *conf = NULL;
     804                 : 
     805           24107 :   if (!base)
     806            1050 :     return;
     807                 : 
     808           23057 :   conf = base->conf;
     809                 : 
     810           23057 :   ASSERT(vstr__check_spare_base(conf));
     811                 :   
     812           23057 :   vstr__free_cache(base);
     813                 : 
     814           23057 :   vstr_del(base, 1, base->len);
     815                 : 
     816           23057 :   if (base->free_do)
     817                 :   {
     818           23057 :     if (base->grpalloc_cache == base->conf->grpalloc_cache)
     819                 :     { /* FIXME: massive hack */
     820           23022 :       base->beg = (Vstr_node *)base->conf->spare_base_beg;
     821           23022 :       base->conf->spare_base_beg = base;
     822           23022 :       ++base->conf->spare_base_num;
     823                 :     }
     824                 :     else
     825                 :     {
     826              35 :       if (base->cache_available)
     827                 :       {
     828              25 :         if (VSTR__CACHE(base)->vec)
     829                 :         {
     830               5 :           VSTR__F(VSTR__CACHE(base)->vec->v);
     831               5 :           VSTR__F(VSTR__CACHE(base)->vec->t);          
     832                 :         }
     833              25 :         VSTR__F(VSTR__CACHE(base));
     834                 :       }
     835              35 :       VSTR__F(base);
     836                 :     }
     837                 :   }
     838                 :   
     839           23057 :   ASSERT(vstr__check_spare_base(conf));
     840                 :   
     841           23057 :   vstr__del_conf(conf);
     842                 : }
     843                 : 
     844                 : static Vstr_base *vstr__make_base_cache(Vstr_conf *conf)
     845            8196 : {
     846            8196 :   Vstr_base *base = NULL;
     847            8196 :   size_t sz = 0;
     848            8196 :   unsigned int num = 0;
     849            8196 :   Vstr__cache *cache = NULL;
     850                 :   
     851            8196 :   switch (conf->grpalloc_cache)
     852                 :   {
     853                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_NONE:
     854            1061 :       num = 0; sz = sizeof(struct Vstr_base);            break;
     855                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_POS:
     856            6826 :       num = 1; sz = sizeof(struct Vstr__base_p_cache);   break;
     857                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC:
     858              41 :       num = 2; sz = sizeof(struct Vstr__base_pi_cache);  break;
     859                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR:
     860             268 :       num = 3; sz = sizeof(struct Vstr__base_pic_cache);
     861                 :       
     862              71 :       ASSERT_NO_SWITCH_DEF();
     863                 :   }
     864                 :     
     865            8196 :   if (!(base = VSTR__MK(sz)))
     866             148 :     goto malloc_fail_base;
     867                 :   
     868            8048 :   base->grpalloc_cache = conf->grpalloc_cache;
     869                 :   
     870            8048 :   base->cache_internal = TRUE;
     871                 :   
     872                 :   /* allocate cache pointers */
     873            8048 :   if (!num)
     874                 :   {
     875            1061 :     base->cache_available = FALSE;
     876            1061 :     ASSERT(conf->no_cache);
     877            1061 :     return (base);
     878                 :   }
     879                 : 
     880            6987 :   if (!(cache = VSTR__MK(sizeof(Vstr__cache) + (sizeof(void *) * num))))
     881             147 :     goto malloc_fail_cache;
     882                 :   
     883            6840 :   cache->sz  = num;
     884            6840 :   cache->vec = NULL;
     885                 :   
     886            6840 :   vstr_wrap_memset(cache->data, 0, sizeof(void *) * num);
     887                 :   
     888            6840 :   VSTR__CACHE(base)     = cache;
     889            6840 :   base->cache_available = TRUE;
     890                 :   
     891                 :   /* NOTE: hand init/allocate empty data for each cache type,
     892                 :    * this should really be in vstr_cache.c ... */
     893            6840 :   switch (conf->grpalloc_cache)
     894                 :   {
     895                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR:
     896                 :     {
     897             265 :       struct Vstr__base_pic_cache *ubase = (struct Vstr__base_pic_cache *)base;
     898             265 :       Vstr__cache_data_cstr *data = &ubase->real_cstr;
     899                 :     
     900             265 :       data->ref = NULL;
     901             265 :       vstr_cache_set(base, 3, data);
     902             297 :       ASSERT(vstr_cache_get(base, 3) == data);
     903                 :     }
     904             297 :     ASSERT(cache->sz >= 3);
     905                 :     /* FALLTHOUGH */
     906                 : 
     907                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC:
     908                 :     {
     909             306 :       struct Vstr__base_pi_cache *ubase = (struct Vstr__base_pi_cache *)base;
     910             306 :       Vstr__cache_data_iovec *data = &ubase->real_iov;
     911             306 :       size_t alloc_sz = 1 + conf->iov_min_alloc + conf->iov_min_offset;
     912                 :     
     913             306 :       VSTR__CACHE(base)->vec = data;
     914                 :     
     915             306 :       data->v = VSTR__MK(sizeof(struct iovec) * alloc_sz);
     916             306 :       data->t = NULL;
     917             306 :       data->off = conf->iov_min_offset;
     918             306 :       data->sz = 0;
     919                 :     
     920             306 :       if (!data->v)
     921               1 :         goto malloc_fail_vec_v;
     922                 :     
     923             305 :       assert(!data->t);
     924             305 :       data->t = VSTR__MK(alloc_sz);
     925                 :     
     926             305 :       if (!data->t)
     927               1 :         goto malloc_fail_vec_t;
     928                 :     
     929             304 :       data->sz = alloc_sz;
     930            5484 :       assert(!data->off);
     931                 : 
     932                 :       /* this is left NULL so that we don't call the cb */
     933            5484 :       ASSERT(vstr_cache_get(base, 2) == NULL);
     934                 :     }
     935            5484 :     ASSERT(cache->sz >= 2);
     936                 :     /* FALLTHOUGH */
     937                 :     
     938                 :     case VSTR_TYPE_CNTL_CONF_GRPALLOC_POS:
     939                 :     {
     940            6838 :       struct Vstr__base_p_cache *ubase = (struct Vstr__base_p_cache *)base;
     941            6838 :       Vstr__cache_data_pos *data = &ubase->real_pos;
     942                 :     
     943            6838 :       data->node = NULL;
     944                 :     
     945            6838 :       vstr_cache_set(base, 1, data);
     946            1429 :       ASSERT(vstr_cache_get(base, 1) == data);
     947                 :     }
     948            1429 :     ASSERT(cache->sz >= 1);
     949               0 :     ASSERT_NO_SWITCH_DEF();
     950                 :   }
     951                 : 
     952            6838 :   return (base);
     953                 :   
     954                 :  malloc_fail_vec_t:
     955               1 :   VSTR__F(VSTR__CACHE(base)->vec->v);
     956                 :  malloc_fail_vec_v:
     957               2 :   VSTR__F(VSTR__CACHE(base));
     958                 :  malloc_fail_cache:
     959             149 :   VSTR__F(base);
     960                 :  malloc_fail_base:
     961             297 :   return (NULL);
     962                 : }
     963                 : 
     964                 : Vstr_base *vstr_make_base(Vstr_conf *conf)
     965           23530 : {
     966           23530 :   Vstr_base *base = NULL;
     967                 : 
     968           23530 :   if (!conf)
     969           18660 :     conf = vstr__options.def;
     970                 : 
     971           23530 :   ASSERT(vstr__check_spare_nodes(conf));
     972           23530 :   ASSERT(vstr__check_spare_base(conf));
     973                 :   
     974           23530 :   if (conf->spare_base_num)
     975                 :   {
     976           15334 :     Vstr__cache *cache = NULL;
     977                 :   
     978           15334 :     base = conf->spare_base_beg;
     979           15334 :     conf->spare_base_beg = (Vstr_base *)base->beg;
     980           15334 :     --conf->spare_base_num;
     981                 : 
     982           15334 :     ASSERT(base->grpalloc_cache == conf->grpalloc_cache);
     983                 :     
     984           15334 :     ASSERT(base->cache_internal);
     985                 : 
     986           15334 :     cache = VSTR__CACHE(base);
     987           15334 :     if (base->grpalloc_cache != VSTR_TYPE_CNTL_CONF_GRPALLOC_NONE)
     988           15328 :       VSTR__DEBUG_MALLOC_CHECK_MEM(cache);
     989                 :     
     990           15334 :     switch (conf->grpalloc_cache)
     991                 :     {
     992                 :       case VSTR_TYPE_CNTL_CONF_GRPALLOC_CSTR:
     993                 :       {
     994           12408 :         struct Vstr__base_pic_cache *ubase = (struct Vstr__base_pic_cache *)base;
     995           12408 :         Vstr__cache_data_cstr *data = &ubase->real_cstr;
     996                 :         
     997           12408 :         data->ref = NULL;
     998           12408 :         vstr_cache_set(base, 3, data);
     999           14436 :         ASSERT(vstr_cache_get(base, 3) == data);
    1000                 :       }
    1001           14436 :       ASSERT(cache->sz >= 3);
    1002                 :       /* FALLTHOUGH */
    1003                 :       
    1004                 :       case VSTR_TYPE_CNTL_CONF_GRPALLOC_IOVEC:
    1005                 :         /* this is left NULL so that we don't call the cb */
    1006           14516 :         ASSERT(vstr_cache_get(base, 2) == NULL);
    1007           14516 :         ASSERT(cache->sz >= 2);
    1008                 :         /* FALLTHOUGH */
    1009                 :         
    1010                 :       case VSTR_TYPE_CNTL_CONF_GRPALLOC_POS:
    1011                 :       {
    1012           15305 :         struct Vstr__base_p_cache *ubase = (struct Vstr__base_p_cache *)base;
    1013           15305 :         Vstr__cache_data_pos *data = &ubase->real_pos;
    1014                 :         
    1015           15305 :         data->node = NULL;
    1016                 :         
    1017           15305 :         vstr_cache_set(base, 1, data);
    1018           15305 :         ASSERT(vstr_cache_get(base, 1) == data);
    1019                 :       }
    1020           15305 :       ASSERT(cache->sz >= 1);
    1021                 :       /* FALLTHOUGH */
    1022                 :       
    1023                 :       case VSTR_TYPE_CNTL_CONF_GRPALLOC_NONE:
    1024                 :         
    1025           12007 :         ASSERT_NO_SWITCH_DEF();
    1026                 :     }
    1027                 :   }
    1028            8196 :   else if (!(base = vstr__make_base_cache(conf)))
    1029             297 :     goto malloc_fail_base;
    1030                 : 
    1031           23233 :   vstr__init_base(conf, base);
    1032                 : 
    1033           23233 :   base->free_do = TRUE;
    1034                 : 
    1035           23233 :   ASSERT(base->conf == conf);
    1036           23233 :   ASSERT(vstr__check_spare_nodes(conf));
    1037           23233 :   ASSERT(vstr__check_real_nodes(base));
    1038           23233 :   ASSERT(vstr__check_spare_base(conf));
    1039                 : 
    1040           23233 :   return (base);
    1041                 : 
    1042                 :  malloc_fail_base:
    1043             297 :   conf->malloc_bad = TRUE;
    1044             297 :   return (NULL);
    1045                 : }
    1046                 : 
    1047                 : Vstr_node *vstr__base_split_node(Vstr_base *base, Vstr_node *node, size_t pos)
    1048            3813 : {
    1049            3813 :   Vstr_node *beg = NULL;
    1050                 : 
    1051            3813 :   assert(base && pos && (pos <= node->len));
    1052                 : 
    1053            3813 :   switch (node->type)
    1054                 :   {
    1055                 :     case VSTR_TYPE_NODE_BUF:
    1056            2478 :       if (!vstr_cntl_conf(base->conf,
    1057                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_BUF, 1, UINT_MAX))
    1058              35 :         return (NULL);
    1059                 : 
    1060            2443 :       --base->conf->spare_buf_num;
    1061            2443 :       beg = (Vstr_node *)base->conf->spare_buf_beg;
    1062            2443 :       base->conf->spare_buf_beg = (Vstr_node_buf *)beg->next;
    1063                 : 
    1064            2443 :       vstr_wrap_memcpy(((Vstr_node_buf *)beg)->buf,
    1065                 :                        ((Vstr_node_buf *)node)->buf + pos, node->len - pos);
    1066                 : 
    1067                 :       /* poison the split */
    1068            2443 :       ASSERT(vstr_wrap_memset(((Vstr_node_buf *)node)->buf + pos, 0xFE,
    1069                 :                               node->len - pos));
    1070            1971 :       break;
    1071                 : 
    1072                 :     case VSTR_TYPE_NODE_NON:
    1073              27 :       if (!vstr_cntl_conf(base->conf,
    1074                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_NON, 1, UINT_MAX))
    1075               3 :         return (NULL);
    1076                 : 
    1077              24 :       --base->conf->spare_non_num;
    1078              24 :       beg = (Vstr_node *)base->conf->spare_non_beg;
    1079              24 :       base->conf->spare_non_beg = (Vstr_node_non *)beg->next;
    1080              24 :       break;
    1081                 : 
    1082                 :     case VSTR_TYPE_NODE_PTR:
    1083             878 :       if (!vstr_cntl_conf(base->conf,
    1084                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_PTR, 1, UINT_MAX))
    1085              43 :         return (NULL);
    1086                 : 
    1087             835 :       --base->conf->spare_ptr_num;
    1088             835 :       beg = (Vstr_node *)base->conf->spare_ptr_beg;
    1089             835 :       base->conf->spare_ptr_beg = (Vstr_node_ptr *)beg->next;
    1090                 : 
    1091             835 :       ((Vstr_node_ptr *)beg)->ptr = ((char *)((Vstr_node_ptr *)node)->ptr) + pos;
    1092             835 :       break;
    1093                 : 
    1094                 :     case VSTR_TYPE_NODE_REF:
    1095                 :     {
    1096             430 :       Vstr_ref *ref = NULL;
    1097                 : 
    1098             430 :       if (!vstr_cntl_conf(base->conf,
    1099                 :                           VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF, 1, UINT_MAX))
    1100               5 :         return (NULL);
    1101                 : 
    1102             425 :       --base->conf->spare_ref_num;
    1103             425 :       beg = (Vstr_node *)base->conf->spare_ref_beg;
    1104             425 :       base->conf->spare_ref_beg = (Vstr_node_ref *)beg->next;
    1105                 : 
    1106             425 :       ref = ((Vstr_node_ref *)node)->ref;
    1107             425 :       ((Vstr_node_ref *)beg)->ref = vstr_ref_add(ref);
    1108             425 :       ((Vstr_node_ref *)beg)->off = ((Vstr_node_ref *)node)->off + pos;
    1109                 :     }
    1110                 : 
    1111              97 :     ASSERT_NO_SWITCH_DEF();
    1112                 :   }
    1113                 : 
    1114            3727 :   ++base->num;
    1115                 : 
    1116            3727 :   base->iovec_upto_date = FALSE;
    1117                 : 
    1118            3727 :   beg->len = node->len - pos;
    1119                 : 
    1120            3727 :   if (!(beg->next = node->next))
    1121            3120 :     base->end = beg;
    1122            3727 :   node->next = beg;
    1123                 : 
    1124            3727 :   node->len = pos;
    1125                 : 
    1126            3727 :   return (node);
    1127                 : }
    1128                 : 
    1129                 : static int vstr__make_spare_node(Vstr_conf *conf, unsigned int type)
    1130          733200 : {
    1131          733200 :   Vstr_node *node = NULL;
    1132                 : 
    1133          733200 :   switch (type)
    1134                 :   {
    1135                 :     case VSTR_TYPE_NODE_BUF:
    1136          515437 :       node = VSTR__MK(sizeof(Vstr_node_buf) + conf->buf_sz);
    1137          515437 :       break;
    1138                 :     case VSTR_TYPE_NODE_NON:
    1139            1949 :       node = VSTR__MK(sizeof(Vstr_node_non));
    1140            1949 :       break;
    1141                 :     case VSTR_TYPE_NODE_PTR:
    1142          129236 :       node = VSTR__MK(sizeof(Vstr_node_ptr));
    1143          129236 :       break;
    1144                 :     case VSTR_TYPE_NODE_REF:
    1145           86574 :       node = VSTR__MK(sizeof(Vstr_node_ref));
    1146           86574 :       break;
    1147                 : 
    1148                 :     default:
    1149               4 :       ASSERT_RET(FALSE, FALSE);
    1150                 :   }
    1151                 : 
    1152          733196 :   if (!node)
    1153                 :   {
    1154           32753 :     conf->malloc_bad = TRUE;
    1155           32753 :     return (FALSE);
    1156                 :   }
    1157                 : 
    1158          700443 :   node->len = 0;
    1159          700443 :   node->type = type;
    1160                 : 
    1161          700443 :   switch (type)
    1162                 :   {
    1163                 :     case VSTR_TYPE_NODE_BUF:
    1164          483261 :       node->next = (Vstr_node *)conf->spare_buf_beg;
    1165          483261 :       conf->spare_buf_beg = (Vstr_node_buf *)node;
    1166          483261 :       ++conf->spare_buf_num;
    1167          483261 :       break;
    1168                 : 
    1169                 :     case VSTR_TYPE_NODE_NON:
    1170            1917 :       node->next = (Vstr_node *)conf->spare_non_beg;
    1171            1917 :       conf->spare_non_beg = (Vstr_node_non *)node;
    1172            1917 :       ++conf->spare_non_num;
    1173            1917 :       break;
    1174                 : 
    1175                 :     case VSTR_TYPE_NODE_PTR:
    1176          128868 :       node->next = (Vstr_node *)conf->spare_ptr_beg;
    1177          128868 :       conf->spare_ptr_beg = (Vstr_node_ptr *)node;
    1178          128868 :       ++conf->spare_ptr_num;
    1179          128868 :       break;
    1180                 : 
    1181                 :     case VSTR_TYPE_NODE_REF:
    1182           86397 :       node->next = (Vstr_node *)conf->spare_ref_beg;
    1183           86397 :       conf->spare_ref_beg = (Vstr_node_ref *)node;
    1184           86397 :       ++conf->spare_ref_num;
    1185                 :       break;
    1186                 :   }
    1187                 : 
    1188          700443 :   return (TRUE);
    1189                 : }
    1190                 : 
    1191                 : unsigned int vstr_make_spare_nodes(Vstr_conf *passed_conf, unsigned int type,
    1192                 :                                    unsigned int num)
    1193          351795 : {
    1194          351795 :   Vstr_conf *conf = passed_conf ? passed_conf : vstr__options.def;
    1195          351795 :   unsigned int count = 0;
    1196                 : 
    1197          772331 :   assert(vstr__check_spare_nodes(conf));
    1198                 : 
    1199         1052238 :   while (count < num)
    1200                 :   {
    1201          733200 :     if (!vstr__make_spare_node(conf, type))
    1202                 :     {
    1203           32757 :       assert(vstr__check_spare_nodes(conf));
    1204                 : 
    1205           32757 :       return (count);
    1206                 :     }
    1207                 : 
    1208          700443 :     ++count;
    1209                 :   }
    1210          319038 :   assert(count == num);
    1211                 : 
    1212          319038 :   assert(vstr__check_spare_nodes(conf));
    1213                 : 
    1214          319038 :   return (count);
    1215                 : }
    1216                 : 
    1217                 : static int vstr__free_spare_node(Vstr_conf *conf, unsigned int type)
    1218          765365 : {
    1219          765365 :   Vstr_node *scan = NULL;
    1220                 : 
    1221          765365 :   switch (type)
    1222                 :   {
    1223                 :     case VSTR_TYPE_NODE_BUF:
    1224          553435 :       if (!conf->spare_buf_beg)
    1225           80382 :         return (FALSE);
    1226                 : 
    1227          473053 :       scan = (Vstr_node *)conf->spare_buf_beg;
    1228                 : 
    1229          473053 :       assert(scan->type == type);
    1230                 : 
    1231          473053 :       conf->spare_buf_beg = (Vstr_node_buf *)scan->next;
    1232          473053 :       --conf->spare_buf_num;
    1233          473053 :       VSTR__F(scan);
    1234          473053 :       break;
    1235                 : 
    1236                 :     case VSTR_TYPE_NODE_NON:
    1237            3495 :       if (!conf->spare_non_beg)
    1238            1578 :         return (FALSE);
    1239                 : 
    1240            1917 :       scan = (Vstr_node *)conf->spare_non_beg;
    1241                 : 
    1242            1917 :       assert(scan->type == VSTR_TYPE_NODE_NON);
    1243                 : 
    1244            1917 :       conf->spare_non_beg = (Vstr_node_non *)scan->next;
    1245            1917 :       --conf->spare_non_num;
    1246            1917 :       VSTR__F(scan);
    1247            1917 :       break;
    1248                 : 
    1249                 :     case VSTR_TYPE_NODE_PTR:
    1250          125931 :       if (!conf->spare_ptr_beg)
    1251            2567 :         return (FALSE);
    1252                 : 
    1253          123364 :       scan = (Vstr_node *)conf->spare_ptr_beg;
    1254                 : 
    1255          123364 :       assert(scan->type == VSTR_TYPE_NODE_PTR);
    1256                 : 
    1257          123364 :       conf->spare_ptr_beg = (Vstr_node_ptr *)scan->next;
    1258          123364 :       --conf->spare_ptr_num;
    1259          123364 :       VSTR__F(scan);
    1260          123364 :       break;
    1261                 : 
    1262                 :     case VSTR_TYPE_NODE_REF:
    1263           82500 :       if (!conf->spare_ref_beg)
    1264            1607 :         return (FALSE);
    1265                 : 
    1266           80893 :       scan = (Vstr_node *)conf->spare_ref_beg;
    1267                 : 
    1268           80893 :       assert(scan->type == type);
    1269                 : 
    1270           80893 :       conf->spare_ref_beg = (Vstr_node_ref *)scan->next;
    1271           80893 :       --conf->spare_ref_num;
    1272           80893 :       VSTR__F(scan);
    1273                 : 
    1274           21043 :       ASSERT_NO_SWITCH_DEF();
    1275                 :   }
    1276                 : 
    1277          679231 :   return (TRUE);
    1278                 : }
    1279                 : 
    1280                 : unsigned int vstr_free_spare_nodes(Vstr_conf *passed_conf, unsigned int type,
    1281                 :                                    unsigned int num)
    1282          110523 : {
    1283          110523 :   Vstr_conf *conf = passed_conf ? passed_conf : vstr__options.def;
    1284          110523 :   unsigned int count = 0;
    1285                 : 
    1286          515151 :   assert(vstr__check_spare_nodes(conf));
    1287                 : 
    1288          789754 :   while (count < num)
    1289                 :   {
    1290          765365 :     if (!vstr__free_spare_node(conf, type))
    1291           86134 :       return (count);
    1292                 : 
    1293          679231 :     ++count;
    1294                 :   }
    1295           24389 :   assert(count == num);
    1296                 : 
    1297           24389 :   assert(vstr__check_spare_nodes(conf));
    1298                 : 
    1299           24389 :   return (count);
    1300                 : }
    1301                 : 
    1302                 : /* vstr_base__pos() but returns a (Vstr_node **) instead of (Vstr_node *) */
    1303                 : Vstr_node **vstr__base_ptr_pos(const Vstr_base *base, size_t *pos,
    1304                 :                                unsigned int *num)
    1305          782733 : {
    1306          782733 :   Vstr_node *const *scan = &base->beg;
    1307                 : 
    1308          782733 :   ASSERT(base && pos && num);
    1309                 :   
    1310          782733 :   *pos += base->used;
    1311          782733 :   *num = 1;
    1312                 : 
    1313          783135 :   while (*pos > (*scan)->len)
    1314                 :   {
    1315             402 :     *pos -= (*scan)->len;
    1316                 : 
    1317             402 :     ASSERT((*scan)->next);
    1318             402 :     scan = &(*scan)->next;
    1319             402 :     ++*num;
    1320                 :   }
    1321                 : 
    1322          782733 :   return ((Vstr_node **) scan);
    1323                 : }
    1324                 : 
    1325                 : struct Vstr__conf_ref_linked
    1326                 : {
    1327                 :  Vstr_conf *conf;
    1328                 :  unsigned int l_ref;
    1329                 : };
    1330                 : 
    1331                 : /* put node on reference list */
    1332                 : static int vstr__convert_buf_ref_add(Vstr_conf *conf, Vstr_node *node)
    1333           18207 : {
    1334           18207 :   struct Vstr__conf_ref_linked *ln_ref;
    1335                 : 
    1336           18207 :   if (!(ln_ref = conf->ref_link))
    1337                 :   {
    1338            2802 :     if (!(ln_ref = VSTR__MK(sizeof(struct Vstr__conf_ref_linked))))
    1339               9 :       return (FALSE);
    1340                 : 
    1341            2793 :     ln_ref->conf = conf;
    1342            2793 :     ln_ref->l_ref = 0;
    1343                 : 
    1344            2793 :     conf->ref_link = ln_ref;
    1345            2793 :     ++conf->ref;
    1346                 :   }
    1347           18198 :   ASSERT(ln_ref->l_ref < VSTR__CONF_REF_LINKED_SZ);
    1348                 : 
    1349           18198 :   ++ln_ref->l_ref;
    1350                 :   /* this cast isn't ISO 9899:1999 compliant ... but fuck it */
    1351           18198 :   node->next = (Vstr_node *)ln_ref;
    1352                 : 
    1353           18198 :   if (ln_ref->l_ref >= VSTR__CONF_REF_LINKED_SZ)
    1354            2222 :     conf->ref_link = NULL;
    1355                 : 
    1356           18198 :   return (TRUE);
    1357                 : }
    1358                 : 
    1359                 : /* call back ... relink */
    1360                 : static void vstr__ref_cb_relink_bufnode_ref(Vstr_ref *ref)
    1361           18207 : {
    1362           18207 :   ASSERT(ref);
    1363                 :   
    1364           18207 :   if (ref->ptr)
    1365                 :   {
    1366           18198 :     char *tmp = ref->ptr;
    1367           18198 :     Vstr_node_buf *node = NULL;
    1368           18198 :     struct Vstr__conf_ref_linked *ln_ref = NULL;
    1369           18198 :     Vstr_conf *conf = NULL;
    1370                 : 
    1371           18198 :     tmp -= offsetof(Vstr_node_buf, buf);
    1372           18198 :     node = (Vstr_node_buf *)tmp;
    1373           18198 :     ln_ref = (struct Vstr__conf_ref_linked *)(node->s.next);
    1374                 : 
    1375           18198 :     conf = ln_ref->conf;
    1376                 : 
    1377                 :     /* manual relink ... Also ISO 9899:1999 violation */
    1378           18198 :     node->s.next = (Vstr_node *)ln_ref->conf->spare_buf_beg;
    1379           18198 :     ln_ref->conf->spare_buf_beg = node;
    1380           18198 :     ++ln_ref->conf->spare_buf_num;
    1381                 : 
    1382           18198 :     if (!--ln_ref->l_ref)
    1383                 :     {
    1384            2793 :       if (ln_ref->conf->ref_link == ln_ref)
    1385             571 :         ln_ref->conf->ref_link = NULL;
    1386                 : 
    1387            2793 :       VSTR__F(ln_ref);
    1388            2793 :       vstr__del_conf(conf);
    1389                 :     }
    1390                 :   }
    1391                 : }
    1392                 : 
    1393                 : void vstr__swap_node_X_X(const Vstr_base *base, size_t pos,
    1394                 :                          Vstr_node *node)
    1395              30 : {
    1396              30 :   Vstr_node *old_scan = NULL;
    1397              30 :   size_t old_scan_len = 0;
    1398              30 :   Vstr_node **scan = NULL;
    1399              30 :   unsigned int num = 0;
    1400              30 :   Vstr__cache_data_pos *data = NULL;
    1401                 : 
    1402              30 :   scan = vstr__base_ptr_pos(base, &pos, &num);
    1403                 : 
    1404              30 :   old_scan = *scan;
    1405              30 :   old_scan_len = old_scan->len;
    1406                 : 
    1407              30 :   node->next = (*scan)->next;
    1408              30 :   vstr__relink_nodes(base->conf, *scan, &(*scan)->next, 1);
    1409              30 :   *scan = node;
    1410                 : 
    1411              30 :   if (!node->next)
    1412              25 :     ((Vstr_base *)base)->end = node;
    1413                 : 
    1414              30 :   if (node == base->beg)
    1415              25 :     ((Vstr_base *)base)->used = 0;
    1416                 : 
    1417              30 :   if ((data = vstr_cache_get(base, base->conf->cache_pos_cb_pos)) &&
    1418                 :       (data->node == old_scan))
    1419                 :   {
    1420               5 :     data->node = NULL;
    1421                 : 
    1422               5 :     if (node->len >= old_scan_len)
    1423               5 :       data->node = node;
    1424                 :   }
    1425                 : 
    1426              30 :   switch (node->type)
    1427                 :   {
    1428                 :     /* -- note, should work, but not called like so currently --
    1429                 :       case VSTR_TYPE_NODE_BUF: ((Vstr_base *)base)->node_buf_used = TRUE; break;
    1430                 :       case VSTR_TYPE_NODE_NON: ((Vstr_base *)base)->node_non_used = TRUE; break;
    1431                 :     */
    1432              20 :     case VSTR_TYPE_NODE_PTR: ((Vstr_base *)base)->node_ptr_used = TRUE; break;
    1433              10 :     case VSTR_TYPE_NODE_REF: ((Vstr_base *)base)->node_ref_used = TRUE;
    1434               2 :       ASSERT_NO_SWITCH_DEF();
    1435                 :   }
    1436                 : 
    1437              30 :   vstr__cache_iovec_reset_node(base, node, num);
    1438                 : }
    1439                 : 
    1440                 : 
    1441                 : int vstr__chg_node_buf_ref(const Vstr_base *base,
    1442                 :                            Vstr_node **scan, unsigned int num)
    1443           18228 : {
    1444           18228 :   Vstr__cache_data_pos *data = NULL;
    1445           18228 :   Vstr_node *next_node = (*scan)->next; /* must be done now... */
    1446           18228 :   Vstr_ref *ref = NULL;
    1447           18228 :   Vstr_node_ref *node_ref = NULL;
    1448                 : 
    1449           18228 :   assert((*scan)->type == VSTR_TYPE_NODE_BUF);
    1450                 : 
    1451           18228 :   if (!vstr_cntl_conf(base->conf, VSTR_CNTL_CONF_SET_NUM_RANGE_SPARE_REF,
    1452                 :                       1, UINT_MAX))
    1453               1 :     goto fail_malloc_nodes;
    1454                 : 
    1455           18227 :   if (!base->conf->ref_grp_buf2ref)
    1456                 :   {
    1457             549 :     Vstr_ref_grp_ptr *tmp = NULL;
    1458                 : 
    1459             549 :     if (!(tmp = vstr__ref_grp_make(vstr__ref_cb_relink_bufnode_ref, 0)))
    1460              12 :       goto fail_malloc_ref;
    1461             537 :     base->conf->ref_grp_buf2ref = tmp;
    1462                 :   }
    1463                 : 
    1464           18215 :   if (!(ref = vstr__ref_grp_add(&base->conf->ref_grp_buf2ref,
    1465                 :                                 ((Vstr_node_buf *)(*scan))->buf)))
    1466               8 :     goto fail_malloc_ref;
    1467           18207 :   if (!vstr__convert_buf_ref_add(base->conf, *scan))
    1468               9 :     goto fail_malloc_conv_buf;
    1469                 : 
    1470           18198 :   --base->conf->spare_ref_num;
    1471           18198 :   node_ref = base->conf->spare_ref_beg;
    1472           18198 :   base->conf->spare_ref_beg = (Vstr_node_ref *)node_ref->s.next;
    1473                 : 
    1474           18198 :   ((Vstr_base *)base)->node_ref_used = TRUE;
    1475                 : 
    1476           18198 :   node_ref->s.len = (*scan)->len;
    1477           18198 :   node_ref->ref = ref;
    1478           18198 :   node_ref->off = 0;
    1479           18198 :   if ((base->beg == *scan) && base->used)
    1480                 :   {
    1481             859 :     node_ref->s.len -= base->used;
    1482             859 :     node_ref->off = base->used;
    1483             859 :     ((Vstr_base *)base)->used = 0;
    1484                 :   }
    1485                 : 
    1486           18198 :   if (!(node_ref->s.next = next_node))
    1487             491 :     ((Vstr_base *)base)->end = &node_ref->s;
    1488                 : 
    1489                 :   /* NOTE: we have just changed the type of the node, must update the cache */
    1490           18198 :   if ((data = vstr_cache_get(base, base->conf->cache_pos_cb_pos)) &&
    1491                 :       (data->node == *scan))
    1492             126 :     data->node = &node_ref->s;
    1493           18198 :   if (base->iovec_upto_date)
    1494                 :   {
    1495           17821 :     ASSERT(num);
    1496           17821 :     num += VSTR__CACHE(base)->vec->off - 1;
    1497           17821 :     assert(VSTR__CACHE(base)->vec->t[num] == VSTR_TYPE_NODE_BUF);
    1498           17821 :     VSTR__CACHE(base)->vec->t[num] = VSTR_TYPE_NODE_REF;
    1499                 :   }
    1500                 : 
    1501           18198 :   *scan = &node_ref->s;
    1502                 : 
    1503           18198 :   return (TRUE);
    1504                 : 
    1505                 :  fail_malloc_conv_buf:
    1506               9 :   ref->ptr = NULL;
    1507               9 :   vstr_ref_del(ref);
    1508                 :  fail_malloc_ref:
    1509              29 :   base->conf->malloc_bad = TRUE;
    1510                 :  fail_malloc_nodes:
    1511              30 :   return (FALSE);
    1512                 : }

Generated by: LTP GCOV extension version 1.1