/* Copyright (C) 2007-2008 The Android Open Source Project ** ** This software is licensed under the terms of the GNU General Public ** License version 2, as published by the Free Software Foundation, and ** may be copied, distributed, and modified under those terms. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. */ #include "qemu-common.h" #include "android/utils/misc.h" #include "android/utils/stralloc.h" #include "android/utils/debug.h" #include #include #include #define E(...) derror(__VA_ARGS__) extern void print_tabular( const char** strings, int count, const char* prefix, int width ) { int nrows, ncols, r, c, n, maxw = 0; for (n = 0; n < count; n++) { int len = strlen(strings[n]); if (len > maxw) maxw = len; } maxw += 2; ncols = width/maxw; nrows = (count + ncols-1)/ncols; for (r = 0; r < nrows; r++) { printf( "%s", prefix ); for (c = 0; c < ncols; c++) { int index = c*nrows + r; if (index >= count) { break; } printf( "%-*s", maxw, strings[index] ); } printf( "\n" ); } } extern void string_translate_char( char* str, char from, char to ) { char* p = str; while (p != NULL && (p = strchr(p, from)) != NULL) *p++ = to; } extern void buffer_translate_char( char* buff, unsigned buffLen, const char* src, char fromChar, char toChar ) { int len = strlen(src); if (len >= buffLen) len = buffLen-1; memcpy(buff, src, len); buff[len] = 0; string_translate_char( buff, fromChar, toChar ); } /** TEMP CHAR STRINGS ** ** implement a circular ring of temporary string buffers **/ typedef struct Temptring { struct TempString* next; char* buffer; int size; } TempString; #define MAX_TEMP_STRINGS 16 static TempString _temp_strings[ MAX_TEMP_STRINGS ]; static int _temp_string_n; extern char* tempstr_get( int size ) { TempString* t = &_temp_strings[_temp_string_n]; if ( ++_temp_string_n >= MAX_TEMP_STRINGS ) _temp_string_n = 0; size += 1; /* reserve 1 char for terminating zero */ if (t->size < size) { t->buffer = realloc( t->buffer, size ); if (t->buffer == NULL) { derror( "%s: could not allocate %d bytes", __FUNCTION__, size ); exit(1); } t->size = size; } return t->buffer; } extern char* tempstr_format( const char* fmt, ... ) { va_list args; char* result; STRALLOC_DEFINE(s); va_start(args, fmt); stralloc_formatv(s, fmt, args); va_end(args); result = stralloc_to_tempstr(s); stralloc_reset(s); return result; } /** QUOTING ** ** dumps a human-readable version of a string. this replaces ** newlines with \n, etc... **/ extern const char* quote_bytes( const char* str, int len ) { STRALLOC_DEFINE(s); char* q; stralloc_add_quote_bytes( s, str, len ); q = stralloc_to_tempstr( s ); stralloc_reset(s); return q; } extern const char* quote_str( const char* str ) { int len = strlen(str); return quote_bytes( str, len ); } /** HEXADECIMAL CHARACTER SEQUENCES **/ static int hexdigit( int c ) { unsigned d; d = (unsigned)(c - '0'); if (d < 10) return d; d = (unsigned)(c - 'a'); if (d < 6) return d+10; d = (unsigned)(c - 'A'); if (d < 6) return d+10; return -1; } int hex2int( const uint8_t* hex, int len ) { int result = 0; while (len > 0) { int c = hexdigit(*hex++); if (c < 0) return -1; result = (result << 4) | c; len --; } return result; } void int2hex( uint8_t* hex, int len, int val ) { static const uint8_t hexchars[16] = "0123456789abcdef"; while ( --len >= 0 ) *hex++ = hexchars[(val >> (len*4)) & 15]; } /** STRING PARAMETER PARSING **/ int strtoi(const char *nptr, char **endptr, int base) { long val; errno = 0; val = strtol(nptr, endptr, base); if (errno) { return (val == LONG_MAX) ? INT_MAX : INT_MIN; } else { if (val == (int)val) { return (int)val; } else { errno = ERANGE; return val > 0 ? INT_MAX : INT_MIN; } } } int get_token_value(const char* params, const char* name, char* value, int val_size) { const char* val_end; int len = strlen(name); const char* par_end = params + strlen(params); const char* par_start = strstr(params, name); /* Search for 'name=' */ while (par_start != NULL) { /* Make sure that we're within the parameters buffer. */ if ((par_end - par_start) < len) { par_start = NULL; break; } /* Make sure that par_start starts at the beginning of , and only * then check for '=' value separator. */ if ((par_start == params || (*(par_start - 1) == ' ')) && par_start[len] == '=') { break; } /* False positive. Move on... */ par_start = strstr(par_start + 1, name); } if (par_start == NULL) { return -1; } /* Advance past 'name=', and calculate value's string length. */ par_start += len + 1; val_end = strchr(par_start, ' '); if (val_end == NULL) { val_end = par_start + strlen(par_start); } len = val_end - par_start; /* Check if fits... */ if ((len + 1) <= val_size) { memcpy(value, par_start, len); value[len] = '\0'; return 0; } else { return len + 1; } } int get_token_value_alloc(const char* params, const char* name, char** value) { char tmp; int res; /* Calculate size of string buffer required for the value. */ const int val_size = get_token_value(params, name, &tmp, 0); if (val_size < 0) { *value = NULL; return val_size; } /* Allocate string buffer, and retrieve the value. */ *value = (char*)malloc(val_size); if (*value == NULL) { E("%s: Unable to allocated %d bytes for string buffer.", __FUNCTION__, val_size); return -2; } res = get_token_value(params, name, *value, val_size); if (res) { E("%s: Unable to retrieve value into allocated buffer.", __FUNCTION__); free(*value); *value = NULL; } return res; } int get_token_value_int(const char* params, const char* name, int* value) { char val_str[64]; // Should be enough for all numeric values. if (!get_token_value(params, name, val_str, sizeof(val_str))) { errno = 0; *value = strtoi(val_str, (char**)NULL, 10); if (errno) { E("%s: Value '%s' of the parameter '%s' in '%s' is not a decimal number.", __FUNCTION__, val_str, name, params); return -2; } else { return 0; } } else { return -1; } }