2
* Copyright (C) 2005 The Android Open Source Project
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
8
* http://www.apache.org/licenses/LICENSE-2.0
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.
17
#include <utils/Debug.h>
19
#include <utils/misc.h>
27
// ---------------------------------------------------------------------
29
static const char indentStr[] =
33
const char* stringForIndent(int32_t indentLevel)
35
ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
36
return indentStr + (off < 0 ? 0 : off);
39
// ---------------------------------------------------------------------
41
static void defaultPrintFunc(void* cookie, const char* txt)
46
// ---------------------------------------------------------------------
48
static inline int isident(int c)
50
return isalnum(c) || c == '_';
53
static inline bool isasciitype(char c)
55
if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
59
static inline char makehexdigit(uint32_t val)
61
return "0123456789abcdef"[val&0xF];
64
static char* appendhexnum(uint32_t val, char* out)
66
for( int32_t i=28; i>=0; i-=4 ) {
67
*out++ = makehexdigit( val>>i );
73
static inline char makeupperhexdigit(uint32_t val)
75
return "0123456789ABCDEF"[val&0xF];
78
static char* appendupperhexnum(uint32_t val, char* out)
80
for( int32_t i=28; i>=0; i-=4 ) {
81
*out++ = makeupperhexdigit( val>>i );
87
static char* appendcharornum(char c, char* out, bool skipzero = true)
89
if (skipzero && c == 0) return out;
98
*out++ = makehexdigit(c>>4);
99
*out++ = makehexdigit(c);
103
static char* typetostring(uint32_t type, char* out,
104
bool fullContext = true,
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);
115
// now even less strict!
116
// valid = isasciitype(c[3]);
120
while (valid && i<3) {
122
if (!zero) valid = false;
125
//if (!isasciitype(c[i])) valid = false;
129
// if all zeros, not a valid type code.
130
if (zero) valid = false;
132
valid = isident(c[3]) ? true : false;
135
while (valid && i<3) {
137
if (!zero) valid = false;
140
if (!isident(c[i])) valid = false;
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++ = '\'';
160
return appendhexnum(type, pos);
163
void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
166
char* end = typetostring(typeCode, buffer);
168
func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
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)
176
if (alignment == 0) {
177
if (bytesPerLine >= 16) alignment = 4;
178
else if (bytesPerLine >= 8) alignment = 2;
181
if (func == NULL) func = defaultPrintFunc;
185
unsigned char *pos = (unsigned char *)buf;
188
if (singleLineBytesCutoff < 0) func(cookie, "\n");
189
func(cookie, "(NULL)");
194
if (singleLineBytesCutoff < 0) func(cookie, "\n");
195
func(cookie, "(empty)");
199
if ((int32_t)length < 0) {
200
if (singleLineBytesCutoff < 0) func(cookie, "\n");
202
sprintf(buf, "(bad length: %zu)", length);
208
static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
210
if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
212
const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
213
bool newLine = false;
218
} else if (!oneLine) {
223
for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
224
long remain = length;
227
if (!oneLine && !cStyle) {
228
sprintf(c, "0x%08x: ", (int)offset);
235
for (word = 0; word < bytesPerLine; ) {
237
#ifdef HAVE_LITTLE_ENDIAN
238
const size_t startIndex = word+(alignment-(alignment?1:0));
239
const ssize_t dir = -1;
241
const size_t startIndex = word;
242
const ssize_t dir = 1;
245
for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
248
if (index == 0 && word > 0 && alignment > 0) {
253
const unsigned char val = *(pos+startIndex+(index*dir));
254
*c++ = makehexdigit(val>>4);
255
*c++ = makehexdigit(val);
256
} else if (!oneLine) {
262
if (index == 0 && word > 0) {
270
const unsigned char val = *(pos+startIndex+(index*dir));
271
*c++ = makehexdigit(val>>4);
272
*c++ = makehexdigit(val);
285
for (index = 0; index < bytesPerLine; index++) {
288
const unsigned char val = pos[index];
289
*c++ = (val >= ' ' && val < 127) ? val : '.';
290
} else if (!oneLine) {
296
if (length > bytesPerLine) *c++ = '\n';
298
if (remain > 0) *c++ = ',';
302
if (newLine && indent) func(cookie, stringForIndent(indent));
304
func(cookie, buffer);
307
if (length <= bytesPerLine) break;
308
length -= bytesPerLine;
312
if (indent > 0) func(cookie, stringForIndent(indent-1));
317
}; // namespace android