提交 4ff133e3 authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 132e613f
/*
* Copyright 2004-2007 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.tools.net;
import java.util.Random;
/**
* This class converts binary to base64 and vice versa.
*/
public class Base64 {
private static final byte[] CODE = new byte[64];
private static final byte[] REV = new byte[256];
static {
for (int i = 'A'; i <= 'Z'; i++) {
CODE[i - 'A'] = (byte) i;
CODE[i - 'A' + 26] = (byte) (i + 'a' - 'A');
}
for (int i = 0; i < 10; i++) {
CODE[i + 2 * 26] = (byte) ('0' + i);
}
CODE[62] = (byte) '+';
CODE[63] = (byte) '/';
for (int i = 0; i < 255; i++) {
REV[i] = -1;
}
for (int i = 0; i < 64; i++) {
REV[CODE[i]] = (byte) i;
}
}
private static void check(String a, String b) {
if (!a.equals(b)) {
throw new Error("missmatch: " + a + " <> " + b);
}
}
public static void main(String[] args) {
check(new String(encode(new byte[] {})), "");
check(new String(encode("A".getBytes())), "QQ==");
check(new String(encode("AB".getBytes())), "QUI=");
check(new String(encode("ABC".getBytes())), "QUJD");
check(new String(encode("ABCD".getBytes())), "QUJDRA==");
check(new String(decode(new byte[] {})), "");
check(new String(decode("QQ==".getBytes())), "A");
check(new String(decode("QUI=".getBytes())), "AB");
check(new String(decode("QUJD".getBytes())), "ABC");
check(new String(decode("QUJDRA==".getBytes())), "ABCD");
int len = 10000;
test(false, len);
test(true, len);
test(false, len);
test(true, len);
}
private static void test(boolean fast, int len) {
Random random = new Random(10);
long time = System.currentTimeMillis();
byte[] bin = new byte[len];
random.nextBytes(bin);
for (int i = 0; i < len; i++) {
byte[] dec;
if (fast) {
byte[] enc = encodeFast(bin);
dec = decodeFast(enc);
} else {
byte[] enc = encode(bin);
dec = decode(enc);
}
test(bin, dec);
}
time = System.currentTimeMillis() - time;
System.out.println("fast=" + fast + " time=" + time);
}
private static void test(byte[] in, byte[] out) {
if (in.length != out.length) {
throw new Error("Length error");
}
for (int i = 0; i < in.length; i++) {
if (in[i] != out[i]) {
throw new Error("Error at " + i);
}
}
}
public static byte[] encode(byte[] bin) {
byte[] code = CODE;
int size = bin.length;
int len = ((size + 2) / 3) * 4;
byte[] enc = new byte[len];
int fast = size / 3 * 3, i = 0, j = 0;
for (; i < fast; i += 3, j += 4) {
int a = ((bin[i] & 255) << 16) + ((bin[i + 1] & 255) << 8) + (bin[i + 2] & 255);
enc[j] = code[a >> 18];
enc[j + 1] = code[(a >> 12) & 63];
enc[j + 2] = code[(a >> 6) & 63];
enc[j + 3] = code[a & 63];
}
if (i < size) {
int a = (bin[i++] & 255) << 16;
enc[j] = code[a >> 18];
if (i < size) {
a += (bin[i] & 255) << 8;
enc[j + 2] = code[(a >> 6) & 63];
} else {
enc[j + 2] = (byte) '=';
}
enc[j + 1] = code[(a >> 12) & 63];
enc[j + 3] = (byte) '=';
}
return enc;
}
public static byte[] encodeFast(byte[] bin) {
byte[] code = CODE;
int size = bin.length;
int len = ((size * 4) + 2) / 3;
byte[] enc = new byte[len];
int fast = size / 3 * 3, i = 0, j = 0;
for (; i < fast; i += 3, j += 4) {
int a = ((bin[i] & 255) << 16) + ((bin[i + 1] & 255) << 8) + (bin[i + 2] & 255);
enc[j] = code[a >> 18];
enc[j + 1] = code[(a >> 12) & 63];
enc[j + 2] = code[(a >> 6) & 63];
enc[j + 3] = code[a & 63];
}
if (i < size) {
int a = (bin[i++] & 255) << 16;
enc[j] = code[a >> 18];
if (i < size) {
a += (bin[i] & 255) << 8;
enc[j + 2] = code[(a >> 6) & 63];
}
enc[j + 1] = code[(a >> 12) & 63];
}
return enc;
}
public static byte[] trim(byte[] enc) {
byte[] rev = REV;
int j = 0, size = enc.length;
if (size > 1 && enc[size - 2] == '=') {
size--;
}
if (size > 0 && enc[size - 1] == '=') {
size--;
}
for (int i = 0; i < size; i++) {
if (rev[enc[i] & 255] < 0) {
j++;
}
}
if (j == 0) {
return enc;
}
byte[] buff = new byte[size - j];
for (int i = 0, k = 0; i < size; i++) {
int x = enc[i] & 255;
if (rev[x] >= 0) {
buff[k++] = (byte) x;
}
}
return buff;
}
public static byte[] decode(byte[] enc) {
enc = trim(enc);
byte[] rev = REV;
int len = enc.length, size = (len * 3) / 4;
if (len > 0 && enc[len - 1] == '=') {
size--;
if (len > 1 && enc[len - 2] == '=') {
size--;
}
}
byte[] bin = new byte[size];
int fast = size / 3 * 3, i = 0, j = 0;
for (; i < fast; i += 3, j += 4) {
int a = (rev[enc[j] & 255] << 18) + (rev[enc[j + 1] & 255] << 12) +
(rev[enc[j + 2] & 255] << 6) + rev[enc[j + 3] & 255];
bin[i] = (byte) (a >> 16);
bin[i + 1] = (byte) (a >> 8);
bin[i + 2] = (byte) a;
}
if (i < size) {
int a = (rev[enc[j] & 255] << 10) + (rev[enc[j + 1] & 255] << 4);
bin[i++] = (byte) (a >> 8);
if (i < size) {
a += rev[enc[j + 2] & 255] >> 2;
bin[i] = (byte) a;
}
}
return bin;
}
public static byte[] decodeFast(byte[] enc) {
byte[] rev = REV;
int len = enc.length, size = (len * 3) / 4;
byte[] bin = new byte[size];
int fast = size / 3 * 3, i = 0, j = 0;
for (; i < fast; i += 3, j += 4) {
int a = (rev[enc[j] & 255] << 18) + (rev[enc[j + 1] & 255] << 12) +
(rev[enc[j + 2] & 255] << 6) + rev[enc[j + 3] & 255];
bin[i] = (byte) (a >> 16);
bin[i + 1] = (byte) (a >> 8);
bin[i + 2] = (byte) a;
}
if (i < size) {
int a = (rev[enc[j] & 255] << 10) + (rev[enc[j + 1] & 255] << 4);
bin[i++] = (byte) (a >> 8);
if (i < size) {
a += rev[enc[j + 2] & 255] >> 2;
bin[i] = (byte) a;
}
}
return bin;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论