diff options
Diffstat (limited to 'android/utils/stralloc.c')
-rw-r--r-- | android/utils/stralloc.c | 300 |
1 files changed, 300 insertions, 0 deletions
diff --git a/android/utils/stralloc.c b/android/utils/stralloc.c new file mode 100644 index 0000000..2a924e4 --- /dev/null +++ b/android/utils/stralloc.c @@ -0,0 +1,300 @@ +/* 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 "android/utils/stralloc.h" +#include "android/utils/debug.h" +#include "android/utils/misc.h" +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <limits.h> + +extern void +stralloc_tabular( stralloc_t* out, + 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++) { + stralloc_add_str( out, prefix ); + for (c = 0; c < ncols; c++) { + int index = c*nrows + r; + if (index >= count) { + break; + } + stralloc_add_format( out, "%-*s", maxw, strings[index] ); + } + stralloc_add_str( out, "\n" ); + } +} + +/** DYNAMIC STRINGS + **/ + +extern void +stralloc_reset( stralloc_t* s ) +{ + free(s->s); + s->s = NULL; + s->n = 0; + s->a = 0; +} + +extern void +stralloc_ready( stralloc_t* s, unsigned int len ) +{ + unsigned old_max = s->a; + unsigned new_max = old_max; + + while (new_max < len) { + unsigned new_max2 = new_max + (new_max >> 1) + 16; + if (new_max2 < new_max) + new_max2 = UINT_MAX; + new_max = new_max2; + } + + s->s = realloc( s->s, new_max ); + if (s->s == NULL) { + derror( "%s: not enough memory to reallocate %ld bytes", + __FUNCTION__, new_max ); + exit(1); + } + s->a = new_max; +} + +extern void +stralloc_readyplus( stralloc_t* s, unsigned int len ) +{ + unsigned len2 = s->n + len; + + if (len2 < s->n) { /* overflow ? */ + derror("%s: trying to grow by too many bytes: %ld", + __FUNCTION__, len); + exit(1); + } + stralloc_ready( s, len2 ); +} + +extern void +stralloc_copy( stralloc_t* s, stralloc_t* from ) +{ + stralloc_ready(s, from->n); + memcpy( s->s, from->s, from->n ); + s->n = from->n; +} + +extern void +stralloc_append( stralloc_t* s, stralloc_t* from ) +{ + stralloc_readyplus( s, from->n ); + memcpy( s->s + s->n, from->s, from->n ); + s->n += from->n; +} + +extern void +stralloc_add_c( stralloc_t* s, int c ) +{ + stralloc_add_bytes( s, (char*)&c, 1 ); +} + +extern void +stralloc_add_str( stralloc_t* s, const char* str ) +{ + stralloc_add_bytes( s, str, strlen(str) ); +} + +extern void +stralloc_add_bytes( stralloc_t* s, const void* from, unsigned len ) +{ + stralloc_readyplus( s, len ); + memcpy( s->s + s->n, from, len ); + s->n += len; +} + +extern char* +stralloc_cstr( stralloc_t* s ) +{ + stralloc_readyplus( s, 1 ); + s->s[s->n] = 0; + return s->s; +} + +extern char* +stralloc_to_tempstr( stralloc_t* s ) +{ + char* q = tempstr_get( s->n ); + + memcpy( q, s->s, s->n ); + q[s->n] = 0; + return q; +} + +extern void +stralloc_formatv( stralloc_t* s, const char* fmt, va_list args ) +{ + stralloc_reset(s); + stralloc_ready(s,10); + + while (1) { + int n; + va_list args2; + + va_copy(args2, args); + n = vsnprintf( s->s, s->a, fmt, args2 ); + va_end(args2); + + /* funky old C libraries returns -1 when truncation occurs */ + if (n > -1 && n < s->a) { + s->n = n; + break; + } + if (n > -1) { /* we now precisely what we need */ + stralloc_ready( s, n+1 ); + } else { + stralloc_ready( s, s->a*2 ); + } + } +} + + +extern void +stralloc_format( stralloc_t* s, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + stralloc_formatv(s, fmt, args); + va_end(args); +} + +extern void +stralloc_add_formatv( stralloc_t* s, const char* fmt, va_list args ) +{ + STRALLOC_DEFINE(s2); + stralloc_formatv(s2, fmt, args); + stralloc_append( s, s2 ); + stralloc_reset( s2 ); +} + +extern void +stralloc_add_format( stralloc_t* s, const char* fmt, ... ) +{ + va_list args; + va_start(args, fmt); + stralloc_add_formatv( s, fmt, args ); + va_end(args); +} + +extern void +stralloc_add_quote_c( stralloc_t* s, int c ) +{ + stralloc_add_quote_bytes( s, (char*)&c, 1 ); +} + +extern void +stralloc_add_quote_str( stralloc_t* s, const char* str ) +{ + stralloc_add_quote_bytes( s, str, strlen(str) ); +} + +extern void +stralloc_add_quote_bytes( stralloc_t* s, const void* from, unsigned len ) +{ + uint8_t* p = (uint8_t*) from; + uint8_t* end = p + len; + + for ( ; p < end; p++ ) { + int c = p[0]; + + if (c == '\\') { + stralloc_add_str( s, "\\\\" ); + } else if (c >= ' ' && c < 128) { + stralloc_add_c( s, c ); + } else if (c == '\n') { + stralloc_add_str( s, "\\n" ); + } else if (c == '\t') { + stralloc_add_str( s, "\\t" ); + } else if (c == '\r') { + stralloc_add_str( s, "\\r" ); + } else { + stralloc_add_format( s, "\\x%02x", c ); + } + } +} + +extern void +stralloc_add_hex( stralloc_t* s, unsigned value, int num_digits ) +{ + const char hexdigits[16] = "0123456789abcdef"; + int nn; + + if (num_digits <= 0) + return; + + stralloc_readyplus(s, num_digits); + for (nn = num_digits-1; nn >= 0; nn--) { + s->s[s->n+nn] = hexdigits[value & 15]; + value >>= 4; + } + s->n += num_digits; +} + +extern void +stralloc_add_hexdump( stralloc_t* s, void* base, int size, const char* prefix ) +{ + uint8_t* p = (uint8_t*)base; + const int max_count = 16; + int prefix_len = strlen(prefix); + + while (size > 0) { + int count = size > max_count ? max_count : size; + int count2; + int n; + + stralloc_add_bytes( s, prefix, prefix_len ); + stralloc_add_hex( s, p[0], 2 ); + + for (n = 1; n < count; n++) { + stralloc_add_c( s, ' ' ); + stralloc_add_hex( s, p[n], 2 ); + } + + count2 = 4 + 3*(max_count - count); + stralloc_readyplus( s, count2 ); + memset( s->s + s->n, ' ', count2 ); + s->n += count2; + + stralloc_readyplus(s, count+1); + for (n = 0; n < count; n++) { + int c = p[n]; + + if (c < 32 || c > 127) + c = '.'; + + s->s[s->n++] = c; + } + s->s[s->n++] = '\n'; + + size -= count; + p += count; + } +} + |