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
stralloc_tabular(stralloc_t * out,const char ** strings,int count,const char * prefix,int width)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
stralloc_reset(stralloc_t * s)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
stralloc_ready(stralloc_t * s,unsigned int len)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
stralloc_readyplus(stralloc_t * s,unsigned int len)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
stralloc_copy(stralloc_t * s,stralloc_t * from)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
stralloc_append(stralloc_t * s,stralloc_t * from)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
stralloc_add_c(stralloc_t * s,int c)114 stralloc_add_c( stralloc_t* s, int c )
115 {
116 stralloc_add_bytes( s, (char*)&c, 1 );
117 }
118
119 extern void
stralloc_add_str(stralloc_t * s,const char * str)120 stralloc_add_str( stralloc_t* s, const char* str )
121 {
122 stralloc_add_bytes( s, str, strlen(str) );
123 }
124
125 extern void
stralloc_add_bytes(stralloc_t * s,const void * from,unsigned len)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*
stralloc_cstr(stralloc_t * s)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 extern char*
stralloc_to_tempstr(stralloc_t * s)142 stralloc_to_tempstr( stralloc_t* s )
143 {
144 char* q = tempstr_get( s->n );
145
146 memcpy( q, s->s, s->n );
147 q[s->n] = 0;
148 return q;
149 }
150
151 extern void
stralloc_formatv(stralloc_t * s,const char * fmt,va_list args)152 stralloc_formatv( stralloc_t* s, const char* fmt, va_list args )
153 {
154 stralloc_reset(s);
155 stralloc_ready(s,10);
156
157 while (1) {
158 int n;
159 va_list args2;
160
161 va_copy(args2, args);
162 n = vsnprintf( s->s, s->a, fmt, args2 );
163 va_end(args2);
164
165 /* funky old C libraries returns -1 when truncation occurs */
166 if (n > -1 && n < s->a) {
167 s->n = n;
168 break;
169 }
170 if (n > -1) { /* we now precisely what we need */
171 stralloc_ready( s, n+1 );
172 } else {
173 stralloc_ready( s, s->a*2 );
174 }
175 }
176 }
177
178
179 extern void
stralloc_format(stralloc_t * s,const char * fmt,...)180 stralloc_format( stralloc_t* s, const char* fmt, ... )
181 {
182 va_list args;
183 va_start(args, fmt);
184 stralloc_formatv(s, fmt, args);
185 va_end(args);
186 }
187
188 extern void
stralloc_add_formatv(stralloc_t * s,const char * fmt,va_list args)189 stralloc_add_formatv( stralloc_t* s, const char* fmt, va_list args )
190 {
191 STRALLOC_DEFINE(s2);
192 stralloc_formatv(s2, fmt, args);
193 stralloc_append( s, s2 );
194 stralloc_reset( s2 );
195 }
196
197 extern void
stralloc_add_format(stralloc_t * s,const char * fmt,...)198 stralloc_add_format( stralloc_t* s, const char* fmt, ... )
199 {
200 va_list args;
201 va_start(args, fmt);
202 stralloc_add_formatv( s, fmt, args );
203 va_end(args);
204 }
205
206 extern void
stralloc_add_quote_c(stralloc_t * s,int c)207 stralloc_add_quote_c( stralloc_t* s, int c )
208 {
209 stralloc_add_quote_bytes( s, (char*)&c, 1 );
210 }
211
212 extern void
stralloc_add_quote_str(stralloc_t * s,const char * str)213 stralloc_add_quote_str( stralloc_t* s, const char* str )
214 {
215 stralloc_add_quote_bytes( s, str, strlen(str) );
216 }
217
218 extern void
stralloc_add_quote_bytes(stralloc_t * s,const void * from,unsigned len)219 stralloc_add_quote_bytes( stralloc_t* s, const void* from, unsigned len )
220 {
221 uint8_t* p = (uint8_t*) from;
222 uint8_t* end = p + len;
223
224 for ( ; p < end; p++ ) {
225 int c = p[0];
226
227 if (c == '\\') {
228 stralloc_add_str( s, "\\\\" );
229 } else if (c >= ' ' && c < 128) {
230 stralloc_add_c( s, c );
231 } else if (c == '\n') {
232 stralloc_add_str( s, "\\n" );
233 } else if (c == '\t') {
234 stralloc_add_str( s, "\\t" );
235 } else if (c == '\r') {
236 stralloc_add_str( s, "\\r" );
237 } else {
238 stralloc_add_format( s, "\\x%02x", c );
239 }
240 }
241 }
242
243 extern void
stralloc_add_hex(stralloc_t * s,unsigned value,int num_digits)244 stralloc_add_hex( stralloc_t* s, unsigned value, int num_digits )
245 {
246 const char hexdigits[16] = "0123456789abcdef";
247 int nn;
248
249 if (num_digits <= 0)
250 return;
251
252 stralloc_readyplus(s, num_digits);
253 for (nn = num_digits-1; nn >= 0; nn--) {
254 s->s[s->n+nn] = hexdigits[value & 15];
255 value >>= 4;
256 }
257 s->n += num_digits;
258 }
259
260 extern void
stralloc_add_hexdump(stralloc_t * s,void * base,int size,const char * prefix)261 stralloc_add_hexdump( stralloc_t* s, void* base, int size, const char* prefix )
262 {
263 uint8_t* p = (uint8_t*)base;
264 const int max_count = 16;
265 int prefix_len = strlen(prefix);
266
267 while (size > 0) {
268 int count = size > max_count ? max_count : size;
269 int count2;
270 int n;
271
272 stralloc_add_bytes( s, prefix, prefix_len );
273 stralloc_add_hex( s, p[0], 2 );
274
275 for (n = 1; n < count; n++) {
276 stralloc_add_c( s, ' ' );
277 stralloc_add_hex( s, p[n], 2 );
278 }
279
280 count2 = 4 + 3*(max_count - count);
281 stralloc_readyplus( s, count2 );
282 memset( s->s + s->n, ' ', count2 );
283 s->n += count2;
284
285 stralloc_readyplus(s, count+1);
286 for (n = 0; n < count; n++) {
287 int c = p[n];
288
289 if (c < 32 || c > 127)
290 c = '.';
291
292 s->s[s->n++] = c;
293 }
294 s->s[s->n++] = '\n';
295
296 size -= count;
297 p += count;
298 }
299 }
300
301