Home | History | Annotate | Download | only in util
      1 /*
      2  * Copyright (C) 2009 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 package com.android.providers.contacts.util;
     17 
     18 /**
     19  * Basic hex operations: from byte array to string and vice versa.
     20  *
     21  * TODO: move to the framework and consider implementing as native code.
     22  */
     23 public class Hex {
     24 
     25     private static final char[] HEX_DIGITS = new char[]{
     26             '0', '1', '2', '3', '4', '5', '6', '7',
     27             '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
     28     };
     29 
     30     private static final char[] FIRST_CHAR = new char[256];
     31     private static final char[] SECOND_CHAR = new char[256];
     32     static {
     33         for (int i = 0; i < 256; i++) {
     34             FIRST_CHAR[i] = HEX_DIGITS[(i >> 4) & 0xF];
     35             SECOND_CHAR[i] = HEX_DIGITS[i & 0xF];
     36         }
     37     }
     38 
     39     private static final byte[] DIGITS = new byte['f'+1];
     40     static {
     41         for (int i = 0; i <= 'F'; i++) {
     42             DIGITS[i] = -1;
     43         }
     44         for (byte i = 0; i < 10; i++) {
     45             DIGITS['0' + i] = i;
     46         }
     47         for (byte i = 0; i < 6; i++) {
     48             DIGITS['A' + i] = (byte)(10 + i);
     49             DIGITS['a' + i] = (byte)(10 + i);
     50         }
     51     }
     52 
     53     /**
     54      * Quickly converts a byte array to a hexadecimal string representation.
     55      *
     56      * @param array byte array, possibly zero-terminated.
     57      */
     58     public static String encodeHex(byte[] array, boolean zeroTerminated) {
     59         char[] cArray = new char[array.length * 2];
     60 
     61         int j = 0;
     62         for (int i = 0; i < array.length; i++) {
     63             int index = array[i] & 0xFF;
     64             if (zeroTerminated && index == 0 && i == array.length-1) {
     65                 break;
     66             }
     67 
     68             cArray[j++] = FIRST_CHAR[index];
     69             cArray[j++] = SECOND_CHAR[index];
     70         }
     71 
     72         return new String(cArray, 0, j);
     73     }
     74 
     75     /**
     76      * Quickly converts a hexadecimal string to a byte array.
     77      *
     78      * TODO Use checked exceptions instead of RuntimeException.  Apparently normalized names *may*
     79      * contain non-hex strings and we want to make sure the provider won't crash even with such
     80      * input.
     81      */
     82     public static byte[] decodeHex(String hexString) {
     83         int length = hexString.length();
     84 
     85         if ((length & 0x01) != 0) {
     86             throw new IllegalArgumentException("Odd number of characters: " + hexString);
     87         }
     88 
     89         boolean badHex = false;
     90         byte[] out = new byte[length >> 1];
     91         for (int i = 0, j = 0; j < length; i++) {
     92             int c1 = hexString.charAt(j++);
     93             if (c1 > 'f') {
     94                 badHex = true;
     95                 break;
     96             }
     97 
     98             final byte d1 = DIGITS[c1];
     99             if (d1 == -1) {
    100                 badHex = true;
    101                 break;
    102             }
    103 
    104             int c2 = hexString.charAt(j++);
    105             if (c2 > 'f') {
    106                 badHex = true;
    107                 break;
    108             }
    109 
    110             final byte d2 = DIGITS[c2];
    111             if (d2 == -1) {
    112                 badHex = true;
    113                 break;
    114             }
    115 
    116             out[i] = (byte) (d1 << 4 | d2);
    117         }
    118 
    119         if (badHex) {
    120             throw new IllegalArgumentException("Invalid hexadecimal digit: " + hexString);
    121         }
    122 
    123         return out;
    124     }
    125 }
    126