/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.tomcat.util.buf;

import java.io.ByteArrayOutputStream;
import org.apache.tomcat.util.res.StringManager;

/**
 * Library of utility methods useful in dealing with converting byte arrays
 * to and from strings of hexadecimal digits.
 * Code from Ajp11, from Apache's JServ.
 *
 * @author Craig R. McClanahan
 */

public final class HexUtils {


    // -------------------------------------------------------------- Constants


    /**
     *  Table for HEX to DEC byte translation.
     */
    public static final int[] DEC = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        00, 01, 02, 03, 04, 05, 06, 07,  8,  9, -1, -1, -1, -1, -1, -1,
        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
    };


    /**
     * Table for DEC to HEX byte translation.
     */
    public static final byte[] HEX = 
    { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5', 
      (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b', 
      (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' };


    /**
     * The string manager for this package.
     */
    private static StringManager sm =
	StringManager.getManager("org.apache.tomcat.util.buf.res");


    // --------------------------------------------------------- Static Methods


    /**
     * Convert a String of hexadecimal digits into the corresponding
     * byte array by encoding each two hexadecimal digits as a byte.
     *
     * @param digits Hexadecimal digits representation
     *
     * @exception IllegalArgumentException if an invalid hexadecimal digit
     *  is found, or the input string contains an odd number of hexadecimal
     *  digits
     */
    public static byte[] convert(String digits) {

	ByteArrayOutputStream baos = new ByteArrayOutputStream();
	for (int i = 0; i < digits.length(); i += 2) {
	    char c1 = digits.charAt(i);
	    if ((i+1) >= digits.length())
		throw new IllegalArgumentException
		    (sm.getString("hexUtil.odd"));
	    char c2 = digits.charAt(i + 1);
	    byte b = 0;
	    if ((c1 >= '0') && (c1 <= '9'))
		b += ((c1 - '0') * 16);
	    else if ((c1 >= 'a') && (c1 <= 'f'))
		b += ((c1 - 'a' + 10) * 16);
	    else if ((c1 >= 'A') && (c1 <= 'F'))
		b += ((c1 - 'A' + 10) * 16);
	    else
		throw new IllegalArgumentException
		    (sm.getString("hexUtil.bad"));
	    if ((c2 >= '0') && (c2 <= '9'))
		b += (c2 - '0');
	    else if ((c2 >= 'a') && (c2 <= 'f'))
		b += (c2 - 'a' + 10);
	    else if ((c2 >= 'A') && (c2 <= 'F'))
		b += (c2 - 'A' + 10);
	    else
		throw new IllegalArgumentException
		    (sm.getString("hexUtil.bad"));
	    baos.write(b);
	}
	return (baos.toByteArray());

    }


    /**
     * Convert a byte array into a printable format containing a
     * String of hexadecimal digit characters (two per byte).
     *
     * @param bytes Byte array representation
     */
    public static String convert(byte bytes[]) {

	StringBuffer sb = new StringBuffer(bytes.length * 2);
	for (int i = 0; i < bytes.length; i++) {
	    sb.append(convertDigit((int) (bytes[i] >> 4)));
	    sb.append(convertDigit((int) (bytes[i] & 0x0f)));
	}
	return (sb.toString());

    }

    /**
     * Convert 4 hex digits to an int, and return the number of converted
     * bytes.
     *
     * @param hex Byte array containing exactly four hexadecimal digits
     *
     * @exception IllegalArgumentException if an invalid hexadecimal digit
     *  is included
     */
    public static int convert2Int( byte[] hex ) {
	// Code from Ajp11, from Apache's JServ
    
	// assert b.length==4
	// assert valid data
	int len;
	if(hex.length < 4 ) return 0;
	if( DEC[hex[0]]<0 )
	    throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
	len = DEC[hex[0]];
	len = len << 4;
	if( DEC[hex[1]]<0 )
	    throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
	len += DEC[hex[1]];
	len = len << 4;
	if( DEC[hex[2]]<0 )
	    throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
	len += DEC[hex[2]];
	len = len << 4;
	if( DEC[hex[3]]<0 )
	    throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
	len += DEC[hex[3]];
	return len;
    }



    /**
     * [Private] Convert the specified value (0 .. 15) to the corresponding
     * hexadecimal digit.
     *
     * @param value Value to be converted
     */
    private static char convertDigit(int value) {

	value &= 0x0f;
	if (value >= 10)
	    return ((char) (value - 10 + 'a'));
	else
	    return ((char) (value + '0'));

    }


}
