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

       1                 : #define VSTR_SC_C
       2                 : /*
       3                 :  *  Copyright (C) 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                 : /* functions which are shortcuts */
      22                 : 
      23                 : #include "main.h"
      24                 : 
      25                 : int vstr_sc_fmt_cb_beg(Vstr_base *base, size_t *pos,
      26                 :                        Vstr_fmt_spec *spec, size_t *obj_len,
      27                 :                        unsigned int flags)
      28          145644 : {
      29          145644 :   char sign = 0;
      30          145644 :   size_t space_len = 0;
      31          145644 :   size_t zero_len = 0;
      32          145644 :   size_t xobj_len = 0;
      33          145644 :   size_t quote_len = 0;
      34          145644 :   int num_p = FALSE;
      35                 :   
      36          145644 :   if (flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR)
      37                 :   {
      38           29348 :     if (spec->fmt_precision && spec->fmt_field_width &&
      39                 :         (spec->obj_field_width > spec->obj_precision))
      40               5 :       spec->obj_field_width = spec->obj_precision;
      41                 : 
      42           29348 :     if (spec->fmt_precision && (*obj_len > spec->obj_precision))
      43              20 :       *obj_len = spec->obj_precision;
      44                 :   }
      45                 :   
      46          145644 :   if (!(flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NUM))
      47           61569 :     spec->fmt_zero = FALSE;
      48                 :   else
      49                 :   {
      50           84075 :     unsigned int num_base = 10;
      51                 : 
      52           84075 :     num_p = TRUE;
      53                 :     
      54           84075 :     if (0) { }
      55           84075 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, HEXNUM_L, HEXNUM_H))
      56            4716 :       num_base = 16;
      57           79359 :     else if (flags & VSTR_FLAG01(SC_FMT_CB_BEG_OBJ, OCTNUM))
      58            2318 :       num_base =  8;
      59           77041 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, BINNUM_L, BINNUM_H))
      60           49761 :       num_base =  2;
      61                 :       
      62           84075 :     if (!spec->fmt_hash)
      63           66846 :       flags &= ~VSTR_FLAG05(SC_FMT_CB_BEG_OBJ,
      64                 :                             HEXNUM_L, HEXNUM_H, OCTNUM, BINNUM_L, BINNUM_H);
      65                 :       
      66           84075 :     if (spec->fmt_quote) /* setup length with ',' additions properly */
      67                 :     {
      68            2884 :       quote_len  = vstr__add_fmt_grouping_num_sz(base, num_base, *obj_len);
      69            2884 :       quote_len -= *obj_len;
      70            2884 :       if (!quote_len) /* speed */
      71            1901 :         spec->fmt_quote = FALSE;
      72            2884 :       xobj_len += quote_len;
      73                 :     }
      74                 :     
      75           84075 :     if (flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NEG)
      76                 :     {
      77            1178 :       sign = '-';
      78            1178 :       ++xobj_len;
      79                 :     }
      80           82897 :     else if ((flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NUM) && spec->fmt_plus)
      81                 :     {
      82             300 :       sign = '+';
      83             300 :       ++xobj_len;
      84                 :     }
      85           82597 :     else if ((flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NUM) && spec->fmt_space)
      86                 :     {
      87              30 :       sign = ' ';
      88              30 :       ++xobj_len;
      89                 :     }
      90                 : 
      91           84075 :     if (0) { }
      92           84075 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, HEXNUM_L, HEXNUM_H))
      93            1814 :       xobj_len += 2;
      94           82261 :     else if (flags & VSTR_FLAG01(SC_FMT_CB_BEG_OBJ, OCTNUM))
      95             871 :       xobj_len += 1;
      96           81390 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, BINNUM_L, BINNUM_H))
      97           13220 :       xobj_len += 2;
      98                 : 
      99                 :     /* xtra object length's don't count with the precision */
     100           84075 :     if (spec->fmt_precision && ((*obj_len + quote_len) < spec->obj_precision))
     101                 :     {
     102           10719 :       spec->obj_precision -= (*obj_len + quote_len);
     103           10719 :       zero_len = spec->obj_precision;
     104           10719 :       spec->fmt_zero = FALSE;
     105                 :     }
     106                 :   }
     107                 :     
     108          145644 :   if (spec->fmt_field_width &&
     109                 :       ((*obj_len + xobj_len + zero_len) < spec->obj_field_width))
     110                 :   {
     111           57389 :     spec->obj_field_width -= (*obj_len + xobj_len + zero_len);
     112           57389 :     if (spec->fmt_zero)
     113            3339 :       zero_len  = spec->obj_field_width;
     114                 :     else
     115           54050 :       space_len = spec->obj_field_width;
     116                 :   }
     117                 :   else
     118           88255 :     spec->fmt_field_width = FALSE;
     119                 :   
     120          145644 :   if (!spec->fmt_minus && space_len)
     121                 :   {
     122           26098 :     if (!vstr_add_rep_chr(base, *pos, ' ', space_len))
     123            2623 :       return (FALSE);
     124           23475 :     *pos += space_len;
     125           23475 :     space_len = 0;
     126                 :   }
     127                 : 
     128          143021 :   if (num_p)
     129                 :   {
     130           81624 :     if (sign)
     131                 :     {
     132            1474 :       if (!vstr_add_rep_chr(base, *pos, sign, 1))
     133              36 :         return (FALSE);
     134            1438 :       ++*pos;
     135                 :     }
     136                 : 
     137           81588 :     if (0) { }
     138           81588 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, HEXNUM_L, HEXNUM_H))
     139                 :     {
     140            1814 :       char hexout = 'x';
     141                 :       
     142            1814 :       if (flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_HEXNUM_H)
     143             902 :         hexout = 'X';
     144                 :       
     145            1814 :       if (!vstr_add_rep_chr(base, *pos, '0', 1))
     146              48 :         return (FALSE);
     147            1766 :       ++*pos;
     148            1766 :       if (!vstr_add_rep_chr(base, *pos, hexout, 1))
     149              48 :         return (FALSE);
     150            1718 :       ++*pos;
     151                 :     }
     152           79774 :     else if (flags & VSTR_FLAG01(SC_FMT_CB_BEG_OBJ, OCTNUM))
     153                 :     {
     154             871 :       if (!vstr_add_rep_chr(base, *pos, '0', 1))
     155              24 :         return (FALSE);
     156             847 :       ++*pos;
     157                 :     }
     158           78903 :     else if (flags & VSTR_FLAG02(SC_FMT_CB_BEG_OBJ, BINNUM_L, BINNUM_H))
     159                 :     {
     160           13070 :       char binout = 'b';
     161                 :       
     162           13070 :       if (flags & VSTR_FLAG_SC_FMT_CB_BEG_OBJ_BINNUM_H)
     163            2402 :         binout = 'B';
     164                 :       
     165           13070 :       if (!vstr_add_rep_chr(base, *pos, '0', 1))
     166             189 :         return (FALSE);
     167           12881 :       ++*pos;
     168           12881 :       if (!vstr_add_rep_chr(base, *pos, binout, 1))
     169             180 :         return (FALSE);
     170           12701 :       ++*pos;
     171                 :     }
     172                 :     
     173           81099 :     if (zero_len)
     174                 :     {
     175           13506 :       if (!vstr_add_rep_chr(base, *pos, '0', zero_len))
     176            2374 :         return (FALSE);
     177           11132 :       *pos += zero_len;
     178           11132 :       zero_len = 0;
     179                 :     }
     180                 :   }
     181                 :   
     182          140122 :   spec->obj_precision    = quote_len;
     183          140122 :   spec->obj_field_width  = space_len;
     184                 : 
     185          140122 :   return (TRUE);
     186                 : }
     187                 : 
     188                 : int vstr_sc_fmt_cb_end(Vstr_base *base, size_t pos,
     189                 :                        Vstr_fmt_spec *spec, size_t obj_len)
     190          125393 : {
     191          125393 :   size_t space_len = 0;
     192                 : 
     193          125393 :   if (spec->fmt_field_width)
     194           40288 :     space_len += spec->obj_field_width;
     195                 : 
     196          125393 :   if (spec->fmt_quote) /* number grows */
     197             653 :     obj_len   += spec->obj_precision;
     198                 :   
     199          125393 :   if (spec->fmt_minus)
     200           22064 :     if (!vstr_add_rep_chr(base, pos + obj_len, ' ', space_len))
     201            3232 :       return (FALSE);
     202                 : 
     203          122161 :   return (TRUE);
     204                 : }
     205                 : 
     206                 : static int vstr__sc_fmt_add_cb_vstr(Vstr_base *base, size_t pos,
     207                 :                                     Vstr_fmt_spec *spec)
     208            1495 : {
     209            1495 :   Vstr_base *sf          = VSTR_FMT_CB_ARG_PTR(spec, 0);
     210            1495 :   size_t sf_pos          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     211            1495 :   size_t sf_len          = VSTR_FMT_CB_ARG_VAL(spec, size_t, 2);
     212            1495 :   unsigned int sf_flags  = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 3);
     213                 : 
     214            1495 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     215                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     216               3 :     return (FALSE);
     217                 : 
     218            1492 :   if (!vstr_add_vstr(base, pos, sf, sf_pos, sf_len, sf_flags))
     219               2 :     return (FALSE);
     220                 : 
     221            1490 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     222               3 :     return (FALSE);
     223                 : 
     224            1487 :   return (TRUE);
     225                 : }
     226                 : 
     227                 : int vstr_sc_fmt_add_vstr(Vstr_conf *conf, const char *name)
     228            6095 : {
     229            6095 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_vstr,
     230                 :                        VSTR_TYPE_FMT_PTR_VOID,
     231                 :                        VSTR_TYPE_FMT_SIZE_T,
     232                 :                        VSTR_TYPE_FMT_SIZE_T,
     233                 :                        VSTR_TYPE_FMT_UINT,
     234                 :                        VSTR_TYPE_FMT_END));
     235                 : }
     236                 : 
     237                 : static int vstr__sc_fmt_add_cb_buf(Vstr_base *base, size_t pos,
     238                 :                                    Vstr_fmt_spec *spec)
     239             446 : {
     240             446 :   const char *buf = VSTR_FMT_CB_ARG_PTR(spec, 0);
     241             446 :   size_t sf_len   = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     242                 : 
     243             446 :   if (!buf)
     244                 :   {
     245              15 :     buf = base->conf->loc->null_ref->ptr;
     246              15 :     if (sf_len > base->conf->loc->null_len)
     247              10 :       sf_len = base->conf->loc->null_len;
     248                 :   }
     249                 : 
     250             446 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     251                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     252               3 :     return (FALSE);
     253                 : 
     254             443 :   if (!vstr_add_buf(base, pos, buf, sf_len))
     255               3 :     return (FALSE);
     256                 : 
     257             440 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     258               3 :     return (FALSE);
     259                 : 
     260             437 :   return (TRUE);
     261                 : }
     262                 : 
     263                 : int vstr_sc_fmt_add_buf(Vstr_conf *conf, const char *name)
     264            5892 : {
     265            5892 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_buf,
     266                 :                        VSTR_TYPE_FMT_PTR_CHAR,
     267                 :                        VSTR_TYPE_FMT_SIZE_T,
     268                 :                        VSTR_TYPE_FMT_END));
     269                 : }
     270                 : 
     271                 : static int vstr__sc_fmt_add_cb_ptr(Vstr_base *base, size_t pos,
     272                 :                                    Vstr_fmt_spec *spec)
     273             422 : {
     274             422 :   const char *ptr = VSTR_FMT_CB_ARG_PTR(spec, 0);
     275             422 :   size_t sf_len   = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     276                 : 
     277             422 :   if (!ptr)
     278                 :   {
     279              15 :     ptr = base->conf->loc->null_ref->ptr;
     280              15 :     if (sf_len > base->conf->loc->null_len)
     281              10 :       sf_len = base->conf->loc->null_len;
     282                 :   }
     283                 : 
     284             422 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     285                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     286               3 :     return (FALSE);
     287                 : 
     288             419 :   if (!vstr_add_ptr(base, pos, ptr, sf_len))
     289               2 :     return (FALSE);
     290                 : 
     291             417 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     292               2 :     return (FALSE);
     293                 : 
     294             415 :   return (TRUE);
     295                 : }
     296                 : 
     297                 : int vstr_sc_fmt_add_ptr(Vstr_conf *conf, const char *name)
     298            5745 : {
     299            5745 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ptr,
     300                 :                        VSTR_TYPE_FMT_PTR_CHAR,
     301                 :                        VSTR_TYPE_FMT_SIZE_T,
     302                 :                        VSTR_TYPE_FMT_END));
     303                 : }
     304                 : 
     305                 : static int vstr__sc_fmt_add_cb_non(Vstr_base *base, size_t pos,
     306                 :                                    Vstr_fmt_spec *spec)
     307             400 : {
     308             400 :   size_t sf_len   = VSTR_FMT_CB_ARG_VAL(spec, size_t, 0);
     309                 : 
     310             400 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     311                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     312               3 :     return (FALSE);
     313                 : 
     314             397 :   if (!vstr_add_non(base, pos, sf_len))
     315               2 :     return (FALSE);
     316                 : 
     317             395 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     318               3 :     return (FALSE);
     319                 : 
     320             392 :   return (TRUE);
     321                 : }
     322                 : 
     323                 : int vstr_sc_fmt_add_non(Vstr_conf *conf, const char *name)
     324            5619 : {
     325            5619 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_non,
     326                 :                        VSTR_TYPE_FMT_SIZE_T,
     327                 :                        VSTR_TYPE_FMT_END));
     328                 : }
     329                 : 
     330                 : static int vstr__sc_fmt_add_cb_ref(Vstr_base *base, size_t pos,
     331                 :                                    Vstr_fmt_spec *spec)
     332             400 : {
     333             400 :   Vstr_ref *ref = VSTR_FMT_CB_ARG_PTR(spec, 0);
     334             400 :   size_t sf_off = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     335             400 :   size_t sf_len = VSTR_FMT_CB_ARG_VAL(spec, size_t, 2);
     336                 : 
     337             400 :   assert(ref);
     338                 : 
     339             400 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     340                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     341               3 :     return (FALSE);
     342                 : 
     343             397 :   if (!vstr_add_ref(base, pos, ref, sf_off, sf_len))
     344               2 :     return (FALSE);
     345                 : 
     346             395 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     347               3 :     return (FALSE);
     348                 : 
     349             392 :   return (TRUE);
     350                 : }
     351                 : 
     352                 : int vstr_sc_fmt_add_ref(Vstr_conf *conf, const char *name)
     353            8995 : {
     354            8995 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ref,
     355                 :                        VSTR_TYPE_FMT_PTR_VOID,
     356                 :                        VSTR_TYPE_FMT_SIZE_T,
     357                 :                        VSTR_TYPE_FMT_SIZE_T,
     358                 :                        VSTR_TYPE_FMT_END));
     359                 : }
     360                 : 
     361                 : static int vstr__sc_fmt_add_cb_rep_chr(Vstr_base *base, size_t pos,
     362                 :                                        Vstr_fmt_spec *spec)
     363             382 : {
     364             382 :   int chr       = VSTR_FMT_CB_ARG_VAL(spec, int, 0);
     365             382 :   size_t sf_len = VSTR_FMT_CB_ARG_VAL(spec, size_t, 1);
     366                 : 
     367             382 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &sf_len,
     368                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_STR))
     369               2 :     return (FALSE);
     370                 : 
     371             380 :   if (!vstr_add_rep_chr(base, pos, chr, sf_len))
     372               4 :     return (FALSE);
     373                 : 
     374             376 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     375               2 :     return (FALSE);
     376                 : 
     377             374 :   return (TRUE);
     378                 : }
     379                 : 
     380                 : int vstr_sc_fmt_add_rep_chr(Vstr_conf *conf, const char *name)
     381            5192 : {
     382            5192 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_rep_chr,
     383                 :                        VSTR_TYPE_FMT_INT,
     384                 :                        VSTR_TYPE_FMT_SIZE_T,
     385                 :                        VSTR_TYPE_FMT_END));
     386                 : }
     387                 : 
     388                 : #define BKMG_SWITCH() \
     389                 :     if (0) do { /* do nothing */ } while (FALSE)
     390                 : 
     391                 : #define BKMG_CASE(x, y)                              \
     392                 :     else if (bkmg >= val_ ## x )                     \
     393                 :       do                                             \
     394                 :       {                                              \
     395                 :         bkmg_whole = bkmg / val_ ## x ;              \
     396                 :         mov_dot_back = y;                            \
     397                 :         end_bkmg = buf_ ## x ;                       \
     398                 :       } while (FALSE)
     399                 : 
     400                 : #define BKMG_LEN_NUM(x, Ty, z) do {                  \
     401                 :       Ty bkmg_tmp = (z);                             \
     402                 :       x = 1;                                         \
     403                 :       while (bkmg_tmp >= 10)                         \
     404                 :       {                                              \
     405                 :         ++ x;                                        \
     406                 :         bkmg_tmp /= 10;                              \
     407                 :       }                                              \
     408                 :     } while (FALSE)
     409                 : 
     410                 : 
     411                 : static int vstr__sc_fmt_add_cb_bkmg__beg(Vstr_base *base, size_t *pos,
     412                 :                                          Vstr_fmt_spec *spec, size_t *sf_len,
     413                 :                                          unsigned int val_len,
     414                 :                                          unsigned int mov_dot_back,
     415                 :                                          const char *end_bkmg,
     416                 :                                          unsigned int *ret_prec,
     417                 :                                          char buf_dot[2])
     418           23503 : {
     419           23503 :   unsigned int prec = 0;
     420                 :   
     421                 :   /* NOTE: hard to do due to . and , -- change cb_beg ?
     422                 :    *       shouldn't trigger anyway */
     423           23503 :   spec->fmt_quote = FALSE;
     424                 :   
     425           23503 :   if (spec->fmt_precision)
     426             216 :     prec = spec->obj_precision;
     427                 :   else
     428           23287 :     prec = 2;
     429           23503 :   spec->fmt_precision = FALSE; /* for cb_beg */
     430                 :   
     431           23503 :   if (prec > mov_dot_back)
     432           20545 :     prec = mov_dot_back;
     433                 : 
     434                 :   /* One of...
     435                 :    * NNN '.' N+ end_bkmg
     436                 :    * NNN        end_bkmg */
     437           23503 :   *sf_len = val_len + !!prec + prec + strlen(end_bkmg);
     438                 :   
     439           23503 :   if (!vstr_sc_fmt_cb_beg(base, pos, spec, sf_len,
     440                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NUM))
     441               7 :     return (FALSE);
     442                 :   
     443           23496 :   if (prec)
     444            2846 :     buf_dot[0] = '.';
     445                 : 
     446           23496 :   *ret_prec = prec;
     447                 : 
     448           23496 :   return (TRUE);
     449                 : }
     450                 : 
     451                 : static int vstr__sc_fmt_add_cb_bkmg__end(Vstr_base *base, size_t pos,
     452                 :                                          Vstr_fmt_spec *spec, size_t sf_len,
     453                 :                                          unsigned int val_len,
     454                 :                                          unsigned int mov_dot_back,
     455                 :                                          unsigned int prec,
     456                 :                                          unsigned int num_added)
     457           23455 : {
     458           23455 :   size_t num_keep = 0;
     459                 :   
     460           23455 :   assert(val_len == (num_added - mov_dot_back));
     461           23455 :   assert(num_added >= val_len);
     462           23455 :   assert(num_added > mov_dot_back);
     463                 : 
     464           23455 :   if (prec && !vstr_mov(base, pos + val_len,
     465                 :                         base, pos + num_added + 1, 1))
     466              12 :     return (FALSE);
     467                 : 
     468           23443 :   num_keep = val_len + prec;
     469           23443 :   if (num_added > num_keep)
     470            2898 :     vstr_del(base, pos + 1 + num_keep + !!prec, (num_added - num_keep));
     471                 : 
     472           23443 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, sf_len))
     473               3 :     return (FALSE);
     474                 : 
     475           23440 :   return (TRUE);
     476                 : }
     477                 : 
     478                 : static int vstr__sc_fmt_add_cb_bkmg__uint(Vstr_base *base, size_t pos,
     479                 :                                           Vstr_fmt_spec *spec,
     480                 :                                           const char *buf_B,
     481                 :                                           const char *buf_K,
     482                 :                                           const char *buf_M,
     483                 :                                           const char *buf_G)
     484             175 : {
     485             175 :   const unsigned int val_K = (1000);
     486             175 :   const unsigned int val_M = (1000 * 1000);
     487             175 :   const unsigned int val_G = (1000 * 1000 * 1000);
     488             175 :   unsigned int bkmg = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 0);
     489             175 :   unsigned int bkmg_whole = bkmg;
     490             175 :   unsigned int val_len = 0;
     491             175 :   size_t sf_len = SIZE_MAX;
     492             175 :   const char *end_bkmg = buf_B;
     493             175 :   unsigned int num_added = 0;
     494             175 :   unsigned int mov_dot_back = 0;
     495             175 :   unsigned int prec = 0;
     496             175 :   char buf_dot[2] = {0, 0};
     497             175 :   int num_iadded = 0;
     498                 :   
     499             175 :   assert(strlen(buf_B) <= strlen(buf_M));
     500             175 :   assert(strlen(buf_K) == strlen(buf_M));
     501             175 :   assert(strlen(buf_K) == strlen(buf_G));
     502                 : 
     503             175 :   BKMG_SWITCH();
     504             175 :   BKMG_CASE(G,  9);
     505              98 :   BKMG_CASE(M,  6);
     506              60 :   BKMG_CASE(K,  3);
     507                 : 
     508             175 :   BKMG_LEN_NUM(val_len, unsigned int, bkmg_whole);
     509                 : 
     510             175 :   if (!vstr__sc_fmt_add_cb_bkmg__beg(base, &pos, spec, &sf_len, val_len,
     511                 :                                      mov_dot_back, end_bkmg, &prec, buf_dot))
     512               3 :     return (FALSE);
     513                 :   
     514             172 :   if (!vstr_add_sysfmt(base, pos, "%u%n%s%s", bkmg, &num_iadded,
     515                 :                        buf_dot, end_bkmg))
     516              14 :     return (FALSE);
     517             158 :   num_added = num_iadded;
     518                 : 
     519             158 :   return (vstr__sc_fmt_add_cb_bkmg__end(base, pos, spec, sf_len, val_len,
     520                 :                                         mov_dot_back, prec, num_added));
     521                 : }
     522                 : 
     523                 : static int vstr__sc_fmt_add_cb_bkmg__uintmax(Vstr_base *base, size_t pos,
     524                 :                                              Vstr_fmt_spec *spec,
     525                 :                                              const char *buf_B,
     526                 :                                              const char *buf_K,
     527                 :                                              const char *buf_M,
     528                 :                                              const char *buf_G,
     529                 :                                              const char *buf_T,
     530                 :                                              const char *buf_P,
     531                 :                                              const char *buf_E)
     532           23328 : {
     533           23328 :   const unsigned int val_K = (1000U);
     534           23328 :   const unsigned int val_M = (1000U * 1000U);
     535           23328 :   const unsigned int val_G = (1000U * 1000U * 1000U);
     536           23328 :   const uintmax_t    val_T = (1000ULL * val_G);
     537           23328 :   const uintmax_t    val_P = (1000ULL * val_T);
     538           23328 :   const uintmax_t    val_E = (1000ULL * val_P);
     539           23328 :   uintmax_t bkmg = VSTR_FMT_CB_ARG_VAL(spec, uintmax_t, 0);
     540           23328 :   uintmax_t bkmg_whole = bkmg;
     541           23328 :   unsigned int val_len = 0;
     542           23328 :   size_t sf_len = SIZE_MAX;
     543           23328 :   const char *end_bkmg = buf_B;
     544           23328 :   unsigned int num_added = 0;
     545           23328 :   unsigned int mov_dot_back = 0;
     546           23328 :   unsigned int prec = 0;
     547           23328 :   char buf_dot[2] = {0, 0};
     548           23328 :   int num_iadded = 0;
     549                 : 
     550           23328 :   assert(strlen(buf_B) <= strlen(buf_M));
     551           23328 :   assert(strlen(buf_K) == strlen(buf_M));
     552           23328 :   assert(strlen(buf_K) == strlen(buf_G));
     553           23328 :   assert(strlen(buf_K) == strlen(buf_T));
     554           23328 :   assert(strlen(buf_K) == strlen(buf_P));
     555           23328 :   assert(strlen(buf_K) == strlen(buf_E));
     556                 : 
     557           23328 :   BKMG_SWITCH();
     558           23328 :   BKMG_CASE(E, 18);
     559           23303 :   BKMG_CASE(P, 15);
     560           23252 :   BKMG_CASE(T, 12);
     561           23215 :   BKMG_CASE(G,  9);
     562           23200 :   BKMG_CASE(M,  6);
     563           22975 :   BKMG_CASE(K,  3);
     564                 : 
     565           23328 :   BKMG_LEN_NUM(val_len, uintmax_t, bkmg_whole);
     566                 :   
     567           23328 :   if (!vstr__sc_fmt_add_cb_bkmg__beg(base, &pos, spec, &sf_len, val_len,
     568                 :                                      mov_dot_back, end_bkmg, &prec, buf_dot))
     569               4 :     return (FALSE);
     570                 :   
     571           23324 :   if (!vstr_add_sysfmt(base, pos, "%ju%n%s%s", bkmg, &num_iadded,
     572                 :                        buf_dot, end_bkmg))
     573              27 :     return (FALSE);
     574           23297 :   num_added = num_iadded;
     575                 : 
     576           23297 :   return (vstr__sc_fmt_add_cb_bkmg__end(base, pos, spec, sf_len, val_len,
     577                 :                                         mov_dot_back, prec, num_added));
     578                 : }
     579                 : 
     580                 : static int vstr__sc_fmt_add_cb_bkmg_Byte_uint(Vstr_base *base, size_t pos,
     581                 :                                               Vstr_fmt_spec *spec)
     582             106 : {
     583             106 :   return (vstr__sc_fmt_add_cb_bkmg__uint(base, pos, spec,
     584                 :                                          "B", "KB", "MB", "GB"));
     585                 : }
     586                 : 
     587                 : int vstr_sc_fmt_add_bkmg_Byte_uint(Vstr_conf *conf, const char *name)
     588            5066 : {
     589            5066 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_Byte_uint,
     590                 :                        VSTR_TYPE_FMT_UINT,
     591                 :                        VSTR_TYPE_FMT_END));
     592                 : }
     593                 : 
     594                 : static int vstr__sc_fmt_add_cb_bkmg_Bytes_uint(Vstr_base *base, size_t pos,
     595                 :                                                Vstr_fmt_spec *spec)
     596              24 : {
     597              24 :   return (vstr__sc_fmt_add_cb_bkmg__uint(base, pos, spec,
     598                 :                                          "B/s", "KB/s", "MB/s", "GB/s"));
     599                 : }
     600                 : 
     601                 : int vstr_sc_fmt_add_bkmg_Bytes_uint(Vstr_conf *conf, const char *name)
     602            4968 : {
     603            4968 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_Bytes_uint,
     604                 :                        VSTR_TYPE_FMT_UINT,
     605                 :                        VSTR_TYPE_FMT_END));
     606                 : }
     607                 : 
     608                 : static int vstr__sc_fmt_add_cb_bkmg_bit_uint(Vstr_base *base, size_t pos,
     609                 :                                              Vstr_fmt_spec *spec)
     610              30 : {
     611              30 :   return (vstr__sc_fmt_add_cb_bkmg__uint(base, pos, spec,
     612                 :                                          "b", "Kb", "Mb", "Gb"));
     613                 : }
     614                 : 
     615                 : int vstr_sc_fmt_add_bkmg_bit_uint(Vstr_conf *conf, const char *name)
     616            4870 : {
     617            4870 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_bit_uint,
     618                 :                        VSTR_TYPE_FMT_UINT,
     619                 :                        VSTR_TYPE_FMT_END));
     620                 : }
     621                 : 
     622                 : static int vstr__sc_fmt_add_cb_bkmg_bits_uint(Vstr_base *base, size_t pos,
     623                 :                                               Vstr_fmt_spec *spec)
     624              15 : {
     625              15 :   return (vstr__sc_fmt_add_cb_bkmg__uint(base, pos, spec,
     626                 :                                          "b/s", "Kb/s", "Mb/s", "Gb/s"));
     627                 : }
     628                 : 
     629                 : int vstr_sc_fmt_add_bkmg_bits_uint(Vstr_conf *conf, const char *name)
     630            4772 : {
     631            4772 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_bits_uint,
     632                 :                        VSTR_TYPE_FMT_UINT,
     633                 :                        VSTR_TYPE_FMT_END));
     634                 : }
     635                 : 
     636                 : /* intmax */
     637                 : 
     638                 : static int vstr__sc_fmt_add_cb_bkmg_Byte_uintmax(Vstr_base *base, size_t pos,
     639                 :                                                  Vstr_fmt_spec *spec)
     640           23264 : {
     641           23264 :   return (vstr__sc_fmt_add_cb_bkmg__uintmax(base, pos, spec, "B",
     642                 :                                             "KB", "MB", "GB",
     643                 :                                             "TB", "PB", "EB"));
     644                 : }
     645                 : 
     646                 : int vstr_sc_fmt_add_bkmg_Byte_uintmax(Vstr_conf *conf, const char *name)
     647            4674 : {
     648            4674 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_Byte_uintmax,
     649                 :                        VSTR_TYPE_FMT_UINTMAX_T,
     650                 :                        VSTR_TYPE_FMT_END));
     651                 : }
     652                 : 
     653                 : static int vstr__sc_fmt_add_cb_bkmg_Bytes_uintmax(Vstr_base *base, size_t pos,
     654                 :                                                   Vstr_fmt_spec *spec)
     655              22 : {
     656              22 :   return (vstr__sc_fmt_add_cb_bkmg__uintmax(base, pos, spec, "B/s",
     657                 :                                             "KB/s", "MB/s", "GB/s",
     658                 :                                             "TB/s", "PB/s", "EB/s"));
     659                 : }
     660                 : 
     661                 : int vstr_sc_fmt_add_bkmg_Bytes_uintmax(Vstr_conf *conf, const char *name)
     662            4576 : {
     663            4576 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_Bytes_uintmax,
     664                 :                        VSTR_TYPE_FMT_UINTMAX_T,
     665                 :                        VSTR_TYPE_FMT_END));
     666                 : }
     667                 : 
     668                 : static int vstr__sc_fmt_add_cb_bkmg_bit_uintmax(Vstr_base *base, size_t pos,
     669                 :                                                 Vstr_fmt_spec *spec)
     670              15 : {
     671              15 :   return (vstr__sc_fmt_add_cb_bkmg__uintmax(base, pos, spec, "b",
     672                 :                                             "Kb", "Mb", "Gb",
     673                 :                                             "Tb", "Pb", "Eb"));
     674                 : }
     675                 : 
     676                 : int vstr_sc_fmt_add_bkmg_bit_uintmax(Vstr_conf *conf, const char *name)
     677            4478 : {
     678            4478 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_bit_uintmax,
     679                 :                        VSTR_TYPE_FMT_UINTMAX_T,
     680                 :                        VSTR_TYPE_FMT_END));
     681                 : }
     682                 : 
     683                 : static int vstr__sc_fmt_add_cb_bkmg_bits_uintmax(Vstr_base *base, size_t pos,
     684                 :                                                  Vstr_fmt_spec *spec)
     685              27 : {
     686              27 :   return (vstr__sc_fmt_add_cb_bkmg__uintmax(base, pos, spec, "b/s",
     687                 :                                             "Kb/s", "Mb/s", "Gb/s",
     688                 :                                             "Tb/s", "Pb/s", "Eb/s"));
     689                 : }
     690                 : 
     691                 : int vstr_sc_fmt_add_bkmg_bits_uintmax(Vstr_conf *conf, const char *name)
     692            4380 : {
     693            4380 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_bkmg_bits_uintmax,
     694                 :                        VSTR_TYPE_FMT_UINTMAX_T,
     695                 :                        VSTR_TYPE_FMT_END));
     696                 : }
     697                 : 
     698                 : static unsigned int vstr__sc_fmt_num10_len(unsigned int num)
     699            7347 : { /* could use the log10() trick, but then we'd have to link in the math
     700                 :    * library */
     701            7347 :   unsigned int ret = 0;
     702                 : 
     703           22811 :   while (num > 0)
     704                 :   {
     705           15464 :     num /= 10;
     706           15464 :     ++ret;
     707                 :   }
     708                 : 
     709            7347 :   if (!ret) return (1); /* 0 == one character */
     710                 : 
     711            6290 :   return (ret);
     712                 : }
     713                 : 
     714                 : static unsigned int vstr__sc_fmt_num16_len(unsigned int num)
     715            8432 : {
     716            8432 :   ASSERT(num < 0x00010000);
     717                 :   /*
     718                 :     if (num & 0xF0000000) return (8);
     719                 :     if (num & 0x0F000000) return (7);
     720                 :     if (num & 0x00F00000) return (6);
     721                 :     if (num & 0x000F0000) return (5);
     722                 :   */
     723                 :   
     724            8432 :   if (num & 0x0000F000) return (4);
     725            7590 :   if (num & 0x00000F00) return (3);
     726            7051 :   if (num & 0x000000F0) return (2);
     727            5494 :   if (num & 0x0000000F) return (1);
     728                 : 
     729            2915 :   return (1);
     730                 : }
     731                 : 
     732                 : /*
     733                 :  * Note that :: expansion at either end doesn't remove as many characters...
     734                 :  *
     735                 :  * 1. a:a:a:a:b:b:b:b -> a:a:a:a:b:b:b:b
     736                 :  * 2. a:a:a:a:b:b:b:0 -> a:a:a:a:b:b:b::
     737                 :  * 3. a:a:a:a:b:b:0:0 -> a:a:a:a:b:b::
     738                 :  * 4. 0:0:a:a:b:b:b:b -> ::a:a:b:b:b:b
     739                 :  * 5. 0:a:a:a:b:b:b:b -> ::a:a:a:b:b:b:b
     740                 :  * 6. a:a:a:0:0:b:b:b -> a:a:a::b:b:b
     741                 :  *
     742                 :  * ...it's not obvious if you should change in the 2nd and 5th cases.
     743                 :  *
     744                 :  */
     745                 : static unsigned int vstr__sc_fmt_num_ipv6_compact(unsigned int *ips,
     746                 :                                                   unsigned int max_num,
     747                 :                                                   size_t *pos)
     748             916 : {
     749             916 :   unsigned int scan = 0;
     750             916 :   unsigned int ret_max = 0;
     751             916 :   unsigned int ret_cur = 0;
     752             916 :   int atend = 0;
     753                 : 
     754            7144 :   while (scan < max_num)
     755                 :   {
     756            6228 :     if (!ips[scan])
     757            2152 :       ++ret_cur;
     758                 :     else
     759                 :     {
     760            4076 :       if ((ret_cur > ret_max) ||
     761                 :           ((ret_cur == ret_max) && (ret_cur != scan) && atend))
     762                 :       {
     763             921 :         if (ret_cur == scan)
     764             486 :           atend = 1;
     765                 :         else
     766             435 :           atend = 0;
     767             921 :         *pos = scan - ret_cur;
     768             921 :         ret_max = ret_cur;
     769                 :       }
     770            4076 :       ret_cur = 0;
     771                 :     }
     772                 : 
     773            6228 :     ++scan;
     774                 :   }
     775             916 :   if (ret_cur == scan)
     776              15 :     atend = 1;
     777             916 :   if (ret_cur > ret_max)
     778                 :   {
     779              50 :     atend += 1;
     780              50 :     ret_max = ret_cur;
     781              50 :     *pos = scan - ret_cur;
     782                 :   }
     783                 : 
     784             916 :   return (!ret_max ? 0 : (1 + ((ret_max - 1) * 2) - atend));
     785                 : }
     786                 : 
     787                 : static int vstr__sc_fmt_add_cb_ipv4_vec(Vstr_base *base, size_t pos,
     788                 :                                         Vstr_fmt_spec *spec)
     789             389 : {
     790             389 :   unsigned int *ips = VSTR_FMT_CB_ARG_PTR(spec, 0);
     791             389 :   size_t len = 0;
     792                 : 
     793             389 :   assert((ips[0] <= 255) && (ips[1] <= 255) &&
     794                 :          (ips[2] <= 255) && (ips[3] <= 255));
     795                 : 
     796             389 :   len = (vstr__sc_fmt_num10_len(ips[0]) + vstr__sc_fmt_num10_len(ips[1]) +
     797                 :          vstr__sc_fmt_num10_len(ips[2]) + vstr__sc_fmt_num10_len(ips[3]) + 3);
     798                 : 
     799             389 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &len,
     800                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
     801              16 :     return (FALSE);
     802                 : 
     803             373 :   if (!vstr_add_fmt(base, pos, "%u.%u.%u.%u",
     804                 :                     ips[0], ips[1], ips[2], ips[3]))
     805               7 :     return (FALSE);
     806                 : 
     807             366 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, len))
     808              16 :     return (FALSE);
     809                 : 
     810             350 :   return (TRUE);
     811                 : }
     812                 : 
     813                 : int vstr_sc_fmt_add_ipv4_vec(Vstr_conf *conf, const char *name)
     814            4086 : {
     815            4086 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv4_vec,
     816                 :                        VSTR_TYPE_FMT_PTR_VOID,
     817                 :                        VSTR_TYPE_FMT_END));
     818                 : }
     819                 : 
     820                 : static unsigned int vstr__sc_fmt_num_ipv6_std(unsigned int *ips,
     821                 :                                               unsigned int max_num)
     822            1205 : {
     823            1205 :   unsigned int scan = 0;
     824            1205 :   unsigned int ret = 0;
     825                 : 
     826            9637 :   while (scan < max_num)
     827                 :   {
     828            8432 :     ret += vstr__sc_fmt_num16_len(ips[scan]);
     829            8432 :     ++scan;
     830                 :   }
     831                 : 
     832            1205 :   return (ret);
     833                 : }
     834                 : 
     835                 : static int vstr__sc_fmt_num_ipv6(unsigned int *ips, unsigned int type,
     836                 :                                  size_t *pos_compact, size_t *ret_len)
     837            1989 : {
     838            1989 :   size_t len = 0;
     839                 : 
     840            1989 :   assert((ips[0] <= 0xFFFF) && (ips[1] <= 0xFFFF) &&
     841                 :          (ips[2] <= 0xFFFF) && (ips[3] <= 0xFFFF) &&
     842                 :          (ips[4] <= 0xFFFF) && (ips[5] <= 0xFFFF) &&
     843                 :          (ips[6] <= 0xFFFF) && (ips[7] <= 0xFFFF));
     844                 : 
     845            1989 :   switch (type)
     846                 :   {
     847                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_ALIGNED:
     848             636 :       len = 7 + 4*8; break;
     849                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_STD:
     850             235 :       len = (vstr__sc_fmt_num_ipv6_std(ips, 8) + 7); break;
     851                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_COMPACT:
     852                 :     {
     853             366 :       size_t len_minus = vstr__sc_fmt_num_ipv6_compact(ips, 8, pos_compact);
     854             366 :       len = (vstr__sc_fmt_num_ipv6_std(ips, 8) + 7 - len_minus);
     855                 :     }
     856             366 :     break;
     857                 :     
     858                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_ALIGNED:
     859                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_STD:
     860                 :     case VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_COMPACT:
     861                 :     {
     862             744 :       if (0) { }
     863             744 :       else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_ALIGNED)
     864             140 :         len = 6 + 4*6;
     865             604 :       else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_STD)
     866              54 :         len = (vstr__sc_fmt_num_ipv6_std(ips, 6) + 6);
     867             550 :       else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_COMPACT)
     868                 :       {
     869             550 :         size_t len_minus = vstr__sc_fmt_num_ipv6_compact(ips, 6, pos_compact);
     870             550 :         len = (vstr__sc_fmt_num_ipv6_std(ips, 6) + 6 - len_minus);
     871                 :       }
     872                 :       
     873                 :       /* add the ipv4 address on the end using the last 2 16bit entities */
     874             744 :       len += vstr__sc_fmt_num10_len((ips[6] >> 8) & 0xFF);
     875             744 :       len += vstr__sc_fmt_num10_len((ips[6] >> 0) & 0xFF);
     876             744 :       len += vstr__sc_fmt_num10_len((ips[7] >> 8) & 0xFF);
     877             744 :       len += vstr__sc_fmt_num10_len((ips[7] >> 0) & 0xFF);
     878             744 :       len += 3;
     879                 :     }
     880             744 :     break;
     881                 : 
     882                 :     default:
     883               8 :       ASSERT_RET(FALSE, FALSE);
     884                 :   }
     885                 : 
     886            1981 :   *ret_len = len;
     887                 : 
     888            1981 :   return (TRUE);
     889                 : }
     890                 : 
     891                 : static int vstr__sc_fmt_prnt_ipv6_compact(Vstr_base *base, size_t pos,
     892                 :                                           unsigned int *ips,
     893                 :                                           unsigned int max_num,
     894                 :                                           size_t pos_compact)
     895             892 : {
     896             892 :   unsigned int scan = 0;
     897             892 :   int done = FALSE;
     898                 : 
     899            5439 :   while (scan < max_num)
     900                 :   {
     901            4708 :     int len = 0;
     902                 : 
     903            4708 :     if (scan == pos_compact)
     904                 :     {
     905            1513 :       assert(!ips[scan]);
     906            2765 :       while ((scan < max_num) && !ips[scan])
     907            1900 :         ++scan;
     908                 : 
     909             865 :       if (!vstr_add_rep_chr(base, pos, ':', 2))
     910              34 :         return (FALSE);
     911             831 :       pos += 2;
     912                 : 
     913             831 :       done = FALSE;
     914             831 :       continue;
     915                 :     }
     916                 : 
     917            3843 :     if (!vstr_add_fmt(base, pos, "%s%X%n", done ? ":" : "", ips[scan], &len))
     918             127 :       return (FALSE);
     919            3716 :     pos += len;
     920                 : 
     921            3716 :     done = TRUE;
     922            3716 :     ++scan;
     923                 :   }
     924                 : 
     925             731 :   if ((max_num != 8) && done) /* NOTE: hack to make sure the string ends
     926                 :                                * in a ':' character for the ipv4 part */
     927             384 :     if (!vstr_add_rep_chr(base, pos, ':', 1))
     928              16 :       return (FALSE);
     929                 : 
     930             715 :   return (TRUE);
     931                 : }
     932                 : 
     933                 : static int vstr__sc_fmt_prnt_ipv6(Vstr_base *base, size_t pos,
     934                 :                                   unsigned int type,
     935                 :                                   unsigned int *ips,
     936                 :                                   size_t pos_compact)
     937            1908 : {
     938            1908 :   size_t orig_len = base->len;
     939                 : 
     940            1908 :   if (0) { }
     941            1908 :   else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_ALIGNED)
     942                 :   {
     943             133 :     if (!vstr_add_fmt(base, pos, "%04X:%04X:%04X:%04X:%04X:%04X:",
     944                 :                       ips[0], ips[1], ips[2], ips[3],
     945                 :                       ips[4], ips[5]))
     946              15 :       return (FALSE);
     947                 :   }
     948            1775 :   else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_STD)
     949                 :   {
     950             223 :     if (!vstr_add_fmt(base, pos, "%X:%X:%X:%X:%X:%X:%X:%X",
     951                 :                       ips[0], ips[1], ips[2], ips[3],
     952                 :                       ips[4], ips[5], ips[6], ips[7]))
     953              12 :       return (FALSE);
     954                 :   }
     955            1552 :   else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_STD)
     956                 :   {
     957              43 :     if (!vstr_add_fmt(base, pos, "%X:%X:%X:%X:%X:%X:",
     958                 :                       ips[0], ips[1], ips[2], ips[3],
     959                 :                       ips[4], ips[5]))
     960               7 :       return (FALSE);
     961                 :   }
     962            1509 :   else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_COMPACT)
     963                 :   {
     964             353 :     if (!vstr__sc_fmt_prnt_ipv6_compact(base, pos, ips, 8, pos_compact))
     965              11 :       return (FALSE);
     966                 :   }
     967            1156 :   else if (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_COMPACT)
     968                 :   {
     969             539 :     if (!vstr__sc_fmt_prnt_ipv6_compact(base, pos, ips, 6, pos_compact))
     970             166 :       return (FALSE);
     971                 :   }
     972                 :   else /* if (type == VSTR_TYPE_SC_FMT_CB_IPV6_ALIGNED) */
     973                 :   { /* always last ... so prints with screwed types */
     974             617 :     if (!vstr_add_fmt(base, pos, "%04X:%04X:%04X:%04X:%04X:%04X:%04X:%04X",
     975                 :                       ips[0], ips[1], ips[2], ips[3],
     976                 :                       ips[4], ips[5], ips[6], ips[7]))
     977              37 :       return (FALSE);
     978                 :   }
     979                 : 
     980            1660 :   pos += base->len - orig_len;
     981                 : 
     982            1660 :   if ((type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_ALIGNED) ||
     983                 :       (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_STD) ||
     984                 :       (type == VSTR_TYPE_SC_FMT_CB_IPV6_IPV4_COMPACT))
     985             527 :     if (!vstr_add_fmt(base, pos, "%u.%u.%u.%u",
     986                 :                       (ips[6] >> 8) & 0xFF, (ips[6] >> 0) & 0xFF,
     987                 :                       (ips[7] >> 8) & 0xFF, (ips[7] >> 0) & 0xFF))
     988             136 :       return (FALSE);
     989                 : 
     990            1524 :   return (TRUE);
     991                 : }
     992                 : 
     993                 : static int vstr__sc_fmt_add_cb_ipv6_vec(Vstr_base *base, size_t pos,
     994                 :                                         Vstr_fmt_spec *spec)
     995             730 : {
     996             730 :   unsigned int *ips = VSTR_FMT_CB_ARG_PTR(spec, 0);
     997             730 :   unsigned int type = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 1);
     998             730 :   size_t len = 0;
     999             730 :   size_t pos_compact = 9;
    1000                 : 
    1001             730 :   if (!vstr__sc_fmt_num_ipv6(ips, type, &pos_compact, &len))
    1002               4 :     return (FALSE);
    1003                 : 
    1004             726 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &len,
    1005                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
    1006              10 :     return (FALSE);
    1007                 : 
    1008             716 :   if (!vstr__sc_fmt_prnt_ipv6(base, pos, type, ips, pos_compact))
    1009             154 :     return (FALSE);
    1010                 : 
    1011             562 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, len))
    1012              10 :     return (FALSE);
    1013                 : 
    1014             552 :   return (TRUE);
    1015                 : }
    1016                 : 
    1017                 : int vstr_sc_fmt_add_ipv6_vec(Vstr_conf *conf, const char *name)
    1018            3967 : {
    1019            3967 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv6_vec,
    1020                 :                        VSTR_TYPE_FMT_PTR_VOID,
    1021                 :                        VSTR_TYPE_FMT_UINT,
    1022                 :                        VSTR_TYPE_FMT_END));
    1023                 : }
    1024                 : 
    1025                 : static int vstr__sc_fmt_add_cb_ipv4_vec_cidr(Vstr_base *base, size_t pos,
    1026                 :                                              Vstr_fmt_spec *spec)
    1027             312 : {
    1028             312 :   unsigned int *ips = VSTR_FMT_CB_ARG_PTR(spec, 0);
    1029             312 :   unsigned int cidr = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 1);
    1030             312 :   size_t len = 0;
    1031                 : 
    1032             312 :   assert((ips[0] <= 255) && (ips[1] <= 255) &&
    1033                 :          (ips[2] <= 255) && (ips[3] <= 255) && (cidr <= 32));
    1034                 : 
    1035             312 :   len = (vstr__sc_fmt_num10_len(ips[0]) + vstr__sc_fmt_num10_len(ips[1]) +
    1036                 :          vstr__sc_fmt_num10_len(ips[2]) + vstr__sc_fmt_num10_len(ips[3]) +
    1037                 :          vstr__sc_fmt_num10_len(cidr) + 4);
    1038                 : 
    1039             312 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &len,
    1040                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
    1041              15 :     return (FALSE);
    1042                 : 
    1043             297 :   if (!vstr_add_fmt(base, pos, "%u.%u.%u.%u/%u",
    1044                 :                     ips[0], ips[1], ips[2], ips[3], cidr))
    1045               8 :     return (FALSE);
    1046                 : 
    1047             289 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, len))
    1048              15 :     return (FALSE);
    1049                 : 
    1050             274 :   return (TRUE);
    1051                 : }
    1052                 : 
    1053                 : int vstr_sc_fmt_add_ipv4_vec_cidr(Vstr_conf *conf, const char *name)
    1054            3820 : {
    1055            3820 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv4_vec_cidr,
    1056                 :                        VSTR_TYPE_FMT_PTR_VOID,
    1057                 :                        VSTR_TYPE_FMT_UINT,
    1058                 :                        VSTR_TYPE_FMT_END));
    1059                 : }
    1060                 : 
    1061                 : static int vstr__sc_fmt_add_cb_ipv6_vec_cidr(Vstr_base *base, size_t pos,
    1062                 :                                              Vstr_fmt_spec *spec)
    1063            1259 : {
    1064            1259 :   unsigned int *ips = VSTR_FMT_CB_ARG_PTR(spec, 0);
    1065            1259 :   unsigned int type = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 1);
    1066            1259 :   unsigned int cidr = VSTR_FMT_CB_ARG_VAL(spec, unsigned int, 2);
    1067            1259 :   size_t len = 0;
    1068            1259 :   size_t saved_len = 0;
    1069            1259 :   size_t pos_compact = 9;
    1070            1259 :   size_t orig_len = 0;
    1071                 : 
    1072            1259 :   assert(cidr <= 128);
    1073                 : 
    1074            1259 :   if (!vstr__sc_fmt_num_ipv6(ips, type, &pos_compact, &len))
    1075               4 :     return (FALSE);
    1076                 :   
    1077            1255 :   len += 1 + vstr__sc_fmt_num10_len(cidr);
    1078            1255 :   saved_len = len;
    1079                 :   
    1080            1255 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &len,
    1081                 :                           VSTR_FLAG_SC_FMT_CB_BEG_OBJ_ATOM))
    1082              63 :     return (FALSE);
    1083                 : 
    1084            1192 :   orig_len = base->len;
    1085            1192 :   if (!vstr__sc_fmt_prnt_ipv6(base, pos, type, ips, pos_compact))
    1086             230 :     return (FALSE);
    1087             962 :   if (!vstr_add_fmt(base, pos + (base->len - orig_len), "/%u", cidr))
    1088              34 :     return (FALSE);
    1089             928 :   ASSERT((base->len - orig_len) == saved_len);
    1090                 :   
    1091             928 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, len))
    1092              63 :     return (FALSE);
    1093                 : 
    1094             865 :   return (TRUE);
    1095                 : }
    1096                 : 
    1097                 : int vstr_sc_fmt_add_ipv6_vec_cidr(Vstr_conf *conf, const char *name)
    1098            3652 : {
    1099            3652 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_ipv6_vec_cidr,
    1100                 :                        VSTR_TYPE_FMT_PTR_VOID,
    1101                 :                        VSTR_TYPE_FMT_UINT,
    1102                 :                        VSTR_TYPE_FMT_UINT,
    1103                 :                        VSTR_TYPE_FMT_END));
    1104                 : }
    1105                 : 
    1106                 : #define VSTR__SC_FMT_MAKE_CB_BASE2(T, Tn, up) \
    1107                 :   T val = VSTR_FMT_CB_ARG_VAL(spec, T, 0); \
    1108                 :   int flags = (VSTR_FLAG_SC_FMT_CB_BEG_OBJ_NUM | \
    1109                 :                ((up) ? \
    1110                 :                 VSTR_FLAG_SC_FMT_CB_BEG_OBJ_BINNUM_H : \
    1111                 :                 VSTR_FLAG_SC_FMT_CB_BEG_OBJ_BINNUM_L)); \
    1112                 :   char buf[(sizeof(T) * CHAR_BIT) + 1]; \
    1113                 :   size_t obj_len = 0; \
    1114                 :   size_t len = 0; \
    1115                 :   \
    1116                 :   len = obj_len = vstr_sc_conv_num_ ## Tn (buf, sizeof(buf), val, "01", 2); \
    1117                 :   \
    1118                 :   if (!vstr_sc_fmt_cb_beg(base, &pos, spec, &len, flags)) \
    1119                 :     return (FALSE); \
    1120                 :   \
    1121                 :   if (!vstr_sc_add_grpbasenum_buf(base, pos, 2, buf, obj_len)) \
    1122                 :     return (FALSE); \
    1123                 :   \
    1124                 :   if (!vstr_sc_fmt_cb_end(base, pos, spec, len)) \
    1125                 :     return (FALSE); \
    1126                 :   \
    1127                 :   return (TRUE)
    1128                 : 
    1129                 : static int vstr__sc_fmt_add_cb_upper_base2_uint(Vstr_base *base, size_t pos,
    1130                 :                                                 Vstr_fmt_spec *spec)
    1131            4804 : {
    1132            4804 :   VSTR__SC_FMT_MAKE_CB_BASE2(unsigned int, uint, TRUE);
    1133                 : }
    1134                 : 
    1135                 : int vstr_sc_fmt_add_upper_base2_uint(Vstr_conf *conf, const char *name)
    1136            3498 : {
    1137            3498 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_upper_base2_uint,
    1138                 :                        VSTR_TYPE_FMT_UINT,
    1139                 :                        VSTR_TYPE_FMT_END));
    1140                 : }
    1141                 : 
    1142                 : static int vstr__sc_fmt_add_cb_upper_base2_ulong(Vstr_base *base, size_t pos,
    1143                 :                                                  Vstr_fmt_spec *spec)
    1144            6885 : {
    1145            6885 :   VSTR__SC_FMT_MAKE_CB_BASE2(unsigned long, ulong, TRUE);
    1146                 : }
    1147                 : 
    1148                 : int vstr_sc_fmt_add_upper_base2_ulong(Vstr_conf *conf, const char *name)
    1149            3400 : {
    1150            3400 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_upper_base2_ulong,
    1151                 :                        VSTR_TYPE_FMT_ULONG,
    1152                 :                        VSTR_TYPE_FMT_END));
    1153                 : }
    1154                 : 
    1155                 : static int vstr__sc_fmt_add_cb_upper_base2_size(Vstr_base *base, size_t pos,
    1156                 :                                                 Vstr_fmt_spec *spec)
    1157            6794 : {
    1158            6794 :   VSTR__SC_FMT_MAKE_CB_BASE2(size_t, size, TRUE);
    1159                 : }
    1160                 : 
    1161                 : int vstr_sc_fmt_add_upper_base2_size(Vstr_conf *conf, const char *name)
    1162            3302 : {
    1163            3302 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_upper_base2_size,
    1164                 :                        VSTR_TYPE_FMT_SIZE_T,
    1165                 :                        VSTR_TYPE_FMT_END));
    1166                 : }
    1167                 : 
    1168                 : static int vstr__sc_fmt_add_cb_upper_base2_uintmax(Vstr_base *base, size_t pos,
    1169                 :                                                    Vstr_fmt_spec *spec)
    1170            6794 : {
    1171            6794 :   VSTR__SC_FMT_MAKE_CB_BASE2(uintmax_t, uintmax, TRUE);
    1172                 : }
    1173                 : 
    1174                 : int vstr_sc_fmt_add_upper_base2_uintmax(Vstr_conf *conf, const char *name)
    1175            3204 : {
    1176            3204 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_upper_base2_uintmax,
    1177                 :                        VSTR_TYPE_FMT_UINTMAX_T,
    1178                 :                        VSTR_TYPE_FMT_END));
    1179                 : }
    1180                 : 
    1181                 : static int vstr__sc_fmt_add_cb_lower_base2_uint(Vstr_base *base, size_t pos,
    1182                 :                                                 Vstr_fmt_spec *spec)
    1183            4764 : {
    1184            4764 :   VSTR__SC_FMT_MAKE_CB_BASE2(unsigned int, uint, FALSE);
    1185                 : }
    1186                 : 
    1187                 : int vstr_sc_fmt_add_lower_base2_uint(Vstr_conf *conf, const char *name)
    1188            3106 : {
    1189            3106 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_lower_base2_uint,
    1190                 :                        VSTR_TYPE_FMT_UINT,
    1191                 :                        VSTR_TYPE_FMT_END));
    1192                 : }
    1193                 : 
    1194                 : static int vstr__sc_fmt_add_cb_lower_base2_ulong(Vstr_base *base, size_t pos,
    1195                 :                                                  Vstr_fmt_spec *spec)
    1196            6044 : {
    1197            6044 :   VSTR__SC_FMT_MAKE_CB_BASE2(unsigned long, ulong, FALSE);
    1198                 : }
    1199                 : 
    1200                 : int vstr_sc_fmt_add_lower_base2_ulong(Vstr_conf *conf, const char *name)
    1201            3008 : {
    1202            3008 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_lower_base2_ulong,
    1203                 :                        VSTR_TYPE_FMT_ULONG,
    1204                 :                        VSTR_TYPE_FMT_END));
    1205                 : }
    1206                 : 
    1207                 : static int vstr__sc_fmt_add_cb_lower_base2_size(Vstr_base *base, size_t pos,
    1208                 :                                                 Vstr_fmt_spec *spec)
    1209            6872 : {
    1210            6872 :   VSTR__SC_FMT_MAKE_CB_BASE2(size_t, size, FALSE);
    1211                 : }
    1212                 : 
    1213                 : int vstr_sc_fmt_add_lower_base2_size(Vstr_conf *conf, const char *name)
    1214            2910 : {
    1215            2910 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_lower_base2_size,
    1216                 :                        VSTR_TYPE_FMT_SIZE_T,
    1217                 :                        VSTR_TYPE_FMT_END));
    1218                 : }
    1219                 : 
    1220                 : static int vstr__sc_fmt_add_cb_lower_base2_uintmax(Vstr_base *base, size_t pos,
    1221                 :                                                    Vstr_fmt_spec *spec)
    1222            6794 : {
    1223            6794 :   VSTR__SC_FMT_MAKE_CB_BASE2(uintmax_t, uintmax, FALSE);
    1224                 : }
    1225                 : 
    1226                 : int vstr_sc_fmt_add_lower_base2_uintmax(Vstr_conf *conf, const char *name)
    1227            2812 : {
    1228            2812 :   return (vstr_fmt_add(conf, name, vstr__sc_fmt_add_cb_lower_base2_uintmax,
    1229                 :                        VSTR_TYPE_FMT_UINTMAX_T,
    1230                 :                        VSTR_TYPE_FMT_END));
    1231                 : }
    1232                 : 
    1233                 : #define VSTR__SC_FMT_ADD(x, n, nchk)                                    \
    1234                 :     if (ret &&                                                          \
    1235                 :         !VSTR_SC_FMT_ADD(conf, vstr_sc_fmt_add_ ## x, "{" n, nchk, "}")) \
    1236                 :       ret = FALSE
    1237                 : 
    1238                 : int vstr_sc_fmt_add_all(Vstr_conf *conf)
    1239             885 : {
    1240             885 :   int ret = TRUE;
    1241                 :   
    1242             885 :   VSTR__SC_FMT_ADD(vstr, "vstr", "p%zu%zu%u");
    1243             885 :   VSTR__SC_FMT_ADD(buf, "buf", "s%zu");
    1244             885 :   VSTR__SC_FMT_ADD(ptr, "ptr", "s%zu");
    1245             885 :   VSTR__SC_FMT_ADD(non, "non", "zu");
    1246             885 :   VSTR__SC_FMT_ADD(ref, "ref", "p%zu%zu");
    1247                 : 
    1248                 :   /* FIXME: tmp because I screwed up the definition for 1.0.0 --
    1249                 :    * had wrong types */
    1250             885 :   if (!(vstr_sc_fmt_add_ref (conf, "{ref" ":%"       "p%u%zu}") &&
    1251                 :         vstr_sc_fmt_add_ref (conf, "{ref" ":%" "*"   "p%u%zu}") &&
    1252                 :         vstr_sc_fmt_add_ref (conf, "{ref" ":%"  ".*" "p%u%zu}") &&
    1253                 :         vstr_sc_fmt_add_ref (conf, "{ref" ":%" "*.*" "p%u%zu}")))
    1254              16 :     ret = FALSE;
    1255                 : 
    1256             885 :   VSTR__SC_FMT_ADD(rep_chr, "rep_chr", "c%zu");
    1257                 : 
    1258             885 :   VSTR__SC_FMT_ADD(bkmg_Byte_uint,  "BKMG.u",   "u");
    1259             885 :   VSTR__SC_FMT_ADD(bkmg_Bytes_uint, "BKMG/s.u", "u");
    1260             885 :   VSTR__SC_FMT_ADD(bkmg_bit_uint,   "bKMG.u",   "u");
    1261             885 :   VSTR__SC_FMT_ADD(bkmg_bits_uint,  "bKMG/s.u", "u");
    1262                 :   
    1263             885 :   VSTR__SC_FMT_ADD(bkmg_Byte_uintmax,  "BKMG.ju",   "ju");
    1264             885 :   VSTR__SC_FMT_ADD(bkmg_Bytes_uintmax, "BKMG/s.ju", "ju");
    1265             885 :   VSTR__SC_FMT_ADD(bkmg_bit_uintmax,   "bKMG.ju",   "ju");
    1266             885 :   VSTR__SC_FMT_ADD(bkmg_bits_uintmax,  "bKMG/s.ju", "ju");
    1267                 : 
    1268             885 :   if (ret && !vstr__sc_fmt_add_posix(conf))
    1269              28 :     ret = FALSE;
    1270                 : 
    1271             885 :   VSTR__SC_FMT_ADD(ipv4_vec, "ipv4.v", "p");
    1272             885 :   VSTR__SC_FMT_ADD(ipv6_vec, "ipv6.v", "p%u");
    1273             885 :   VSTR__SC_FMT_ADD(ipv4_vec_cidr, "ipv4.v+C", "p%u");
    1274             885 :   VSTR__SC_FMT_ADD(ipv6_vec_cidr, "ipv6.v+C", "p%u%u");
    1275                 : 
    1276             885 :   VSTR__SC_FMT_ADD(upper_base2_uint,    "B.u",   "u");
    1277             885 :   VSTR__SC_FMT_ADD(upper_base2_ulong,   "B.lu", "lu");
    1278             885 :   VSTR__SC_FMT_ADD(upper_base2_size,    "B.zu", "zu");
    1279             885 :   VSTR__SC_FMT_ADD(upper_base2_uintmax, "B.ju", "ju");
    1280                 :   
    1281             885 :   VSTR__SC_FMT_ADD(lower_base2_uint,    "b.u",   "u");
    1282             885 :   VSTR__SC_FMT_ADD(lower_base2_ulong,   "b.lu", "lu");
    1283             885 :   VSTR__SC_FMT_ADD(lower_base2_size,    "b.zu", "zu");
    1284             885 :   VSTR__SC_FMT_ADD(lower_base2_uintmax, "b.ju", "ju");
    1285                 :   
    1286             885 :   return (ret);
    1287                 : }
    1288                 : #undef VSTR__SC_FMT_ADD
    1289                 : 
    1290                 : void vstr_sc_basename(const Vstr_base *base, size_t pos, size_t len,
    1291                 :                       size_t *ret_pos, size_t *ret_len)
    1292              55 : {
    1293              55 :   size_t ls = vstr_srch_chr_rev(base, pos, len, '/');
    1294              55 :   size_t end_pos = vstr_sc_poslast(pos, len);
    1295                 : 
    1296              55 :   if (!ls)
    1297                 :   {
    1298              15 :     *ret_pos = pos;
    1299              15 :     *ret_len = len;
    1300                 :   }
    1301              40 :   else if (ls == pos)
    1302                 :   {
    1303               5 :     *ret_pos = pos;
    1304               5 :     *ret_len = 0;
    1305                 :   }
    1306              35 :   else if (ls == end_pos)
    1307                 :   {
    1308              15 :     ls = vstr_spn_cstr_chrs_rev(base, pos, len, "/");
    1309              15 :     vstr_sc_basename(base, pos, len - ls, ret_pos, ret_len);
    1310                 :   }
    1311                 :   else
    1312                 :   {
    1313              20 :     ++ls;
    1314              20 :     *ret_pos = ls;
    1315              20 :     *ret_len = len - (ls - pos);
    1316                 :   }
    1317                 : }
    1318                 : 
    1319                 : void vstr_sc_dirname(const Vstr_base *base, size_t pos, size_t len,
    1320                 :                      size_t *ret_len)
    1321              62 : {
    1322              62 :   size_t ls = vstr_srch_chr_rev(base, pos, len, '/');
    1323              62 :   size_t end_pos = vstr_sc_poslast(pos, len);
    1324                 : 
    1325              62 :   if (!ls)
    1326              10 :     *ret_len = 0;
    1327              52 :   else if (ls == end_pos)
    1328                 :   {
    1329              20 :     ls = vstr_spn_cstr_chrs_rev(base, pos, len, "/");
    1330              20 :     len -= ls;
    1331              20 :     if (!len)
    1332              10 :       *ret_len = 1;
    1333                 :     else
    1334              10 :       vstr_sc_dirname(base, pos, len, ret_len);
    1335                 :   }
    1336                 :   else
    1337                 :   {
    1338              32 :     len = VSTR_SC_POSDIFF(pos, ls);
    1339              32 :     *ret_len = len - vstr_spn_cstr_chrs_rev(base, pos, len - 1, "/");
    1340                 :   }
    1341                 : }
    1342                 : 
    1343                 : int vstr_sc_add_grpbasenum_buf(Vstr_base *base, size_t pos,
    1344                 :                                unsigned int num_base,
    1345                 :                                const void *passed_buf, size_t len)
    1346           59320 : {
    1347           59320 :   size_t orig_pos      = pos;
    1348           59320 :   const char *buf      = passed_buf; /* so we can move it */
    1349           59320 :   Vstr_locale_num_base *srch = NULL;
    1350           59320 :   int done = FALSE;
    1351                 : 
    1352           59320 :   ASSERT(base && buf);
    1353                 :   
    1354           59320 :   srch = vstr__loc_num_srch(base->conf->loc, num_base, FALSE);
    1355          113205 :   while (len)
    1356                 :   {
    1357           67579 :     unsigned int num = vstr__add_fmt_grouping_mod(srch->grouping->ptr, len);
    1358                 : 
    1359           67579 :     if (done)
    1360                 :     {
    1361           16457 :       if (!vstr_add_buf(base, pos,
    1362                 :                         srch->thousands_sep_ref->ptr, srch->thousands_sep_len))
    1363              53 :         goto malloc_failed;
    1364                 :       
    1365           16404 :       pos += srch->thousands_sep_len;
    1366                 :     }
    1367                 :     
    1368           67526 :     if (!vstr_add_buf(base, pos, buf, num))
    1369           13641 :       goto malloc_failed;
    1370                 :     
    1371           53885 :     pos += num;
    1372           53885 :     buf += num;
    1373           53885 :     ASSERT(num <= len);
    1374           53885 :     len -= num;
    1375                 : 
    1376           53885 :     done = TRUE;
    1377                 :   }
    1378                 : 
    1379           45626 :   return (TRUE);
    1380                 :   
    1381                 :  malloc_failed:
    1382           13694 :   vstr_del(base, orig_pos + 1, pos - orig_pos);
    1383                 :   
    1384           13694 :   return (FALSE);  
    1385                 : }
    1386                 : 
    1387                 : int vstr_sc_add_grpbasenum_ptr(Vstr_base *base, size_t pos,
    1388                 :                                unsigned int num_base,
    1389                 :                                const void *passed_ptr, size_t len)
    1390              22 : {
    1391              22 :   size_t orig_pos = pos;
    1392              22 :   const char *ptr = passed_ptr; /* so we can move it */
    1393              22 :   Vstr_locale_num_base *srch = NULL;
    1394              22 :   int done = FALSE;
    1395                 : 
    1396              22 :   ASSERT(base && ptr);
    1397                 : 
    1398              22 :   srch = vstr__loc_num_srch(base->conf->loc, num_base, FALSE);
    1399              84 :   while (len)
    1400                 :   {
    1401              69 :     unsigned int num = vstr__add_fmt_grouping_mod(srch->grouping->ptr, len);
    1402                 : 
    1403              69 :     if (done)
    1404                 :     {
    1405              47 :       if (!vstr_add_ref(base, pos,
    1406                 :                         srch->thousands_sep_ref, 0, srch->thousands_sep_len))
    1407               3 :         goto malloc_failed;
    1408                 :       
    1409              44 :       pos += srch->thousands_sep_len;
    1410                 :     }
    1411                 :     
    1412              66 :     if (!vstr_add_ptr(base, pos, ptr, num))
    1413               4 :       goto malloc_failed;
    1414                 :     
    1415              62 :     pos += num;
    1416              62 :     ptr += num;
    1417              62 :     ASSERT(num <= len);
    1418              62 :     len -= num;
    1419                 : 
    1420              62 :     done = TRUE;
    1421                 :   }
    1422                 : 
    1423              15 :   return (TRUE);
    1424                 :   
    1425                 :  malloc_failed:
    1426               7 :   vstr_del(base, orig_pos + 1, pos - orig_pos);
    1427                 :   
    1428               7 :   return (FALSE);  
    1429                 : }
    1430                 : 
    1431                 : int vstr_sc_add_grpbasenum_ref(Vstr_base *base, size_t pos,
    1432                 :                                unsigned int num_base,
    1433                 :                                Vstr_ref *ref, size_t off, size_t len)
    1434              24 : {
    1435              24 :   size_t orig_pos = pos;
    1436              24 :   Vstr_locale_num_base *srch = NULL;
    1437              24 :   int done = FALSE;
    1438                 : 
    1439              24 :   ASSERT(base && ref);
    1440                 :   
    1441              24 :   srch = vstr__loc_num_srch(base->conf->loc, num_base, FALSE);
    1442              88 :   while (len)
    1443                 :   {
    1444              78 :     unsigned int num = vstr__add_fmt_grouping_mod(srch->grouping->ptr, len);
    1445                 : 
    1446              78 :     if (done)
    1447                 :     {
    1448              54 :       if (!vstr_add_ref(base, pos,
    1449                 :                         srch->thousands_sep_ref, 0, srch->thousands_sep_len))
    1450               6 :         goto malloc_failed;
    1451                 :       
    1452              48 :       pos += srch->thousands_sep_len;
    1453                 :     }
    1454                 :     
    1455              72 :     if (!vstr_add_ref(base, pos, ref, off, num))
    1456               8 :       goto malloc_failed;
    1457                 :     
    1458              64 :     pos += num;
    1459              64 :     off += num;
    1460              64 :     ASSERT(num <= len);
    1461              64 :     len -= num;
    1462                 : 
    1463              64 :     done = TRUE;
    1464                 :   }
    1465                 : 
    1466              10 :   return (TRUE);
    1467                 :   
    1468                 :  malloc_failed:
    1469              14 :   vstr_del(base, orig_pos + 1, pos - orig_pos);
    1470                 :   
    1471              14 :   return (FALSE);  
    1472                 : }
    1473                 : 
    1474                 : #define VSTR__SC_CONV_NUM(T) \
    1475                 :   char buf_beg[BUF_NUM_TYPE_SZ(T)]; \
    1476                 :   char *buf = buf_beg + sizeof(buf_beg); \
    1477                 :   size_t ret = 0; \
    1478                 :   \
    1479                 :   ASSERT_RET(out && chrs_base, 0); \
    1480                 :   ASSERT_RET(num_base >= 2, 0); \
    1481                 :   ASSERT_RET(len >= 2, 0); \
    1482                 :   \
    1483                 :   if (!val) { out[0] = chrs_base[0]; out[1] = 0; return (1); } \
    1484                 :   \
    1485                 :   VSTR__ADD_FMT_NUM(T, val, num_base); \
    1486                 :   \
    1487                 :   ret = (sizeof(buf_beg) - (buf - buf_beg)); \
    1488                 :   \
    1489                 :   if (len <= ret) { out[0] = 0; return (0); } \
    1490                 :   \
    1491                 :   vstr_wrap_memcpy(out, buf, ret); \
    1492                 :   out[ret] = 0; \
    1493                 :   \
    1494                 :   return (ret)
    1495                 : 
    1496                 : size_t vstr_sc_conv_num_uint(char *out, size_t len, unsigned int val,
    1497                 :                              const char *chrs_base, unsigned int num_base)
    1498           16627 : {
    1499           16627 :   VSTR__SC_CONV_NUM(unsigned int);
    1500                 : }
    1501                 : 
    1502                 : size_t vstr_sc_conv_num10_uint(char *out, size_t len, unsigned int val)
    1503           33101 : {
    1504           33101 :   static const char chrs_base[] = "0123456789";
    1505           33101 :   const unsigned int num_base = 10;
    1506           33101 :   VSTR__SC_CONV_NUM(unsigned int);
    1507                 : }
    1508                 : 
    1509                 : size_t vstr_sc_conv_num_ulong(char *out, size_t len, unsigned long val,
    1510                 :                               const char *chrs_base, unsigned int num_base)
    1511           12934 : {
    1512           12934 :   VSTR__SC_CONV_NUM(unsigned long);
    1513                 : }
    1514                 : 
    1515                 : size_t vstr_sc_conv_num10_ulong(char *out, size_t len, unsigned long val)
    1516               5 : {
    1517               5 :   static const char chrs_base[] = "0123456789";
    1518               5 :   const unsigned int num_base = 10;
    1519               5 :   VSTR__SC_CONV_NUM(unsigned long);
    1520                 : }
    1521                 : 
    1522                 : size_t vstr_sc_conv_num_size(char *out, size_t len, size_t val,
    1523                 :                              const char *chrs_base, unsigned int num_base)
    1524           13671 : {
    1525           13671 :   VSTR__SC_CONV_NUM(size_t);
    1526                 : }
    1527                 : 
    1528                 : size_t vstr_sc_conv_num10_size(char *out, size_t len, size_t val)
    1529             140 : {
    1530             140 :   static const char chrs_base[] = "0123456789";
    1531             140 :   const unsigned int num_base = 10;
    1532             140 :   VSTR__SC_CONV_NUM(size_t);
    1533                 : }
    1534                 : 
    1535                 : size_t vstr_sc_conv_num_uintmax(char *out, size_t len, uintmax_t val,
    1536                 :                                const char *chrs_base, unsigned int num_base)
    1537           13593 : {
    1538           13593 :   VSTR__SC_CONV_NUM(uintmax_t);
    1539                 : }
    1540                 : 
    1541                 : size_t vstr_sc_conv_num10_uintmax(char *out, size_t len, uintmax_t val)
    1542            1498 : {
    1543            1498 :   static const char chrs_base[] = "0123456789";
    1544            1498 :   const unsigned int num_base = 10;
    1545            1498 :   VSTR__SC_CONV_NUM(uintmax_t);
    1546                 : }

Generated by: LTP GCOV extension version 1.1