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 "qemu-common.h"
     14 #include "android/utils/misc.h"
     15 #include "android/utils/stralloc.h"
     16 #include "android/utils/debug.h"
     17 #include <string.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 
     21 #define  E(...)    derror(__VA_ARGS__)
     22 
     23 extern void
     24 print_tabular( const char** strings, int  count,
     25                const char*  prefix,  int  width )
     26 {
     27     int  nrows, ncols, r, c, n, maxw = 0;
     28 
     29     for (n = 0; n < count; n++) {
     30         int  len = strlen(strings[n]);
     31         if (len > maxw)
     32             maxw = len;
     33     }
     34     maxw += 2;
     35     ncols = width/maxw;
     36     nrows = (count + ncols-1)/ncols;
     37 
     38     for (r = 0; r < nrows; r++) {
     39         printf( "%s", prefix );
     40         for (c = 0; c < ncols; c++) {
     41             int  index = c*nrows + r;
     42             if (index >= count) {
     43                 break;
     44             }
     45             printf( "%-*s", maxw, strings[index] );
     46         }
     47         printf( "\n" );
     48     }
     49 }
     50 
     51 extern void
     52 string_translate_char( char*  str, char from, char to )
     53 {
     54     char*  p = str;
     55     while (p != NULL && (p = strchr(p, from)) != NULL)
     56         *p++ = to;
     57 }
     58 
     59 extern void
     60 buffer_translate_char( char*        buff,
     61                        unsigned     buffLen,
     62                        const char*  src,
     63                        char         fromChar,
     64                        char         toChar )
     65 {
     66     int    len = strlen(src);
     67 
     68     if (len >= buffLen)
     69         len = buffLen-1;
     70 
     71     memcpy(buff, src, len);
     72     buff[len] = 0;
     73 
     74     string_translate_char( buff, fromChar, toChar );
     75 }
     76 
     77 
     78 /** TEMP CHAR STRINGS
     79  **
     80  ** implement a circular ring of temporary string buffers
     81  **/
     82 
     83 typedef struct Temptring {
     84     struct TempString*  next;
     85     char*               buffer;
     86     int                 size;
     87 } TempString;
     88 
     89 #define  MAX_TEMP_STRINGS   16
     90 
     91 static TempString  _temp_strings[ MAX_TEMP_STRINGS ];
     92 static int         _temp_string_n;
     93 
     94 extern char*
     95 tempstr_get( int  size )
     96 {
     97     TempString*  t = &_temp_strings[_temp_string_n];
     98 
     99     if ( ++_temp_string_n >= MAX_TEMP_STRINGS )
    100         _temp_string_n = 0;
    101 
    102     size += 1;  /* reserve 1 char for terminating zero */
    103 
    104     if (t->size < size) {
    105         t->buffer = realloc( t->buffer, size );
    106         if (t->buffer == NULL) {
    107             derror( "%s: could not allocate %d bytes",
    108                     __FUNCTION__, size );
    109             exit(1);
    110         }
    111         t->size   = size;
    112     }
    113     return  t->buffer;
    114 }
    115 
    116 extern char*
    117 tempstr_format( const char*  fmt, ... )
    118 {
    119     va_list  args;
    120     char*    result;
    121     STRALLOC_DEFINE(s);
    122     va_start(args, fmt);
    123     stralloc_formatv(s, fmt, args);
    124     va_end(args);
    125     result = stralloc_to_tempstr(s);
    126     stralloc_reset(s);
    127     return result;
    128 }
    129 
    130 /** QUOTING
    131  **
    132  ** dumps a human-readable version of a string. this replaces
    133  ** newlines with \n, etc...
    134  **/
    135 
    136 extern const char*
    137 quote_bytes( const char*  str, int  len )
    138 {
    139     STRALLOC_DEFINE(s);
    140     char*  q;
    141 
    142     stralloc_add_quote_bytes( s, str, len );
    143     q = stralloc_to_tempstr( s );
    144     stralloc_reset(s);
    145     return q;
    146 }
    147 
    148 extern const char*
    149 quote_str( const char*  str )
    150 {
    151     int  len = strlen(str);
    152     return quote_bytes( str, len );
    153 }
    154 
    155 /** HEXADECIMAL CHARACTER SEQUENCES
    156  **/
    157 
    158 static int
    159 hexdigit( int  c )
    160 {
    161     unsigned  d;
    162 
    163     d = (unsigned)(c - '0');
    164     if (d < 10) return d;
    165 
    166     d = (unsigned)(c - 'a');
    167     if (d < 6) return d+10;
    168 
    169     d = (unsigned)(c - 'A');
    170     if (d < 6) return d+10;
    171 
    172     return -1;
    173 }
    174 
    175 int
    176 hex2int( const uint8_t*  hex, int  len )
    177 {
    178     int  result = 0;
    179     while (len > 0) {
    180         int  c = hexdigit(*hex++);
    181         if (c < 0)
    182             return -1;
    183 
    184         result = (result << 4) | c;
    185         len --;
    186     }
    187     return result;
    188 }
    189 
    190 void
    191 int2hex( uint8_t*  hex, int  len, int  val )
    192 {
    193     static const uint8_t  hexchars[16] = "0123456789abcdef";
    194     while ( --len >= 0 )
    195         *hex++ = hexchars[(val >> (len*4)) & 15];
    196 }
    197 
    198 /** STRING PARAMETER PARSING
    199  **/
    200 
    201 int
    202 strtoi(const char *nptr, char **endptr, int base)
    203 {
    204     long val;
    205 
    206     errno = 0;
    207     val = strtol(nptr, endptr, base);
    208     if (errno) {
    209         return (val == LONG_MAX) ? INT_MAX : INT_MIN;
    210     } else {
    211         if (val == (int)val) {
    212             return (int)val;
    213         } else {
    214             errno = ERANGE;
    215             return val > 0 ? INT_MAX : INT_MIN;
    216         }
    217     }
    218 }
    219 
    220 int
    221 get_token_value(const char* params, const char* name, char* value, int val_size)
    222 {
    223     const char* val_end;
    224     int len = strlen(name);
    225     const char* par_end = params + strlen(params);
    226     const char* par_start = strstr(params, name);
    227 
    228     /* Search for 'name=' */
    229     while (par_start != NULL) {
    230         /* Make sure that we're within the parameters buffer. */
    231         if ((par_end - par_start) < len) {
    232             par_start = NULL;
    233             break;
    234         }
    235         /* Make sure that par_start starts at the beginning of <name>, and only
    236          * then check for '=' value separator. */
    237         if ((par_start == params || (*(par_start - 1) == ' ')) &&
    238                 par_start[len] == '=') {
    239             break;
    240         }
    241         /* False positive. Move on... */
    242         par_start = strstr(par_start + 1, name);
    243     }
    244     if (par_start == NULL) {
    245         return -1;
    246     }
    247 
    248     /* Advance past 'name=', and calculate value's string length. */
    249     par_start += len + 1;
    250     val_end = strchr(par_start, ' ');
    251     if (val_end == NULL) {
    252         val_end = par_start + strlen(par_start);
    253     }
    254     len = val_end - par_start;
    255 
    256     /* Check if fits... */
    257     if ((len + 1) <= val_size) {
    258         memcpy(value, par_start, len);
    259         value[len] = '\0';
    260         return 0;
    261     } else {
    262         return len + 1;
    263     }
    264 }
    265 
    266 int
    267 get_token_value_alloc(const char* params, const char* name, char** value)
    268 {
    269     char tmp;
    270     int res;
    271 
    272     /* Calculate size of string buffer required for the value. */
    273     const int val_size = get_token_value(params, name, &tmp, 0);
    274     if (val_size < 0) {
    275         *value = NULL;
    276         return val_size;
    277     }
    278 
    279     /* Allocate string buffer, and retrieve the value. */
    280     *value = (char*)malloc(val_size);
    281     if (*value == NULL) {
    282         E("%s: Unable to allocated %d bytes for string buffer.",
    283           __FUNCTION__, val_size);
    284         return -2;
    285     }
    286     res = get_token_value(params, name, *value, val_size);
    287     if (res) {
    288         E("%s: Unable to retrieve value into allocated buffer.", __FUNCTION__);
    289         free(*value);
    290         *value = NULL;
    291     }
    292 
    293     return res;
    294 }
    295 
    296 int
    297 get_token_value_int(const char* params, const char* name, int* value)
    298 {
    299     char val_str[64];   // Should be enough for all numeric values.
    300     if (!get_token_value(params, name, val_str, sizeof(val_str))) {
    301         errno = 0;
    302         *value = strtoi(val_str, (char**)NULL, 10);
    303         if (errno) {
    304             E("%s: Value '%s' of the parameter '%s' in '%s' is not a decimal number.",
    305               __FUNCTION__, val_str, name, params);
    306             return -2;
    307         } else {
    308             return 0;
    309         }
    310     } else {
    311         return -1;
    312     }
    313 }
    314