001: package uk.org.ponder.stringutil;
002:
003: /** This class encodes supplied byte data as characters in a modified Base64 system.
004: * It accepts data as byte arrays and native types, which are written direct
005: * to a supplied CharWrap as plain ASCII characters.
006: */
007: public class ByteToCharBase64 {
008: /** This array maps the characters to their 6-bit values */
009: public final static char pem_array[] = {
010: // 0 1 2 3 4 5 6 7
011: 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 0
012: 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 1
013: 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 2
014: 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', // 3
015: 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', // 4
016: 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', // 5
017: 'w', 'x', 'y', 'z', '0', '1', '2', '3', // 6
018: '4', '5', '6', '7', '8', '9', '(', '_' // 7
019: };
020:
021: // NB !!!!! characters + and / have been replaced with ( and ) for
022: // file and URL safety.
023: // NB - formerly - and _, these have been reclaimed.
024: // public static void getOutputWidth(int inputbytes) {
025: // }
026:
027: /** Writes the supplied byte data to the supplied CharWrap in Base64-encoded
028: * form.
029: * @param out The CharWrap to receive the encoded characters.
030: * @param data A byte array holding the data to be encoded.
031: * @param offset The offset within the byte array of the data to be encoded.
032: * @param len The length of the data to be encoded.
033: * @param pad <code>true</code> if the output data should be right-padded
034: * with the <code>A</code> character. NB, the Base64 standard is actually
035: * to right-pad with the <code>=</code> character, look into this.
036: */
037: public static void writeBytes(CharWrap out, byte data[],
038: int offset, int len, boolean pad) {
039: byte b0, b1, b2;
040: int index;
041: while (len > 0) {
042: // not correct! This should be right-aligned!!!
043: int this len = len % 3;
044: if (this len == 1) { // 1 byte - send out aaaaaabb 0000
045: b0 = data[offset];
046: index = (b0 >>> 2) & 0x3F;
047: if (pad || index != 0) {
048: out.append(pem_array[index]);
049: pad = true;
050: }
051: index = (b0 << 4) & 0x30;
052: if (pad || index != 0) {
053: out.append(pem_array[index]);
054: pad = true;
055: }
056: } else if (this len == 2) { // 2 byte - aaaaaabb bbbbcccc 00
057: b0 = data[offset];
058: b1 = data[offset + 1];
059: index = (b0 >>> 2) & 0x3F;
060: if (pad || index != 0) {
061: out.append(pem_array[index]);
062: pad = true;
063: }
064: index = ((b0 << 4) & 0x30) + ((b1 >>> 4) & 0xf);
065: if (pad || index != 0) {
066: out.append(pem_array[index]);
067: pad = true;
068: }
069: index = (b1 << 2) & 0x3c;
070: if (pad || index != 0) {
071: out.append(pem_array[index]);
072: pad = true;
073: }
074: } else { // 3 byte - aaaaaabb bbbbcccc ccdddddd
075: b0 = data[offset];
076: b1 = data[offset + 1];
077: b2 = data[offset + 2];
078: index = (b0 >>> 2) & 0x3F;
079: if (pad || index != 0) {
080: out.append(pem_array[index]);
081: pad = true;
082: }
083: index = ((b0 << 4) & 0x30) + ((b1 >>> 4) & 0xf);
084: if (pad || index != 0) {
085: out.append(pem_array[index]);
086: pad = true;
087: }
088: index = ((b1 << 2) & 0x3c) + ((b2 >>> 6) & 0x3);
089: if (pad || index != 0) {
090: out.append(pem_array[index]);
091: pad = true;
092: }
093: index = b2 & 0x3F;
094: if (pad || index != 0) {
095: out.append(pem_array[index]);
096: pad = true;
097: }
098: }
099: len -= 3;
100: offset += 3;
101: }
102: }
103:
104: /** Writes the specified <code>long</code> encoded as Base64 characters
105: * to the supplied CharWrap. The <code>long</code> is interpreted as a
106: * big-endian byte sequence in the usual sane way.
107: * @param out The CharWrap to receive the encoded characters.
108: * @param towrite The <code>long</code> to be encoded as Base64.
109: * @param <code>true</code> if the characters are to be right-padded
110: * with <code>A</code>
111: */
112:
113: public static void writeLong(CharWrap out, long towrite, boolean pad) {
114: // up to 11 bytes
115: System.out.println("writeLong: " + towrite);
116: for (int bits = 60; bits >= 0; bits -= 6) {
117: int index = ((int) (towrite >> bits)) & 0x3f;
118: System.out.print(index + " ");
119: if (pad || index != 0) {
120: out.append(pem_array[index]);
121: pad = true;
122: }
123: }
124: }
125:
126: /** Writes the specified <code>int</code> encoded as Base64 characters
127: * to the supplied CharWrap. The <code>int</code> is interpreted as a
128: * big-endian byte sequence in the usual sane way.
129: * @param out The CharWrap to receive the encoded characters.
130: * @param towrite The <code>int</code> to be encoded as Base64.
131: * @param <code>true</code> if the characters are to be right-padded
132: * with <code>A</code>
133: */
134:
135: public static void writeInt(CharWrap out, int towrite, boolean pad) {
136: // up to 6 bytes: aabbbbbb ccccccdd ddddeeee eeffffff
137: for (int bits = 30; bits >= 0; bits -= 6) {
138: int index = (towrite >> bits) & 0x3f;
139: if (pad || index != 0) {
140: out.append(pem_array[index]);
141: pad = true;
142: }
143: }
144: }
145: }
|