Debug.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. #include <binder/Debug.h>
  17. #include <utils/misc.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <ctype.h>
  21. namespace android {
  22. // ---------------------------------------------------------------------
  23. static const char indentStr[] =
  24. " "
  25. " ";
  26. const char* stringForIndent(int32_t indentLevel)
  27. {
  28. ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
  29. return indentStr + (off < 0 ? 0 : off);
  30. }
  31. // ---------------------------------------------------------------------
  32. static void defaultPrintFunc(void* /*cookie*/, const char* txt)
  33. {
  34. printf("%s", txt);
  35. }
  36. // ---------------------------------------------------------------------
  37. static inline int isident(int c)
  38. {
  39. return isalnum(c) || c == '_';
  40. }
  41. static inline bool isasciitype(char c)
  42. {
  43. if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
  44. return false;
  45. }
  46. static inline char makehexdigit(uint32_t val)
  47. {
  48. return "0123456789abcdef"[val&0xF];
  49. }
  50. static char* appendhexnum(uint32_t val, char* out)
  51. {
  52. for( int32_t i=28; i>=0; i-=4 ) {
  53. *out++ = makehexdigit( val>>i );
  54. }
  55. *out = 0;
  56. return out;
  57. }
  58. static char* appendcharornum(char c, char* out, bool skipzero = true)
  59. {
  60. if (skipzero && c == 0) return out;
  61. if (isasciitype(c)) {
  62. *out++ = c;
  63. return out;
  64. }
  65. *out++ = '\\';
  66. *out++ = 'x';
  67. *out++ = makehexdigit(c>>4);
  68. *out++ = makehexdigit(c);
  69. return out;
  70. }
  71. static char* typetostring(uint32_t type, char* out,
  72. bool fullContext = true,
  73. bool strict = false)
  74. {
  75. char* pos = out;
  76. char c[4];
  77. c[0] = (char)((type>>24)&0xFF);
  78. c[1] = (char)((type>>16)&0xFF);
  79. c[2] = (char)((type>>8)&0xFF);
  80. c[3] = (char)(type&0xFF);
  81. bool valid;
  82. if( !strict ) {
  83. // now even less strict!
  84. // valid = isasciitype(c[3]);
  85. valid = true;
  86. int32_t i = 0;
  87. bool zero = true;
  88. while (valid && i<3) {
  89. if (c[i] == 0) {
  90. if (!zero) valid = false;
  91. } else {
  92. zero = false;
  93. //if (!isasciitype(c[i])) valid = false;
  94. }
  95. i++;
  96. }
  97. // if all zeros, not a valid type code.
  98. if (zero) valid = false;
  99. } else {
  100. valid = isident(c[3]) ? true : false;
  101. int32_t i = 0;
  102. bool zero = true;
  103. while (valid && i<3) {
  104. if (c[i] == 0) {
  105. if (!zero) valid = false;
  106. } else {
  107. zero = false;
  108. if (!isident(c[i])) valid = false;
  109. }
  110. i++;
  111. }
  112. }
  113. if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) {
  114. if( fullContext ) *pos++ = '\'';
  115. pos = appendcharornum(c[0], pos);
  116. pos = appendcharornum(c[1], pos);
  117. pos = appendcharornum(c[2], pos);
  118. pos = appendcharornum(c[3], pos);
  119. if( fullContext ) *pos++ = '\'';
  120. *pos = 0;
  121. return pos;
  122. }
  123. if( fullContext ) {
  124. *pos++ = '0';
  125. *pos++ = 'x';
  126. }
  127. return appendhexnum(type, pos);
  128. }
  129. void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
  130. {
  131. char buffer[32];
  132. char* end = typetostring(typeCode, buffer);
  133. *end = 0;
  134. func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
  135. }
  136. void printHexData(int32_t indent, const void *buf, size_t length,
  137. size_t bytesPerLine, int32_t singleLineBytesCutoff,
  138. size_t alignment, bool cStyle,
  139. debugPrintFunc func, void* cookie)
  140. {
  141. if (alignment == 0) {
  142. if (bytesPerLine >= 16) alignment = 4;
  143. else if (bytesPerLine >= 8) alignment = 2;
  144. else alignment = 1;
  145. }
  146. if (func == NULL) func = defaultPrintFunc;
  147. size_t offset;
  148. unsigned char *pos = (unsigned char *)buf;
  149. if (pos == NULL) {
  150. if (singleLineBytesCutoff < 0) func(cookie, "\n");
  151. func(cookie, "(NULL)");
  152. return;
  153. }
  154. if (length == 0) {
  155. if (singleLineBytesCutoff < 0) func(cookie, "\n");
  156. func(cookie, "(empty)");
  157. return;
  158. }
  159. if ((int32_t)length < 0) {
  160. if (singleLineBytesCutoff < 0) func(cookie, "\n");
  161. char buf[64];
  162. sprintf(buf, "(bad length: %zu)", length);
  163. func(cookie, buf);
  164. return;
  165. }
  166. char buffer[256];
  167. static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
  168. if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
  169. const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
  170. bool newLine = false;
  171. if (cStyle) {
  172. indent++;
  173. func(cookie, "{\n");
  174. newLine = true;
  175. } else if (!oneLine) {
  176. func(cookie, "\n");
  177. newLine = true;
  178. }
  179. for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
  180. long remain = length;
  181. char* c = buffer;
  182. if (!oneLine && !cStyle) {
  183. sprintf(c, "0x%08x: ", (int)offset);
  184. c += 12;
  185. }
  186. size_t index;
  187. size_t word;
  188. for (word = 0; word < bytesPerLine; ) {
  189. const size_t startIndex = word+(alignment-(alignment?1:0));
  190. const ssize_t dir = -1;
  191. for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
  192. if (!cStyle) {
  193. if (index == 0 && word > 0 && alignment > 0) {
  194. *c++ = ' ';
  195. }
  196. if (remain-- > 0) {
  197. const unsigned char val = *(pos+startIndex+(index*dir));
  198. *c++ = makehexdigit(val>>4);
  199. *c++ = makehexdigit(val);
  200. } else if (!oneLine) {
  201. *c++ = ' ';
  202. *c++ = ' ';
  203. }
  204. } else {
  205. if (remain > 0) {
  206. if (index == 0 && word > 0) {
  207. *c++ = ',';
  208. *c++ = ' ';
  209. }
  210. if (index == 0) {
  211. *c++ = '0';
  212. *c++ = 'x';
  213. }
  214. const unsigned char val = *(pos+startIndex+(index*dir));
  215. *c++ = makehexdigit(val>>4);
  216. *c++ = makehexdigit(val);
  217. remain--;
  218. }
  219. }
  220. }
  221. word += index;
  222. }
  223. if (!cStyle) {
  224. remain = length;
  225. *c++ = ' ';
  226. *c++ = '\'';
  227. for (index = 0; index < bytesPerLine; index++) {
  228. if (remain-- > 0) {
  229. const unsigned char val = pos[index];
  230. *c++ = (val >= ' ' && val < 127) ? val : '.';
  231. } else if (!oneLine) {
  232. *c++ = ' ';
  233. }
  234. }
  235. *c++ = '\'';
  236. if (length > bytesPerLine) *c++ = '\n';
  237. } else {
  238. if (remain > 0) *c++ = ',';
  239. *c++ = '\n';
  240. }
  241. if (newLine && indent) func(cookie, stringForIndent(indent));
  242. *c = 0;
  243. func(cookie, buffer);
  244. newLine = true;
  245. if (length <= bytesPerLine) break;
  246. length -= bytesPerLine;
  247. }
  248. if (cStyle) {
  249. if (indent > 0) func(cookie, stringForIndent(indent-1));
  250. func(cookie, "};");
  251. }
  252. }
  253. }; // namespace android