001: /*
002: * Copyright 1999-2004 The Apache Software Foundation
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.tomcat.util.buf;
018:
019: import java.io.ByteArrayOutputStream;
020: import org.apache.tomcat.util.res.StringManager;
021:
022: /**
023: * Library of utility methods useful in dealing with converting byte arrays
024: * to and from strings of hexadecimal digits.
025: * Code from Ajp11, from Apache's JServ.
026: *
027: * @author Craig R. McClanahan
028: */
029:
030: public final class HexUtils {
031:
032: // -------------------------------------------------------------- Constants
033:
034: /**
035: * Table for HEX to DEC byte translation.
036: */
037: public static final int[] DEC = { -1, -1, -1, -1, -1, -1, -1, -1,
038: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
039: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
040: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 00, 01, 02, 03, 04,
041: 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12,
042: 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
043: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10,
044: 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
045: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
046: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
047: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
048: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
049: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
050: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
051: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
052: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
053: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
054: -1, -1, -1, -1, -1, -1, -1, -1, };
055:
056: /**
057: * Table for DEC to HEX byte translation.
058: */
059: public static final byte[] HEX = { (byte) '0', (byte) '1',
060: (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
061: (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
062: (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' };
063:
064: /**
065: * The string manager for this package.
066: */
067: private static StringManager sm = StringManager
068: .getManager("org.apache.tomcat.util.buf.res");
069:
070: // --------------------------------------------------------- Static Methods
071:
072: /**
073: * Convert a String of hexadecimal digits into the corresponding
074: * byte array by encoding each two hexadecimal digits as a byte.
075: *
076: * @param digits Hexadecimal digits representation
077: *
078: * @exception IllegalArgumentException if an invalid hexadecimal digit
079: * is found, or the input string contains an odd number of hexadecimal
080: * digits
081: */
082: public static byte[] convert(String digits) {
083:
084: ByteArrayOutputStream baos = new ByteArrayOutputStream();
085: for (int i = 0; i < digits.length(); i += 2) {
086: char c1 = digits.charAt(i);
087: if ((i + 1) >= digits.length())
088: throw new IllegalArgumentException(sm
089: .getString("hexUtil.odd"));
090: char c2 = digits.charAt(i + 1);
091: byte b = 0;
092: if ((c1 >= '0') && (c1 <= '9'))
093: b += ((c1 - '0') * 16);
094: else if ((c1 >= 'a') && (c1 <= 'f'))
095: b += ((c1 - 'a' + 10) * 16);
096: else if ((c1 >= 'A') && (c1 <= 'F'))
097: b += ((c1 - 'A' + 10) * 16);
098: else
099: throw new IllegalArgumentException(sm
100: .getString("hexUtil.bad"));
101: if ((c2 >= '0') && (c2 <= '9'))
102: b += (c2 - '0');
103: else if ((c2 >= 'a') && (c2 <= 'f'))
104: b += (c2 - 'a' + 10);
105: else if ((c2 >= 'A') && (c2 <= 'F'))
106: b += (c2 - 'A' + 10);
107: else
108: throw new IllegalArgumentException(sm
109: .getString("hexUtil.bad"));
110: baos.write(b);
111: }
112: return (baos.toByteArray());
113:
114: }
115:
116: /**
117: * Convert a byte array into a printable format containing a
118: * String of hexadecimal digit characters (two per byte).
119: *
120: * @param bytes Byte array representation
121: */
122: public static String convert(byte bytes[]) {
123:
124: StringBuffer sb = new StringBuffer(bytes.length * 2);
125: for (int i = 0; i < bytes.length; i++) {
126: sb.append(convertDigit((int) (bytes[i] >> 4)));
127: sb.append(convertDigit((int) (bytes[i] & 0x0f)));
128: }
129: return (sb.toString());
130:
131: }
132:
133: /**
134: * Convert 4 hex digits to an int, and return the number of converted
135: * bytes.
136: *
137: * @param hex Byte array containing exactly four hexadecimal digits
138: *
139: * @exception IllegalArgumentException if an invalid hexadecimal digit
140: * is included
141: */
142: public static int convert2Int(byte[] hex) {
143: // Code from Ajp11, from Apache's JServ
144:
145: // assert b.length==4
146: // assert valid data
147: int len;
148: if (hex.length < 4)
149: return 0;
150: if (DEC[hex[0]] < 0)
151: throw new IllegalArgumentException(sm
152: .getString("hexUtil.bad"));
153: len = DEC[hex[0]];
154: len = len << 4;
155: if (DEC[hex[1]] < 0)
156: throw new IllegalArgumentException(sm
157: .getString("hexUtil.bad"));
158: len += DEC[hex[1]];
159: len = len << 4;
160: if (DEC[hex[2]] < 0)
161: throw new IllegalArgumentException(sm
162: .getString("hexUtil.bad"));
163: len += DEC[hex[2]];
164: len = len << 4;
165: if (DEC[hex[3]] < 0)
166: throw new IllegalArgumentException(sm
167: .getString("hexUtil.bad"));
168: len += DEC[hex[3]];
169: return len;
170: }
171:
172: /**
173: * [Private] Convert the specified value (0 .. 15) to the corresponding
174: * hexadecimal digit.
175: *
176: * @param value Value to be converted
177: */
178: private static char convertDigit(int value) {
179:
180: value &= 0x0f;
181: if (value >= 10)
182: return ((char) (value - 10 + 'a'));
183: else
184: return ((char) (value + '0'));
185:
186: }
187:
188: }
|