mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds Character.digit implementation with honest Unicode support.
This commit is contained in:
parent
8055edd547
commit
0f2bf64975
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.unicode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class UnicodeHelper {
|
||||||
|
static char hexDigit(int value) {
|
||||||
|
return value < 10 ? (char)('0' + value) : (char)('A' + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int valueOfHexDigit(char digit) {
|
||||||
|
return digit <= '9' ? digit - '0' : digit - 'A' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeIntByte(int[] data) {
|
||||||
|
char[] chars = new char[data.length / 2 * 5];
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < data.length;) {
|
||||||
|
int val = data[i++];
|
||||||
|
int shift = 32;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
shift -= 8;
|
||||||
|
chars[j++] = (char)('z' + ((val >> shift) & 0xFF));
|
||||||
|
}
|
||||||
|
chars[j++] = (char)('z' + (data[i++] & 0xFF));
|
||||||
|
}
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] decodeIntByte(String text) {
|
||||||
|
int[] data = new int[2 * (text.length() / 5)];
|
||||||
|
int j = 0;
|
||||||
|
for (int i = 0; i < data.length;) {
|
||||||
|
int val = 0;
|
||||||
|
for (int k = 0; k < 4; ++k) {
|
||||||
|
val = (val << 8) | (text.charAt(j++) - 'z');
|
||||||
|
}
|
||||||
|
data[i++] = val;
|
||||||
|
data[i++] = text.charAt(j++) - 'z';
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.unicode;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import org.teavm.common.IntegerArray;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class UnicodeSupport {
|
||||||
|
private static AtomicBoolean filled = new AtomicBoolean();
|
||||||
|
private static volatile CountDownLatch latch = new CountDownLatch(0);
|
||||||
|
private static int[] digitValues;
|
||||||
|
|
||||||
|
private static void parseUnicodeData() {
|
||||||
|
IntegerArray digitValues = new IntegerArray(4096);
|
||||||
|
try (BufferedReader reader = new BufferedReader(new InputStreamReader(UnicodeHelper.class
|
||||||
|
.getResourceAsStream("UnicodeData.txt")))) {
|
||||||
|
while (true) {
|
||||||
|
String line = reader.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (line.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String[] fields = splitLine(line);
|
||||||
|
int charCode = parseHex(fields[0]);
|
||||||
|
if (!fields[6].isEmpty()) {
|
||||||
|
int digit = Integer.parseInt(fields[6]);
|
||||||
|
digitValues.add(charCode);
|
||||||
|
digitValues.add(digit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Error reading unicode data", e);
|
||||||
|
}
|
||||||
|
IntegerArray letterDigitValues = new IntegerArray(256);
|
||||||
|
for (int i = 'A'; i <= 'Z'; ++i) {
|
||||||
|
letterDigitValues.add(i);
|
||||||
|
letterDigitValues.add(i - 'A' + 10);
|
||||||
|
}
|
||||||
|
for (int i = 'a'; i <= 'z'; ++i) {
|
||||||
|
letterDigitValues.add(i);
|
||||||
|
letterDigitValues.add(i - 'a' + 10);
|
||||||
|
}
|
||||||
|
for (int i = '\uFF21'; i <= '\uFF3A'; ++i) {
|
||||||
|
letterDigitValues.add(i);
|
||||||
|
letterDigitValues.add(i - '\uFF21' + 10);
|
||||||
|
}
|
||||||
|
for (int i = '\uFF41'; i <= '\uFF5A'; ++i) {
|
||||||
|
letterDigitValues.add(i);
|
||||||
|
letterDigitValues.add(i - '\uFF41' + 10);
|
||||||
|
}
|
||||||
|
UnicodeSupport.digitValues = mergePairs(digitValues.getAll(), letterDigitValues.getAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String[] splitLine(String line) {
|
||||||
|
List<String> parts = new ArrayList<>();
|
||||||
|
int index = 0;
|
||||||
|
while (true) {
|
||||||
|
int next = line.indexOf(';', index);
|
||||||
|
if (next == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parts.add(line.substring(index, next));
|
||||||
|
index = next + 1;
|
||||||
|
}
|
||||||
|
parts.add(line.substring(index));
|
||||||
|
return parts.toArray(new String[parts.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] mergePairs(int[] a, int[] b) {
|
||||||
|
int[] result = new int[a.length + b.length];
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int t = 0;
|
||||||
|
while (true) {
|
||||||
|
if (i == a.length) {
|
||||||
|
while (i < a.length) {
|
||||||
|
result[t++] = a[i++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else if (j == b.length) {
|
||||||
|
while (j < b.length) {
|
||||||
|
result[t++] = b[j++];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (a[i] < b[j]) {
|
||||||
|
result[t++] = a[i++];
|
||||||
|
result[t++] = a[i++];
|
||||||
|
} else {
|
||||||
|
result[t++] = b[j++];
|
||||||
|
result[t++] = b[j++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int parseHex(String text) {
|
||||||
|
int value = 0;
|
||||||
|
for (int i = 0; i < text.length(); ++i) {
|
||||||
|
value = value << 4 | UnicodeHelper.valueOfHexDigit(text.charAt(i));
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ensureUnicodeData() {
|
||||||
|
if (filled.compareAndSet(false, true)) {
|
||||||
|
parseUnicodeData();
|
||||||
|
latch = null;
|
||||||
|
} else {
|
||||||
|
CountDownLatch latchCopy = latch;
|
||||||
|
if (latchCopy != null) {
|
||||||
|
try {
|
||||||
|
latchCopy.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int[] getDigitValues() {
|
||||||
|
ensureUnicodeData();
|
||||||
|
return digitValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,7 +16,11 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.teavm.classlib.impl.unicode.UnicodeHelper;
|
||||||
|
import org.teavm.classlib.impl.unicode.UnicodeSupport;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
|
import org.teavm.dependency.DependencyChecker;
|
||||||
|
import org.teavm.dependency.DependencyPlugin;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
@ -26,7 +30,7 @@ import org.teavm.model.ValueType;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class CharacterNativeGenerator implements Generator {
|
public class CharacterNativeGenerator implements Generator, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
|
@ -37,6 +41,18 @@ public class CharacterNativeGenerator implements Generator {
|
||||||
generateToLowerCaseInt(context, writer);
|
generateToLowerCaseInt(context, writer);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "obtainDigitMapping":
|
||||||
|
generateObtainDigitMapping(writer);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void methodAchieved(DependencyChecker checker, MethodReference method) {
|
||||||
|
switch (method.getName()) {
|
||||||
|
case "obtainDigitMapping":
|
||||||
|
achieveObtainDigitMapping(checker, method);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,4 +65,13 @@ public class CharacterNativeGenerator implements Generator {
|
||||||
writer.append("return String.fromCharCode(").append(context.getParameterName(1))
|
writer.append("return String.fromCharCode(").append(context.getParameterName(1))
|
||||||
.append(").toLowerCase().charCodeAt(0);").softNewLine();
|
.append(").toLowerCase().charCodeAt(0);").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void generateObtainDigitMapping(SourceWriter writer) throws IOException {
|
||||||
|
writer.append("return $rt_str(\"").append(UnicodeHelper.encodeIntByte(UnicodeSupport.getDigitValues()))
|
||||||
|
.append("\");").softNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void achieveObtainDigitMapping(DependencyChecker checker, MethodReference method) {
|
||||||
|
checker.attachMethodGraph(method).getResultNode().propagate("java.lang.String");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,42 +19,72 @@ import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.codegen.SourceWriter;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
import org.teavm.javascript.ni.Injector;
|
||||||
|
import org.teavm.javascript.ni.InjectorContext;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public class ClassNativeGenerator implements Generator {
|
public class ClassNativeGenerator implements Generator, Injector {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "isInstance":
|
|
||||||
generateIsInstance(context, writer);
|
|
||||||
break;
|
|
||||||
case "isAssignable":
|
|
||||||
generateIsAssignableFrom(context, writer);
|
|
||||||
break;
|
|
||||||
case "getComponentType0":
|
case "getComponentType0":
|
||||||
generateGetComponentType(context, writer);
|
generateGetComponentType(context, writer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateIsInstance(GeneratorContext context, SourceWriter writer) throws IOException {
|
|
||||||
writer.append("return $rt_isInstance(").append(context.getParameterName(1)).append(", ")
|
|
||||||
.append(context.getParameterName(0)).append(".$data);").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateIsAssignableFrom(GeneratorContext context, SourceWriter writer) throws IOException {
|
|
||||||
writer.append("return $rt_isAssignable(").append(context.getParameterName(1)).append(".$data, ")
|
|
||||||
.append(context.getParameterName(0)).append(".$data;").softNewLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException {
|
private void generateGetComponentType(GeneratorContext context, SourceWriter writer) throws IOException {
|
||||||
String thisArg = context.getParameterName(0);
|
String thisArg = context.getParameterName(0);
|
||||||
writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
|
writer.append("var item = " + thisArg + ".$data.$meta.item;").softNewLine();
|
||||||
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
|
writer.append("return item != null ? $rt_cls(item) : null;").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
|
switch (methodRef.getName()) {
|
||||||
|
case "isInstance":
|
||||||
|
generateIsInstance(context);
|
||||||
|
break;
|
||||||
|
case "isAssignableFrom":
|
||||||
|
generateIsAssignableFrom(context);
|
||||||
|
break;
|
||||||
|
case "booleanClass":
|
||||||
|
generateBooleanClass(context);
|
||||||
|
break;
|
||||||
|
case "intClass":
|
||||||
|
generateIntClass(context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsAssignableFrom(InjectorContext context) throws IOException {
|
||||||
|
SourceWriter writer = context.getWriter();
|
||||||
|
writer.append("$rt_isAssignable(");
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
writer.append(".$data,").ws();
|
||||||
|
context.writeExpr(context.getArgument(0));
|
||||||
|
writer.append(".$data)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIsInstance(InjectorContext context) throws IOException {
|
||||||
|
SourceWriter writer = context.getWriter();
|
||||||
|
writer.append("$rt_isInstance(");
|
||||||
|
context.writeExpr(context.getArgument(1));
|
||||||
|
writer.append(",").ws();
|
||||||
|
context.writeExpr(context.getArgument(0));
|
||||||
|
writer.append(".$data)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateBooleanClass(InjectorContext context) throws IOException {
|
||||||
|
context.getWriter().append("$rt_cls($rt_booleancls())");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void generateIntClass(InjectorContext context) throws IOException {
|
||||||
|
context.getWriter().append("$rt_cls($rt_intcls())");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ import org.teavm.dependency.DependencyPlugin;
|
||||||
import org.teavm.dependency.MethodGraph;
|
import org.teavm.dependency.MethodGraph;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.Generator;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
import org.teavm.javascript.ni.GeneratorContext;
|
||||||
|
import org.teavm.javascript.ni.Injector;
|
||||||
|
import org.teavm.javascript.ni.InjectorContext;
|
||||||
import org.teavm.model.MethodDescriptor;
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
@ -30,24 +32,30 @@ import org.teavm.model.ValueType;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev <konsoletyper@gmail.com>
|
* @author Alexey Andreev <konsoletyper@gmail.com>
|
||||||
*/
|
*/
|
||||||
public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
public class ObjectNativeGenerator implements Generator, Injector, DependencyPlugin {
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getDescriptor().getName()) {
|
switch (methodRef.getDescriptor().getName()) {
|
||||||
case "<init>":
|
case "<init>":
|
||||||
generateInit(context, writer);
|
generateInit(context, writer);
|
||||||
break;
|
break;
|
||||||
case "getClass":
|
|
||||||
generateGetClass(context, writer);
|
|
||||||
break;
|
|
||||||
case "hashCode":
|
case "hashCode":
|
||||||
generateHashCode(context, writer);
|
generateHashCode(context, writer);
|
||||||
break;
|
break;
|
||||||
case "clone":
|
case "clone":
|
||||||
generateClone(context, writer);
|
generateClone(context, writer);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
|
switch (methodRef.getName()) {
|
||||||
|
case "getClass":
|
||||||
|
generateGetClass(context);
|
||||||
|
break;
|
||||||
case "wrap":
|
case "wrap":
|
||||||
generateWrap(context, writer);
|
generateWrap(context);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,9 +79,11 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine();
|
writer.append(context.getParameterName(0)).append(".$id = $rt_nextId();").softNewLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateGetClass(GeneratorContext context, SourceWriter writer) throws IOException {
|
private void generateGetClass(InjectorContext context) throws IOException {
|
||||||
String thisArg = context.getParameterName(0);
|
SourceWriter writer = context.getWriter();
|
||||||
writer.append("return $rt_cls(").append(thisArg).append(".constructor);").softNewLine();
|
writer.append("$rt_cls(");
|
||||||
|
context.writeExpr(context.getArgument(0));
|
||||||
|
writer.append(".constructor)");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void achieveGetClass(DependencyChecker checker, MethodReference method) {
|
private void achieveGetClass(DependencyChecker checker, MethodReference method) {
|
||||||
|
@ -102,8 +112,8 @@ public class ObjectNativeGenerator implements Generator, DependencyPlugin {
|
||||||
graph.getVariableNode(0).connect(graph.getResultNode());
|
graph.getVariableNode(0).connect(graph.getResultNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWrap(GeneratorContext context, SourceWriter writer) throws IOException {
|
private void generateWrap(InjectorContext context) throws IOException {
|
||||||
writer.append("return ").append(context.getParameterName(1)).append(";").softNewLine();
|
context.writeExpr(context.getArgument(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void achieveWrap(DependencyChecker checker, MethodReference method) {
|
private void achieveWrap(DependencyChecker checker, MethodReference method) {
|
||||||
|
|
|
@ -16,26 +16,26 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.teavm.codegen.SourceWriter;
|
import org.teavm.javascript.ni.Injector;
|
||||||
import org.teavm.javascript.ni.Generator;
|
import org.teavm.javascript.ni.InjectorContext;
|
||||||
import org.teavm.javascript.ni.GeneratorContext;
|
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class StringNativeGenerator implements Generator {
|
public class StringNativeGenerator implements Injector {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void generate(GeneratorContext context, SourceWriter writer, MethodReference methodRef) throws IOException {
|
public void generate(InjectorContext context, MethodReference methodRef) throws IOException {
|
||||||
switch (methodRef.getName()) {
|
switch (methodRef.getName()) {
|
||||||
case "wrap":
|
case "wrap":
|
||||||
generateWrap(context, writer);
|
generateWrap(context);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void generateWrap(GeneratorContext context, SourceWriter writer) throws IOException {
|
private void generateWrap(InjectorContext context) throws IOException {
|
||||||
writer.append("return ").append(context.getParameterName(1)).softNewLine();
|
context.writeExpr(context.getArgument(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.teavm.javascript.ni.Rename;
|
||||||
public class TBoolean extends TObject implements TSerializable, TComparable<TBoolean> {
|
public class TBoolean extends TObject implements TSerializable, TComparable<TBoolean> {
|
||||||
public static final TBoolean TRUE = new TBoolean(true);
|
public static final TBoolean TRUE = new TBoolean(true);
|
||||||
public static final TBoolean FALSE = new TBoolean(false);
|
public static final TBoolean FALSE = new TBoolean(false);
|
||||||
public static final Class<Boolean> TYPE = boolean.class;
|
public static final TClass<TBoolean> TYPE = TClass.booleanClass();
|
||||||
private boolean value;
|
private boolean value;
|
||||||
|
|
||||||
public TBoolean(boolean value) {
|
public TBoolean(boolean value) {
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.classlib.impl.unicode.UnicodeHelper;
|
||||||
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,9 +24,54 @@ import org.teavm.javascript.ni.GeneratedBy;
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class TCharacter {
|
public class TCharacter {
|
||||||
|
public static final int MIN_RADIX = 2;
|
||||||
|
public static final int MAX_RADIX = 36;
|
||||||
|
private static int[] digitMapping;
|
||||||
|
|
||||||
@GeneratedBy(CharacterNativeGenerator.class)
|
@GeneratedBy(CharacterNativeGenerator.class)
|
||||||
public static native char toLowerCase(char ch);
|
public static native char toLowerCase(char ch);
|
||||||
|
|
||||||
@GeneratedBy(CharacterNativeGenerator.class)
|
@GeneratedBy(CharacterNativeGenerator.class)
|
||||||
public static native int toLowerCase(int ch);
|
public static native int toLowerCase(int ch);
|
||||||
|
|
||||||
|
public static int digit(char ch, int radix) {
|
||||||
|
return digit((int)ch, radix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int digit(int codePoint, int radix) {
|
||||||
|
if (radix < MIN_RADIX || radix > MAX_RADIX) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int d = digit(codePoint);
|
||||||
|
return d <= radix ? d : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int digit(int codePoint) {
|
||||||
|
int[] digitMapping = getDigitMapping();
|
||||||
|
int l = 0;
|
||||||
|
int u = (digitMapping.length / 2) - 1;
|
||||||
|
while (u >= l) {
|
||||||
|
int idx = (l + u) / 2;
|
||||||
|
int val = digitMapping[idx * 2];
|
||||||
|
if (codePoint > val) {
|
||||||
|
l = idx + 1;
|
||||||
|
} else if (codePoint < val) {
|
||||||
|
u = idx - 1;
|
||||||
|
} else {
|
||||||
|
return digitMapping[idx * 2 + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int[] getDigitMapping() {
|
||||||
|
if (digitMapping == null) {
|
||||||
|
digitMapping = UnicodeHelper.decodeIntByte(obtainDigitMapping());
|
||||||
|
}
|
||||||
|
return digitMapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GeneratedBy(CharacterNativeGenerator.class)
|
||||||
|
@PluggableDependency(CharacterNativeGenerator.class)
|
||||||
|
private static native String obtainDigitMapping();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
package org.teavm.classlib.java.lang;
|
package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
|
import org.teavm.javascript.ni.InjectedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -32,9 +33,12 @@ public class TClass<T> extends TObject {
|
||||||
return new TClass<>();
|
return new TClass<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(ClassNativeGenerator.class)
|
@InjectedBy(ClassNativeGenerator.class)
|
||||||
public native boolean isInstance(TObject obj);
|
public native boolean isInstance(TObject obj);
|
||||||
|
|
||||||
|
@InjectedBy(ClassNativeGenerator.class)
|
||||||
|
public native boolean isAssignableFrom(TClass<?> obj);
|
||||||
|
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
@ -57,4 +61,10 @@ public class TClass<T> extends TObject {
|
||||||
|
|
||||||
@GeneratedBy(ClassNativeGenerator.class)
|
@GeneratedBy(ClassNativeGenerator.class)
|
||||||
private native TClass<?> getComponentType0();
|
private native TClass<?> getComponentType0();
|
||||||
|
|
||||||
|
@InjectedBy(ClassNativeGenerator.class)
|
||||||
|
static native TClass<TBoolean> booleanClass();
|
||||||
|
|
||||||
|
@InjectedBy(ClassNativeGenerator.class)
|
||||||
|
static native TClass<TInteger> integerClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class TInteger extends TNumber implements TComparable<TInteger> {
|
||||||
|
public static final int SIZE = 32;
|
||||||
|
public static final int MIN_VALUE = (2 << (SIZE - 1));
|
||||||
|
public static final int MAX_VALUE = (2 << (SIZE - 1)) - 1;
|
||||||
|
public static final TClass<TInteger> TYPE = TClass.integerClass();
|
||||||
|
private int value;
|
||||||
|
|
||||||
|
public TInteger(int value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(TInteger other) {
|
||||||
|
return compare(value, other.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int intValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long longValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float floatValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double doubleValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int compare(int x, int y) {
|
||||||
|
return x > y ? 1 : x < y ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public static int parseInt(TString s, int radix) throws TNumberFormatException {
|
||||||
|
return 0;
|
||||||
|
}*/
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.java.lang;
|
||||||
|
|
||||||
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public abstract class TNumber extends TObject implements TSerializable {
|
||||||
|
public abstract int intValue();
|
||||||
|
|
||||||
|
public abstract long longValue();
|
||||||
|
|
||||||
|
public abstract float floatValue();
|
||||||
|
|
||||||
|
public abstract double doubleValue();
|
||||||
|
|
||||||
|
public byte byteValue() {
|
||||||
|
return (byte)intValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public short shortValue() {
|
||||||
|
return (short)intValue();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class TNumberFormatException extends TIllegalArgumentException {
|
||||||
|
private static final long serialVersionUID = 6872736757931546482L;
|
||||||
|
|
||||||
|
public TNumberFormatException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TNumberFormatException(TString message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,7 @@ package org.teavm.classlib.java.lang;
|
||||||
|
|
||||||
import org.teavm.dependency.PluggableDependency;
|
import org.teavm.dependency.PluggableDependency;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.GeneratedBy;
|
||||||
|
import org.teavm.javascript.ni.InjectedBy;
|
||||||
import org.teavm.javascript.ni.Rename;
|
import org.teavm.javascript.ni.Rename;
|
||||||
import org.teavm.javascript.ni.Superclass;
|
import org.teavm.javascript.ni.Superclass;
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ public class TObject {
|
||||||
@Rename("<init>")
|
@Rename("<init>")
|
||||||
private native void init();
|
private native void init();
|
||||||
|
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
@InjectedBy(ObjectNativeGenerator.class)
|
||||||
@Rename("getClass")
|
@Rename("getClass")
|
||||||
@PluggableDependency(ObjectNativeGenerator.class)
|
@PluggableDependency(ObjectNativeGenerator.class)
|
||||||
public native final TClass<?> getClass0();
|
public native final TClass<?> getClass0();
|
||||||
|
@ -82,7 +83,7 @@ public class TObject {
|
||||||
protected void finalize() throws TThrowable {
|
protected void finalize() throws TThrowable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(ObjectNativeGenerator.class)
|
@InjectedBy(ObjectNativeGenerator.class)
|
||||||
@PluggableDependency(ObjectNativeGenerator.class)
|
@PluggableDependency(ObjectNativeGenerator.class)
|
||||||
public static native TObject wrap(Object obj);
|
public static native TObject wrap(Object obj);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import org.teavm.classlib.impl.charset.*;
|
||||||
import org.teavm.classlib.java.io.TSerializable;
|
import org.teavm.classlib.java.io.TSerializable;
|
||||||
import org.teavm.classlib.java.io.TUnsupportedEncodingException;
|
import org.teavm.classlib.java.io.TUnsupportedEncodingException;
|
||||||
import org.teavm.classlib.java.util.TArrays;
|
import org.teavm.classlib.java.util.TArrays;
|
||||||
import org.teavm.javascript.ni.GeneratedBy;
|
import org.teavm.javascript.ni.InjectedBy;
|
||||||
import org.teavm.javascript.ni.Rename;
|
import org.teavm.javascript.ni.Rename;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -548,7 +548,7 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
|
||||||
return hashCode;
|
return hashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GeneratedBy(StringNativeGenerator.class)
|
@InjectedBy(StringNativeGenerator.class)
|
||||||
public static native TString wrap(String str);
|
public static native TString wrap(String str);
|
||||||
|
|
||||||
public TString toLowerCase() {
|
public TString toLowerCase() {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2014 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.java.lang;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class CharacterTest {
|
||||||
|
@Test
|
||||||
|
public void digitsRecognized() {
|
||||||
|
assertEquals(2, Character.digit('2', 10));
|
||||||
|
assertEquals(-1, Character.digit('.', 10));
|
||||||
|
assertEquals(6, Character.digit('\u096C', 10));
|
||||||
|
assertEquals(15, Character.digit('F', 16));
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user