• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <utils/Debug.h>
18 
19 #include <utils/misc.h>
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24 
25 namespace android {
26 
27 // ---------------------------------------------------------------------
28 
29 static const char indentStr[] =
30 "                                                                            "
31 "                                                                            ";
32 
stringForIndent(int32_t indentLevel)33 const char* stringForIndent(int32_t indentLevel)
34 {
35     ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
36     return indentStr + (off < 0 ? 0 : off);
37 }
38 
39 // ---------------------------------------------------------------------
40 
defaultPrintFunc(void * cookie,const char * txt)41 static void defaultPrintFunc(void* cookie, const char* txt)
42 {
43     printf("%s", txt);
44 }
45 
46 // ---------------------------------------------------------------------
47 
isident(int c)48 static inline int isident(int c)
49 {
50     return isalnum(c) || c == '_';
51 }
52 
isasciitype(char c)53 static inline bool isasciitype(char c)
54 {
55     if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
56     return false;
57 }
58 
makehexdigit(uint32_t val)59 static inline char makehexdigit(uint32_t val)
60 {
61     return "0123456789abcdef"[val&0xF];
62 }
63 
appendhexnum(uint32_t val,char * out)64 static char* appendhexnum(uint32_t val, char* out)
65 {
66     for( int32_t i=28; i>=0; i-=4 ) {
67         *out++ = makehexdigit( val>>i );
68     }
69     *out = 0;
70     return out;
71 }
72 
makeupperhexdigit(uint32_t val)73 static inline char makeupperhexdigit(uint32_t val)
74 {
75     return "0123456789ABCDEF"[val&0xF];
76 }
77 
appendupperhexnum(uint32_t val,char * out)78 static char* appendupperhexnum(uint32_t val, char* out)
79 {
80     for( int32_t i=28; i>=0; i-=4 ) {
81         *out++ = makeupperhexdigit( val>>i );
82     }
83     *out = 0;
84     return out;
85 }
86 
appendcharornum(char c,char * out,bool skipzero=true)87 static char* appendcharornum(char c, char* out, bool skipzero = true)
88 {
89     if (skipzero && c == 0) return out;
90 
91     if (isasciitype(c)) {
92         *out++ = c;
93         return out;
94     }
95 
96     *out++ = '\\';
97     *out++ = 'x';
98     *out++ = makehexdigit(c>>4);
99     *out++ = makehexdigit(c);
100     return out;
101 }
102 
typetostring(uint32_t type,char * out,bool fullContext=true,bool strict=false)103 static char* typetostring(uint32_t type, char* out,
104                           bool fullContext = true,
105                           bool strict = false)
106 {
107     char* pos = out;
108     char c[4];
109     c[0] = (char)((type>>24)&0xFF);
110     c[1] = (char)((type>>16)&0xFF);
111     c[2] = (char)((type>>8)&0xFF);
112     c[3] = (char)(type&0xFF);
113     bool valid;
114     if( !strict ) {
115         // now even less strict!
116         // valid = isasciitype(c[3]);
117         valid = true;
118         int32_t i = 0;
119         bool zero = true;
120         while (valid && i<3) {
121             if (c[i] == 0) {
122                 if (!zero) valid = false;
123             } else {
124                 zero = false;
125                 //if (!isasciitype(c[i])) valid = false;
126             }
127             i++;
128         }
129         // if all zeros, not a valid type code.
130         if (zero) valid = false;
131     } else {
132         valid = isident(c[3]) ? true : false;
133         int32_t i = 0;
134         bool zero = true;
135         while (valid && i<3) {
136             if (c[i] == 0) {
137                 if (!zero) valid = false;
138             } else {
139                 zero = false;
140                 if (!isident(c[i])) valid = false;
141             }
142             i++;
143         }
144     }
145     if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) {
146         if( fullContext ) *pos++ = '\'';
147         pos = appendcharornum(c[0], pos);
148         pos = appendcharornum(c[1], pos);
149         pos = appendcharornum(c[2], pos);
150         pos = appendcharornum(c[3], pos);
151         if( fullContext ) *pos++ = '\'';
152         *pos = 0;
153         return pos;
154     }
155 
156     if( fullContext ) {
157         *pos++ = '0';
158         *pos++ = 'x';
159     }
160     return appendhexnum(type, pos);
161 }
162 
printTypeCode(uint32_t typeCode,debugPrintFunc func,void * cookie)163 void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
164 {
165     char buffer[32];
166     char* end = typetostring(typeCode, buffer);
167     *end = 0;
168     func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
169 }
170 
printHexData(int32_t indent,const void * buf,size_t length,size_t bytesPerLine,int32_t singleLineBytesCutoff,size_t alignment,bool cStyle,debugPrintFunc func,void * cookie)171 void printHexData(int32_t indent, const void *buf, size_t length,
172     size_t bytesPerLine, int32_t singleLineBytesCutoff,
173     size_t alignment, bool cStyle,
174     debugPrintFunc func, void* cookie)
175 {
176     if (alignment == 0) {
177         if (bytesPerLine >= 16) alignment = 4;
178         else if (bytesPerLine >= 8) alignment = 2;
179         else alignment = 1;
180     }
181     if (func == NULL) func = defaultPrintFunc;
182 
183     size_t offset;
184 
185     unsigned char *pos = (unsigned char *)buf;
186 
187     if (pos == NULL) {
188         if (singleLineBytesCutoff < 0) func(cookie, "\n");
189         func(cookie, "(NULL)");
190         return;
191     }
192 
193     if (length == 0) {
194         if (singleLineBytesCutoff < 0) func(cookie, "\n");
195         func(cookie, "(empty)");
196         return;
197     }
198 
199     if ((int32_t)length < 0) {
200         if (singleLineBytesCutoff < 0) func(cookie, "\n");
201         char buf[64];
202         sprintf(buf, "(bad length: %zu)", length);
203         func(cookie, buf);
204         return;
205     }
206 
207     char buffer[256];
208     static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
209 
210     if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
211 
212     const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
213     bool newLine = false;
214     if (cStyle) {
215         indent++;
216         func(cookie, "{\n");
217         newLine = true;
218     } else if (!oneLine) {
219         func(cookie, "\n");
220         newLine = true;
221     }
222 
223     for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
224         long remain = length;
225 
226         char* c = buffer;
227         if (!oneLine && !cStyle) {
228             sprintf(c, "0x%08x: ", (int)offset);
229             c += 12;
230         }
231 
232         size_t index;
233         size_t word;
234 
235         for (word = 0; word < bytesPerLine; ) {
236 
237 #ifdef HAVE_LITTLE_ENDIAN
238             const size_t startIndex = word+(alignment-(alignment?1:0));
239             const ssize_t dir = -1;
240 #else
241             const size_t startIndex = word;
242             const ssize_t dir = 1;
243 #endif
244 
245             for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
246 
247                 if (!cStyle) {
248                     if (index == 0 && word > 0 && alignment > 0) {
249                         *c++ = ' ';
250                     }
251 
252                     if (remain-- > 0) {
253                         const unsigned char val = *(pos+startIndex+(index*dir));
254                         *c++ = makehexdigit(val>>4);
255                         *c++ = makehexdigit(val);
256                     } else if (!oneLine) {
257                         *c++ = ' ';
258                         *c++ = ' ';
259                     }
260                 } else {
261                     if (remain > 0) {
262                         if (index == 0 && word > 0) {
263                             *c++ = ',';
264                             *c++ = ' ';
265                         }
266                         if (index == 0) {
267                             *c++ = '0';
268                             *c++ = 'x';
269                         }
270                         const unsigned char val = *(pos+startIndex+(index*dir));
271                         *c++ = makehexdigit(val>>4);
272                         *c++ = makehexdigit(val);
273                         remain--;
274                     }
275                 }
276             }
277 
278             word += index;
279         }
280 
281         if (!cStyle) {
282             remain = length;
283             *c++ = ' ';
284             *c++ = '\'';
285             for (index = 0; index < bytesPerLine; index++) {
286 
287                 if (remain-- > 0) {
288                     const unsigned char val = pos[index];
289                     *c++ = (val >= ' ' && val < 127) ? val : '.';
290                 } else if (!oneLine) {
291                     *c++ = ' ';
292                 }
293             }
294 
295             *c++ = '\'';
296             if (length > bytesPerLine) *c++ = '\n';
297         } else {
298             if (remain > 0) *c++ = ',';
299             *c++ = '\n';
300         }
301 
302         if (newLine && indent) func(cookie, stringForIndent(indent));
303         *c = 0;
304         func(cookie, buffer);
305         newLine = true;
306 
307         if (length <= bytesPerLine) break;
308         length -= bytesPerLine;
309     }
310 
311     if (cStyle) {
312         if (indent > 0) func(cookie, stringForIndent(indent-1));
313         func(cookie, "};");
314     }
315 }
316 
317 }; // namespace android
318 
319