mirror of
https://github.com/konsoletyper/teavm.git
synced 2024-11-27 01:30:35 +08:00
Get rid of Base64 class in TeaVM compiler
This commit is contained in:
parent
8fbf62ebac
commit
a39e6eb47e
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class Base64 {
|
||||
private static char[] alphabet = new char[64];
|
||||
private static int[] reverse = new int[256];
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (char c = 'A'; c <= 'Z'; ++c) {
|
||||
alphabet[i++] = c;
|
||||
}
|
||||
for (char c = 'a'; c <= 'z'; ++c) {
|
||||
alphabet[i++] = c;
|
||||
}
|
||||
for (char c = '0'; c <= '9'; ++c) {
|
||||
alphabet[i++] = c;
|
||||
}
|
||||
alphabet[i++] = '+';
|
||||
alphabet[i++] = '/';
|
||||
|
||||
Arrays.fill(reverse, -1);
|
||||
for (i = 0; i < alphabet.length; ++i) {
|
||||
reverse[alphabet[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private Base64() {
|
||||
}
|
||||
|
||||
public static byte[] decode(String text) {
|
||||
int outputSize = ((text.length() - 1) / 4 + 1) * 3;
|
||||
int i;
|
||||
int j;
|
||||
for (i = text.length() - 1; i >= 0 && text.charAt(i) == '='; --i) {
|
||||
--outputSize;
|
||||
}
|
||||
byte[] output = new byte[outputSize];
|
||||
|
||||
int triples = (outputSize / 3) * 3;
|
||||
i = 0;
|
||||
for (j = 0; j < triples;) {
|
||||
int a = decode(text.charAt(i++));
|
||||
int b = decode(text.charAt(i++));
|
||||
int c = decode(text.charAt(i++));
|
||||
int d = decode(text.charAt(i++));
|
||||
int out = (a << 18) | (b << 12) | (c << 6) | d;
|
||||
output[j++] = (byte) (out >>> 16);
|
||||
output[j++] = (byte) (out >>> 8);
|
||||
output[j++] = (byte) out;
|
||||
}
|
||||
int rem = output.length - j;
|
||||
if (rem == 1) {
|
||||
int a = decode(text.charAt(i));
|
||||
int b = decode(text.charAt(i + 1));
|
||||
output[j] = (byte) ((a << 2) | (b >>> 4));
|
||||
} else if (rem == 2) {
|
||||
int a = decode(text.charAt(i));
|
||||
int b = decode(text.charAt(i + 1));
|
||||
int c = decode(text.charAt(i + 2));
|
||||
output[j] = (byte) ((a << 2) | (b >>> 4));
|
||||
output[j + 1] = (byte) ((b << 4) | (c >>> 2));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
private static int decode(char c) {
|
||||
return c < 256 ? reverse[c] : -1;
|
||||
}
|
||||
}
|
153
classlib/src/main/java/org/teavm/classlib/impl/Base64Impl.java
Normal file
153
classlib/src/main/java/org/teavm/classlib/impl/Base64Impl.java
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 2015 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.classlib.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class Base64Impl {
|
||||
private static byte[] alphabet = new byte[64];
|
||||
private static int[] reverse = new int[256];
|
||||
|
||||
static {
|
||||
int i = 0;
|
||||
for (char c = 'A'; c <= 'Z'; ++c) {
|
||||
alphabet[i++] = (byte) c;
|
||||
}
|
||||
for (char c = 'a'; c <= 'z'; ++c) {
|
||||
alphabet[i++] = (byte) c;
|
||||
}
|
||||
for (char c = '0'; c <= '9'; ++c) {
|
||||
alphabet[i++] = (byte) c;
|
||||
}
|
||||
alphabet[i++] = '+';
|
||||
alphabet[i++] = '/';
|
||||
|
||||
Arrays.fill(reverse, -1);
|
||||
for (i = 0; i < alphabet.length; ++i) {
|
||||
reverse[alphabet[i]] = i;
|
||||
}
|
||||
}
|
||||
|
||||
private Base64Impl() {
|
||||
}
|
||||
|
||||
public static byte[] decode(byte[] text) {
|
||||
int outputSize = (text.length / 4) * 3;
|
||||
int rem = text.length % 4;
|
||||
if (rem == 2 || rem == 3) {
|
||||
outputSize += rem - 1;
|
||||
}
|
||||
int i;
|
||||
for (i = text.length - 1; i >= 0 && text[i] == '='; --i) {
|
||||
--outputSize;
|
||||
}
|
||||
byte[] output = new byte[outputSize];
|
||||
decode(text, output);
|
||||
return output;
|
||||
}
|
||||
|
||||
public static void decode(byte[] text, byte[] output) {
|
||||
int inputSize = text.length;
|
||||
int i;
|
||||
for (i = text.length - 1; i >= 0 && text[i] == '='; --i) {
|
||||
--inputSize;
|
||||
}
|
||||
int triples = (inputSize / 4) * 4;
|
||||
|
||||
i = 0;
|
||||
int j = 0;
|
||||
while (i < triples) {
|
||||
int a = decode(text[i++]);
|
||||
int b = decode(text[i++]);
|
||||
int c = decode(text[i++]);
|
||||
int d = decode(text[i++]);
|
||||
int out = (a << 18) | (b << 12) | (c << 6) | d;
|
||||
output[j++] = (byte) (out >>> 16);
|
||||
output[j++] = (byte) (out >>> 8);
|
||||
output[j++] = (byte) out;
|
||||
}
|
||||
|
||||
int rem = inputSize - i;
|
||||
if (rem == 2) {
|
||||
int a = decode(text[i]);
|
||||
int b = decode(text[i + 1]);
|
||||
output[j] = (byte) ((a << 2) | (b >>> 4));
|
||||
} else if (rem == 3) {
|
||||
int a = decode(text[i]);
|
||||
int b = decode(text[i + 1]);
|
||||
int c = decode(text[i + 2]);
|
||||
output[j] = (byte) ((a << 2) | (b >>> 4));
|
||||
output[j + 1] = (byte) ((b << 4) | (c >>> 2));
|
||||
}
|
||||
}
|
||||
|
||||
private static int decode(byte c) {
|
||||
return reverse[c];
|
||||
}
|
||||
|
||||
public static byte[] encode(byte[] data, boolean pad) {
|
||||
int outputSize = ((data.length + 2) / 3) * 4;
|
||||
if (!pad) {
|
||||
int rem = data.length % 3;
|
||||
if (rem != 0) {
|
||||
outputSize -= 3 - rem;
|
||||
}
|
||||
}
|
||||
byte[] output = new byte[outputSize];
|
||||
encode(data, output, pad);
|
||||
return output;
|
||||
}
|
||||
|
||||
public static int encode(byte[] data, byte[] output, boolean pad) {
|
||||
int triples = (data.length / 3) * 3;
|
||||
|
||||
int i = 0;
|
||||
int j;
|
||||
for (j = 0; j < triples;) {
|
||||
output[i++] = encode((byte) (data[j] >>> 2));
|
||||
output[i++] = encode((byte) ((data[j] << 4) | (data[j + 1] >>> 4)));
|
||||
++j;
|
||||
output[i++] = encode((byte) ((data[j] << 2) | (data[j + 1] >>> 6)));
|
||||
++j;
|
||||
output[i++] = encode(data[j]);
|
||||
++j;
|
||||
}
|
||||
|
||||
int rem = data.length - j;
|
||||
if (rem == 1) {
|
||||
output[i++] = encode((byte) (data[j] >>> 2));
|
||||
output[i++] = encode((byte) (data[j] << 4));
|
||||
if (pad) {
|
||||
output[i++] = '=';
|
||||
output[i++] = '=';
|
||||
}
|
||||
} else if (rem == 2) {
|
||||
output[i++] = encode((byte) (data[j] >>> 2));
|
||||
output[i++] = encode((byte) ((data[j] << 4) | (data[j + 1] >>> 4)));
|
||||
++j;
|
||||
output[i++] = encode((byte) (data[j] << 2));
|
||||
if (pad) {
|
||||
output[i++] = '=';
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
private static byte encode(byte b) {
|
||||
return alphabet[b & 63];
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@ import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.ServiceLoader;
|
||||
@ -31,6 +30,7 @@ import org.teavm.backend.javascript.spi.Injector;
|
||||
import org.teavm.backend.javascript.spi.InjectorContext;
|
||||
import org.teavm.classlib.ResourceSupplier;
|
||||
import org.teavm.classlib.ResourceSupplierContext;
|
||||
import org.teavm.classlib.impl.Base64Impl;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
||||
@ -69,10 +69,14 @@ public class ClassLoaderNativeGenerator implements Injector {
|
||||
}
|
||||
first = false;
|
||||
writer.newLine();
|
||||
String data = Base64.getEncoder().encodeToString(IOUtils.toByteArray(new BufferedInputStream(input)));
|
||||
byte[] dataBytes = Base64Impl.encode(IOUtils.toByteArray(new BufferedInputStream(input)), true);
|
||||
char[] dataChars = new char[dataBytes.length];
|
||||
for (int i = 0; i < dataBytes.length; ++i) {
|
||||
dataChars[i] = (char) dataBytes[i];
|
||||
}
|
||||
writer.append("\"").append(RenderingUtil.escapeString(resource)).append("\"");
|
||||
writer.ws().append(':').ws();
|
||||
writer.append("\"").append(data).append("\"");
|
||||
writer.append("\"").append(new String(dataChars)).append("\"");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ package org.teavm.classlib.java.lang;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import org.teavm.backend.javascript.spi.InjectedBy;
|
||||
import org.teavm.classlib.impl.Base64;
|
||||
import org.teavm.classlib.impl.Base64Impl;
|
||||
import org.teavm.jso.JSBody;
|
||||
import org.teavm.jso.JSIndexer;
|
||||
import org.teavm.jso.JSObject;
|
||||
@ -50,7 +50,11 @@ public abstract class TClassLoader extends TObject {
|
||||
}
|
||||
JSObject data = resources.getResource(name);
|
||||
String dataString = resourceToString(data);
|
||||
return dataString == null ? null : new ByteArrayInputStream(Base64.decode(dataString));
|
||||
byte[] bytes = new byte[dataString.length()];
|
||||
for (int i = 0; i < bytes.length; ++i) {
|
||||
bytes[i] = (byte) dataString.charAt(i);
|
||||
}
|
||||
return dataString == null ? null : new ByteArrayInputStream(Base64Impl.decode(bytes));
|
||||
}
|
||||
|
||||
public static InputStream getSystemResourceAsStream(String name) {
|
||||
|
@ -23,17 +23,59 @@ public class Base64Test {
|
||||
@Test
|
||||
public void decoderWorks() {
|
||||
assertEquals("q", decode("cQ=="));
|
||||
assertEquals("q", decode("cQ"));
|
||||
assertEquals("qw", decode("cXc="));
|
||||
assertEquals("qw", decode("cXc"));
|
||||
assertEquals("qwe", decode("cXdl"));
|
||||
assertEquals("qwer", decode("cXdlcg=="));
|
||||
assertEquals("qwer", decode("cXdlcg"));
|
||||
assertEquals("qwert", decode("cXdlcnQ="));
|
||||
assertEquals("qwerty", decode("cXdlcnR5"));
|
||||
assertEquals("qwertyu", decode("cXdlcnR5dQ=="));
|
||||
assertEquals("qwertyu", decode("cXdlcnR5dQ"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encoderWorks() {
|
||||
assertEquals("cQ==", encode("q"));
|
||||
assertEquals("cXc=", encode("qw"));
|
||||
assertEquals("cXdl", encode("qwe"));
|
||||
assertEquals("cXdlcg==", encode("qwer"));
|
||||
assertEquals("cXdlcnQ=", encode("qwert"));
|
||||
assertEquals("cXdlcnR5", encode("qwerty"));
|
||||
assertEquals("cXdlcnR5dQ==", encode("qwertyu"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void encoderNoPadWorks() {
|
||||
assertEquals("cQ", encodeNoPad("q"));
|
||||
assertEquals("cXc", encodeNoPad("qw"));
|
||||
assertEquals("cXdl", encodeNoPad("qwe"));
|
||||
assertEquals("cXdlcg", encodeNoPad("qwer"));
|
||||
assertEquals("cXdlcnQ", encodeNoPad("qwert"));
|
||||
assertEquals("cXdlcnR5", encodeNoPad("qwerty"));
|
||||
assertEquals("cXdlcnR5dQ", encodeNoPad("qwertyu"));
|
||||
}
|
||||
|
||||
private String decode(String text) {
|
||||
try {
|
||||
return new String(Base64.decode(text), "UTF-8");
|
||||
return new String(Base64Impl.decode(text.getBytes("UTF-8")), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String encode(String text) {
|
||||
try {
|
||||
return new String(Base64Impl.encode(text.getBytes("UTF-8"), true), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeNoPad(String text) {
|
||||
try {
|
||||
return new String(Base64Impl.encode(text.getBytes("UTF-8"), false), "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user