Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2007 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 package com.android.dexgen.util;
     18 
     19 /**
     20  * Utilities for formatting numbers as hexadecimal.
     21  */
     22 public final class Hex {
     23     /**
     24      * This class is uninstantiable.
     25      */
     26     private Hex() {
     27         // This space intentionally left blank.
     28     }
     29 
     30     /**
     31      * Formats a {@code long} as an 8-byte unsigned hex value.
     32      *
     33      * @param v value to format
     34      * @return {@code non-null;} formatted form
     35      */
     36     public static String u8(long v) {
     37         char[] result = new char[16];
     38         for (int i = 0; i < 16; i++) {
     39             result[15 - i] = Character.forDigit((int) v & 0x0f, 16);
     40             v >>= 4;
     41         }
     42 
     43         return new String(result);
     44     }
     45 
     46     /**
     47      * Formats an {@code int} as a 4-byte unsigned hex value.
     48      *
     49      * @param v value to format
     50      * @return {@code non-null;} formatted form
     51      */
     52     public static String u4(int v) {
     53         char[] result = new char[8];
     54         for (int i = 0; i < 8; i++) {
     55             result[7 - i] = Character.forDigit(v & 0x0f, 16);
     56             v >>= 4;
     57         }
     58 
     59         return new String(result);
     60     }
     61 
     62     /**
     63      * Formats an {@code int} as a 3-byte unsigned hex value.
     64      *
     65      * @param v value to format
     66      * @return {@code non-null;} formatted form
     67      */
     68     public static String u3(int v) {
     69         char[] result = new char[6];
     70         for (int i = 0; i < 6; i++) {
     71             result[5 - i] = Character.forDigit(v & 0x0f, 16);
     72             v >>= 4;
     73         }
     74 
     75         return new String(result);
     76     }
     77 
     78     /**
     79      * Formats an {@code int} as a 2-byte unsigned hex value.
     80      *
     81      * @param v value to format
     82      * @return {@code non-null;} formatted form
     83      */
     84     public static String u2(int v) {
     85         char[] result = new char[4];
     86         for (int i = 0; i < 4; i++) {
     87             result[3 - i] = Character.forDigit(v & 0x0f, 16);
     88             v >>= 4;
     89         }
     90 
     91         return new String(result);
     92     }
     93 
     94     /**
     95      * Formats an {@code int} as either a 2-byte unsigned hex value
     96      * (if the value is small enough) or a 4-byte unsigned hex value (if
     97      * not).
     98      *
     99      * @param v value to format
    100      * @return {@code non-null;} formatted form
    101      */
    102     public static String u2or4(int v) {
    103         if (v == (char) v) {
    104             return u2(v);
    105         } else {
    106             return u4(v);
    107         }
    108     }
    109 
    110     /**
    111      * Formats an {@code int} as a 1-byte unsigned hex value.
    112      *
    113      * @param v value to format
    114      * @return {@code non-null;} formatted form
    115      */
    116     public static String u1(int v) {
    117         char[] result = new char[2];
    118         for (int i = 0; i < 2; i++) {
    119             result[1 - i] = Character.forDigit(v & 0x0f, 16);
    120             v >>= 4;
    121         }
    122 
    123         return new String(result);
    124     }
    125 
    126     /**
    127      * Formats an {@code int} as a 4-bit unsigned hex nibble.
    128      *
    129      * @param v value to format
    130      * @return {@code non-null;} formatted form
    131      */
    132     public static String uNibble(int v) {
    133         char[] result = new char[1];
    134 
    135         result[0] = Character.forDigit(v & 0x0f, 16);
    136         return new String(result);
    137     }
    138 
    139     /**
    140      * Formats a {@code long} as an 8-byte signed hex value.
    141      *
    142      * @param v value to format
    143      * @return {@code non-null;} formatted form
    144      */
    145     public static String s8(long v) {
    146         char[] result = new char[17];
    147 
    148         if (v < 0) {
    149             result[0] = '-';
    150             v = -v;
    151         } else {
    152             result[0] = '+';
    153         }
    154 
    155         for (int i = 0; i < 16; i++) {
    156             result[16 - i] = Character.forDigit((int) v & 0x0f, 16);
    157             v >>= 4;
    158         }
    159 
    160         return new String(result);
    161     }
    162 
    163     /**
    164      * Formats an {@code int} as a 4-byte signed hex value.
    165      *
    166      * @param v value to format
    167      * @return {@code non-null;} formatted form
    168      */
    169     public static String s4(int v) {
    170         char[] result = new char[9];
    171 
    172         if (v < 0) {
    173             result[0] = '-';
    174             v = -v;
    175         } else {
    176             result[0] = '+';
    177         }
    178 
    179         for (int i = 0; i < 8; i++) {
    180             result[8 - i] = Character.forDigit(v & 0x0f, 16);
    181             v >>= 4;
    182         }
    183 
    184         return new String(result);
    185     }
    186 
    187     /**
    188      * Formats an {@code int} as a 2-byte signed hex value.
    189      *
    190      * @param v value to format
    191      * @return {@code non-null;} formatted form
    192      */
    193     public static String s2(int v) {
    194         char[] result = new char[5];
    195 
    196         if (v < 0) {
    197             result[0] = '-';
    198             v = -v;
    199         } else {
    200             result[0] = '+';
    201         }
    202 
    203         for (int i = 0; i < 4; i++) {
    204             result[4 - i] = Character.forDigit(v & 0x0f, 16);
    205             v >>= 4;
    206         }
    207 
    208         return new String(result);
    209     }
    210 
    211     /**
    212      * Formats an {@code int} as a 1-byte signed hex value.
    213      *
    214      * @param v value to format
    215      * @return {@code non-null;} formatted form
    216      */
    217     public static String s1(int v) {
    218         char[] result = new char[3];
    219 
    220         if (v < 0) {
    221             result[0] = '-';
    222             v = -v;
    223         } else {
    224             result[0] = '+';
    225         }
    226 
    227         for (int i = 0; i < 2; i++) {
    228             result[2 - i] = Character.forDigit(v & 0x0f, 16);
    229             v >>= 4;
    230         }
    231 
    232         return new String(result);
    233     }
    234 
    235     /**
    236      * Formats a hex dump of a portion of a {@code byte[]}. The result
    237      * is always newline-terminated, unless the passed-in length was zero,
    238      * in which case the result is always the empty string ({@code ""}).
    239      *
    240      * @param arr {@code non-null;} array to format
    241      * @param offset {@code >= 0;} offset to the part to dump
    242      * @param length {@code >= 0;} number of bytes to dump
    243      * @param outOffset {@code >= 0;} first output offset to print
    244      * @param bpl {@code >= 0;} number of bytes of output per line
    245      * @param addressLength {@code {2,4,6,8};} number of characters for each address
    246      * header
    247      * @return {@code non-null;} a string of the dump
    248      */
    249     public static String dump(byte[] arr, int offset, int length,
    250                               int outOffset, int bpl, int addressLength) {
    251         int end = offset + length;
    252 
    253         // twos-complement math trick: ((x < 0) || (y < 0)) <=> ((x|y) < 0)
    254         if (((offset | length | end) < 0) || (end > arr.length)) {
    255             throw new IndexOutOfBoundsException("arr.length " +
    256                                                 arr.length + "; " +
    257                                                 offset + "..!" + end);
    258         }
    259 
    260         if (outOffset < 0) {
    261             throw new IllegalArgumentException("outOffset < 0");
    262         }
    263 
    264         if (length == 0) {
    265             return "";
    266         }
    267 
    268         StringBuffer sb = new StringBuffer(length * 4 + 6);
    269         boolean bol = true;
    270         int col = 0;
    271 
    272         while (length > 0) {
    273             if (col == 0) {
    274                 String astr;
    275                 switch (addressLength) {
    276                     case 2:  astr = Hex.u1(outOffset); break;
    277                     case 4:  astr = Hex.u2(outOffset); break;
    278                     case 6:  astr = Hex.u3(outOffset); break;
    279                     default: astr = Hex.u4(outOffset); break;
    280                 }
    281                 sb.append(astr);
    282                 sb.append(": ");
    283             } else if ((col & 1) == 0) {
    284                 sb.append(' ');
    285             }
    286             sb.append(Hex.u1(arr[offset]));
    287             outOffset++;
    288             offset++;
    289             col++;
    290             if (col == bpl) {
    291                 sb.append('\n');
    292                 col = 0;
    293             }
    294             length--;
    295         }
    296 
    297         if (col != 0) {
    298             sb.append('\n');
    299         }
    300 
    301         return sb.toString();
    302     }
    303 }
    304