001: package org.bouncycastle.util.encoders;
002:
003: import java.io.IOException;
004: import java.io.OutputStream;
005:
006: public class HexEncoder implements Encoder {
007: protected final byte[] encodingTable = { (byte) '0', (byte) '1',
008: (byte) '2', (byte) '3', (byte) '4', (byte) '5', (byte) '6',
009: (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
010: (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' };
011:
012: /*
013: * set up the decoding table.
014: */
015: protected final byte[] decodingTable = new byte[128];
016:
017: protected void initialiseDecodingTable() {
018: for (int i = 0; i < encodingTable.length; i++) {
019: decodingTable[encodingTable[i]] = (byte) i;
020: }
021:
022: decodingTable['A'] = decodingTable['a'];
023: decodingTable['B'] = decodingTable['b'];
024: decodingTable['C'] = decodingTable['c'];
025: decodingTable['D'] = decodingTable['d'];
026: decodingTable['E'] = decodingTable['e'];
027: decodingTable['F'] = decodingTable['f'];
028: }
029:
030: public HexEncoder() {
031: initialiseDecodingTable();
032: }
033:
034: /**
035: * encode the input data producing a Hex output stream.
036: *
037: * @return the number of bytes produced.
038: */
039: public int encode(byte[] data, int off, int length, OutputStream out)
040: throws IOException {
041: for (int i = off; i < (off + length); i++) {
042: int v = data[i] & 0xff;
043:
044: out.write(encodingTable[(v >>> 4)]);
045: out.write(encodingTable[v & 0xf]);
046: }
047:
048: return length * 2;
049: }
050:
051: private boolean ignore(char c) {
052: return (c == '\n' || c == '\r' || c == '\t' || c == ' ');
053: }
054:
055: /**
056: * decode the Hex encoded byte data writing it to the given output stream,
057: * whitespace characters will be ignored.
058: *
059: * @return the number of bytes produced.
060: */
061: public int decode(byte[] data, int off, int length, OutputStream out)
062: throws IOException {
063: byte b1, b2;
064: int outLen = 0;
065:
066: int end = off + length;
067:
068: while (end > off) {
069: if (!ignore((char) data[end - 1])) {
070: break;
071: }
072:
073: end--;
074: }
075:
076: int i = off;
077: while (i < end) {
078: while (i < end && ignore((char) data[i])) {
079: i++;
080: }
081:
082: b1 = decodingTable[data[i++]];
083:
084: while (i < end && ignore((char) data[i])) {
085: i++;
086: }
087:
088: b2 = decodingTable[data[i++]];
089:
090: out.write((b1 << 4) | b2);
091:
092: outLen++;
093: }
094:
095: return outLen;
096: }
097:
098: /**
099: * decode the Hex encoded String data writing it to the given output stream,
100: * whitespace characters will be ignored.
101: *
102: * @return the number of bytes produced.
103: */
104: public int decode(String data, OutputStream out) throws IOException {
105: byte b1, b2;
106: int length = 0;
107:
108: int end = data.length();
109:
110: while (end > 0) {
111: if (!ignore(data.charAt(end - 1))) {
112: break;
113: }
114:
115: end--;
116: }
117:
118: int i = 0;
119: while (i < end) {
120: while (i < end && ignore(data.charAt(i))) {
121: i++;
122: }
123:
124: b1 = decodingTable[data.charAt(i++)];
125:
126: while (i < end && ignore(data.charAt(i))) {
127: i++;
128: }
129:
130: b2 = decodingTable[data.charAt(i++)];
131:
132: out.write((b1 << 4) | b2);
133:
134: length++;
135: }
136:
137: return length;
138: }
139: }
|