Home | History | Annotate | Download | only in utils
      1 /* Copyright (C) 2007-2008 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 
     13 #include "android/utils/stralloc.h"
     14 #include "android/utils/debug.h"
     15 #include "android/utils/misc.h"
     16 #include <string.h>
     17 #include <stdlib.h>
     18 #include <stdio.h>
     19 #include <limits.h>
     20 
     21 extern void
     22 stralloc_tabular( stralloc_t*  out,
     23                   const char** strings, int  count,
     24                   const char*  prefix,  int  width )
     25 {
     26     int  nrows, ncols, r, c, n, maxw = 0;
     27 
     28     for (n = 0; n < count; n++) {
     29         int  len = strlen(strings[n]);
     30         if (len > maxw)
     31             maxw = len;
     32     }
     33     maxw += 2;
     34     ncols = width/maxw;
     35     nrows = (count + ncols-1)/ncols;
     36 
     37     for (r = 0; r < nrows; r++) {
     38         stralloc_add_str( out, prefix );
     39         for (c = 0; c < ncols; c++) {
     40             int  index = c*nrows + r;
     41             if (index >= count) {
     42                 break;
     43             }
     44             stralloc_add_format( out, "%-*s", maxw, strings[index] );
     45         }
     46         stralloc_add_str( out, "\n" );
     47     }
     48 }
     49 
     50 /** DYNAMIC STRINGS
     51  **/
     52 
     53 extern void
     54 stralloc_reset( stralloc_t*  s )
     55 {
     56     free(s->s);
     57     s->s = NULL;
     58     s->n = 0;
     59     s->a = 0;
     60 }
     61 
     62 extern void
     63 stralloc_ready( stralloc_t*  s, unsigned int  len )
     64 {
     65     unsigned  old_max = s->a;
     66     unsigned  new_max = old_max;
     67 
     68     while (new_max < len) {
     69         unsigned  new_max2 = new_max + (new_max >> 1) + 16;
     70         if (new_max2 < new_max)
     71             new_max2 = UINT_MAX;
     72         new_max = new_max2;
     73     }
     74 
     75     s->s = realloc( s->s, new_max );
     76     if (s->s == NULL) {
     77         derror( "%s: not enough memory to reallocate %ld bytes",
     78                 __FUNCTION__, new_max );
     79         exit(1);
     80     }
     81     s->a = new_max;
     82 }
     83 
     84 extern void
     85 stralloc_readyplus( stralloc_t*  s, unsigned int  len )
     86 {
     87     unsigned  len2 = s->n + len;
     88 
     89     if (len2 < s->n) { /* overflow ? */
     90         derror("%s: trying to grow by too many bytes: %ld",
     91                __FUNCTION__, len);
     92         exit(1);
     93     }
     94     stralloc_ready( s, len2 );
     95 }
     96 
     97 extern void
     98 stralloc_copy( stralloc_t*  s, stralloc_t*  from )
     99 {
    100     stralloc_ready(s, from->n);
    101     memcpy( s->s, from->s, from->n );
    102     s->n = from->n;
    103 }
    104 
    105 extern void
    106 stralloc_append( stralloc_t*  s, stralloc_t*  from )
    107 {
    108     stralloc_readyplus( s, from->n );
    109     memcpy( s->s + s->n, from->s, from->n );
    110     s->n += from->n;
    111 }
    112 
    113 extern void
    114 stralloc_add_c( stralloc_t*  s, int  c )
    115 {
    116     stralloc_add_bytes( s, (char*)&c, 1 );
    117 }
    118 
    119 extern void
    120 stralloc_add_str( stralloc_t*  s, const char*  str )
    121 {
    122     stralloc_add_bytes( s, str, strlen(str) );
    123 }
    124 
    125 extern void
    126 stralloc_add_bytes( stralloc_t*  s, const void*  from, unsigned len )
    127 {
    128     stralloc_readyplus( s, len );
    129     memcpy( s->s + s->n, from, len );
    130     s->n += len;
    131 }
    132 
    133 extern char*
    134 stralloc_cstr( stralloc_t*  s )
    135 {
    136     stralloc_readyplus( s, 1 );
    137     s->s[s->n] = 0;
    138     return s->s;
    139 }
    140 
    141 extern char*
    142 stralloc_to_tempstr( stralloc_t*  s )
    143 {
    144     char*  q = tempstr_get( s->n );
    145 
    146     memcpy( q, s->s, s->n );
    147     q[s->n] = 0;
    148     return q;
    149 }
    150 
    151 extern void
    152 stralloc_formatv( stralloc_t*  s, const char*  fmt, va_list  args )
    153 {
    154     stralloc_reset(s);
    155     stralloc_ready(s,10);
    156 
    157     while (1) {
    158         int      n;
    159         va_list  args2;
    160 
    161         va_copy(args2, args);
    162         n = vsnprintf( s->s, s->a, fmt, args2 );
    163         va_end(args2);
    164 
    165         /* funky old C libraries returns -1 when truncation occurs */
    166         if (n > -1 && n < s->a) {
    167             s->n = n;
    168             break;
    169         }
    170         if (n > -1) {  /* we now precisely what we need */
    171             stralloc_ready( s, n+1 );
    172         } else {
    173             stralloc_ready( s, s->a*2 );
    174         }
    175     }
    176 }
    177 
    178 
    179 extern void
    180 stralloc_format( stralloc_t*  s, const char*  fmt, ... )
    181 {
    182     va_list  args;
    183     va_start(args, fmt);
    184     stralloc_formatv(s, fmt, args);
    185     va_end(args);
    186 }
    187 
    188 extern void
    189 stralloc_add_formatv( stralloc_t*  s, const char*  fmt, va_list  args )
    190 {
    191     STRALLOC_DEFINE(s2);
    192     stralloc_formatv(s2, fmt, args);
    193     stralloc_append( s, s2 );
    194     stralloc_reset( s2 );
    195 }
    196 
    197 extern void
    198 stralloc_add_format( stralloc_t*  s, const char*  fmt, ... )
    199 {
    200     va_list  args;
    201     va_start(args, fmt);
    202     stralloc_add_formatv( s, fmt, args );
    203     va_end(args);
    204 }
    205 
    206 extern void
    207 stralloc_add_quote_c( stralloc_t*  s, int  c )
    208 {
    209     stralloc_add_quote_bytes( s, (char*)&c, 1 );
    210 }
    211 
    212 extern void
    213 stralloc_add_quote_str( stralloc_t*  s, const char*  str )
    214 {
    215     stralloc_add_quote_bytes( s, str, strlen(str) );
    216 }
    217 
    218 extern void
    219 stralloc_add_quote_bytes( stralloc_t*  s, const void*  from, unsigned  len )
    220 {
    221     uint8_t*   p   = (uint8_t*) from;
    222     uint8_t*   end = p + len;
    223 
    224     for ( ; p < end; p++ ) {
    225         int  c = p[0];
    226 
    227         if (c == '\\') {
    228             stralloc_add_str( s, "\\\\" );
    229         } else if (c >= ' ' && c < 128) {
    230             stralloc_add_c( s, c );
    231         } else if (c == '\n') {
    232             stralloc_add_str( s, "\\n" );
    233         } else if (c == '\t') {
    234             stralloc_add_str( s, "\\t" );
    235         } else if (c == '\r') {
    236             stralloc_add_str( s, "\\r" );
    237         } else {
    238             stralloc_add_format( s, "\\x%02x", c );
    239         }
    240     }
    241 }
    242 
    243 extern void
    244 stralloc_add_hex( stralloc_t*  s, unsigned  value, int  num_digits )
    245 {
    246     const char   hexdigits[16] = "0123456789abcdef";
    247     int          nn;
    248 
    249     if (num_digits <= 0)
    250         return;
    251 
    252     stralloc_readyplus(s, num_digits);
    253     for (nn = num_digits-1; nn >= 0; nn--) {
    254         s->s[s->n+nn] = hexdigits[value & 15];
    255         value >>= 4;
    256     }
    257     s->n += num_digits;
    258 }
    259 
    260 extern void
    261 stralloc_add_hexdump( stralloc_t*  s, void*  base, int  size, const char*  prefix )
    262 {
    263     uint8_t*   p          = (uint8_t*)base;
    264     const int  max_count  = 16;
    265     int        prefix_len = strlen(prefix);
    266 
    267     while (size > 0) {
    268         int          count = size > max_count ? max_count : size;
    269         int          count2;
    270         int          n;
    271 
    272         stralloc_add_bytes( s, prefix, prefix_len );
    273         stralloc_add_hex( s, p[0], 2 );
    274 
    275         for (n = 1; n < count; n++) {
    276             stralloc_add_c( s, ' ' );
    277             stralloc_add_hex( s, p[n], 2 );
    278         }
    279 
    280         count2 = 4 + 3*(max_count - count);
    281         stralloc_readyplus( s, count2 );
    282         memset( s->s + s->n, ' ', count2 );
    283         s->n += count2;
    284 
    285         stralloc_readyplus(s, count+1);
    286         for (n = 0; n < count; n++) {
    287             int  c = p[n];
    288 
    289             if (c < 32 || c > 127)
    290                 c = '.';
    291 
    292             s->s[s->n++] = c;
    293         }
    294         s->s[s->n++] = '\n';
    295 
    296         size -= count;
    297         p    += count;
    298     }
    299 }
    300 
    301