• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 void
stralloc_lstrip(stralloc_t * s)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
stralloc_rstrip(stralloc_t * s)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
stralloc_strip(stralloc_t * s)169 stralloc_strip( stralloc_t* s )
170 {
171     stralloc_rstrip(s);
172     stralloc_lstrip(s);
173 }
174 
175 extern char*
stralloc_to_tempstr(stralloc_t * s)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
stralloc_formatv(stralloc_t * s,const char * fmt,va_list args)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
stralloc_format(stralloc_t * s,const char * fmt,...)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
stralloc_add_formatv(stralloc_t * s,const char * fmt,va_list args)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
stralloc_add_format(stralloc_t * s,const char * fmt,...)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
stralloc_add_quote_c(stralloc_t * s,int c)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
stralloc_add_quote_str(stralloc_t * s,const char * str)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
stralloc_add_quote_bytes(stralloc_t * s,const void * from,unsigned len)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
stralloc_add_hex(stralloc_t * s,unsigned value,int num_digits)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
stralloc_add_hexdump(stralloc_t * s,void * base,int size,const char * prefix)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