mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-09 00:14:10 -08:00
Merge branch 'decimal-format'
This commit is contained in:
commit
c38c07becc
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2014 Alexey Andreev.
|
* Copyright 2015 Alexey Andreev.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -15,62 +15,59 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.impl.unicode;
|
package org.teavm.classlib.impl.unicode;
|
||||||
|
|
||||||
import org.teavm.platform.metadata.Resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public interface CLDRDecimalData extends Resource {
|
public class CLDRDecimalData {
|
||||||
int getMaximumFractionDigits();
|
int groupingSeparator;
|
||||||
|
int decimalSeparator;
|
||||||
|
int listSeparator;
|
||||||
|
int perMille;
|
||||||
|
int percent;
|
||||||
|
String NaN;
|
||||||
|
String infinity;
|
||||||
|
int minusSign;
|
||||||
|
int monetaryDecimalSeparator;
|
||||||
|
String exponentSeparator;
|
||||||
|
|
||||||
void setMaximumFractionDigits(int value);
|
public int getGroupingSeparator() {
|
||||||
|
return groupingSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
int getMaximumIntegerDigits();
|
public int getDecimalSeparator() {
|
||||||
|
return decimalSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
void setMaximumIntegerDigits(int value);
|
public int getListSeparator() {
|
||||||
|
return listSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
int getMinimumFractionDigits();
|
public int getPerMille() {
|
||||||
|
return perMille;
|
||||||
|
}
|
||||||
|
|
||||||
void setMinimumFractionDigits(int value);
|
public int getPercent() {
|
||||||
|
return percent;
|
||||||
|
}
|
||||||
|
|
||||||
int getMinimumIntegerDigits();
|
public String getNaN() {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
|
||||||
void setMinimumIntegerDigits(int value);
|
public String getInfinity() {
|
||||||
|
return infinity;
|
||||||
|
}
|
||||||
|
|
||||||
int getGroupingSeparator();
|
public int getMinusSign() {
|
||||||
|
return minusSign;
|
||||||
|
}
|
||||||
|
|
||||||
void setGroupingSeparator(int value);
|
public int getMonetaryDecimalSeparator() {
|
||||||
|
return monetaryDecimalSeparator;
|
||||||
|
}
|
||||||
|
|
||||||
int getDecimalSeparator();
|
public String getExponentSeparator() {
|
||||||
|
return exponentSeparator;
|
||||||
void setDecimalSeparator(int value);
|
}
|
||||||
|
|
||||||
int getPerMill();
|
|
||||||
|
|
||||||
void setPerMill(int value);
|
|
||||||
|
|
||||||
int getPercent();
|
|
||||||
|
|
||||||
void setPercent(int value);
|
|
||||||
|
|
||||||
String getNaN();
|
|
||||||
|
|
||||||
void setNaN(String nan);
|
|
||||||
|
|
||||||
String getInfinity();
|
|
||||||
|
|
||||||
void setInfinity(String infinity);
|
|
||||||
|
|
||||||
int getMinusSign();
|
|
||||||
|
|
||||||
void setMinusSign(int value);
|
|
||||||
|
|
||||||
int getMonetaryDecimalSeparator();
|
|
||||||
|
|
||||||
void setMonetaryDecimalSeparator(int value);
|
|
||||||
|
|
||||||
String getExponentSeparator();
|
|
||||||
|
|
||||||
void setExponentSeparator(String value);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,14 +200,15 @@ public class CLDRHelper {
|
||||||
return res.getValue();
|
return res.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CLDRDecimalData resolveDecimalData(String language, String country) {
|
public static DecimalData resolveDecimalData(String language, String country) {
|
||||||
ResourceMap<CLDRDecimalData> map = getDecimalDataMap();
|
ResourceMap<DecimalData> map = getDecimalDataMap();
|
||||||
String localeCode = getCode(language, country);
|
String localeCode = getCode(language, country);
|
||||||
return map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) :
|
return map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) :
|
||||||
map.get("root");
|
map.get("root");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native ResourceMap<CLDRDecimalData> getDecimalDataMap();
|
@MetadataProvider(DecimalMetadataGenerator.class)
|
||||||
|
private static native ResourceMap<DecimalData> getDecimalDataMap();
|
||||||
|
|
||||||
public static CurrencyLocalization resolveCurrency(String language, String country, String currency) {
|
public static CurrencyLocalization resolveCurrency(String language, String country, String currency) {
|
||||||
String localeCode = getCode(language, country);
|
String localeCode = getCode(language, country);
|
||||||
|
|
|
@ -38,6 +38,7 @@ public class CLDRLocale {
|
||||||
CLDRDateFormats timeFormats;
|
CLDRDateFormats timeFormats;
|
||||||
CLDRDateFormats dateTimeFormats;
|
CLDRDateFormats dateTimeFormats;
|
||||||
CLDRTimeZone[] timeZones;
|
CLDRTimeZone[] timeZones;
|
||||||
|
CLDRDecimalData decimalData = new CLDRDecimalData();
|
||||||
|
|
||||||
public Map<String, String> getLanguages() {
|
public Map<String, String> getLanguages() {
|
||||||
return Collections.unmodifiableMap(languages);
|
return Collections.unmodifiableMap(languages);
|
||||||
|
@ -90,4 +91,8 @@ public class CLDRLocale {
|
||||||
public CLDRTimeZone[] getTimeZones() {
|
public CLDRTimeZone[] getTimeZones() {
|
||||||
return timeZones.clone();
|
return timeZones.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CLDRDecimalData getDecimalData() {
|
||||||
|
return decimalData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,9 +127,12 @@ public class CLDRReader {
|
||||||
readDateTimeFormats(localeName, localeInfo, root);
|
readDateTimeFormats(localeName, localeInfo, root);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "currencies.json": {
|
case "currencies.json":
|
||||||
readCurrencies(localeName, localeInfo, input);
|
readCurrencies(localeName, localeInfo, input);
|
||||||
}
|
break;
|
||||||
|
case "numbers.json":
|
||||||
|
readNumbers(localeName, localeInfo, input);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -207,6 +210,23 @@ public class CLDRReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readNumbers(String localeCode, CLDRLocale locale, InputStream input) {
|
||||||
|
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
||||||
|
JsonObject numbersJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
||||||
|
.get("numbers").getAsJsonObject();
|
||||||
|
String numbering = numbersJson.get("defaultNumberingSystem").getAsString();
|
||||||
|
JsonObject symbolsJson = numbersJson.get("symbols-numberSystem-" + numbering).getAsJsonObject();
|
||||||
|
locale.decimalData.decimalSeparator = symbolsJson.get("decimal").getAsString().charAt(0);
|
||||||
|
locale.decimalData.groupingSeparator = symbolsJson.get("group").getAsString().charAt(0);
|
||||||
|
locale.decimalData.listSeparator = symbolsJson.get("list").getAsString().charAt(0);
|
||||||
|
locale.decimalData.percent = symbolsJson.get("percentSign").getAsString().charAt(0);
|
||||||
|
locale.decimalData.minusSign = symbolsJson.get("minusSign").getAsString().charAt(0);
|
||||||
|
locale.decimalData.exponentSeparator = symbolsJson.get("exponential").getAsString();
|
||||||
|
locale.decimalData.perMille = symbolsJson.get("perMille").getAsString().charAt(0);
|
||||||
|
locale.decimalData.infinity = symbolsJson.get("infinity").getAsString();
|
||||||
|
locale.decimalData.NaN = symbolsJson.get("nan").getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
private void readEras(String localeCode, CLDRLocale locale, JsonObject root) {
|
private void readEras(String localeCode, CLDRLocale locale, JsonObject root) {
|
||||||
JsonObject erasJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
JsonObject erasJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
||||||
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
|
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* 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 org.teavm.platform.metadata.Resource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public interface DecimalData extends Resource {
|
||||||
|
int getGroupingSeparator();
|
||||||
|
|
||||||
|
void setGroupingSeparator(int value);
|
||||||
|
|
||||||
|
int getDecimalSeparator();
|
||||||
|
|
||||||
|
void setDecimalSeparator(int value);
|
||||||
|
|
||||||
|
int getListSeparator();
|
||||||
|
|
||||||
|
void setListSeparator(int value);
|
||||||
|
|
||||||
|
int getPerMille();
|
||||||
|
|
||||||
|
void setPerMille(int value);
|
||||||
|
|
||||||
|
int getPercent();
|
||||||
|
|
||||||
|
void setPercent(int value);
|
||||||
|
|
||||||
|
String getNaN();
|
||||||
|
|
||||||
|
void setNaN(String nan);
|
||||||
|
|
||||||
|
String getInfinity();
|
||||||
|
|
||||||
|
void setInfinity(String infinity);
|
||||||
|
|
||||||
|
int getMinusSign();
|
||||||
|
|
||||||
|
void setMinusSign(int value);
|
||||||
|
|
||||||
|
String getExponentSeparator();
|
||||||
|
|
||||||
|
void setExponentSeparator(String value);
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* 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.unicode;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.platform.metadata.MetadataGenerator;
|
||||||
|
import org.teavm.platform.metadata.MetadataGeneratorContext;
|
||||||
|
import org.teavm.platform.metadata.Resource;
|
||||||
|
import org.teavm.platform.metadata.ResourceMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class DecimalMetadataGenerator implements MetadataGenerator {
|
||||||
|
@Override
|
||||||
|
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||||
|
CLDRReader reader = context.getService(CLDRReader.class);
|
||||||
|
ResourceMap<DecimalData> map = context.createResourceMap();
|
||||||
|
for (Map.Entry<String, CLDRLocale> entry : reader.getKnownLocales().entrySet()) {
|
||||||
|
CLDRDecimalData data = entry.getValue().getDecimalData();
|
||||||
|
DecimalData dataRes = context.createResource(DecimalData.class);
|
||||||
|
dataRes.setDecimalSeparator(data.getDecimalSeparator());
|
||||||
|
dataRes.setExponentSeparator(data.getExponentSeparator());
|
||||||
|
dataRes.setGroupingSeparator(data.getGroupingSeparator());
|
||||||
|
dataRes.setInfinity(data.getInfinity());
|
||||||
|
dataRes.setListSeparator(data.getListSeparator());
|
||||||
|
dataRes.setMinusSign(data.getMinusSign());
|
||||||
|
dataRes.setNaN(data.getNaN());
|
||||||
|
dataRes.setPercent(data.getPercent());
|
||||||
|
dataRes.setPerMille(data.getPerMille());
|
||||||
|
map.put(entry.getKey(), dataRes);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
}
|
|
@ -169,7 +169,7 @@ public class TDouble extends TNumber implements TComparable<TDouble> {
|
||||||
return mantissa * decimalExponent(exp);
|
return mantissa * decimalExponent(exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static double decimalExponent(int n) {
|
public static double decimalExponent(int n) {
|
||||||
double d;
|
double d;
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
d = 0.1;
|
d = 0.1;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,304 @@
|
||||||
|
/*
|
||||||
|
* 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.java.text;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import org.teavm.classlib.java.text.TDecimalFormat.FormatField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
class TDecimalFormatParser {
|
||||||
|
private FormatField[] positivePrefix;
|
||||||
|
private FormatField[] positiveSuffix;
|
||||||
|
private FormatField[] negativePrefix;
|
||||||
|
private FormatField[] negativeSuffix;
|
||||||
|
private int groupSize;
|
||||||
|
private int minimumIntLength;
|
||||||
|
private int intLength;
|
||||||
|
private int minimumFracLength;
|
||||||
|
private int fracLength;
|
||||||
|
private int exponentLength;
|
||||||
|
private boolean decimalSeparatorRequired;
|
||||||
|
private String string;
|
||||||
|
private int index;
|
||||||
|
private int multiplier;
|
||||||
|
|
||||||
|
public void parse(String string) {
|
||||||
|
groupSize = 0;
|
||||||
|
minimumFracLength = 0;
|
||||||
|
fracLength = 0;
|
||||||
|
exponentLength = 0;
|
||||||
|
decimalSeparatorRequired = false;
|
||||||
|
multiplier = 1;
|
||||||
|
this.string = string;
|
||||||
|
index = 0;
|
||||||
|
positivePrefix = parseText(false, false);
|
||||||
|
if (index == string.length()) {
|
||||||
|
throw new IllegalArgumentException("Positive number pattern not found in " + string);
|
||||||
|
}
|
||||||
|
parseNumber(true);
|
||||||
|
negativePrefix = null;
|
||||||
|
negativeSuffix = null;
|
||||||
|
if (index < string.length() && string.charAt(index) != ';') {
|
||||||
|
positiveSuffix = parseText(true, false);
|
||||||
|
}
|
||||||
|
if (index < string.length()) {
|
||||||
|
if (string.charAt(index++) != ';') {
|
||||||
|
throw new IllegalArgumentException("Expected ';' at " + index + " in " + string);
|
||||||
|
}
|
||||||
|
negativePrefix = parseText(false, true);
|
||||||
|
parseNumber(false);
|
||||||
|
negativeSuffix = parseText(true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void apply(TDecimalFormat format) {
|
||||||
|
format.positivePrefix = positivePrefix;
|
||||||
|
format.positiveSuffix = positiveSuffix;
|
||||||
|
if (negativePrefix != null) {
|
||||||
|
format.negativePrefix = negativePrefix;
|
||||||
|
} else {
|
||||||
|
format.negativePrefix = new FormatField[positivePrefix.length + 1];
|
||||||
|
System.arraycopy(positivePrefix, 0, format.negativePrefix, 1, positivePrefix.length);
|
||||||
|
format.negativePrefix[0] = new TDecimalFormat.MinusField();
|
||||||
|
}
|
||||||
|
format.negativeSuffix = negativeSuffix != null ? negativeSuffix : positiveSuffix;
|
||||||
|
format.setGroupingSize(groupSize);
|
||||||
|
format.setGroupingUsed(groupSize > 0);
|
||||||
|
format.setMinimumIntegerDigits(!decimalSeparatorRequired ? minimumIntLength :
|
||||||
|
Math.max(1, minimumIntLength));
|
||||||
|
format.setMaximumIntegerDigits(intLength);
|
||||||
|
format.setMinimumFractionDigits(minimumFracLength);
|
||||||
|
format.setMaximumFractionDigits(fracLength);
|
||||||
|
format.setDecimalSeparatorAlwaysShown(decimalSeparatorRequired);
|
||||||
|
format.exponentDigits = exponentLength;
|
||||||
|
format.setMultiplier(multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
FormatField[] parseText(boolean suffix, boolean end) {
|
||||||
|
List<FormatField> fields = new ArrayList<>();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
loop: while (index < string.length()) {
|
||||||
|
char c = string.charAt(index);
|
||||||
|
switch (c) {
|
||||||
|
case '#':
|
||||||
|
case '0':
|
||||||
|
if (suffix) {
|
||||||
|
throw new IllegalArgumentException("Prefix contains special character at " + index + " in " +
|
||||||
|
string);
|
||||||
|
}
|
||||||
|
break loop;
|
||||||
|
case ';':
|
||||||
|
if (end) {
|
||||||
|
throw new IllegalArgumentException("Prefix contains special character at " + index + " in " +
|
||||||
|
string);
|
||||||
|
}
|
||||||
|
break loop;
|
||||||
|
case '.':
|
||||||
|
case 'E':
|
||||||
|
throw new IllegalArgumentException("Prefix contains special character at " + index + " in " +
|
||||||
|
string);
|
||||||
|
case '\'': {
|
||||||
|
++index;
|
||||||
|
int next = string.indexOf('\'', index);
|
||||||
|
if (next < 0) {
|
||||||
|
throw new IllegalArgumentException("Quote opened at " + index + " was not closed in " +
|
||||||
|
string);
|
||||||
|
}
|
||||||
|
if (next == index) {
|
||||||
|
sb.append('\'');
|
||||||
|
} else {
|
||||||
|
sb.append(string.substring(index, next));
|
||||||
|
}
|
||||||
|
index = next + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Currency symbol ¤
|
||||||
|
case '\u00A4':
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
fields.add(new TDecimalFormat.TextField(sb.toString()));
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
fields.add(new TDecimalFormat.CurrencyField());
|
||||||
|
++index;
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
fields.add(new TDecimalFormat.TextField(sb.toString()));
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
fields.add(new TDecimalFormat.PercentField());
|
||||||
|
++index;
|
||||||
|
multiplier = 100;
|
||||||
|
break;
|
||||||
|
// Per mill symbol
|
||||||
|
case '\u2030':
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
fields.add(new TDecimalFormat.TextField(sb.toString()));
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
fields.add(new TDecimalFormat.PerMillField());
|
||||||
|
++index;
|
||||||
|
multiplier = 1000;
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
fields.add(new TDecimalFormat.TextField(sb.toString()));
|
||||||
|
sb.setLength(0);
|
||||||
|
}
|
||||||
|
fields.add(new TDecimalFormat.MinusField());
|
||||||
|
++index;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sb.append(c);
|
||||||
|
++index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sb.length() > 0) {
|
||||||
|
fields.add(new TDecimalFormat.TextField(sb.toString()));
|
||||||
|
}
|
||||||
|
return fields.toArray(new FormatField[fields.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseNumber(boolean apply) {
|
||||||
|
parseIntegerPart(apply);
|
||||||
|
if (index < string.length() && string.charAt(index) == '.') {
|
||||||
|
++index;
|
||||||
|
parseFractionalPart(apply);
|
||||||
|
}
|
||||||
|
if (index < string.length() && string.charAt(index) == 'E') {
|
||||||
|
++index;
|
||||||
|
parseExponent(apply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseIntegerPart(boolean apply) {
|
||||||
|
int start = index;
|
||||||
|
int lastGroup = index;
|
||||||
|
boolean optionalDigits = true;
|
||||||
|
int length = 0;
|
||||||
|
int minimumLength = 0;
|
||||||
|
loop: while (index < string.length()) {
|
||||||
|
switch (string.charAt(index)) {
|
||||||
|
case '#':
|
||||||
|
if (!optionalDigits) {
|
||||||
|
throw new IllegalArgumentException("Unexpected '#' at non-optional digit part at " + index +
|
||||||
|
" in " + string);
|
||||||
|
}
|
||||||
|
++length;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
if (lastGroup == index) {
|
||||||
|
throw new IllegalArgumentException("Two group separators at " + index + " in " + string);
|
||||||
|
}
|
||||||
|
if (apply) {
|
||||||
|
groupSize = index - lastGroup;
|
||||||
|
}
|
||||||
|
lastGroup = index + 1;
|
||||||
|
break;
|
||||||
|
case '0':
|
||||||
|
optionalDigits = false;
|
||||||
|
++length;
|
||||||
|
++minimumLength;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (length == 0) {
|
||||||
|
throw new IllegalArgumentException("Pattern does not specify integer digits at " + index +
|
||||||
|
" in " + string);
|
||||||
|
}
|
||||||
|
if (lastGroup == index) {
|
||||||
|
throw new IllegalArgumentException("Group separator at the end of number at " + index + " in " + string);
|
||||||
|
}
|
||||||
|
if (apply && lastGroup > start) {
|
||||||
|
groupSize = index - lastGroup;
|
||||||
|
}
|
||||||
|
if (apply) {
|
||||||
|
intLength = length;
|
||||||
|
minimumIntLength = minimumLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseFractionalPart(boolean apply) {
|
||||||
|
boolean optionalDigits = false;
|
||||||
|
int length = 0;
|
||||||
|
int minimumLength = 0;
|
||||||
|
loop: while (index < string.length()) {
|
||||||
|
switch (string.charAt(index)) {
|
||||||
|
case '#':
|
||||||
|
++length;
|
||||||
|
optionalDigits = true;
|
||||||
|
break;
|
||||||
|
case ',':
|
||||||
|
throw new IllegalArgumentException("Group separator found at fractional part at " + index +
|
||||||
|
" in " + string);
|
||||||
|
case '0':
|
||||||
|
if (optionalDigits) {
|
||||||
|
throw new IllegalArgumentException("Unexpected '0' at optional digit part at " + index +
|
||||||
|
" in " + string);
|
||||||
|
}
|
||||||
|
++length;
|
||||||
|
++minimumLength;
|
||||||
|
break;
|
||||||
|
case '.':
|
||||||
|
throw new IllegalArgumentException("Unexpected second decimal separator at " + index +
|
||||||
|
" in " + string);
|
||||||
|
default:
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (apply) {
|
||||||
|
fracLength = length;
|
||||||
|
minimumFracLength = minimumLength;
|
||||||
|
decimalSeparatorRequired = length == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void parseExponent(boolean apply) {
|
||||||
|
int length = 0;
|
||||||
|
loop: while (index < string.length()) {
|
||||||
|
switch (string.charAt(index)) {
|
||||||
|
case '#':
|
||||||
|
case ',':
|
||||||
|
case '.':
|
||||||
|
case 'E':
|
||||||
|
throw new IllegalArgumentException("Unexpected char at exponent at " + index +
|
||||||
|
" in " + string);
|
||||||
|
case '0':
|
||||||
|
++length;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
if (length == 0) {
|
||||||
|
throw new IllegalArgumentException("Pattern does not specify exponent digits at " + index +
|
||||||
|
" in " + string);
|
||||||
|
}
|
||||||
|
if (apply) {
|
||||||
|
exponentLength = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.text;
|
package org.teavm.classlib.java.text;
|
||||||
|
|
||||||
import org.teavm.classlib.impl.unicode.CLDRDecimalData;
|
import org.teavm.classlib.impl.unicode.DecimalData;
|
||||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||||
import org.teavm.classlib.java.util.TLocale;
|
import org.teavm.classlib.java.util.TLocale;
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ import org.teavm.classlib.java.util.TLocale;
|
||||||
*
|
*
|
||||||
* @author Alexey Andreev
|
* @author Alexey Andreev
|
||||||
*/
|
*/
|
||||||
public class TDecimalFormatSymbols {
|
public class TDecimalFormatSymbols implements Cloneable {
|
||||||
private TLocale locale;
|
private TLocale locale;
|
||||||
private char zeroDigit;
|
private char zeroDigit;
|
||||||
private char groupingSeparator;
|
private char groupingSeparator;
|
||||||
|
@ -48,18 +48,18 @@ public class TDecimalFormatSymbols {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initData() {
|
private void initData() {
|
||||||
CLDRDecimalData data = CLDRHelper.resolveDecimalData(locale.getLanguage(), locale.getCountry());
|
DecimalData data = CLDRHelper.resolveDecimalData(locale.getLanguage(), locale.getCountry());
|
||||||
zeroDigit = '0';
|
zeroDigit = '0';
|
||||||
groupingSeparator = (char)data.getGroupingSeparator();
|
groupingSeparator = (char)data.getGroupingSeparator();
|
||||||
decimalSeparator = (char)data.getDecimalSeparator();
|
decimalSeparator = (char)data.getDecimalSeparator();
|
||||||
perMill = (char)data.getPerMill();
|
perMill = (char)data.getPerMille();
|
||||||
percent = (char)data.getPercent();
|
percent = (char)data.getPercent();
|
||||||
digit = '#';
|
digit = '#';
|
||||||
patternSeparator = ';';
|
patternSeparator = ';';
|
||||||
NaN = data.getNaN();
|
NaN = data.getNaN();
|
||||||
infinity = data.getInfinity();
|
infinity = data.getInfinity();
|
||||||
minusSign = (char)data.getMinusSign();
|
minusSign = (char)data.getMinusSign();
|
||||||
monetaryDecimalSeparator = (char)data.getMonetaryDecimalSeparator();
|
monetaryDecimalSeparator = (char)data.getDecimalSeparator();
|
||||||
exponentSeparator = data.getExponentSeparator();
|
exponentSeparator = data.getExponentSeparator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.classlib.java.text;
|
package org.teavm.classlib.java.text;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||||
|
import org.teavm.classlib.java.math.TRoundingMode;
|
||||||
|
import org.teavm.classlib.java.util.TCurrency;
|
||||||
import org.teavm.classlib.java.util.TLocale;
|
import org.teavm.classlib.java.util.TLocale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,9 +28,11 @@ import org.teavm.classlib.java.util.TLocale;
|
||||||
public abstract class TNumberFormat extends TFormat {
|
public abstract class TNumberFormat extends TFormat {
|
||||||
public static final int INTEGER_FIELD = 0;
|
public static final int INTEGER_FIELD = 0;
|
||||||
public static final int FRACTION_FIELD = 1;
|
public static final int FRACTION_FIELD = 1;
|
||||||
private boolean groupingUsed = true, parseIntegerOnly = false;
|
private boolean groupingUsed = true, parseIntegerOnly;
|
||||||
private int maximumIntegerDigits = 40, minimumIntegerDigits = 1,
|
private int maximumIntegerDigits = 40, minimumIntegerDigits = 1,
|
||||||
maximumFractionDigits = 3, minimumFractionDigits = 0;
|
maximumFractionDigits = 3, minimumFractionDigits = 0;
|
||||||
|
private TRoundingMode roundingMode = TRoundingMode.HALF_EVEN;
|
||||||
|
TCurrency currency = TCurrency.getInstance(TLocale.getDefault());
|
||||||
|
|
||||||
public TNumberFormat() {
|
public TNumberFormat() {
|
||||||
}
|
}
|
||||||
|
@ -37,6 +42,14 @@ public abstract class TNumberFormat extends TFormat {
|
||||||
return super.clone();
|
return super.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TCurrency getCurrency() {
|
||||||
|
return currency;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrency(TCurrency currency) {
|
||||||
|
this.currency = currency;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object object) {
|
public boolean equals(Object object) {
|
||||||
if (object == this) {
|
if (object == this) {
|
||||||
|
@ -51,7 +64,9 @@ public abstract class TNumberFormat extends TFormat {
|
||||||
&& maximumFractionDigits == obj.maximumFractionDigits
|
&& maximumFractionDigits == obj.maximumFractionDigits
|
||||||
&& maximumIntegerDigits == obj.maximumIntegerDigits
|
&& maximumIntegerDigits == obj.maximumIntegerDigits
|
||||||
&& minimumFractionDigits == obj.minimumFractionDigits
|
&& minimumFractionDigits == obj.minimumFractionDigits
|
||||||
&& minimumIntegerDigits == obj.minimumIntegerDigits;
|
&& minimumIntegerDigits == obj.minimumIntegerDigits
|
||||||
|
&& roundingMode == obj.roundingMode
|
||||||
|
&& currency == obj.currency;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String format(double value) {
|
public final String format(double value) {
|
||||||
|
@ -140,7 +155,8 @@ public abstract class TNumberFormat extends TFormat {
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return (groupingUsed ? 1231 : 1237) + (parseIntegerOnly ? 1231 : 1237)
|
return (groupingUsed ? 1231 : 1237) + (parseIntegerOnly ? 1231 : 1237)
|
||||||
+ maximumFractionDigits + maximumIntegerDigits
|
+ maximumFractionDigits + maximumIntegerDigits
|
||||||
+ minimumFractionDigits + minimumIntegerDigits;
|
+ minimumFractionDigits + minimumIntegerDigits +
|
||||||
|
roundingMode.hashCode() + Objects.hashCode(currency);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isGroupingUsed() {
|
public boolean isGroupingUsed() {
|
||||||
|
@ -211,6 +227,14 @@ public abstract class TNumberFormat extends TFormat {
|
||||||
parseIntegerOnly = value;
|
parseIntegerOnly = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TRoundingMode getRoundingMode() {
|
||||||
|
return roundingMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoundingMode(TRoundingMode roundingMode) {
|
||||||
|
this.roundingMode = roundingMode;
|
||||||
|
}
|
||||||
|
|
||||||
public static class Field extends TFormat.Field {
|
public static class Field extends TFormat.Field {
|
||||||
public static final Field SIGN = new Field("sign");
|
public static final Field SIGN = new Field("sign");
|
||||||
public static final Field INTEGER = new Field("integer");
|
public static final Field INTEGER = new Field("integer");
|
||||||
|
|
|
@ -20,7 +20,7 @@ package org.teavm.classlib.java.util;
|
||||||
* @author shannah
|
* @author shannah
|
||||||
*/
|
*/
|
||||||
public class TObservable {
|
public class TObservable {
|
||||||
TList<TObserver> observers = new TArrayList<TObserver>();
|
TList<TObserver> observers = new TArrayList<>();
|
||||||
|
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public class TObservable {
|
||||||
/**
|
/**
|
||||||
* Adds the specified observer to the list of observers. If it is already
|
* Adds the specified observer to the list of observers. If it is already
|
||||||
* registered, it is not added a second time.
|
* registered, it is not added a second time.
|
||||||
*
|
*
|
||||||
* @param observer
|
* @param observer
|
||||||
* the Observer to add.
|
* the Observer to add.
|
||||||
*/
|
*/
|
||||||
|
@ -58,7 +58,7 @@ public class TObservable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of observers registered to this {@code Observable}.
|
* Returns the number of observers registered to this {@code Observable}.
|
||||||
*
|
*
|
||||||
* @return the number of observers.
|
* @return the number of observers.
|
||||||
*/
|
*/
|
||||||
public int countObservers() {
|
public int countObservers() {
|
||||||
|
@ -68,7 +68,7 @@ public class TObservable {
|
||||||
/**
|
/**
|
||||||
* Removes the specified observer from the list of observers. Passing null
|
* Removes the specified observer from the list of observers. Passing null
|
||||||
* won't do anything.
|
* won't do anything.
|
||||||
*
|
*
|
||||||
* @param observer
|
* @param observer
|
||||||
* the observer to remove.
|
* the observer to remove.
|
||||||
*/
|
*/
|
||||||
|
@ -85,7 +85,7 @@ public class TObservable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the changed flag for this {@code Observable}.
|
* Returns the changed flag for this {@code Observable}.
|
||||||
*
|
*
|
||||||
* @return {@code true} when the changed flag for this {@code Observable} is
|
* @return {@code true} when the changed flag for this {@code Observable} is
|
||||||
* set, {@code false} otherwise.
|
* set, {@code false} otherwise.
|
||||||
*/
|
*/
|
||||||
|
@ -108,11 +108,10 @@ public class TObservable {
|
||||||
* If {@code hasChanged()} returns {@code true}, calls the {@code update()}
|
* If {@code hasChanged()} returns {@code true}, calls the {@code update()}
|
||||||
* method for every Observer in the list of observers using the specified
|
* method for every Observer in the list of observers using the specified
|
||||||
* argument. Afterwards calls {@code clearChanged()}.
|
* argument. Afterwards calls {@code clearChanged()}.
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* the argument passed to {@code update()}.
|
* the argument passed to {@code update()}.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public void notifyObservers(Object data) {
|
public void notifyObservers(Object data) {
|
||||||
int size = 0;
|
int size = 0;
|
||||||
TObserver[] arrays = null;
|
TObserver[] arrays = null;
|
||||||
|
|
|
@ -65,6 +65,10 @@ public final class TeaVMTestRunner {
|
||||||
.withDescription("qualified class names of transformers")
|
.withDescription("qualified class names of transformers")
|
||||||
.withLongOpt("transformers")
|
.withLongOpt("transformers")
|
||||||
.create("T"));
|
.create("T"));
|
||||||
|
options.addOption(OptionBuilder
|
||||||
|
.withDescription("Incremental build")
|
||||||
|
.withLongOpt("incremental")
|
||||||
|
.create('i'));
|
||||||
|
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
printUsage(options);
|
printUsage(options);
|
||||||
|
@ -97,6 +101,10 @@ public final class TeaVMTestRunner {
|
||||||
tool.getTransformers().add(instantiateTransformer(transformerType));
|
tool.getTransformers().add(instantiateTransformer(transformerType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (commandLine.hasOption('i')) {
|
||||||
|
tool.setIncremental(true);
|
||||||
|
}
|
||||||
|
|
||||||
args = commandLine.getArgs();
|
args = commandLine.getArgs();
|
||||||
if (args.length == 0) {
|
if (args.length == 0) {
|
||||||
System.err.println("You did not specify any test classes");
|
System.err.println("You did not specify any test classes");
|
||||||
|
|
30
teavm-core/src/main/java/org/teavm/cache/NoCache.java
vendored
Normal file
30
teavm-core/src/main/java/org/teavm/cache/NoCache.java
vendored
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
* 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.cache;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.METHOD)
|
||||||
|
public @interface NoCache {
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.teavm.cache.NoCache;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
import org.teavm.common.GraphIndexer;
|
import org.teavm.common.GraphIndexer;
|
||||||
import org.teavm.common.Loop;
|
import org.teavm.common.Loop;
|
||||||
|
@ -245,7 +246,7 @@ public class Decompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegularMethodNode decompileRegular(MethodHolder method) {
|
public RegularMethodNode decompileRegular(MethodHolder method) {
|
||||||
if (regularMethodCache == null) {
|
if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) {
|
||||||
return decompileRegularCacheMiss(method);
|
return decompileRegularCacheMiss(method);
|
||||||
}
|
}
|
||||||
RegularMethodNode node = regularMethodCache.get(method.getReference());
|
RegularMethodNode node = regularMethodCache.get(method.getReference());
|
||||||
|
@ -283,7 +284,7 @@ public class Decompiler {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AsyncMethodNode decompileAsync(MethodHolder method) {
|
public AsyncMethodNode decompileAsync(MethodHolder method) {
|
||||||
if (regularMethodCache == null) {
|
if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) {
|
||||||
return decompileAsyncCacheMiss(method);
|
return decompileAsyncCacheMiss(method);
|
||||||
}
|
}
|
||||||
AsyncMethodNode node = regularMethodCache.getAsync(method.getReference());
|
AsyncMethodNode node = regularMethodCache.getAsync(method.getReference());
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.model;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import org.teavm.model.util.ProgramUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -27,11 +28,12 @@ public class InMemoryProgramCache implements ProgramCache {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Program get(MethodReference method) {
|
public Program get(MethodReference method) {
|
||||||
return cache.get(method);
|
Program program = cache.get(method);
|
||||||
|
return program != null ? ProgramUtils.copy(program) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void store(MethodReference method, Program program) {
|
public void store(MethodReference method, Program program) {
|
||||||
cache.put(method, program);
|
cache.put(method, ProgramUtils.copy(program));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -236,7 +236,7 @@ public class TeaVMTool {
|
||||||
symbolTable.update();
|
symbolTable.update();
|
||||||
fileTable.update();
|
fileTable.update();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.info("Cache was not read");
|
log.info("Cache is missing");
|
||||||
}
|
}
|
||||||
vmBuilder.setClassLoader(classLoader).setClassSource(cachedClassSource);
|
vmBuilder.setClassLoader(classLoader).setClassSource(cachedClassSource);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.vm;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import org.teavm.cache.NoCache;
|
||||||
import org.teavm.codegen.*;
|
import org.teavm.codegen.*;
|
||||||
import org.teavm.common.ServiceRepository;
|
import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||||
|
@ -616,7 +617,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
||||||
if (method.getProgram() == null) {
|
if (method.getProgram() == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Program optimizedProgram = incremental && programCache != null ?
|
|
||||||
|
boolean noCache = method.getAnnotations().get(NoCache.class.getName()) != null;
|
||||||
|
Program optimizedProgram = incremental && !noCache && programCache != null ?
|
||||||
programCache.get(method.getReference()) : null;
|
programCache.get(method.getReference()) : null;
|
||||||
if (optimizedProgram == null) {
|
if (optimizedProgram == null) {
|
||||||
optimizedProgram = ProgramUtils.copy(method.getProgram());
|
optimizedProgram = ProgramUtils.copy(method.getProgram());
|
||||||
|
|
|
@ -744,6 +744,9 @@ function Long_rem(a, b) {
|
||||||
return Long_divRem(a, b)[1];
|
return Long_divRem(a, b)[1];
|
||||||
}
|
}
|
||||||
function Long_divRem(a, b) {
|
function Long_divRem(a, b) {
|
||||||
|
if (b.lo == 0 && b.hi == 0) {
|
||||||
|
throw new Error("Division by zero");
|
||||||
|
}
|
||||||
var positive = Long_isNegative(a) === Long_isNegative(b);
|
var positive = Long_isNegative(a) === Long_isNegative(b);
|
||||||
if (Long_isNegative(a)) {
|
if (Long_isNegative(a)) {
|
||||||
a = Long_neg(a);
|
a = Long_neg(a);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.platform.plugin;
|
package org.teavm.platform.plugin;
|
||||||
|
|
||||||
|
import org.teavm.cache.NoCache;
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.javascript.spi.GeneratedBy;
|
import org.teavm.javascript.spi.GeneratedBy;
|
||||||
import org.teavm.model.*;
|
import org.teavm.model.*;
|
||||||
|
@ -49,10 +50,14 @@ class MetadataProviderTransformer implements ClassHolderTransformer {
|
||||||
method.getReference(), ClassScopedMetadataProvider.class.getName(),
|
method.getReference(), ClassScopedMetadataProvider.class.getName(),
|
||||||
PlatformClass.class.getName());
|
PlatformClass.class.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||||
ClassScopedMetadataProviderNativeGenerator.class.getName())));
|
ClassScopedMetadataProviderNativeGenerator.class.getName())));
|
||||||
method.getAnnotations().add(genAnnot);
|
method.getAnnotations().add(genAnnot);
|
||||||
|
|
||||||
|
AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName());
|
||||||
|
method.getAnnotations().add(noCacheAnnot);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,6 +100,9 @@ class MetadataProviderTransformer implements ClassHolderTransformer {
|
||||||
fork.setElse(pe.createBlock());
|
fork.setElse(pe.createBlock());
|
||||||
pe.setField(field.getReference(), field.getType(), pe.invoke(createMethod.getReference()));
|
pe.setField(field.getReference(), field.getType(), pe.invoke(createMethod.getReference()));
|
||||||
pe.jump(resourceFound);
|
pe.jump(resourceFound);
|
||||||
|
|
||||||
|
AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName());
|
||||||
|
method.getAnnotations().add(noCacheAnnot);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean validate(MethodHolder method, Diagnostics diagnostics) {
|
private boolean validate(MethodHolder method, Diagnostics diagnostics) {
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* 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.java.text;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.util.Locale;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class DecimalFormatParseTest {
|
||||||
|
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesNumber() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("#,#00.#");
|
||||||
|
assertEquals(2L, format.parse("2"));
|
||||||
|
assertEquals(23L, format.parse("23"));
|
||||||
|
assertEquals(23L, format.parse("23.0"));
|
||||||
|
assertEquals(2300L, format.parse("2,3,0,0"));
|
||||||
|
assertEquals(23.1, format.parse("23.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesBigNumber() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("#,#00.#");
|
||||||
|
format.setParseBigDecimal(true);
|
||||||
|
assertEquals(BigDecimal.valueOf(2), format.parse("2"));
|
||||||
|
assertEquals(BigDecimal.valueOf(23), format.parse("23"));
|
||||||
|
assertEquals(BigDecimal.valueOf(230, 1), format.parse("23.0"));
|
||||||
|
assertEquals(BigDecimal.valueOf(2300), format.parse("2,3,0,0"));
|
||||||
|
assertEquals(BigDecimal.valueOf(231, 1), format.parse("23.1"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesLargeValue() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("#,#00.#");
|
||||||
|
assertEquals(9223372036854775807L, format.parse("9223372036854775807"));
|
||||||
|
assertEquals(99E18, format.parse("99000000000000000000"));
|
||||||
|
assertEquals(3.333333333333333E20, format.parse("333333333333333333456").doubleValue(), 1000000);
|
||||||
|
assertEquals(10E20, format.parse("999999999999999999999").doubleValue(), 1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesExponential() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("0.#E0");
|
||||||
|
assertEquals(23L, format.parse("2.3E1"));
|
||||||
|
assertEquals(23L, format.parse("2300E-2"));
|
||||||
|
assertEquals(0.23, format.parse("2300E-4").doubleValue(), 0.0001);
|
||||||
|
assertEquals(99E18, format.parse("99E18"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesBigExponential() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("0.#E0");
|
||||||
|
format.setParseBigDecimal(true);
|
||||||
|
assertEquals(BigDecimal.valueOf(23), format.parse("2.3E1"));
|
||||||
|
assertEquals(BigDecimal.valueOf(2300, 2), format.parse("2300E-2"));
|
||||||
|
assertEquals(BigDecimal.valueOf(2300, 4), format.parse("2300E-4"));
|
||||||
|
assertEquals(BigDecimal.valueOf(99, -18), format.parse("99E18"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesPrefixSuffix() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("[0.#E0]");
|
||||||
|
assertEquals(23L, format.parse("[23]"));
|
||||||
|
assertEquals(-23L, format.parse("-[23]"));
|
||||||
|
try {
|
||||||
|
format.parse("23");
|
||||||
|
fail("Exception expected as there aren't neither prefix nor suffix");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
assertEquals(0, e.getErrorOffset());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
format.parse("[23");
|
||||||
|
fail("Exception expected as there is no suffix");
|
||||||
|
} catch (ParseException e) {
|
||||||
|
assertEquals(3, e.getErrorOffset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesPercent() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("0.#E0%");
|
||||||
|
assertEquals(0.23, format.parse("23%").doubleValue(), 0.001);
|
||||||
|
assertEquals(23L, format.parse("2300%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesBigPercent() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("0.#E0%");
|
||||||
|
format.setParseBigDecimal(true);
|
||||||
|
assertEquals(BigDecimal.valueOf(23, 2), format.parse("23%"));
|
||||||
|
assertEquals(BigDecimal.valueOf(23, 0), format.parse("2300%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesSpecial() throws ParseException {
|
||||||
|
DecimalFormat format = createFormat("0.#E0");
|
||||||
|
assertEquals(Double.POSITIVE_INFINITY, format.parse("∞"));
|
||||||
|
assertEquals(Double.NEGATIVE_INFINITY, format.parse("-∞"));
|
||||||
|
assertEquals(-0.0, format.parse("-0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DecimalFormat createFormat(String format) {
|
||||||
|
return new DecimalFormat(format, symbols);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,475 @@
|
||||||
|
/*
|
||||||
|
* 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.java.text;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.math.RoundingMode;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
import java.util.Currency;
|
||||||
|
import java.util.Locale;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Alexey Andreev
|
||||||
|
*/
|
||||||
|
public class DecimalFormatTest {
|
||||||
|
private static DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.ENGLISH);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesIntegerPattern() {
|
||||||
|
DecimalFormat format = createFormat("00");
|
||||||
|
assertEquals(2, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isDecimalSeparatorAlwaysShown());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(0, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(0, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("##");
|
||||||
|
assertEquals(0, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isDecimalSeparatorAlwaysShown());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(0, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(0, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("#,##0");
|
||||||
|
assertEquals(1, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isDecimalSeparatorAlwaysShown());
|
||||||
|
assertTrue(format.isGroupingUsed());
|
||||||
|
assertEquals(3, format.getGroupingSize());
|
||||||
|
assertEquals(0, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(0, format.getMaximumFractionDigits());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void selectsLastGrouping() {
|
||||||
|
DecimalFormat format = new DecimalFormat("#,0,000");
|
||||||
|
assertEquals(4, format.getMinimumIntegerDigits());
|
||||||
|
assertTrue(format.isGroupingUsed());
|
||||||
|
assertEquals(3, format.getGroupingSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesPrefixAndSuffixInPattern() {
|
||||||
|
DecimalFormat format = createFormat("(00)");
|
||||||
|
assertEquals(2, format.getMinimumIntegerDigits());
|
||||||
|
assertEquals("(", format.getPositivePrefix());
|
||||||
|
assertEquals(")", format.getPositiveSuffix());
|
||||||
|
assertEquals("-(", format.getNegativePrefix());
|
||||||
|
assertEquals(")", format.getNegativeSuffix());
|
||||||
|
|
||||||
|
format = createFormat("+(00);-{#}");
|
||||||
|
assertEquals(2, format.getMinimumIntegerDigits());
|
||||||
|
assertEquals("+(", format.getPositivePrefix());
|
||||||
|
assertEquals(")", format.getPositiveSuffix());
|
||||||
|
assertEquals("-{", format.getNegativePrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesFractionalPattern() {
|
||||||
|
DecimalFormat format = createFormat("#.");
|
||||||
|
assertEquals(1, format.getMinimumIntegerDigits());
|
||||||
|
assertTrue(format.isDecimalSeparatorAlwaysShown());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(0, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(0, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("#.00");
|
||||||
|
assertEquals(0, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(2, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(2, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("#.00##");
|
||||||
|
assertEquals(0, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(2, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(4, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("#00.00##");
|
||||||
|
assertEquals(2, format.getMinimumIntegerDigits());
|
||||||
|
assertFalse(format.isGroupingUsed());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(2, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(4, format.getMaximumFractionDigits());
|
||||||
|
|
||||||
|
format = createFormat("#,#00.00##");
|
||||||
|
assertEquals(2, format.getMinimumIntegerDigits());
|
||||||
|
assertTrue(format.isGroupingUsed());
|
||||||
|
assertEquals(3, format.getGroupingSize());
|
||||||
|
assertEquals(2, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(4, format.getMaximumFractionDigits());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parsesExponentialPattern() {
|
||||||
|
DecimalFormat format = createFormat("##0E00");
|
||||||
|
assertEquals(1, format.getMinimumIntegerDigits());
|
||||||
|
assertEquals(0, format.getGroupingSize());
|
||||||
|
assertEquals(0, format.getMinimumFractionDigits());
|
||||||
|
assertEquals(0, format.getMaximumFractionDigits());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsIntegerPart() {
|
||||||
|
DecimalFormat format = createFormat("00");
|
||||||
|
assertEquals("02", format.format(2));
|
||||||
|
assertEquals("23", format.format(23));
|
||||||
|
assertEquals("23", format.format(23.2));
|
||||||
|
assertEquals("24", format.format(23.7));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsBigIntegerPart() {
|
||||||
|
DecimalFormat format = createFormat("00");
|
||||||
|
assertEquals("02", format.format(new BigInteger("2")));
|
||||||
|
assertEquals("23", format.format(new BigInteger("23")));
|
||||||
|
assertEquals("23", format.format(new BigDecimal("23.2")));
|
||||||
|
assertEquals("24", format.format(new BigDecimal("23.7")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsNumber() {
|
||||||
|
DecimalFormat format = createFormat("0.0");
|
||||||
|
assertEquals("23.0", format.format(23));
|
||||||
|
assertEquals("23.2", format.format(23.2));
|
||||||
|
assertEquals("23.2", format.format(23.23));
|
||||||
|
assertEquals("23.3", format.format(23.27));
|
||||||
|
assertEquals("0.0", format.format(0.0001));
|
||||||
|
|
||||||
|
format = createFormat("00000000000000000000000000.0");
|
||||||
|
assertEquals("00000000000000000000000023.0", format.format(23));
|
||||||
|
assertEquals("00002300000000000000000000.0", format.format(23E20));
|
||||||
|
assertEquals("23000000000000000000000000.0", format.format(23E24));
|
||||||
|
|
||||||
|
format = createFormat("0.00000000000000000000000000");
|
||||||
|
assertEquals("23.00000000000000000000000000", format.format(23));
|
||||||
|
assertEquals("0.23000000000000000000000000", format.format(0.23));
|
||||||
|
assertEquals("0.00230000000000000000000000", format.format(0.0023));
|
||||||
|
assertEquals("0.00000000000000000000230000", format.format(23E-22));
|
||||||
|
assertEquals("0.00000000000000000000000023", format.format(23E-26));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsBigNumber() {
|
||||||
|
DecimalFormat format = createFormat("0.0");
|
||||||
|
assertEquals("23.0", format.format(BigInteger.valueOf(23)));
|
||||||
|
assertEquals("23.2", format.format(new BigDecimal("23.2")));
|
||||||
|
assertEquals("23.2", format.format(new BigDecimal("23.23")));
|
||||||
|
assertEquals("23.3", format.format(new BigDecimal("23.27")));
|
||||||
|
assertEquals("0.0", format.format(new BigDecimal("0.0001")));
|
||||||
|
|
||||||
|
format = createFormat("00000000000000000000000000.0");
|
||||||
|
assertEquals("00000000000000000000000023.0", format.format(new BigInteger("23")));
|
||||||
|
assertEquals("00002300000000000000000000.0", format.format(new BigInteger("2300000000000000000000")));
|
||||||
|
assertEquals("23000000000000000000000000.0", format.format(new BigInteger("23000000000000000000000000")));
|
||||||
|
|
||||||
|
format = createFormat("0.00000000000000000000000000");
|
||||||
|
assertEquals("23.00000000000000000000000000", format.format(new BigInteger("23")));
|
||||||
|
assertEquals("0.23000000000000000000000000", format.format(new BigDecimal("0.23")));
|
||||||
|
assertEquals("0.00230000000000000000000000", format.format(new BigDecimal("0.0023")));
|
||||||
|
assertEquals("0.00000000000000000000230000", format.format(new BigDecimal("0.0000000000000000000023")));
|
||||||
|
assertEquals("0.00000000000000000000000023", format.format(new BigDecimal("0.00000000000000000000000023")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsFractionalPart() {
|
||||||
|
DecimalFormat format = createFormat("0.0000####");
|
||||||
|
assertEquals("0.00001235", format.format(0.0000123456));
|
||||||
|
assertEquals("0.00012346", format.format(0.000123456));
|
||||||
|
assertEquals("0.00123456", format.format(0.00123456));
|
||||||
|
assertEquals("0.0123456", format.format(0.0123456));
|
||||||
|
assertEquals("0.1200", format.format(0.12));
|
||||||
|
assertEquals("0.1230", format.format(0.123));
|
||||||
|
assertEquals("0.1234", format.format(0.1234));
|
||||||
|
assertEquals("0.12345", format.format(0.12345));
|
||||||
|
|
||||||
|
format = createFormat("0.##");
|
||||||
|
assertEquals("23", format.format(23));
|
||||||
|
assertEquals("2.3", format.format(2.3));
|
||||||
|
assertEquals("0.23", format.format(0.23));
|
||||||
|
assertEquals("0.02", format.format(0.023));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void roundingWorks() {
|
||||||
|
DecimalFormat format = createFormat("0");
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.UP);
|
||||||
|
assertEquals("3", format.format(2.3));
|
||||||
|
assertEquals("3", format.format(2.7));
|
||||||
|
assertEquals("-3", format.format(-2.3));
|
||||||
|
assertEquals("-3", format.format(-2.7));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.DOWN);
|
||||||
|
assertEquals("2", format.format(2.3));
|
||||||
|
assertEquals("2", format.format(2.7));
|
||||||
|
assertEquals("-2", format.format(-2.3));
|
||||||
|
assertEquals("-2", format.format(-2.7));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
assertEquals("2", format.format(2.3));
|
||||||
|
assertEquals("2", format.format(2.7));
|
||||||
|
assertEquals("-3", format.format(-2.3));
|
||||||
|
assertEquals("-3", format.format(-2.7));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.CEILING);
|
||||||
|
assertEquals("3", format.format(2.3));
|
||||||
|
assertEquals("3", format.format(2.7));
|
||||||
|
assertEquals("-2", format.format(-2.3));
|
||||||
|
assertEquals("-2", format.format(-2.7));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_DOWN);
|
||||||
|
assertEquals("2", format.format(2.3));
|
||||||
|
assertEquals("3", format.format(2.7));
|
||||||
|
assertEquals("2", format.format(2.5));
|
||||||
|
assertEquals("3", format.format(3.5));
|
||||||
|
assertEquals("-2", format.format(-2.5));
|
||||||
|
assertEquals("-3", format.format(-3.5));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
assertEquals("2", format.format(2.3));
|
||||||
|
assertEquals("3", format.format(2.7));
|
||||||
|
assertEquals("3", format.format(2.5));
|
||||||
|
assertEquals("4", format.format(3.5));
|
||||||
|
assertEquals("-3", format.format(-2.5));
|
||||||
|
assertEquals("-4", format.format(-3.5));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_EVEN);
|
||||||
|
assertEquals("2", format.format(2.3));
|
||||||
|
assertEquals("3", format.format(2.7));
|
||||||
|
assertEquals("2", format.format(2.5));
|
||||||
|
assertEquals("4", format.format(3.5));
|
||||||
|
assertEquals("-2", format.format(-2.5));
|
||||||
|
assertEquals("-4", format.format(-3.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void bigRoundingWorks() {
|
||||||
|
DecimalFormat format = createFormat("0");
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.UP);
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-2.3")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-2.7")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.DOWN);
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.3")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.7")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.FLOOR);
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-2.3")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-2.7")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.CEILING);
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.3")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.7")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_DOWN);
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.5")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("3.5")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.5")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-3.5")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_UP);
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.5")));
|
||||||
|
assertEquals("4", format.format(new BigDecimal("3.5")));
|
||||||
|
assertEquals("-3", format.format(new BigDecimal("-2.5")));
|
||||||
|
assertEquals("-4", format.format(new BigDecimal("-3.5")));
|
||||||
|
|
||||||
|
format.setRoundingMode(RoundingMode.HALF_EVEN);
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("3", format.format(new BigDecimal("2.7")));
|
||||||
|
assertEquals("2", format.format(new BigDecimal("2.5")));
|
||||||
|
assertEquals("4", format.format(new BigDecimal("3.5")));
|
||||||
|
assertEquals("-2", format.format(new BigDecimal("-2.5")));
|
||||||
|
assertEquals("-4", format.format(new BigDecimal("-3.5")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsWithGroups() {
|
||||||
|
DecimalFormat format = createFormat("#,###.0");
|
||||||
|
assertEquals("23.0", format.format(23));
|
||||||
|
assertEquals("2,300.0", format.format(2300));
|
||||||
|
assertEquals("2,300,000,000,000,000,000,000.0", format.format(23E20));
|
||||||
|
assertEquals("23,000,000,000,000,000,000,000,000.0", format.format(23E24));
|
||||||
|
|
||||||
|
format = createFormat("000,000,000,000,000,000,000");
|
||||||
|
assertEquals("000,000,000,000,000,000,023", format.format(23));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsBigWithGroups() {
|
||||||
|
DecimalFormat format = createFormat("#,###.0");
|
||||||
|
assertEquals("23.0", format.format(BigInteger.valueOf(23)));
|
||||||
|
assertEquals("2,300.0", format.format(BigInteger.valueOf(2300)));
|
||||||
|
assertEquals("2,300,000,000,000,000,000,000.0", format.format(new BigInteger("2300000000000000000000")));
|
||||||
|
assertEquals("23,000,000,000,000,000,000,000,000.0", format.format(
|
||||||
|
new BigInteger("23000000000000000000000000")));
|
||||||
|
|
||||||
|
format = createFormat("000,000,000,000,000,000,000");
|
||||||
|
assertEquals("000,000,000,000,000,000,023", format.format(BigInteger.valueOf(23)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsLargeValues() {
|
||||||
|
DecimalFormat format = createFormat("0");
|
||||||
|
assertEquals("9223372036854775807", format.format(9223372036854775807L));
|
||||||
|
assertEquals("-9223372036854775808", format.format(-9223372036854775808L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsExponent() {
|
||||||
|
DecimalFormat format = createFormat("000E0");
|
||||||
|
assertEquals("230E-1", format.format(23));
|
||||||
|
assertEquals("230E0", format.format(230));
|
||||||
|
assertEquals("230E1", format.format(2300));
|
||||||
|
assertEquals("123E1", format.format(1234));
|
||||||
|
assertEquals("-123E1", format.format(-1234));
|
||||||
|
|
||||||
|
format = createFormat("0.00E0");
|
||||||
|
assertEquals("2.00E1", format.format(20));
|
||||||
|
assertEquals("2.30E1", format.format(23));
|
||||||
|
assertEquals("2.30E2", format.format(230));
|
||||||
|
assertEquals("1.23E3", format.format(1234));
|
||||||
|
|
||||||
|
format = createFormat("000000000000000000000.00E0");
|
||||||
|
assertEquals("230000000000000000000.00E-19", format.format(23));
|
||||||
|
|
||||||
|
format = createFormat("0.0000000000000000000000E0");
|
||||||
|
assertEquals("2.3000000000000000000000E1", format.format(23));
|
||||||
|
|
||||||
|
format = createFormat("0.0##E0");
|
||||||
|
assertEquals("1.0E0", format.format(1));
|
||||||
|
assertEquals("1.2E1", format.format(12));
|
||||||
|
assertEquals("1.23E2", format.format(123));
|
||||||
|
assertEquals("1.234E3", format.format(1234));
|
||||||
|
assertEquals("1.234E4", format.format(12345));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsBigExponent() {
|
||||||
|
DecimalFormat format = createFormat("000E0");
|
||||||
|
assertEquals("230E-1", format.format(BigInteger.valueOf(23)));
|
||||||
|
assertEquals("230E0", format.format(BigInteger.valueOf(230)));
|
||||||
|
assertEquals("230E1", format.format(BigInteger.valueOf(2300)));
|
||||||
|
assertEquals("123E1", format.format(BigInteger.valueOf(1234)));
|
||||||
|
assertEquals("-123E1", format.format(BigInteger.valueOf(-1234)));
|
||||||
|
|
||||||
|
format = createFormat("0.00E0");
|
||||||
|
assertEquals("2.00E1", format.format(BigInteger.valueOf(20)));
|
||||||
|
assertEquals("2.30E1", format.format(BigInteger.valueOf(23)));
|
||||||
|
assertEquals("2.30E2", format.format(BigInteger.valueOf(230)));
|
||||||
|
assertEquals("1.23E3", format.format(BigInteger.valueOf(1234)));
|
||||||
|
|
||||||
|
format = createFormat("000000000000000000000.00E0");
|
||||||
|
assertEquals("230000000000000000000.00E-19", format.format(BigInteger.valueOf(23)));
|
||||||
|
|
||||||
|
format = createFormat("0.0000000000000000000000E0");
|
||||||
|
assertEquals("2.3000000000000000000000E1", format.format(BigInteger.valueOf(23)));
|
||||||
|
|
||||||
|
format = createFormat("0.0##E0");
|
||||||
|
assertEquals("1.0E0", format.format(BigInteger.valueOf(1)));
|
||||||
|
assertEquals("1.2E1", format.format(BigInteger.valueOf(12)));
|
||||||
|
assertEquals("1.23E2", format.format(BigInteger.valueOf(123)));
|
||||||
|
assertEquals("1.234E3", format.format(BigInteger.valueOf(1234)));
|
||||||
|
assertEquals("1.234E4", format.format(BigInteger.valueOf(12345)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsExponentWithMultiplier() {
|
||||||
|
DecimalFormat format = createFormat("##0.00E0");
|
||||||
|
assertEquals("2.30E0", format.format(2.3));
|
||||||
|
assertEquals("23.0E0", format.format(23));
|
||||||
|
assertEquals("230E0", format.format(230));
|
||||||
|
assertEquals("2.30E3", format.format(2300));
|
||||||
|
assertEquals("23.0E3", format.format(23000));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsBigExponentWithMultiplier() {
|
||||||
|
DecimalFormat format = createFormat("##0.00E0");
|
||||||
|
assertEquals("2.30E0", format.format(new BigDecimal("2.3")));
|
||||||
|
assertEquals("23.0E0", format.format(new BigDecimal("23")));
|
||||||
|
assertEquals("230E0", format.format(new BigDecimal("230")));
|
||||||
|
assertEquals("2.30E3", format.format(new BigDecimal("2300")));
|
||||||
|
assertEquals("23.0E3", format.format(new BigDecimal("23000")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsSpecialValues() {
|
||||||
|
DecimalFormat format = createFormat("0");
|
||||||
|
assertEquals("∞", format.format(Double.POSITIVE_INFINITY));
|
||||||
|
assertEquals("-∞", format.format(Double.NEGATIVE_INFINITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsWithMultiplier() {
|
||||||
|
DecimalFormat format = createFormat("0");
|
||||||
|
format.setMultiplier(2);
|
||||||
|
assertEquals("18446744073709551614", format.format(9223372036854775807L));
|
||||||
|
assertEquals("46", format.format(BigInteger.valueOf(23)));
|
||||||
|
|
||||||
|
format.setMultiplier(100);
|
||||||
|
assertEquals("2300", format.format(23));
|
||||||
|
assertEquals("2300", format.format(BigInteger.valueOf(23)));
|
||||||
|
|
||||||
|
format = createFormat("00E0");
|
||||||
|
format.setMultiplier(2);
|
||||||
|
assertEquals("18E18", format.format(9223372036854775807L));
|
||||||
|
assertEquals("46E0", format.format(BigInteger.valueOf(23)));
|
||||||
|
|
||||||
|
format.setMultiplier(100);
|
||||||
|
assertEquals("23E2", format.format(23));
|
||||||
|
assertEquals("23E2", format.format(BigInteger.valueOf(23)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void formatsSpecial() {
|
||||||
|
DecimalFormat format = createFormat("0%");
|
||||||
|
assertEquals("23%", format.format(0.23));
|
||||||
|
|
||||||
|
format = createFormat("0‰");
|
||||||
|
assertEquals("230‰", format.format(0.23));
|
||||||
|
|
||||||
|
format = createFormat("0.00 ¤");
|
||||||
|
format.setCurrency(Currency.getInstance("RUB"));
|
||||||
|
assertEquals("23.00 RUB", format.format(23));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DecimalFormat createFormat(String format) {
|
||||||
|
return new DecimalFormat(format, symbols);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user