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

       1                 : /* Copyright (c) 2007 James Antill -- See LICENSE file for terms. */
       2                 : 
       3                 : #ifndef USTR_MAIN_H
       4                 : #error " You should have already included ustr-main.h, or just include ustr.h."
       5                 : #endif
       6                 : 
       7                 : USTR_CONF_i_PROTO
       8                 : int ustr__dupx_cmp_eq(size_t sz1, size_t rb1, int x1, int emem1,
       9                 :                       size_t sz2, size_t rb2, int x2, int emem2)
      10          262938 : {
      11          262938 :   if ((!x1 != !x2) || (!emem1 != !emem2))
      12             166 :     return (USTR_FALSE);
      13                 :   
      14          262772 :   if (sz1)
      15                 :   {
      16          262182 :     if (rb1 < 2)
      17          262152 :       rb1 = 2;
      18                 :   }
      19             590 :   else if (rb1 > 4)
      20               2 :     sz1 = 1;
      21                 : 
      22          262772 :   if (sz2)
      23                 :   {
      24          262164 :     if (rb2 < 2)
      25               2 :       rb2 = 2;
      26                 :   }
      27             608 :   else if (rb2 > 4)
      28               4 :     sz2 = 1;
      29                 : 
      30          262772 :   return ((!sz1 == !sz2) && (rb1 == rb2));
      31                 : }
      32                 : 
      33                 : USTR_CONF_i_PROTO size_t ustr__sz_get(const struct Ustr *s1)
      34         1445490 : {
      35         1445490 :   size_t lenn = 0;
      36                 :   
      37         1314164 :   USTR_ASSERT(!ustr_ro(s1));
      38         1314164 :   USTR_ASSERT( ustr_sized(s1));
      39                 :   
      40         1445490 :   lenn = USTR__LEN_LEN(s1);
      41                 :   
      42         2759654 :   return (ustr_xi__embed_val_get(s1->data + 1 + USTR__REF_LEN(s1) + lenn,lenn));
      43                 : }
      44                 : 
      45                 : USTR_CONF_i_PROTO size_t ustr__nb(size_t num)
      46          598775 : {
      47                 :   USTR_ASSERT((num <= 0xFFFFFFFF) || USTR_CONF_HAVE_64bit_SIZE_MAX);
      48                 :   
      49         1522573 :   if (num > 0xFFFFFFFF)                 return (8);
      50         1521845 :   if (num > 0xFFFF)                     return (4);
      51         1521729 :   if (num > 0xFF)                       return (2);
      52         1520717 :   else                                  return (1);
      53                 : }
      54                 : 
      55                 : USTR_CONF_i_PROTO
      56                 : int ustrp__assert_valid(int p, const struct Ustr *s1)
      57         4473973 : {
      58         4473973 :   const char *eos_ptr = 0;
      59         4473973 :   size_t      eos_len = sizeof(USTR_END_ALOCDx);
      60         4473973 :   size_t rbytes = 0;
      61         4473973 :   size_t lbytes = 0;
      62         4473973 :   size_t sbytes = 0;
      63         4473973 :   size_t sz = 0;
      64         4473973 :   size_t oh = 0;
      65                 :   
      66         4473973 :   USTR_ASSERT_RET(s1, USTR_FALSE);
      67         2537925 :   ustr_assert_ret(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1), USTR_FALSE);
      68                 :   
      69         4473973 :   if (!s1->data[0])
      70          985942 :     return (USTR_TRUE);
      71                 : 
      72                 :   /* just make sure for compound "bits" tests */
      73         6981743 :   USTR_ASSERT(( ustr_alloc(s1) || ustr_sized(s1)) != ustr_ro(s1));
      74         6981743 :   USTR_ASSERT((!ustr_alloc(s1) && ustr_sized(s1)) == ustr_fixed(s1));
      75         6976688 :   USTR_ASSERT(( ustr_fixed(s1) && ustr_exact(s1)) == ustr_limited(s1));
      76                 :   
      77         3488031 :   rbytes = USTR__REF_LEN(s1);
      78         3488031 :   lbytes = USTR__LEN_LEN(s1);
      79         3488031 :   ustr_assert_ret(lbytes, USTR_FALSE);
      80                 : 
      81         3488031 :   if (ustr_sized(s1))
      82                 :   {
      83         1051555 :     sbytes = lbytes;
      84         1051555 :     sz = ustr__sz_get(s1);
      85                 :   }
      86         3488031 :   oh = 1 + rbytes + lbytes + sbytes + eos_len;
      87                 :   
      88         3488031 :   USTR_ASSERT_RET(!ustr_sized(s1) || (ustr_len(s1) <= sz), USTR_FALSE);
      89                 : 
      90         4408304 :   USTR_ASSERT(!sz || (ustr__nb(sz) == lbytes) ||
      91                 :               ((ustr__nb(sz) == 1) && (lbytes == 2))); /* 2 is the minimum */
      92                 :   
      93         3488031 :   USTR_ASSERT_RET(!sz || (oh <= sz),                       USTR_FALSE);
      94         3488031 :   USTR_ASSERT_RET(!sz || ((ustr_len(s1) + oh) <= sz),      USTR_FALSE);
      95                 :   
      96         5920440 :   USTR_ASSERT_RET( ustr_exact(s1)  || !ustr_ro(s1),         USTR_FALSE);
      97         4539979 :   USTR_ASSERT_RET(!ustr_enomem(s1) || !ustr_ro(s1),         USTR_FALSE);
      98                 : 
      99                 :   if (!USTR_CONF_USE_EOS_MARK)
     100                 :   {
     101            5461 :     USTR_ASSERT_RET(!ustr_cstr(s1)[ustr_len(s1)], USTR_FALSE);
     102            5461 :     return (USTR_TRUE);
     103                 :   }
     104                 :   
     105         3482570 :   if (ustr_ro(s1))
     106            4083 :     eos_ptr = USTR_END_CONSTx;
     107         3478487 :   else if (ustr_fixed(s1))
     108             316 :     eos_ptr = USTR_END_FIXEDx;
     109                 :   else
     110         3478171 :     eos_ptr = USTR_END_ALOCDx;
     111                 : 
     112         3482570 :   USTR_ASSERT_RET(!memcmp(ustr_cstr(s1) + ustr_len(s1), eos_ptr, eos_len),
     113                 :                   USTR_FALSE);
     114                 : 
     115         3482570 :   return (USTR_TRUE);
     116                 : }
     117                 : /* Due to ustrp_assert_valid() being inline we can't pass 0 for
     118                 :  * ustr_assert_valid() until we've made two ustr_assert_valid() versions.
     119                 :  * Maybe I'll do that for 1.0.3 ... NOTE: We'd need to change the other
     120                 :  * internal ustr_assert_valid() calls. */
     121                 : USTR_CONF_I_PROTO int ustr_assert_valid(const struct Ustr *s1)
     122         3581787 : { return (ustrp__assert_valid(1, s1)); }
     123                 : /* We can't change the API of this function until 2.0.x time, even if we want
     124                 :  * to. But it's no big deal, as we might not want to. */
     125                 : USTR_CONF_I_PROTO int ustrp_assert_valid(const struct Ustrp *s1)
     126              14 : { return (ustrp__assert_valid(1, &s1->s)); }
     127                 : 
     128                 : USTR_CONF_i_PROTO
     129                 : size_t ustrp__assert_valid_subustr(int p, const struct Ustr *s1,
     130                 :                                    size_t pos, size_t len)
     131            2852 : {
     132            2852 :   size_t clen = 0;
     133                 : 
     134                 :   (void) p;
     135            1430 :   USTR_ASSERT(ustrp__assert_valid(p, s1));
     136            2852 :   USTR_ASSERT_RET(pos, 0);
     137                 :   
     138            2852 :   clen = ustr_len(s1);
     139            2852 :   if (((pos == 1) || !len) && (len == clen))
     140             228 :     return (clen);
     141                 :   
     142            2624 :   USTR_ASSERT_RET((clen >= pos), 0);
     143            2590 :   USTR_ASSERT_RET((clen >= (len + --pos)), 0);
     144                 : 
     145            2530 :   return (clen);
     146                 : }
     147                 : /* see comments for ustr_assert_valid() etc. */
     148                 : USTR_CONF_I_PROTO
     149                 : size_t ustr_assert_valid_subustr(const struct Ustr *s1, size_t pos, size_t len)
     150             618 : { return (ustrp__assert_valid_subustr(1, s1, pos, len)); }
     151                 : USTR_CONF_I_PROTO
     152                 : int ustrp_assert_valid_subustrp(const struct Ustrp *s1, size_t pos, size_t len)
     153              12 : { return (ustrp__assert_valid_subustr(1, &s1->s, pos, len)); }
     154                 : 
     155                 : USTR_CONF_I_PROTO char *ustr_wstr(struct Ustr *s1)
     156            4202 : { /* NOTE: Not EI/II so we can call ustr_assert_valid() here. */
     157            4202 :   unsigned char *data = s1->data;
     158            4202 :   size_t lenn = 0;
     159                 :   
     160            2101 :   USTR_ASSERT(ustr_assert_valid(s1));
     161                 :   
     162            4202 :   USTR_ASSERT_RET(!ustr_ro(s1), 0);
     163                 :   
     164            4202 :   lenn = USTR__LEN_LEN(s1);
     165            4202 :   if (ustr_sized(s1))
     166             391 :     lenn *= 2;
     167                 :   
     168            6303 :   return ((char *)(data + 1 + USTR__REF_LEN(s1) + lenn));
     169                 : }
     170                 : 
     171                 : USTR_CONF_I_PROTO int ustr_owner(const struct Ustr *s1)
     172            6683 : {
     173            3952 :   USTR_ASSERT(ustr_assert_valid(s1));
     174                 :   
     175            6683 :   if (ustr_ro(s1))    return (USTR_FALSE);
     176            5629 :   if (ustr_fixed(s1)) return (USTR_TRUE);
     177                 : 
     178            8754 :   switch (USTR__REF_LEN(s1))
     179                 :   {
     180                 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
     181               6 :     case 8: if (s1->data[8]) return (USTR_FALSE);
     182               6 :             if (s1->data[7]) return (USTR_FALSE);
     183               6 :             if (s1->data[6]) return (USTR_FALSE);
     184               6 :             if (s1->data[5]) return (USTR_FALSE);
     185                 : #endif
     186             811 :     case 4: if (s1->data[4]) return (USTR_FALSE);
     187             811 :             if (s1->data[3]) return (USTR_FALSE);
     188            1675 :     case 2: if (s1->data[2]) return (USTR_FALSE);
     189                 :       
     190            3939 :     case 1:                  return (s1->data[1] == 1);
     191                 :       
     192                 :     case 0:
     193                 :       
     194               0 :       USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_owner()");
     195                 :   }
     196                 :   
     197            1521 :   return (USTR_TRUE);  /* Ustr with no ref. count */
     198                 : }
     199                 : 
     200                 : USTR_CONF_I_PROTO int ustr_setf_enomem_err(struct Ustr *s1)
     201             569 : {
     202             338 :   USTR_ASSERT(ustr_assert_valid(s1));
     203                 : 
     204             569 :   errno = USTR__ENOMEM;
     205             569 :   if (!ustr_owner(s1))
     206             230 :     return (USTR_FALSE);
     207                 :   
     208             339 :   s1->data[0] |=  USTR__BIT_ENOMEM;
     209             339 :   return (USTR_TRUE);
     210                 : }
     211                 : USTR_CONF_I_PROTO int ustr_setf_enomem_clr(struct Ustr *s1)
     212             141 : {
     213              70 :   USTR_ASSERT(ustr_assert_valid(s1));
     214                 :   
     215             141 :   errno = 0;
     216             141 :   if (!ustr_owner(s1))
     217               8 :     return (USTR_FALSE);
     218                 :   
     219             133 :   s1->data[0] &= ~USTR__BIT_ENOMEM;
     220             133 :   return (USTR_TRUE);
     221                 : }
     222                 : 
     223                 : USTR_CONF_i_PROTO void ustr__embed_val_set(unsigned char *data,
     224                 :                                            size_t len, size_t val)
     225         1317608 : {
     226         1317608 :   switch (len)
     227                 :   {
     228                 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
     229                 :     case 8:
     230              25 :       data[7] = (val >> 56) & 0xFF;
     231              25 :       data[6] = (val >> 48) & 0xFF;
     232              25 :       data[5] = (val >> 40) & 0xFF;
     233              25 :       data[4] = (val >> 32) & 0xFF;
     234                 : #endif
     235                 :     case 4:
     236          262597 :       data[3] = (val >> 24) & 0xFF;
     237          262597 :       data[2] = (val >> 16) & 0xFF;
     238                 :     case 2:
     239         1312463 :       data[1] = (val >>  8) & 0xFF;
     240                 :     case 1:
     241         1317608 :       data[0] = (val >>  0) & 0xFF;
     242                 : 
     243               0 :       USTR_ASSERT_NO_SWITCH_DEF("Val. length bad for ustr__embed_val_set()");
     244                 :   }
     245         1317608 : }
     246                 : 
     247                 : /* no warn here, because most callers already know it's not going to fail */
     248                 : USTR_CONF_i_PROTO int ustr__ref_set(struct Ustr *s1, size_t ref)
     249         1313904 : {
     250         1313904 :   size_t len = 0;
     251                 :   
     252          656950 :   USTR_ASSERT(ustr_assert_valid(s1));
     253          656950 :   USTR_ASSERT(ustr_alloc(s1));
     254                 : 
     255         1970854 :   if (!(len = USTR__REF_LEN(s1)))
     256             312 :     return (USTR_FALSE);
     257                 :   
     258         1313592 :   ustr__embed_val_set(s1->data + 1, len, ref);
     259                 :   
     260          656794 :   USTR_ASSERT(ustr_assert_valid(s1));
     261                 : 
     262         1313592 :   return (USTR_TRUE);
     263                 : }
     264                 : 
     265                 : USTR_CONF_I_PROTO int ustr_setf_share(struct Ustr *s1)
     266              58 : {
     267              29 :   USTR_ASSERT(ustr_assert_valid(s1));
     268                 : 
     269              58 :   if (!ustr_alloc(s1))
     270               4 :     return (USTR_TRUE);
     271                 :   
     272              54 :   if (!ustr__ref_set(s1, 0))
     273              12 :     return (USTR_FALSE);
     274                 :   
     275              21 :   USTR_ASSERT(ustr_assert_valid(s1));
     276              42 :   return (USTR_TRUE);
     277                 : }
     278                 : USTR_CONF_I_PROTO int ustr_setf_owner(struct Ustr *s1)
     279              24 : {
     280              12 :   USTR_ASSERT(ustr_assert_valid(s1));
     281                 : 
     282              24 :   if (!ustr_alloc(s1))
     283               4 :     return (USTR_FALSE);
     284                 : 
     285              20 :   ustr__ref_set(s1, 1); /* 0 means it's unsharable and so they are the owner */
     286                 :   
     287              10 :   USTR_ASSERT(ustr_assert_valid(s1));
     288              20 :   return (USTR_TRUE);
     289                 : }
     290                 : 
     291                 : USTR_CONF_i_PROTO void ustr__len_set(struct Ustr *s1, size_t len)
     292            3745 : { /* can only validate after the right len is in place */
     293            3745 :   unsigned char *data = s1->data;
     294                 :   
     295            1872 :   USTR_ASSERT(!ustr_ro(s1));
     296            7489 :   ustr__embed_val_set(data + 1 + USTR__REF_LEN(s1), USTR__LEN_LEN(s1), len);
     297            1872 :   USTR_ASSERT(ustr_assert_valid(s1));
     298            3745 : }
     299                 : 
     300                 : USTR_CONF_i_PROTO void ustr__sz_set(struct Ustr *s1, size_t sz)
     301             240 : { /* can't validate as this is called before anything is setup */
     302             240 :   size_t lenn = 0;
     303                 :   
     304             119 :   USTR_ASSERT(!ustr_ro(s1));
     305             119 :   USTR_ASSERT(ustr_sized(s1));
     306                 : 
     307             240 :   lenn = USTR__LEN_LEN(s1);
     308                 :   
     309             359 :   ustr__embed_val_set(s1->data + 1 + USTR__REF_LEN(s1) + lenn, lenn, sz);
     310             240 : }
     311                 : 
     312                 : USTR_CONF_i_PROTO int ustr__ref_add(struct Ustr *s1)
     313         1329921 : {
     314         1329921 :   size_t ref = 0;
     315         1329921 :   size_t lim = 0;
     316                 :   
     317          664960 :   USTR_ASSERT(ustr_assert_valid(s1));
     318                 :   
     319         1329921 :   if (ustr_ro(s1))
     320          393930 :     return (USTR_TRUE);
     321          935991 :   if (ustr_fixed(s1))
     322               8 :     return (USTR_FALSE);
     323                 :   
     324         1403974 :   switch (USTR__REF_LEN(s1))
     325                 :   {
     326                 : #if USTR_CONF_HAVE_64bit_SIZE_MAX
     327               5 :     case 8: if (!lim) lim = 0xFFFFFFFFFFFFFFFFULL;
     328                 : #endif
     329          131087 :     case 4: if (!lim) lim = 0xFFFFFFFFUL;
     330          935387 :     case 2: if (!lim) lim = 0xFFFF;
     331          935955 :     case 1: if (!lim) lim = 0xFF;
     332                 :       
     333          935955 :       ref = ustr_xi__ref_get(s1);
     334          935955 :       if (ref == 0)
     335          280000 :         return (USTR_TRUE);
     336          655955 :       if (ref == lim)
     337              10 :         return (USTR_FALSE);
     338          655945 :       ustr__ref_set(s1, ref + 1);
     339          655945 :       return (USTR_TRUE);
     340                 :   
     341                 :     case 0: /* Ustr with no reference count */
     342                 :       
     343               0 :       USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_add()");
     344                 :   }
     345                 : 
     346              28 :   return (USTR_FALSE);
     347                 : }
     348                 : 
     349                 : USTR_CONF_i_PROTO size_t ustr__ref_del(struct Ustr *s1)
     350         1765675 : {
     351          882838 :   USTR_ASSERT(ustr_assert_valid(s1));
     352                 :   
     353         1765675 :   if (!ustr_alloc(s1))
     354          788252 :     return (-1);
     355                 : 
     356         1466135 :   switch (USTR__REF_LEN(s1))
     357                 :   {
     358                 :     case 8:
     359                 :     case 4:
     360                 :     case 2:
     361                 :     case 1:
     362                 :     {
     363          977191 :       size_t ref = ustr_xi__ref_get(s1);
     364                 :       
     365          977191 :       if (ref == 0)
     366          320030 :         return (-1);
     367          657161 :       if (ref == 1) /* Special case this so it doesn't "go shared"
     368                 :                      * plus this is a common case and doing this is
     369                 :                      * marginally faster */
     370            1216 :         return (0);
     371                 :       
     372          655945 :       ustr__ref_set(s1, ref - 1);
     373          655945 :       return (ref - 1);
     374                 :     }
     375                 :           
     376                 :     case 0: /* Ustr with no reference count */
     377                 : 
     378               0 :       USTR_ASSERT_NO_SWITCH_DEF("Ref. length bad for ustr__ref_del()");
     379                 :   }
     380                 : 
     381             232 :   return (0);
     382                 : }
     383                 : 
     384                 : USTR_CONF_I_PROTO size_t ustr_size_overhead(const struct Ustr *s1)
     385          287337 : {
     386          287337 :   size_t lenn = 0;
     387                 :   
     388          286004 :   USTR_ASSERT(ustr_assert_valid(s1));
     389                 : 
     390          287337 :   if (!s1->data[0])
     391               4 :     return (1);
     392                 : 
     393          287333 :   lenn = USTR__LEN_LEN(s1);
     394          287333 :   if (ustr_sized(s1))
     395             200 :     lenn *= 2;
     396                 :   
     397          573335 :   return (1 + USTR__REF_LEN(s1) + lenn + sizeof(USTR_END_ALOCDx));
     398                 : }
     399                 : 
     400                 : USTR_CONF_I_PROTO size_t ustr_size_alloc(const struct Ustr *s1)
     401          418331 : { /* copy and paste so that ustr_ro() does the right thing */
     402          418331 :   size_t oh = 0;
     403                 : 
     404          417151 :   USTR_ASSERT(ustr_assert_valid(s1));
     405                 :   
     406          418331 :   if (ustr_sized(s1))
     407          131353 :     return (ustr__sz_get(s1));
     408                 : 
     409          286978 :   oh = ustr_size_overhead(s1);
     410          285838 :   USTR_ASSERT((oh + ustr_len(s1)) >= oh);
     411                 :   
     412          286978 :   if (ustr_exact(s1))
     413             175 :     return (ustr_len(s1) + oh);
     414                 : 
     415          286803 :   return (ustr__ns(ustr_len(s1) + oh));
     416                 : }
     417                 : 
     418                 : USTR_CONF_i_PROTO void ustrp__free(struct Ustr_pool *p, struct Ustr *s1)
     419         1765816 : {
     420         1765816 :   if (!s1) return;
     421                 : 
     422          882838 :   USTR_ASSERT(ustrp__assert_valid(!!p, s1));
     423                 :     
     424         1765675 :   if (!ustr__ref_del(s1))
     425                 :   {
     426            1448 :     if (p)
     427             116 :       p->pool_sys_free(p, s1);
     428                 :     else
     429            1332 :       USTR_CONF_FREE(s1);
     430                 :   }
     431                 : }
     432                 : 
     433                 : USTR_CONF_I_PROTO void ustr_free(struct Ustr *s1)
     434         1763588 : { return (ustrp__free(0, s1)); }
     435                 : USTR_CONF_I_PROTO void ustrp_free(struct Ustr_pool *p, struct Ustrp *s1)
     436               4 : { return (ustrp__free(p, &s1->s)); }
     437                 : 
     438                 : /* shortcut -- needs to be here, as lots of things calls this */
     439                 : USTR_CONF_i_PROTO
     440                 : void ustrp__sc_free2(struct Ustr_pool *p, struct Ustr **ps1, struct Ustr *s2)
     441            1308 : {
     442             654 :   USTR_ASSERT(ps1);
     443             654 :   USTR_ASSERT(ustrp__assert_valid(!!p, s2)); /* don't pass NULL */
     444                 :   
     445            1308 :   ustrp__free(p, *ps1);
     446            1308 :   *ps1 = s2;
     447            1308 : }
     448                 : 
     449                 : USTR_CONF_i_PROTO size_t ustr__ns(size_t num)
     450          291273 : {
     451          291273 :   size_t min_sz = 4;
     452                 :   
     453          291273 :   if (num > ((USTR__SIZE_MAX / 4) * 3))
     454               2 :     return (USTR__SIZE_MAX);
     455                 : 
     456                 :   /* *2 is too much, we end up wasting a lot of RAM. So we do *1.5. */
     457         1172466 :   while (min_sz < num)
     458                 :   {
     459          883217 :     size_t adder = min_sz / 2;
     460                 : 
     461          883217 :     min_sz += adder;
     462          883217 :     if (min_sz >= num) break;
     463          877864 :     min_sz += adder;
     464                 :   }
     465                 :       
     466          291271 :   return (min_sz);
     467                 : }
     468                 : 
     469                 : /* ---------------- init - helpers so others can make Ustr's ---------------- */
     470                 : USTR_CONF_I_PROTO size_t ustr_init_size(size_t sz, size_t rbytes, int exact,
     471                 :                                         size_t len)
     472            2578 : {
     473            2578 :   size_t oh  = 0;
     474            2578 :   size_t rsz = sz ? sz : len;
     475            2578 :   size_t lbytes = 0;
     476                 :   
     477            2578 :   USTR_ASSERT_RET((rbytes == 0) ||
     478                 :                   (rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
     479                 :                   (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), 0);
     480                 : 
     481                 :   do
     482                 :   {
     483            2584 :     size_t sbytes = 0;
     484                 : 
     485            1907 :     lbytes = ustr__nb(rsz);
     486            2584 :     if (!sz && ((lbytes == 8) || (rbytes == 8)))
     487             488 :       sz = 1;
     488                 :     
     489            1365 :     USTR_ASSERT(    (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
     490                 :                     (USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
     491                 :   
     492            2584 :     if (sz)
     493                 :     {
     494             670 :       if (rbytes <= 1)
     495             608 :         rbytes = 2;
     496             670 :       if (lbytes <= 1)
     497             184 :         lbytes = 2;
     498             670 :       sbytes = lbytes;
     499                 :     }
     500                 :     
     501            2584 :     oh = 1 + rbytes + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
     502            2584 :     rsz = oh + len;
     503                 :   
     504            2584 :     if (rsz < len)
     505                 :     {
     506             484 :       errno = USTR__EINVAL;
     507             484 :       return (0);
     508                 :     }
     509                 : 
     510            1093 :     USTR_ASSERT((lbytes <= ustr__nb(rsz)) ||
     511                 :                 ((lbytes == 2) && sz && (ustr__nb(rsz) == 1)));
     512            2100 :   } while (lbytes < ustr__nb(rsz));
     513                 :   
     514            2094 :   if (exact)
     515             132 :     return (rsz);
     516                 :   
     517            1962 :   return (ustr__ns(rsz));
     518                 : }
     519                 : 
     520                 : /* NIL terminate -- with possible end marker */
     521                 : USTR_CONF_i_PROTO void ustr__terminate(unsigned char *ptr, int alloc,size_t len)
     522            3601 : {
     523                 :   if (sizeof(USTR_END_ALOCDx) == 1)
     524            2062 :     ptr[len] = 0;
     525            1713 :   else if (alloc)
     526            1695 :     memcpy(ptr + len, USTR_END_ALOCDx, sizeof(USTR_END_ALOCDx));
     527                 :   else
     528              18 :     memcpy(ptr + len, USTR_END_FIXEDx, sizeof(USTR_END_FIXEDx));
     529            3601 : }
     530                 : 
     531                 : USTR_CONF_I_PROTO
     532                 : struct Ustr *ustr_init_alloc(void *data, size_t rsz, size_t sz,
     533                 :                              size_t rbytes, int exact, int emem, size_t len)
     534            1955 : {
     535                 :   static const unsigned char map_big_pow2[9] = {-1, -1, 0, -1, 1, -1, -1, -1,2};
     536                 :   static const unsigned char map_pow2[5] = {0, 1, 2, -1, 3};
     537            1955 :   struct Ustr *ret = data;
     538            1955 :   int nexact = !exact;
     539            1955 :   int sized  = 0;
     540            1955 :   size_t lbytes = 0;
     541            1955 :   size_t sbytes = 0;
     542            1955 :   size_t oh = 0;
     543            1955 :   const size_t eos_len = sizeof(USTR_END_ALOCDx);
     544                 :   
     545            1955 :   USTR_ASSERT_RET((rbytes == 0) ||
     546                 :                   (rbytes == 1) || (rbytes == 2) || (rbytes == 4) ||
     547                 :                   (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)), USTR_NULL);
     548             977 :   USTR_ASSERT(data);
     549             977 :   USTR_ASSERT(exact == !!exact);
     550             977 :   USTR_ASSERT(emem  == !!emem);
     551             977 :   USTR_ASSERT(!sz || (sz == rsz));
     552            1955 :   USTR_ASSERT_RET(!sz || (sz > len), USTR_NULL);
     553                 : 
     554            1955 :   if (!sz && (rbytes == 8))
     555               4 :     sz = rsz; /* whee... */
     556                 :   
     557            1955 :   lbytes = ustr__nb(sz ? sz : len);
     558            1955 :   if (!sz && (lbytes == 8))
     559               4 :     sz = rsz; /* whee... */
     560            1465 :   USTR_ASSERT(lbytes == ustr__nb(sz ? sz : len));
     561                 :   
     562             977 :   USTR_ASSERT(    (lbytes == 1) || (lbytes == 2) || (lbytes == 4) ||
     563                 :                   (USTR_CONF_HAVE_64bit_SIZE_MAX && (lbytes == 8)));
     564                 :   
     565            1955 :   if (sz)
     566                 :   {
     567             227 :     if (sz < (1 + 2 + 2 + 1))
     568              12 :       goto val_inval;
     569                 :     
     570             215 :     if (rbytes <= 1)
     571             167 :       rbytes = 2;
     572             215 :     if (lbytes <= 1)
     573             175 :       lbytes = 2;
     574             215 :     sbytes = lbytes;
     575                 :   }
     576            1943 :   oh = 1 + rbytes + lbytes + sbytes + eos_len;
     577                 : 
     578            1943 :   if (rsz < (oh + len))
     579               4 :     goto val_inval;
     580                 :   
     581            1939 :   if (sz)     sized  = USTR__BIT_HAS_SZ;
     582            1939 :   if (nexact) nexact = USTR__BIT_NEXACT;
     583            1939 :   if (emem)   emem   = USTR__BIT_ENOMEM;
     584                 :     
     585            1939 :   ret->data[0]  = USTR__BIT_ALLOCD | sized | nexact | emem;
     586            1939 :   if (sz)
     587             211 :     ret->data[0] |= (map_big_pow2[rbytes] << 2) | map_big_pow2[lbytes];
     588                 :   else
     589            1728 :     ret->data[0] |= (map_pow2[rbytes] << 2) | map_pow2[lbytes];
     590                 : 
     591            1939 :   ustr__terminate(ret->data, USTR_TRUE, (oh - eos_len) + len);
     592                 : 
     593            1939 :   if (sz)
     594             211 :     ustr__sz_set(ret, sz);
     595            1939 :   ustr__len_set(ret, len);
     596            1939 :   ustr__ref_set(ret,   1);
     597                 : 
     598             969 :   USTR_ASSERT(ustr_assert_valid(ret));
     599             969 :   USTR_ASSERT( ustr_alloc(ret));
     600             969 :   USTR_ASSERT(!ustr_fixed(ret));
     601             969 :   USTR_ASSERT(!ustr_ro(ret));
     602             969 :   USTR_ASSERT( ustr_enomem(ret) == !!emem);
     603             969 :   USTR_ASSERT( ustr_exact(ret)  == exact);
     604             969 :   USTR_ASSERT(!ustr_shared(ret));
     605             969 :   USTR_ASSERT( ustr_owner(ret));
     606                 : 
     607            1939 :   return (ret);
     608                 : 
     609              16 :  val_inval:
     610              16 :   errno = USTR__EINVAL;
     611              16 :   return (USTR_NULL);
     612                 : }
     613                 : USTR_CONF_I_PROTO
     614                 : struct Ustrp *ustrp_init_alloc(void *data, size_t rsz, size_t sz,
     615                 :                                size_t rbytes, int exact, int emem, size_t len)
     616               4 : { return (USTRP(ustr_init_alloc(data, rsz, sz, rbytes, exact, emem, len))); }
     617                 : 
     618                 : USTR_CONF_I_PROTO
     619                 : struct Ustr *ustr_init_fixed(void *data, size_t sz, int exact, size_t len)
     620              47 : {
     621              47 :   struct Ustr *ret = data;
     622              47 :   void *tmp = 0; /* move type between char and unsigned char */
     623              47 :   size_t rbytes = 0;
     624              47 :   const int    emem   = USTR_FALSE;
     625                 :   
     626              23 :   USTR_ASSERT(sz);
     627                 :   
     628              47 :   if (!ustr_init_alloc(data, sz, sz, rbytes, exact, emem, len))
     629              16 :     return (USTR_NULL);
     630                 : 
     631              31 :   tmp = ustr_wstr(ret); /* done here,
     632                 :                            as it might not be valid until we terminate */
     633                 : 
     634              31 :   ret->data[0] &= ~USTR__BIT_ALLOCD;
     635              31 :   ustr__terminate(tmp, USTR_FALSE, len);
     636              46 :   if ((rbytes = USTR__REF_LEN(ret))) /* _large_ */
     637              31 :     ustr__embed_val_set(ret->data + 1, rbytes, 0);
     638                 : 
     639              15 :   USTR_ASSERT(ustr_assert_valid(ret));
     640              15 :   USTR_ASSERT( ustr_fixed(ret));
     641              15 :   USTR_ASSERT(!ustr_alloc(ret));
     642              15 :   USTR_ASSERT(!ustr_ro(ret));
     643              15 :   USTR_ASSERT( ustr_enomem(ret) == emem);
     644              15 :   USTR_ASSERT(!ustr_shared(ret));
     645              15 :   USTR_ASSERT( ustr_owner(ret));
     646                 : 
     647              31 :   return (ret);
     648                 : }
     649                 : USTR_CONF_I_PROTO
     650                 : struct Ustrp *ustrp_init_fixed(void *data, size_t sz, int exact, size_t len)
     651               8 : { return (USTRP(ustr_init_fixed(data, sz, exact, len))); }
     652                 : 
     653                 : USTR_CONF_I_PROTO size_t ustr_size(const struct Ustr *s1)
     654             491 : { /* size of available space in the string */
     655             491 :   size_t oh = 0;
     656                 : 
     657             234 :   USTR_ASSERT(ustr_assert_valid(s1));
     658                 :   
     659             491 :   if (ustr_sized(s1))
     660             104 :     return (ustr__sz_get(s1) - ustr_size_overhead(s1));
     661             387 :   if (ustr_exact(s1))
     662             242 :     return (ustr_len(s1));
     663                 : 
     664             145 :   oh = ustr_size_overhead(s1);
     665             145 :   return (ustr__ns(ustr_len(s1) + oh) - oh);
     666                 : }
     667                 : 
     668                 : /* ---------------- allocations ---------------- */
     669                 : /* NOTE: This is one of the two main "allocation" functions --
     670                 :  * this is the only thing that calls MALLOC. */
     671                 : USTR_CONF_i_PROTO
     672                 : struct Ustr *ustrp__dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes, 
     673                 :                                int exact, int emem, size_t len)
     674            2656 : {
     675            2656 :   struct Ustr *ret = USTR_NULL;
     676            2656 :   struct Ustr *chk = USTR_NULL;
     677            2656 :   size_t rsz = 0;
     678                 :   
     679            1400 :   USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
     680                 :               (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
     681            1400 :   USTR_ASSERT(exact == !!exact);
     682            1400 :   USTR_ASSERT(emem  == !!emem);
     683                 : 
     684            2656 :   if (!len && ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_DEF))
     685              86 :     return (USTR("")); /* We don't go to all the trouble ustr_del() does.
     686                 :                         * Which is probably better overall. */
     687                 :   
     688            2570 :   if (!(rsz = ustr_init_size(sz, rbytes, exact, len)))
     689             480 :     return (USTR_NULL);
     690                 : 
     691            2090 :   if (p)
     692             656 :     ret = p->pool_sys_malloc(p, rsz);
     693                 :   else
     694            1434 :     ret = USTR_CONF_MALLOC(rsz);
     695                 :   
     696            2090 :   if (!ret)
     697                 :   {
     698             190 :     errno = USTR__ENOMEM;
     699             190 :     return (USTR_NULL);
     700                 :   }
     701                 :   
     702            1900 :   chk = ustr_init_alloc(ret, rsz, sz ? rsz : 0, rbytes, exact, emem, len);
     703             950 :   USTR_ASSERT(chk);
     704                 :   
     705             950 :   USTR_ASSERT(ustrp__assert_valid(!!p, ret));
     706            1900 :   return (ret);
     707                 : }
     708                 : 
     709                 : USTR_CONF_i_PROTO
     710                 : int ustrp__rw_realloc(struct Ustr_pool *p, struct Ustr **ps1,
     711                 :                       int sized, size_t osz, size_t nsz)
     712            1037 : {
     713            1037 :   struct Ustr *ret = USTR_NULL;
     714                 :   
     715             968 :   USTR_ASSERT(ustr_alloc(*ps1));
     716             484 :   USTR_ASSERT(osz == ustr_size_alloc(*ps1));
     717             484 :   USTR_ASSERT(sized == !!sized);
     718             968 :   USTR_ASSERT(sized == ustr_sized(*ps1));
     719             437 :   ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, *ps1));
     720                 : 
     721                 :   /*  printf("1. p=%p, osz=%zu, nsz=%zu\n", p, osz, nsz); */
     722            1037 :   if (p)
     723             242 :     ret = p->pool_sys_realloc(p, *ps1, osz, nsz);
     724                 :   else
     725             795 :     ret = USTR_CONF_REALLOC(*ps1, nsz);
     726                 :   
     727            1037 :   if (!ret)
     728                 :   {
     729              71 :     ustr_setf_enomem_err(*ps1);
     730              71 :     return (USTR_FALSE);
     731                 :   }
     732             966 :   if (sized)
     733              28 :     ustr__sz_set(ret, nsz);
     734                 : 
     735             966 :   *ps1 = ret;
     736                 : 
     737             966 :   return (USTR_TRUE);
     738                 : }
     739                 : 
     740                 : USTR_CONF_i_PROTO void ustr__memcpy(struct Ustr *s1, size_t off,
     741                 :                                     const void *ptr, size_t len)
     742            3828 : { /* can't call ustr_wstr() if len == 0, as it might be RO */
     743            3828 :   if (!len)
     744             880 :     return;
     745            2948 :   memcpy(ustr_wstr(s1) + off, ptr, len);
     746                 : }
     747                 : 
     748                 : USTR_CONF_i_PROTO void ustr__memset(struct Ustr *s1, size_t off,
     749                 :                                     int chr, size_t len)
     750             280 : { /* can't call ustr_wstr() if len == 0, as it might be RO */
     751             280 :   if (!len)
     752              17 :     return;
     753             263 :   memset(ustr_wstr(s1) + off, chr, len);
     754                 : }
     755                 : 
     756                 : /* ---------------- del ---------------- */
     757                 : 
     758                 : /* Fine grained management of the space allocated to a sized Ustr */
     759                 : USTR_CONF_i_PROTO
     760                 : int ustrp__realloc(struct Ustr_pool *p, struct Ustr **ps1, size_t nsz)
     761              64 : {
     762              64 :   struct Ustr *s1 = USTR_NULL;
     763              64 :   size_t oh  = 0;
     764              64 :   size_t len = 0;
     765              64 :   size_t msz = 0; /* min size */
     766              64 :   size_t osz = 0; /* old size */
     767              64 :   int    ret = USTR_TRUE;
     768                 :   
     769              32 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
     770                 : 
     771              64 :   s1 = *ps1;
     772              96 :   if (!ustr_sized(s1) || !ustr_alloc(s1) || !ustr_owner(s1))
     773               4 :     return (USTR_FALSE);
     774                 : 
     775              60 :   oh  = ustr_size_overhead(s1);
     776              60 :   len = ustr_len(s1);
     777              60 :   msz = oh + len;
     778                 :   
     779              60 :   if (!nsz)
     780              16 :     nsz = len;
     781              60 :   nsz += oh; /* if this overflows, we'll get it at the msz test */
     782                 :   
     783              60 :   osz = ustr__sz_get(s1);
     784              60 :   if (nsz == osz) /* if there's nothing to do... */
     785               8 :     return (USTR_TRUE);
     786                 : 
     787              52 :   if (nsz < msz) /* we can't go less than the minimum */
     788              16 :     return (USTR_FALSE);
     789                 :   
     790                 :   /* Don't let the length num. bytes go up, as we might as well just dupx()
     791                 :    */
     792              54 :   if (ustr__nb(nsz) > USTR__LEN_LEN(s1))
     793              12 :     return (USTR_FALSE);
     794                 :   
     795              24 :   ret = ustrp__rw_realloc(p, ps1, USTR_TRUE, osz, nsz);
     796              12 :   USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
     797                 : 
     798              24 :   return (ret);
     799                 : }
     800                 : USTR_CONF_I_PROTO int ustr_realloc(struct Ustr **ps1, size_t sz)
     801               8 : { return (ustrp__realloc(0, ps1, sz)); }
     802                 : USTR_CONF_I_PROTO int ustrp_realloc(struct Ustr_pool *p,
     803                 :                                     struct Ustrp **ps1, size_t sz)
     804              56 : {
     805              56 :   struct Ustr *tmp = &(*ps1)->s;
     806              56 :   int ret = ustrp__realloc(p, &tmp, sz);
     807              56 :   *ps1 = USTRP(tmp);
     808              56 :   return (ret);
     809                 : }
     810                 : 
     811                 : /* Can we actually RW to this Ustr, at _this_ moment, _this_ len */
     812                 : USTR_CONF_i_PROTO
     813                 : int ustr__rw_mod(struct Ustr *s1, size_t nlen, size_t *sz, size_t *oh,
     814                 :                  size_t *osz, size_t *nsz, int *alloc)
     815            3213 : {
     816            3213 :   size_t lbytes = 0;
     817            3213 :   size_t sbytes = 0;
     818                 : 
     819            3213 :   if (!ustr_owner(s1))
     820             596 :     return (USTR_FALSE);
     821                 : 
     822            2617 :   *sz = 0;
     823            2617 :   if (ustr_sized(s1))
     824             204 :     *sz = ustr__sz_get(s1);
     825            2617 :   *osz = *sz;
     826                 :   
     827            2617 :   lbytes = USTR__LEN_LEN(s1);
     828            2617 :   if (*sz)
     829             204 :     sbytes = lbytes;
     830            1448 :   USTR_ASSERT(!*sz || (ustr__nb(*sz) == lbytes) ||
     831                 :               ((ustr__nb(*sz) == 1) && (lbytes == 2))); /* 2 is the minimum */
     832                 :   
     833            2617 :   if (ustr__nb(nlen) > lbytes)
     834             256 :     return (USTR_FALSE); /* in theory we could do better, but it's _hard_ */
     835                 :   
     836            3542 :   *oh  = 1 + USTR__REF_LEN(s1) + lbytes + sbytes + sizeof(USTR_END_ALOCDx);
     837            2361 :   *nsz = *oh + nlen;
     838                 : 
     839            2361 :   if (*nsz < nlen)
     840               0 :     return (USTR_FALSE);
     841                 :   if (*nsz > USTR__SIZE_MAX) /* 32bit overflow on 64bit size_t */
     842                 :     return (USTR_FALSE);
     843                 : 
     844            2361 :   *alloc = USTR_FALSE; /* don't need to allocate/deallocate anything */
     845            2361 :   if (*nsz <= *sz)
     846             172 :     return (USTR_TRUE); /* ustr_sized() */
     847                 :   
     848            2189 :   if (!ustr_exact(s1))
     849            2113 :     *nsz = ustr__ns(*nsz);
     850                 :   
     851            2189 :   *osz = ustr_size_alloc(s1);
     852                 :   
     853            2189 :   if (!*sz && (*nsz == *osz))
     854             923 :     return (USTR_TRUE);
     855                 :   
     856            1266 :   *alloc = ustr_alloc(s1); /* _do_   need to deallocate */
     857            1266 :   if (!*sz && (*nsz <= *osz))
     858             520 :     return (USTR_TRUE);
     859                 :   
     860             746 :   if (!*alloc)
     861              12 :     return (USTR_FALSE);
     862                 : 
     863             734 :   return (USTR_TRUE);
     864                 : }
     865                 : 
     866                 : /* NOTE: This is the main "deallocation" function (apart from plain free) --
     867                 :  * this is one of only three things that removes data via. REALLOC.
     868                 :  * Others are in ustr-set.h */
     869                 : USTR_CONF_i_PROTO
     870                 : int ustrp__del(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
     871            1026 : {
     872            1026 :   struct Ustr *s1  = USTR_NULL;
     873            1026 :   struct Ustr *ret = USTR_NULL;
     874            1026 :   size_t sz  = 0;
     875            1026 :   size_t oh  = 0;
     876            1026 :   size_t osz = 0;
     877            1026 :   size_t nsz = 0;
     878            1026 :   size_t clen = 0;
     879            1026 :   size_t nlen = 0;
     880            1026 :   int alloc = USTR_FALSE;
     881                 : 
     882             513 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
     883                 :   
     884            1026 :   if (!len)
     885              64 :     return (USTR_TRUE);
     886                 : 
     887             962 :   s1   = *ps1;
     888             962 :   clen = ustr_len(s1);
     889                 :   /* under certain conditions, we can just return "" as it's much more efficient
     890                 :    * and we don't get anything with not doing it. */
     891            1746 :   if (!(nlen = clen - len) && /* we are deleting everything */
     892                 :       !(ustr_fixed(*ps1) ||   /* NOT in "free" space, or */
     893                 :         (ustr_sized(*ps1) && ustr_owner(*ps1))) &&    /* sized with one ref. */
     894                 :       ustr__dupx_cmp_eq(USTR__DUPX_DEF, USTR__DUPX_FROM(s1))) /* def. config. */
     895                 :   {
     896             244 :     ustrp__sc_free2(p, ps1, USTR(""));
     897             244 :     return (USTR_TRUE);
     898                 :   }
     899                 :   
     900             718 :   if (nlen > clen) /* underflow */
     901               4 :     return (USTR_FALSE);
     902                 : 
     903             714 :   if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
     904                 :   {
     905             690 :     size_t eos_len = sizeof(USTR_END_ALOCDx);
     906                 :     
     907             690 :     if (alloc)
     908                 :     { /* ignore errors? -- can they happen on truncate? */
     909             427 :       int emem = ustr_enomem(*ps1);
     910                 : 
     911             201 :       USTR_ASSERT(nsz < osz);
     912             201 :       USTR_ASSERT(!sz);
     913                 :       
     914             427 :       if (!ustrp__rw_realloc(p, ps1, USTR_FALSE, osz, nsz))
     915                 :       {
     916              10 :         if (!p)
     917                 :         {
     918               2 :           ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, osz));
     919               4 :           USTR__CNTL_MALLOC_CHECK_FIXUP_REALLOC(*ps1, nsz);
     920               2 :           ustr_assert(USTR_CNTL_MALLOC_CHECK_MEM_SZ(*ps1, nsz));
     921                 :         }
     922                 :         
     923              21 :         if (!emem)
     924              21 :           ustr_setf_enomem_clr(*ps1);
     925                 :       }
     926                 :     }
     927                 :       
     928            1035 :     ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
     929             690 :     ustr__len_set(*ps1, nlen);
     930                 :     
     931             345 :     USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
     932             690 :     return (USTR_TRUE);
     933                 :   }
     934                 : 
     935              12 :   USTR_ASSERT(!ustr_limited(s1));
     936                 :   
     937              64 :   if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
     938                 :   {
     939              10 :     ustr_setf_enomem_err(s1);
     940              10 :     return (USTR_FALSE);
     941                 :   }
     942                 : 
     943              14 :   ustr__memcpy(ret, 0, ustr_cstr(s1), nlen);
     944              14 :   ustrp__sc_free2(p, ps1, ret);
     945                 : 
     946               7 :   USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
     947              14 :   return (USTR_TRUE);
     948                 : }
     949                 : USTR_CONF_I_PROTO int ustr_del(struct Ustr **ps1, size_t len)
     950              80 : { return (ustrp__del(0, ps1, len)); }
     951                 : USTR_CONF_I_PROTO
     952                 : int ustrp_del(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
     953              64 : {
     954              64 :   struct Ustr *tmp = &(*ps1)->s;
     955              64 :   int ret = ustrp__del(p, &tmp, len);
     956              64 :   *ps1 = USTRP(tmp);
     957              64 :   return (ret);
     958                 : }
     959                 : 
     960                 : USTR_CONF_i_PROTO
     961                 : int ustrp__del_subustr(struct Ustr_pool *p,
     962                 :                        struct Ustr **ps1, size_t pos, size_t len)
     963             212 : {
     964             212 :   struct Ustr *s1  = USTR_NULL;
     965             212 :   struct Ustr *ret = USTR_NULL;
     966             212 :   size_t sz  = 0;
     967             212 :   size_t oh  = 0;
     968             212 :   size_t osz = 0;
     969             212 :   size_t nsz = 0;
     970             212 :   size_t clen = 0;
     971             212 :   size_t nlen = 0;
     972             212 :   int alloc = USTR_FALSE;
     973             212 :   const char *ocstr = 0;
     974                 :   
     975             105 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
     976                 : 
     977             212 :   if (!len)
     978              48 :     return (USTR_TRUE);
     979                 : 
     980             164 :   s1   = *ps1;
     981             164 :   clen = ustrp__assert_valid_subustr(!!p, s1, pos, len);
     982             164 :   if (!clen)
     983               2 :     return (USTR_FALSE);
     984             162 :   if (--pos == (clen - len)) /* deleting from the end */
     985              22 :     return (ustrp__del(p, ps1, len));
     986                 : 
     987             140 :   nlen = clen - len;
     988              70 :   USTR_ASSERT(nlen < clen);
     989                 :   
     990             140 :   if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
     991                 :   { /* Move everything to the begining and call ustr_del() */
     992             128 :     char *ptr = ustr_wstr(s1);
     993                 :     
     994              64 :     USTR_ASSERT(nlen - pos);
     995                 : 
     996             128 :     memmove(ptr + pos, ptr + pos + len, (nlen - pos));
     997                 : 
     998             128 :     return (ustrp__del(p, ps1, len));
     999                 :   }
    1000                 : 
    1001               6 :   USTR_ASSERT(!ustr_limited(s1));
    1002                 :   
    1003                 :   /* Can't do anything sane, give up and build a new string from scratch */
    1004              34 :   if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
    1005                 :   {
    1006               4 :     ustr_setf_enomem_err(s1);
    1007               4 :     return (USTR_FALSE);
    1008                 :   }
    1009                 : 
    1010               8 :   ocstr = ustr_cstr(s1);
    1011                 : 
    1012               4 :   USTR_ASSERT(pos || (nlen - pos)); /* can be both */
    1013                 :   
    1014               8 :   ustr__memcpy(ret, 0,   ocstr,                    pos);
    1015               8 :   ustr__memcpy(ret, pos, ocstr + pos + len, nlen - pos);
    1016                 : 
    1017               8 :   ustrp__sc_free2(p, ps1, ret);
    1018                 : 
    1019               4 :   USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
    1020               8 :   return (USTR_TRUE);
    1021                 : }
    1022                 : USTR_CONF_I_PROTO int ustr_del_subustr(struct Ustr **ps1, size_t pos,size_t len)
    1023              56 : { return (ustrp__del_subustr(0, ps1, pos, len)); }
    1024                 : USTR_CONF_I_PROTO
    1025                 : int ustrp_del_subustrp(struct Ustr_pool *p,
    1026                 :                        struct Ustrp **ps1, size_t pos, size_t len)
    1027              16 : {
    1028              16 :   struct Ustr *tmp = &(*ps1)->s;
    1029              16 :   int ret = ustrp__del_subustr(p, &tmp, pos, len);
    1030              16 :   *ps1 = USTRP(tmp);
    1031              16 :   return (ret);
    1032                 : }
    1033                 : 
    1034                 : /* ---------------- dupx/dup ---------------- */
    1035                 : 
    1036                 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx_undef(size_t sz, size_t rbytes, 
    1037                 :                                                int exact, int emem, size_t len)
    1038             130 : { return (ustrp__dupx_undef(0, sz, rbytes, exact, emem, len)); }
    1039                 : USTR_CONF_I_PROTO
    1040                 : struct Ustrp *ustrp_dupx_undef(struct Ustr_pool *p, size_t sz, size_t rbytes, 
    1041                 :                                int exact, int emem, size_t len)
    1042             196 : { return (USTRP(ustrp__dupx_undef(p, sz, rbytes, exact, emem, len))); }
    1043                 : 
    1044                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_undef(size_t len)
    1045             124 : { return (ustr_dupx_undef(USTR__DUPX_DEF, len)); }
    1046                 : 
    1047                 : USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_undef(struct Ustr_pool *p, size_t len)
    1048             225 : { return (ustrp_dupx_undef(p, USTR__DUPX_DEF, len)); }
    1049                 : 
    1050                 : USTR_CONF_i_PROTO
    1051                 : struct Ustr *ustrp__dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes, 
    1052                 :                                int exact, int emem)
    1053             102 : { /* set the error bit, so we always get malloc()'d data, then clear it */
    1054             102 :   struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, USTR_TRUE, 0);
    1055             102 :   int eret = USTR_FALSE;
    1056                 : 
    1057             102 :   if (!s1 || emem)
    1058              10 :     return (s1);
    1059                 : 
    1060              92 :   eret = ustr_setf_enomem_clr(s1);
    1061              46 :   USTR_ASSERT(eret);
    1062                 :   
    1063              92 :   return (s1);
    1064                 : }
    1065                 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx_empty(size_t sz, size_t rbytes, 
    1066                 :                                                int exact, int emem)
    1067              28 : { return (ustrp__dupx_empty(0, sz, rbytes, exact, emem)); }
    1068                 : USTR_CONF_I_PROTO
    1069                 : struct Ustrp *ustrp_dupx_empty(struct Ustr_pool *p, size_t sz, size_t rbytes,
    1070                 :                                int exact, int emem)
    1071              30 : { return (USTRP(ustrp__dupx_empty(p, sz, rbytes, exact, emem))); }
    1072                 : 
    1073                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_empty(void)
    1074               8 : { return (ustr_dupx_empty(USTR__DUPX_DEF)); }
    1075                 : 
    1076                 : USTR_CONF_I_PROTO struct Ustrp *ustrp_dup_empty(struct Ustr_pool *p)
    1077              17 : { return (ustrp_dupx_empty(p, USTR__DUPX_DEF)); }
    1078                 : 
    1079                 : USTR_CONF_i_PROTO
    1080                 : struct Ustr *ustrp__dupx_buf(struct Ustr_pool *p, size_t sz, size_t rbytes,
    1081                 :                              int exact, int emem, const void *data, size_t len)
    1082            1130 : {
    1083            1130 :   struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
    1084                 : 
    1085            1130 :   if (!s1)
    1086              76 :     return (USTR_NULL);
    1087                 : 
    1088            1054 :   ustr__memcpy(s1, 0, data, len);
    1089                 : 
    1090             527 :   USTR_ASSERT(ustrp__assert_valid(!!p, s1));
    1091            1054 :   return (s1);
    1092                 : }
    1093                 : USTR_CONF_I_PROTO
    1094                 : struct Ustr *ustr_dupx_buf(size_t sz, size_t rb, int exact,
    1095                 :                            int emem, const void *data, size_t len)
    1096             152 : { return (ustrp__dupx_buf(0, sz, rb, exact, emem, data, len)); }
    1097                 : USTR_CONF_I_PROTO
    1098                 : struct Ustrp *ustrp_dupx_buf(struct Ustr_pool *p, size_t sz, size_t rb,
    1099                 :                              int exact, int emem, const void *data, size_t len)
    1100              36 : { return (USTRP(ustrp__dupx_buf(p, sz, rb, exact, emem, data, len))); }
    1101                 : 
    1102                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_buf(const void *data, size_t len)
    1103             140 : { return (ustr_dupx_buf(USTR__DUPX_DEF, data, len)); }
    1104                 : USTR_CONF_I_PROTO
    1105                 : struct Ustrp *ustrp_dup_buf(struct Ustr_pool *p, const void *data, size_t len)
    1106              25 : { return (USTRP(ustrp_dupx_buf(p, USTR__DUPX_DEF, data, len))); }
    1107                 : 
    1108                 : USTR_CONF_i_PROTO
    1109                 : struct Ustr *ustrp__dup(struct Ustr_pool *p, const struct Ustr *s1)
    1110         1329921 : { /* This ignores the const argument, because it doesn't alter the data, or at
    1111                 :    * all when ustr_ro(). */
    1112          533347 :   ustr_assert(USTR__ASSERT_MALLOC_CHECK_MEM(p, s1));
    1113                 :   
    1114         1329921 :   if (ustr__ref_add((struct Ustr *)s1))
    1115         1329875 :     return ((struct Ustr *)s1);
    1116                 : 
    1117             142 :   return (ustrp__dupx_buf(p, USTR__DUPX_FROM(s1), ustr_cstr(s1), ustr_len(s1)));
    1118                 : }
    1119                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup(const struct Ustr *s1)
    1120         1067684 : { return (ustrp__dup(0, s1)); }
    1121                 : USTR_CONF_I_PROTO
    1122                 : struct Ustrp *ustrp_dup(struct Ustr_pool *p, const struct Ustrp *s1)
    1123              24 : { return (USTRP(ustrp__dup(p, &s1->s))); }
    1124                 : 
    1125                 : USTR_CONF_i_PROTO
    1126                 : struct Ustr *ustrp__dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
    1127                 :                          int exact, int emem, const struct Ustr *s1)
    1128          262260 : { /* the exactneustr of the options is more important than the reference */
    1129          131130 :   USTR_ASSERT((rbytes == 0) || (rbytes == 1) || (rbytes == 2) || (rbytes == 4)||
    1130                 :               (USTR_CONF_HAVE_64bit_SIZE_MAX && (rbytes == 8)));
    1131          131130 :   USTR_ASSERT(exact == !!exact);
    1132          131130 :   USTR_ASSERT(emem  == !!emem);
    1133                 :   
    1134          655682 :   if (ustr__dupx_cmp_eq(sz, rbytes, exact, emem, USTR__DUPX_FROM(s1)))
    1135          262196 :     return (ustrp__dup(p, s1));
    1136                 :   
    1137              64 :   return (ustrp__dupx_buf(p, sz,rbytes,exact,emem, ustr_cstr(s1),ustr_len(s1)));
    1138                 : }
    1139                 : USTR_CONF_I_PROTO struct Ustr *ustr_dupx(size_t sz, size_t rbytes, int exact,
    1140                 :                                          int emem, const struct Ustr *s1)
    1141          262156 : { return (ustrp__dupx(0, sz, rbytes, exact, emem, s1)); }
    1142                 : USTR_CONF_I_PROTO
    1143                 : struct Ustrp *ustrp_dupx(struct Ustr_pool *p, size_t sz, size_t rbytes,
    1144                 :                          int exact, int emem, const struct Ustrp *s1)
    1145               8 : { return (USTRP(ustrp__dupx(p, sz, rbytes, exact, emem, &s1->s))); }
    1146                 : 
    1147                 : USTR_CONF_i_PROTO
    1148                 : struct Ustr *ustrp__dupx_subustr(struct Ustr_pool *p,
    1149                 :                                  size_t sz, size_t rbytes, int exact, int emem,
    1150                 :                                  const struct Ustr *s2, size_t pos, size_t len)
    1151             184 : {
    1152             184 :   size_t clen = 0;
    1153                 :   
    1154              86 :   USTR_ASSERT(ustrp__assert_valid(!!p, s2));
    1155              86 :   USTR_ASSERT(pos);
    1156                 : 
    1157             184 :   if (!len)
    1158              12 :     return (ustrp__dupx_undef(p, sz, rbytes, exact, emem, len));
    1159                 :   
    1160             172 :   clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
    1161             172 :   if (!clen)
    1162              12 :     return (USTR_NULL);
    1163             160 :   if (len == clen)
    1164              20 :     return (ustrp__dupx(p, sz, rbytes, exact, emem, s2));
    1165                 :   
    1166             140 :   return (ustrp__dupx_buf(p,sz,rbytes,exact,emem, ustr_cstr(s2) + --pos, len));
    1167                 : }
    1168                 : USTR_CONF_I_PROTO
    1169                 : struct Ustr *ustr_dupx_subustr(size_t sz, size_t rbytes, int exact, int emem,
    1170                 :                                const struct Ustr *s2, size_t pos, size_t len)
    1171               8 : { return (ustrp__dupx_subustr(0, sz, rbytes, exact, emem, s2, pos, len)); }
    1172                 : USTR_CONF_I_PROTO
    1173                 : struct Ustrp *ustrp_dupx_subustrp(struct Ustr_pool *p,
    1174                 :                                   size_t sz, size_t rbytes, int exact, int emem,
    1175                 :                                   const struct Ustrp *s2, size_t pos,size_t len)
    1176              40 : { return (USTRP(ustrp__dupx_subustr(p, sz, rbytes, exact, emem,
    1177                 :                                     &s2->s, pos, len))); }
    1178                 : 
    1179                 : USTR_CONF_i_PROTO
    1180                 : struct Ustr *ustrp__dup_subustr(struct Ustr_pool *p, const struct Ustr *s2,
    1181                 :                                 size_t pos, size_t len)
    1182             418 : { return (ustrp__dupx_subustr(p, USTR__DUPX_FROM(s2), s2, pos, len)); }
    1183                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_subustr(const struct Ustr *s2,
    1184                 :                                                 size_t pos, size_t len)
    1185               4 : { return (ustrp__dup_subustr(0, s2, pos, len)); }
    1186                 : USTR_CONF_I_PROTO
    1187                 : struct Ustrp *ustrp_dup_subustrp(struct Ustr_pool *p, const struct Ustrp *s2,
    1188                 :                                  size_t pos, size_t len)
    1189               8 : { return (USTRP(ustrp__dup_subustr(p, &s2->s, pos, len))); }
    1190                 : 
    1191                 : USTR_CONF_i_PROTO
    1192                 : struct Ustr *ustrp__dupx_rep_chr(struct Ustr_pool *p,
    1193                 :                                  size_t sz, size_t rbytes, int exact, int emem,
    1194                 :                                  char chr, size_t len)
    1195              24 : {
    1196              24 :   struct Ustr *s1 = ustrp__dupx_undef(p, sz, rbytes, exact, emem, len);
    1197                 :   
    1198              24 :   if (!s1)
    1199               8 :     return (USTR_NULL);
    1200                 : 
    1201              16 :   if (len)
    1202              16 :     ustr__memset(s1, 0, chr, len);
    1203                 : 
    1204               8 :   USTR_ASSERT(ustrp__assert_valid(!!p, s1));
    1205              16 :   return (s1);
    1206                 : }
    1207                 : USTR_CONF_I_PROTO
    1208                 : struct Ustr *ustr_dupx_rep_chr(size_t sz, size_t rbytes, int exact, int emem,
    1209                 :                                char chr, size_t len)
    1210               4 : { return (ustrp__dupx_rep_chr(0, sz, rbytes, exact, emem, chr, len)); }
    1211                 : USTR_CONF_I_PROTO
    1212                 : struct Ustrp *ustrp_dupx_rep_chr(struct Ustr_pool *p,
    1213                 :                                  size_t sz, size_t rbytes, int exact, int emem,
    1214                 :                                  char chr, size_t len)
    1215              20 : { return (USTRP(ustrp__dupx_rep_chr(p, sz, rbytes, exact, emem, chr, len))); }
    1216                 : USTR_CONF_I_PROTO struct Ustr *ustr_dup_rep_chr(char chr, size_t len)
    1217               4 : { return (ustr_dupx_rep_chr(USTR__DUPX_DEF, chr, len)); }
    1218                 : USTR_CONF_I_PROTO
    1219                 : struct Ustrp *ustrp_dup_rep_chr(struct Ustr_pool *p, char chr, size_t len)
    1220              15 : { return (ustrp_dupx_rep_chr(p, USTR__DUPX_DEF, chr, len)); }
    1221                 : 
    1222                 : /* ---------------- add ---------------- */
    1223                 : 
    1224                 : /* NOTE: This is one of the two main "allocation" functions --
    1225                 :  * this is one of three things funcs that gets more data via. REALLOC.
    1226                 :  * Others are in ustr-set.h */
    1227                 : USTR_CONF_i_PROTO
    1228                 : int ustrp__add_undef(struct Ustr_pool *p, struct Ustr **ps1, size_t len)
    1229            1602 : {
    1230            1602 :   struct Ustr *s1  = USTR_NULL;
    1231            1602 :   struct Ustr *ret = USTR_NULL;
    1232            1602 :   size_t clen = 0;
    1233            1602 :   size_t nlen = 0;
    1234            1602 :   size_t sz   = 0;
    1235            1602 :   size_t oh   = 0;
    1236            1602 :   size_t osz  = 0;
    1237            1602 :   size_t nsz  = 0;
    1238            1602 :   int alloc = USTR_FALSE;
    1239                 :   
    1240             819 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
    1241                 :   
    1242            1602 :   if (!len)
    1243               1 :     return (USTR_TRUE);
    1244                 : 
    1245            1601 :   s1   = *ps1;
    1246            1601 :   clen = ustr_len(s1);
    1247            1601 :   if ((nlen = clen + len) < clen) /* overflow */
    1248               4 :     goto fail_enomem;
    1249                 : 
    1250            1597 :   if (ustr__rw_mod(s1, nlen, &sz, &oh, &osz, &nsz, &alloc))
    1251                 :   {
    1252            1157 :     size_t eos_len = sizeof(USTR_END_ALOCDx);
    1253                 : 
    1254            1157 :     if (alloc && !ustrp__rw_realloc(p, ps1, !!sz, osz, nsz))
    1255              42 :       return (USTR_FALSE);
    1256            1673 :     ustr__terminate((*ps1)->data, ustr_alloc(*ps1), (oh - eos_len) + nlen);
    1257            1115 :     ustr__len_set(*ps1, nlen);
    1258                 :     
    1259             558 :     USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
    1260            1115 :     return (USTR_TRUE);
    1261                 :   }
    1262                 : 
    1263             440 :   if (ustr_limited(s1))
    1264                 :   {
    1265               4 :     ustr_setf_enomem_err(s1);
    1266               4 :     return (USTR_FALSE);
    1267                 :   }
    1268                 :   
    1269            1282 :   if (!(ret = ustrp__dupx_undef(p, USTR__DUPX_FROM(s1), nlen)))
    1270             138 :     goto fail_enomem;
    1271                 :   
    1272             298 :   ustr__memcpy(ret, 0, ustr_cstr(s1), ustr_len(s1));
    1273             298 :   ustrp__sc_free2(p, ps1, ret);
    1274                 : 
    1275             149 :   USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
    1276             298 :   return (USTR_TRUE);
    1277                 : 
    1278             142 :  fail_enomem:
    1279             142 :   ustr_setf_enomem_err(s1);
    1280             142 :   return (USTR_FALSE);
    1281                 : }
    1282                 : USTR_CONF_I_PROTO int ustr_add_undef(struct Ustr **ps1, size_t len)
    1283             120 : { return (ustrp__add_undef(0, ps1, len)); }
    1284                 : USTR_CONF_I_PROTO
    1285                 : int ustrp_add_undef(struct Ustr_pool *p, struct Ustrp **ps1, size_t len)
    1286               4 : {
    1287               4 :   struct Ustr *tmp = &(*ps1)->s;
    1288               4 :   int ret = ustrp__add_undef(p, &tmp, len);
    1289               4 :   *ps1 = USTRP(tmp);
    1290               4 :   return (ret);  
    1291                 : }
    1292                 : 
    1293                 : USTR_CONF_i_PROTO int ustrp__add_buf(struct Ustr_pool *p, struct Ustr **ps1,
    1294                 :                                      const void *s2, size_t len)
    1295             564 : {
    1296             564 :   if (!ustrp__add_undef(p, ps1, len))
    1297              14 :     return (USTR_FALSE);
    1298                 : 
    1299             550 :   ustr__memcpy(*ps1, ustr_len(*ps1) - len, s2, len);
    1300                 : 
    1301             550 :   return (USTR_TRUE);
    1302                 : }
    1303                 : USTR_CONF_I_PROTO int ustr_add_buf(struct Ustr **ps1, const void *s2,size_t len)
    1304             228 : { return (ustrp__add_buf(0, ps1, s2, len)); }
    1305                 : USTR_CONF_I_PROTO int ustrp_add_buf(struct Ustr_pool *p, struct Ustrp **ps1,
    1306                 :                                     const void *s2, size_t len)
    1307             224 : {
    1308             224 :   struct Ustr *tmp = &(*ps1)->s;
    1309             224 :   int ret = ustrp__add_buf(p, &tmp, s2, len);
    1310             224 :   *ps1 = USTRP(tmp);
    1311             224 :   return (ret);
    1312                 : }
    1313                 : 
    1314                 : /* If we can use _dup(), otherwise just pretend it's a buf+len */
    1315                 : USTR_CONF_i_PROTO
    1316                 : int ustr__treat_as_buf(const struct Ustr *s1, size_t len1, size_t len2)
    1317             144 : {
    1318              72 :   USTR_ASSERT(!len1 || (len1 == ustr_len(s1))); /* set() uses 0 */
    1319              72 :   USTR_ASSERT((len1 < (len1 + len2)) || !len2); /* no overflow allowed */
    1320                 : 
    1321             144 :   if (len1)
    1322              60 :     return (USTR_TRUE);
    1323                 :   
    1324              84 :   if (ustr_limited(s1))
    1325               4 :     return (USTR_TRUE);
    1326                 : 
    1327              80 :   if (ustr_owner(s1) && (ustr_size(s1) >= len2))
    1328              20 :     return (USTR_TRUE);
    1329                 : 
    1330              60 :   return (USTR_FALSE);
    1331                 : }
    1332                 : 
    1333                 : USTR_CONF_i_PROTO
    1334                 : int ustrp__add(struct Ustr_pool *p, struct Ustr **ps1, const struct Ustr *s2)
    1335             161 : {
    1336             161 :   struct Ustr *ret = USTR_NULL;
    1337             161 :   size_t len1 = 0;
    1338             161 :   size_t len2 = 0;
    1339                 :   
    1340              80 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
    1341              80 :   USTR_ASSERT(ustrp__assert_valid(!!p, s2));
    1342                 : 
    1343             161 :   len1 = ustr_len(*ps1);
    1344             161 :   len2 = ustr_len(s2);
    1345                 : 
    1346             161 :   if (len1 > (len1 + len2))
    1347                 :   {
    1348               1 :     errno = USTR__ENOMEM;
    1349               1 :     return (USTR_FALSE);
    1350                 :   }
    1351                 :   
    1352             160 :   if (!len2)
    1353              12 :     return (USTR_TRUE);
    1354                 :   
    1355             176 :   if ((*ps1 == s2) && ustr_owner(s2) && ustr_alloc(s2))
    1356                 :   { /* only one reference, so we can't take _cstr() before we realloc */
    1357              56 :     if (!ustrp__add_undef(p, ps1, len1))
    1358               6 :       return (USTR_FALSE);
    1359                 :     
    1360              50 :     ustr__memcpy(*ps1, len1, ustr_cstr(*ps1), len1);
    1361                 :     
    1362              25 :     USTR_ASSERT(ustrp__assert_valid(!!p, *ps1));
    1363              50 :     return (USTR_TRUE);
    1364                 :   }
    1365                 :   
    1366              92 :   if (ustr__treat_as_buf(*ps1, len1, len2))
    1367              68 :     return (ustrp__add_buf(p, ps1, ustr_cstr(s2), len2));
    1368                 : 
    1369              12 :   USTR_ASSERT(!len1);
    1370                 :     
    1371              94 :   if (!(ret = ustrp__dupx(p, USTR__DUPX_FROM(*ps1), s2)))
    1372                 :   {
    1373               4 :     ustr_setf_enomem_err(*ps1);
    1374               4 :     return (USTR_FALSE);
    1375                 :   }
    1376                 :   
    1377              20 :   ustrp__sc_free2(p, ps1, ret);
    1378              20 :   return (USTR_TRUE);
    1379                 : }
    1380                 : USTR_CONF_I_PROTO int ustr_add(struct Ustr **ps1, const struct Ustr *s2)
    1381              53 : { return (ustrp__add(0, ps1, s2)); }
    1382                 : USTR_CONF_I_PROTO
    1383                 : int ustrp_add(struct Ustr_pool *p, struct Ustrp **ps1, const struct Ustrp *s2)
    1384              80 : {
    1385              80 :   struct Ustr *tmp = &(*ps1)->s;
    1386              80 :   int ret = ustrp__add(p, &tmp, &s2->s);
    1387              80 :   *ps1 = USTRP(tmp);
    1388              80 :   return (ret);
    1389                 : }
    1390                 : 
    1391                 : USTR_CONF_i_PROTO
    1392                 : int ustrp__add_subustr(struct Ustr_pool *p, struct Ustr **ps1,
    1393                 :                        const struct Ustr *s2, size_t pos, size_t len)
    1394              70 : {
    1395              70 :   size_t clen = 0;
    1396                 :   
    1397              30 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
    1398              30 :   USTR_ASSERT(ustrp__assert_valid(!!p, s2));
    1399              30 :   USTR_ASSERT(pos);
    1400                 : 
    1401              70 :   if (!len)
    1402               0 :     return (USTR_TRUE);
    1403                 :   
    1404              70 :   clen = ustrp__assert_valid_subustr(!!p, s2, pos, len);
    1405              70 :   if (!clen)
    1406              10 :     return (USTR_FALSE);
    1407              60 :   if (len == clen)
    1408               8 :     return (ustrp__add(p, ps1, s2));
    1409                 :   
    1410              52 :   if (*ps1 != s2)
    1411              28 :     return (ustrp__add_buf(p, ps1, ustr_cstr(s2) + pos - 1, len));
    1412                 : 
    1413                 :   /* maybe only one reference, so we can't take _cstr() before we realloc */
    1414              24 :   if (!ustrp__add_undef(p, ps1, len))
    1415               4 :     return (USTR_FALSE);
    1416                 : 
    1417              20 :   ustr__memcpy(*ps1, clen, ustr_cstr(*ps1) + pos - 1, len);
    1418                 : 
    1419              20 :   return (USTR_TRUE);
    1420                 : }
    1421                 : USTR_CONF_I_PROTO int ustr_add_subustr(struct Ustr **ps1, const struct Ustr *s2,
    1422                 :                                        size_t pos, size_t len)
    1423               8 : { return (ustrp__add_subustr(0, ps1, s2, pos, len)); }
    1424                 : USTR_CONF_I_PROTO
    1425                 : int ustrp_add_subustrp(struct Ustr_pool *p, struct Ustrp **ps1,
    1426                 :                        const struct Ustrp *s2, size_t pos, size_t len)
    1427              50 : {
    1428              50 :   struct Ustr *tmp = &(*ps1)->s;
    1429              50 :   int ret = ustrp__add_subustr(p, &tmp, &s2->s, pos, len);
    1430              50 :   *ps1 = USTRP(tmp);
    1431              50 :   return (ret);
    1432                 : }
    1433                 : 
    1434                 : USTR_CONF_i_PROTO int ustrp__add_rep_chr(struct Ustr_pool *p, struct Ustr **ps1,
    1435                 :                                          char chr, size_t len)
    1436              44 : {
    1437              44 :   if (!ustrp__add_undef(p, ps1, len))
    1438               8 :     return (USTR_FALSE);
    1439                 : 
    1440              36 :   ustr__memset(*ps1, ustr_len(*ps1) - len, chr, len);
    1441                 : 
    1442              36 :   return (USTR_TRUE);
    1443                 : }
    1444                 : USTR_CONF_I_PROTO int ustr_add_rep_chr(struct Ustr **ps1, char chr, size_t len)
    1445              24 : { return (ustrp__add_rep_chr(0, ps1, chr, len)); }
    1446                 : USTR_CONF_I_PROTO int ustrp_add_rep_chr(struct Ustr_pool *p, struct Ustrp **ps1,
    1447                 :                                         char chr, size_t len)
    1448              20 : {
    1449              20 :   struct Ustr *tmp = &(*ps1)->s;
    1450              20 :   int ret = ustrp__add_rep_chr(p, &tmp, chr, len);
    1451              20 :   *ps1 = USTRP(tmp);
    1452              20 :   return (ret);
    1453                 : }
    1454                 : 
    1455                 : /* ---------------- shortcut ---------------- */
    1456                 : 
    1457                 : USTR_CONF_I_PROTO void ustr_sc_free2(struct Ustr **ps1, struct Ustr *s2)
    1458             250 : { ustrp__sc_free2(0, ps1, s2); }
    1459                 : USTR_CONF_I_PROTO void ustrp_sc_free2(struct Ustr_pool *p,
    1460                 :                                       struct Ustrp **ps1, struct Ustrp *s2)
    1461              52 : {
    1462              52 :   struct Ustr *tmp = &(*ps1)->s;
    1463              52 :   ustrp__sc_free2(p, &tmp, &s2->s);
    1464              52 :   *ps1 = USTRP(tmp);
    1465              52 : }
    1466                 : 
    1467                 : USTR_CONF_i_PROTO void ustrp__sc_free(struct Ustr_pool *p, struct Ustr **ps1)
    1468             702 : {
    1469             351 :   USTR_ASSERT(ps1);
    1470                 :   
    1471             702 :   ustrp__free(p, *ps1);
    1472             702 :   *ps1 = USTR_NULL;
    1473             702 : }
    1474                 : USTR_CONF_I_PROTO void ustr_sc_free(struct Ustr **ps1)
    1475             682 : { ustrp__sc_free(0, ps1); }
    1476                 : USTR_CONF_I_PROTO void ustrp_sc_free(struct Ustr_pool *p, struct Ustrp **ps1)
    1477              16 : {
    1478              16 :   struct Ustr *tmp = &(*ps1)->s;
    1479              16 :   ustrp__sc_free(p, &tmp);
    1480              16 :   *ps1 = USTRP(tmp);
    1481              16 : }
    1482                 : 
    1483                 : USTR_CONF_i_PROTO void ustrp__sc_del(struct Ustr_pool *p, struct Ustr **ps1)
    1484             224 : {
    1485             224 :   if (!ustrp__del(p, ps1, ustr_len(*ps1)))
    1486                 :     /* Very unlikely, but in this case ignore saving the options/data.
    1487                 :      * We can be a little less efficient etc., but no error handling is nice.
    1488                 :      * Only thing you have to watch for is ustr_enomem() might not "work"
    1489                 :      * after a call to here. */
    1490               4 :     ustrp__sc_free2(p, ps1, USTR(""));
    1491                 :   
    1492             112 :   USTR_ASSERT(!ustr_len(*ps1));
    1493             224 : }
    1494                 : USTR_CONF_I_PROTO void ustr_sc_del(struct Ustr **ps1)
    1495             160 : { ustrp__sc_del(0, ps1); }
    1496                 : USTR_CONF_I_PROTO void ustrp_sc_del(struct Ustr_pool *p, struct Ustrp **ps1)
    1497              36 : {
    1498              36 :   struct Ustr *tmp = &(*ps1)->s;
    1499              36 :   ustrp__sc_del(p, &tmp);
    1500              36 :   *ps1 = USTRP(tmp);
    1501              36 : }
    1502                 : 
    1503                 : USTR_CONF_I_PROTO
    1504                 : void ustr_conf(const struct Ustr *s1, size_t *ret_esz, size_t *ret_ref,
    1505                 :                int *ret_exact, size_t *ret_lenn, size_t *ret_refc)
    1506             396 : {
    1507             396 :   size_t esz   = 0;
    1508             396 :   size_t ref   = 0;
    1509             396 :   int    exact = 0;
    1510             396 :   size_t refc  = 0;
    1511                 :   
    1512             198 :   USTR_ASSERT(ustr_assert_valid(s1));
    1513                 : 
    1514             396 :   if (!ustr_alloc(s1))
    1515                 :   {
    1516             176 :     esz   = USTR_CONF_HAS_SIZE;
    1517             176 :     ref   = USTR_CONF_REF_BYTES;
    1518             176 :     exact = USTR_CONF_EXACT_BYTES;
    1519                 :   }
    1520                 :   else
    1521                 :   {
    1522             220 :     if (ustr_sized(s1))
    1523              12 :       esz = ustr__sz_get(s1);
    1524                 :     else
    1525             208 :       esz = 0;
    1526                 :     
    1527             220 :     ref   = USTR__REF_LEN(s1);
    1528             110 :     exact = ustr_exact(s1);
    1529             220 :     refc  = !!ref;
    1530                 :   }
    1531                 :   
    1532             880 :   USTR_ASSERT(ustr__dupx_cmp_eq(USTR__DUPX_FROM(s1),
    1533                 :                                 esz, ref, exact, ustr_enomem(s1)));
    1534                 : 
    1535             396 :   if (ret_esz)   *ret_esz   = esz;
    1536             396 :   if (ret_ref)   *ret_ref   = ref;
    1537             396 :   if (ret_exact) *ret_exact = exact;
    1538                 : 
    1539             495 :   if (ret_lenn)  *ret_lenn  = USTR__LEN_LEN(s1);
    1540             396 :   if (ret_refc)  *ret_refc  = refc ? ustr_xi__ref_get(s1) : 0;
    1541             396 : }
    1542                 : 
    1543                 : USTR_CONF_i_PROTO
    1544                 : int ustrp__sc_ensure_owner(struct Ustr_pool *p, struct Ustr **ps1)
    1545            1024 : {
    1546            1024 :   struct Ustr *ret = USTR_NULL;
    1547            1024 :   size_t clen = 0;
    1548                 :   
    1549             512 :   USTR_ASSERT(ps1 && ustrp__assert_valid(!!p, *ps1));
    1550                 : 
    1551            1024 :   if (ustr_owner(*ps1))
    1552             824 :     return (USTR_TRUE);
    1553                 : 
    1554             200 :   if (!(clen = ustr_len(*ps1))) /* so ustr_enomem() and ustr_wstr() work */
    1555              76 :     ret = ustrp__dupx_empty(p, USTR__DUPX_FROM(*ps1));
    1556                 :   else
    1557             713 :     ret = ustrp__dupx_buf(p, USTR__DUPX_FROM(*ps1), ustr_cstr(*ps1), clen);
    1558                 : 
    1559             200 :   if (!ret)
    1560              34 :     return (USTR_FALSE);
    1561                 :   
    1562             166 :   ustrp__sc_free2(p, ps1, ret);
    1563                 : 
    1564             166 :   return (USTR_TRUE);
    1565                 : }
    1566                 : USTR_CONF_I_PROTO int ustr_sc_ensure_owner(struct Ustr **ps1)
    1567              96 : { return (ustrp__sc_ensure_owner(0, ps1)); }
    1568                 : USTR_CONF_I_PROTO
    1569                 : int ustrp_sc_ensure_owner(struct Ustr_pool *p, struct Ustrp **ps1)
    1570              20 : {
    1571              20 :   struct Ustr *tmp = &(*ps1)->s;
    1572              20 :   int ret = ustrp__sc_ensure_owner(p, &tmp);
    1573              20 :   *ps1 = USTRP(tmp);
    1574              20 :   return (ret);
    1575                 : }
    1576                 : 
    1577                 : USTR_CONF_i_PROTO char *ustrp__sc_wstr(struct Ustr_pool *p, struct Ustr **ps1)
    1578              82 : {
    1579              82 :   if (!ustrp__sc_ensure_owner(p, ps1))
    1580              14 :     return (USTR_FALSE);
    1581                 : 
    1582              68 :   return (ustr_wstr(*ps1));
    1583                 : }
    1584                 : USTR_CONF_I_PROTO char *ustr_sc_wstr(struct Ustr **ps1)
    1585               8 : { return (ustrp__sc_wstr(0, ps1)); }
    1586                 : USTR_CONF_I_PROTO char *ustrp_sc_wstr(struct Ustr_pool *p, struct Ustrp **ps1)
    1587              10 : {
    1588              10 :   struct Ustr *tmp = &(*ps1)->s;
    1589              10 :   char *ret = ustrp__sc_wstr(p, &tmp);
    1590              10 :   *ps1 = USTRP(tmp);
    1591              10 :   return (ret);
    1592                 : }

Generated by: LTP GCOV extension version 1.4