1 package net.sf.openrocket.util;
3 import java.util.Arrays;
4 import java.util.HashMap;
6 import java.util.Random;
10 public static final int DEFAULT_CHARS_PER_LINE = 72;
12 private static final char[] ALPHABET = new char[] {
13 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
14 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
15 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
16 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
18 private static final char PAD = '=';
20 // private static final byte[] REVERSE;
22 // REVERSE = new byte[128];
23 // Arrays.fill(REVERSE, (byte)-1);
24 // for (int i=0; i<64; i++) {
25 // REVERSE[ALPHABET[i]] = (byte)i;
32 private static final Map<Character,Integer> REVERSE = new HashMap<Character,Integer>();
34 for (int i=0; i<64; i++) {
35 REVERSE.put(ALPHABET[i], i);
43 public static String encode(byte[] data) {
44 return encode(data, DEFAULT_CHARS_PER_LINE);
47 public static String encode(byte[] data, int maxColumn) {
48 StringBuilder builder = new StringBuilder();
51 for (int position=0; position < data.length; position+=3) {
52 if (column+4 > maxColumn) {
56 builder.append(encodeGroup(data, position));
60 return builder.toString();
66 public static byte[] decode(String data) {
67 byte[] array = new byte[data.length()*3/4];
68 char[] block = new char[4];
71 for (int position=0; position < data.length(); ) {
73 for (p=0; p<4 && position < data.length(); position++) {
74 char c = data.charAt(position);
75 if (!Character.isWhitespace(c)) {
84 throw new IllegalArgumentException("Data ended when decoding Base64, data=" + data + ", p="+p);
87 int l = decodeGroup(block, array, length);
92 return Arrays.copyOf(array, length);
100 * Encode three bytes of data into four characters.
102 private static char[] encodeGroup(byte[] data, int position) {
103 char[] c = new char[] { '=','=','=','=' };
104 int b1=0, b2=0, b3=0;
105 int length = data.length - position;
111 b1 = ((int)data[position])&0xFF;
114 b2 = ((int)data[position+1])&0xFF;
117 b3 = ((int)data[position+2])&0xFF;
120 c[0] = ALPHABET[b1>>2];
121 c[1] = ALPHABET[(b1 & 3)<<4 | (b2>>4)];
124 c[2] = ALPHABET[(b2 & 15)<<2 | (b3>>6)];
127 c[3] = ALPHABET[b3 & 0x3f];
133 * Decode four chars from data into 0-3 bytes of data starting at position in array.
134 * @return the number of bytes decoded.
136 private static int decodeGroup(char[] data, byte[] array, int position) {
140 b1 = REVERSE.get(data[0]);
141 b2 = REVERSE.get(data[1]);
142 b3 = REVERSE.get(data[2]);
143 b4 = REVERSE.get(data[3]);
144 } catch (NullPointerException e) {
145 // If auto-boxing fails
146 throw new IllegalArgumentException("Illegal characters in the sequence to be "+
147 "decoded: "+Arrays.toString(data));
150 array[position] = (byte)((b1 << 2) | (b2 >> 4));
151 array[position+1] = (byte)((b2 << 4) | (b3 >> 2));
152 array[position+2] = (byte)((b3 << 6) | (b4));
154 // Check the amount of data decoded
157 if (data[1] == PAD) {
158 throw new IllegalArgumentException("Illegal character padding in sequence to be "+
159 "decoded: "+Arrays.toString(data));