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 void
    142 stralloc_lstrip( stralloc_t*  s )
    143 {
    144     int  count;
    145 
    146     for (count = 0; count < s->n; count++) {
    147         if (s->s[count] != ' ' && s->s[count] != '\t')
    148             break;
    149     }
    150 
    151     if (count > 0) {
    152         memmove(s->s, s->s + count, s->n - count);
    153         s->n -= count;
    154     }
    155 }
    156 
    157 void
    158 stralloc_rstrip( stralloc_t*  s )
    159 {
    160     int  count = s->n;
    161 
    162     while (count > 0 && (s->s[count-1] == ' ' || s->s[count-1] == '\t'))
    163         count--;
    164 
    165     s->n = count;
    166 }
    167 
    168 void
    169 stralloc_strip( stralloc_t* s )
    170 {
    171     stralloc_rstrip(s);
    172     stralloc_lstrip(s);
    173 }
    174 
    175 extern char*
    176 stralloc_to_tempstr( stralloc_t*  s )
    177 {
    178     char*  q = tempstr_get( s->n );
    179 
    180     memcpy( q, s->s, s->n );
    181     q[s->n] = 0;
    182     return q;
    183 }
    184 
    185 extern void
    186 stralloc_formatv( stralloc_t*  s, const char*  fmt, va_list  args )
    187 {
    188     stralloc_reset(s);
    189     stralloc_ready(s,10);
    190 
    191     while (1) {
    192         int      n;
    193         va_list  args2;
    194 
    195         va_copy(args2, args);
    196         n = vsnprintf( s->s, s->a, fmt, args2 );
    197         va_end(args2);
    198 
    199         /* funky old C libraries returns -1 when truncation occurs */
    200         if (n > -1 && n < s->a) {
    201             s->n = n;
    202             break;
    203         }
    204         if (n > -1) {  /* we now precisely what we need */
    205             stralloc_ready( s, n+1 );
    206         } else {
    207             stralloc_ready( s, s->a*2 );
    208         }
    209     }
    210 }
    211 
    212 
    213 extern void
    214 stralloc_format( stralloc_t*  s, const char*  fmt, ... )
    215 {
    216     va_list  args;
    217     va_start(args, fmt);
    218     stralloc_formatv(s, fmt, args);
    219     va_end(args);
    220 }
    221 
    222 extern void
    223 stralloc_add_formatv( stralloc_t*  s, const char*  fmt, va_list  args )
    224 {
    225     STRALLOC_DEFINE(s2);
    226     stralloc_formatv(s2, fmt, args);
    227     stralloc_append( s, s2 );
    228     stralloc_reset( s2 );
    229 }
    230 
    231 extern void
    232 stralloc_add_format( stralloc_t*  s, const char*  fmt, ... )
    233 {
    234     va_list  args;
    235     va_start(args, fmt);
    236     stralloc_add_formatv( s, fmt, args );
    237     va_end(args);
    238 }
    239 
    240 extern void
    241 stralloc_add_quote_c( stralloc_t*  s, int  c )
    242 {
    243     stralloc_add_quote_bytes( s, (char*)&c, 1 );
    244 }
    245 
    246 extern void
    247 stralloc_add_quote_str( stralloc_t*  s, const char*  str )
    248 {
    249     stralloc_add_quote_bytes( s, str, strlen(str) );
    250 }
    251 
    252 extern void
    253 stralloc_add_quote_bytes( stralloc_t*  s, const void*  from, unsigned  len )
    254 {
    255     uint8_t*   p   = (uint8_t*) from;
    256     uint8_t*   end = p + len;
    257 
    258     for ( ; p < end; p++ ) {
    259         int  c = p[0];
    260 
    261         if (c == '\\') {
    262             stralloc_add_str( s, "\\\\" );
    263         } else if (c >= ' ' && c < 128) {
    264             stralloc_add_c( s, c );
    265         } else if (c == '\n') {
    266             stralloc_add_str( s, "\\n" );
    267         } else if (c == '\t') {
    268             stralloc_add_str( s, "\\t" );
    269         } else if (c == '\r') {
    270             stralloc_add_str( s, "\\r" );
    271         } else {
    272             stralloc_add_format( s, "\\x%02x", c );
    273         }
    274     }
    275 }
    276 
    277 extern void
    278 stralloc_add_hex( stralloc_t*  s, unsigned  value, int  num_digits )
    279 {
    280     const char   hexdigits[16] = "0123456789abcdef";
    281     int          nn;
    282 
    283     if (num_digits <= 0)
    284         return;
    285 
    286     stralloc_readyplus(s, num_digits);
    287     for (nn = num_digits-1; nn >= 0; nn--) {
    288         s->s[s->n+nn] = hexdigits[value & 15];
    289         value >>= 4;
    290     }
    291     s->n += num_digits;
    292 }
    293 
    294 extern void
    295 stralloc_add_hexdump( stralloc_t*  s, void*  base, int  size, const char*  prefix )
    296 {
    297     uint8_t*   p          = (uint8_t*)base;
    298     const int  max_count  = 16;
    299     int        prefix_len = strlen(prefix);
    300 
    301     while (size > 0) {
    302         int          count = size > max_count ? max_count : size;
    303         int          count2;
    304         int          n;
    305 
    306         stralloc_add_bytes( s, prefix, prefix_len );
    307         stralloc_add_hex( s, p[0], 2 );
    308 
    309         for (n = 1; n < count; n++) {
    310             stralloc_add_c( s, ' ' );
    311             stralloc_add_hex( s, p[n], 2 );
    312         }
    313 
    314         count2 = 4 + 3*(max_count - count);
    315         stralloc_readyplus( s, count2 );
    316         memset( s->s + s->n, ' ', count2 );
    317         s->n += count2;
    318 
    319         stralloc_readyplus(s, count+1);
    320         for (n = 0; n < count; n++) {
    321             int  c = p[n];
    322 
    323             if (c < 32 || c > 127)
    324                 c = '.';
    325 
    326             s->s[s->n++] = c;
    327         }
    328         s->s[s->n++] = '\n';
    329 
    330         size -= count;
    331         p    += count;
    332     }
    333 }
    334 
    335