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