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