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