mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -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");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -15,62 +15,59 @@
|
|||
*/
|
||||
package org.teavm.classlib.impl.unicode;
|
||||
|
||||
import org.teavm.platform.metadata.Resource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface CLDRDecimalData extends Resource {
|
||||
int getMaximumFractionDigits();
|
||||
public class CLDRDecimalData {
|
||||
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();
|
||||
|
||||
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);
|
||||
public String getExponentSeparator() {
|
||||
return exponentSeparator;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,14 +200,15 @@ public class CLDRHelper {
|
|||
return res.getValue();
|
||||
}
|
||||
|
||||
public static CLDRDecimalData resolveDecimalData(String language, String country) {
|
||||
ResourceMap<CLDRDecimalData> map = getDecimalDataMap();
|
||||
public static DecimalData resolveDecimalData(String language, String country) {
|
||||
ResourceMap<DecimalData> map = getDecimalDataMap();
|
||||
String localeCode = getCode(language, country);
|
||||
return map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) :
|
||||
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) {
|
||||
String localeCode = getCode(language, country);
|
||||
|
|
|
@ -38,6 +38,7 @@ public class CLDRLocale {
|
|||
CLDRDateFormats timeFormats;
|
||||
CLDRDateFormats dateTimeFormats;
|
||||
CLDRTimeZone[] timeZones;
|
||||
CLDRDecimalData decimalData = new CLDRDecimalData();
|
||||
|
||||
public Map<String, String> getLanguages() {
|
||||
return Collections.unmodifiableMap(languages);
|
||||
|
@ -90,4 +91,8 @@ public class CLDRLocale {
|
|||
public CLDRTimeZone[] getTimeZones() {
|
||||
return timeZones.clone();
|
||||
}
|
||||
|
||||
public CLDRDecimalData getDecimalData() {
|
||||
return decimalData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,9 +127,12 @@ public class CLDRReader {
|
|||
readDateTimeFormats(localeName, localeInfo, root);
|
||||
break;
|
||||
}
|
||||
case "currencies.json": {
|
||||
case "currencies.json":
|
||||
readCurrencies(localeName, localeInfo, input);
|
||||
}
|
||||
break;
|
||||
case "numbers.json":
|
||||
readNumbers(localeName, localeInfo, input);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} 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) {
|
||||
JsonObject erasJson = root.get("main").getAsJsonObject().get(localeCode).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);
|
||||
}
|
||||
|
||||
private static double decimalExponent(int n) {
|
||||
public static double decimalExponent(int n) {
|
||||
double d;
|
||||
if (n < 0) {
|
||||
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;
|
||||
|
||||
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.java.util.TLocale;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import org.teavm.classlib.java.util.TLocale;
|
|||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TDecimalFormatSymbols {
|
||||
public class TDecimalFormatSymbols implements Cloneable {
|
||||
private TLocale locale;
|
||||
private char zeroDigit;
|
||||
private char groupingSeparator;
|
||||
|
@ -48,18 +48,18 @@ public class TDecimalFormatSymbols {
|
|||
}
|
||||
|
||||
private void initData() {
|
||||
CLDRDecimalData data = CLDRHelper.resolveDecimalData(locale.getLanguage(), locale.getCountry());
|
||||
DecimalData data = CLDRHelper.resolveDecimalData(locale.getLanguage(), locale.getCountry());
|
||||
zeroDigit = '0';
|
||||
groupingSeparator = (char)data.getGroupingSeparator();
|
||||
decimalSeparator = (char)data.getDecimalSeparator();
|
||||
perMill = (char)data.getPerMill();
|
||||
perMill = (char)data.getPerMille();
|
||||
percent = (char)data.getPercent();
|
||||
digit = '#';
|
||||
patternSeparator = ';';
|
||||
NaN = data.getNaN();
|
||||
infinity = data.getInfinity();
|
||||
minusSign = (char)data.getMinusSign();
|
||||
monetaryDecimalSeparator = (char)data.getMonetaryDecimalSeparator();
|
||||
monetaryDecimalSeparator = (char)data.getDecimalSeparator();
|
||||
exponentSeparator = data.getExponentSeparator();
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,10 @@
|
|||
*/
|
||||
package org.teavm.classlib.java.text;
|
||||
|
||||
import java.util.Objects;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -25,9 +28,11 @@ import org.teavm.classlib.java.util.TLocale;
|
|||
public abstract class TNumberFormat extends TFormat {
|
||||
public static final int INTEGER_FIELD = 0;
|
||||
public static final int FRACTION_FIELD = 1;
|
||||
private boolean groupingUsed = true, parseIntegerOnly = false;
|
||||
private boolean groupingUsed = true, parseIntegerOnly;
|
||||
private int maximumIntegerDigits = 40, minimumIntegerDigits = 1,
|
||||
maximumFractionDigits = 3, minimumFractionDigits = 0;
|
||||
private TRoundingMode roundingMode = TRoundingMode.HALF_EVEN;
|
||||
TCurrency currency = TCurrency.getInstance(TLocale.getDefault());
|
||||
|
||||
public TNumberFormat() {
|
||||
}
|
||||
|
@ -37,6 +42,14 @@ public abstract class TNumberFormat extends TFormat {
|
|||
return super.clone();
|
||||
}
|
||||
|
||||
public TCurrency getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public void setCurrency(TCurrency currency) {
|
||||
this.currency = currency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == this) {
|
||||
|
@ -51,7 +64,9 @@ public abstract class TNumberFormat extends TFormat {
|
|||
&& maximumFractionDigits == obj.maximumFractionDigits
|
||||
&& maximumIntegerDigits == obj.maximumIntegerDigits
|
||||
&& minimumFractionDigits == obj.minimumFractionDigits
|
||||
&& minimumIntegerDigits == obj.minimumIntegerDigits;
|
||||
&& minimumIntegerDigits == obj.minimumIntegerDigits
|
||||
&& roundingMode == obj.roundingMode
|
||||
&& currency == obj.currency;
|
||||
}
|
||||
|
||||
public final String format(double value) {
|
||||
|
@ -140,7 +155,8 @@ public abstract class TNumberFormat extends TFormat {
|
|||
public int hashCode() {
|
||||
return (groupingUsed ? 1231 : 1237) + (parseIntegerOnly ? 1231 : 1237)
|
||||
+ maximumFractionDigits + maximumIntegerDigits
|
||||
+ minimumFractionDigits + minimumIntegerDigits;
|
||||
+ minimumFractionDigits + minimumIntegerDigits +
|
||||
roundingMode.hashCode() + Objects.hashCode(currency);
|
||||
}
|
||||
|
||||
public boolean isGroupingUsed() {
|
||||
|
@ -211,6 +227,14 @@ public abstract class TNumberFormat extends TFormat {
|
|||
parseIntegerOnly = value;
|
||||
}
|
||||
|
||||
public TRoundingMode getRoundingMode() {
|
||||
return roundingMode;
|
||||
}
|
||||
|
||||
public void setRoundingMode(TRoundingMode roundingMode) {
|
||||
this.roundingMode = roundingMode;
|
||||
}
|
||||
|
||||
public static class Field extends TFormat.Field {
|
||||
public static final Field SIGN = new Field("sign");
|
||||
public static final Field INTEGER = new Field("integer");
|
||||
|
|
|
@ -20,7 +20,7 @@ package org.teavm.classlib.java.util;
|
|||
* @author shannah
|
||||
*/
|
||||
public class TObservable {
|
||||
TList<TObserver> observers = new TArrayList<TObserver>();
|
||||
TList<TObserver> observers = new TArrayList<>();
|
||||
|
||||
boolean changed = false;
|
||||
|
||||
|
@ -34,7 +34,7 @@ public class TObservable {
|
|||
/**
|
||||
* Adds the specified observer to the list of observers. If it is already
|
||||
* registered, it is not added a second time.
|
||||
*
|
||||
*
|
||||
* @param observer
|
||||
* the Observer to add.
|
||||
*/
|
||||
|
@ -58,7 +58,7 @@ public class TObservable {
|
|||
|
||||
/**
|
||||
* Returns the number of observers registered to this {@code Observable}.
|
||||
*
|
||||
*
|
||||
* @return the number of observers.
|
||||
*/
|
||||
public int countObservers() {
|
||||
|
@ -68,7 +68,7 @@ public class TObservable {
|
|||
/**
|
||||
* Removes the specified observer from the list of observers. Passing null
|
||||
* won't do anything.
|
||||
*
|
||||
*
|
||||
* @param observer
|
||||
* the observer to remove.
|
||||
*/
|
||||
|
@ -85,7 +85,7 @@ public class TObservable {
|
|||
|
||||
/**
|
||||
* Returns the changed flag for this {@code Observable}.
|
||||
*
|
||||
*
|
||||
* @return {@code true} when the changed flag for this {@code Observable} is
|
||||
* set, {@code false} otherwise.
|
||||
*/
|
||||
|
@ -108,11 +108,10 @@ public class TObservable {
|
|||
* If {@code hasChanged()} returns {@code true}, calls the {@code update()}
|
||||
* method for every Observer in the list of observers using the specified
|
||||
* argument. Afterwards calls {@code clearChanged()}.
|
||||
*
|
||||
*
|
||||
* @param data
|
||||
* the argument passed to {@code update()}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void notifyObservers(Object data) {
|
||||
int size = 0;
|
||||
TObserver[] arrays = null;
|
||||
|
|
|
@ -65,6 +65,10 @@ public final class TeaVMTestRunner {
|
|||
.withDescription("qualified class names of transformers")
|
||||
.withLongOpt("transformers")
|
||||
.create("T"));
|
||||
options.addOption(OptionBuilder
|
||||
.withDescription("Incremental build")
|
||||
.withLongOpt("incremental")
|
||||
.create('i'));
|
||||
|
||||
if (args.length == 0) {
|
||||
printUsage(options);
|
||||
|
@ -97,6 +101,10 @@ public final class TeaVMTestRunner {
|
|||
tool.getTransformers().add(instantiateTransformer(transformerType));
|
||||
}
|
||||
}
|
||||
if (commandLine.hasOption('i')) {
|
||||
tool.setIncremental(true);
|
||||
}
|
||||
|
||||
args = commandLine.getArgs();
|
||||
if (args.length == 0) {
|
||||
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.Objects;
|
||||
import java.util.Set;
|
||||
import org.teavm.cache.NoCache;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.common.GraphIndexer;
|
||||
import org.teavm.common.Loop;
|
||||
|
@ -245,7 +246,7 @@ public class Decompiler {
|
|||
}
|
||||
|
||||
public RegularMethodNode decompileRegular(MethodHolder method) {
|
||||
if (regularMethodCache == null) {
|
||||
if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) {
|
||||
return decompileRegularCacheMiss(method);
|
||||
}
|
||||
RegularMethodNode node = regularMethodCache.get(method.getReference());
|
||||
|
@ -283,7 +284,7 @@ public class Decompiler {
|
|||
}
|
||||
|
||||
public AsyncMethodNode decompileAsync(MethodHolder method) {
|
||||
if (regularMethodCache == null) {
|
||||
if (regularMethodCache == null || method.getAnnotations().get(NoCache.class.getName()) != null) {
|
||||
return decompileAsyncCacheMiss(method);
|
||||
}
|
||||
AsyncMethodNode node = regularMethodCache.getAsync(method.getReference());
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.model;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -27,11 +28,12 @@ public class InMemoryProgramCache implements ProgramCache {
|
|||
|
||||
@Override
|
||||
public Program get(MethodReference method) {
|
||||
return cache.get(method);
|
||||
Program program = cache.get(method);
|
||||
return program != null ? ProgramUtils.copy(program) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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();
|
||||
fileTable.update();
|
||||
} catch (IOException e) {
|
||||
log.info("Cache was not read");
|
||||
log.info("Cache is missing");
|
||||
}
|
||||
vmBuilder.setClassLoader(classLoader).setClassSource(cachedClassSource);
|
||||
} else {
|
||||
|
|
|
@ -17,6 +17,7 @@ package org.teavm.vm;
|
|||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import org.teavm.cache.NoCache;
|
||||
import org.teavm.codegen.*;
|
||||
import org.teavm.common.ServiceRepository;
|
||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||
|
@ -616,7 +617,9 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
|
|||
if (method.getProgram() == null) {
|
||||
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;
|
||||
if (optimizedProgram == null) {
|
||||
optimizedProgram = ProgramUtils.copy(method.getProgram());
|
||||
|
|
|
@ -744,6 +744,9 @@ function Long_rem(a, b) {
|
|||
return Long_divRem(a, b)[1];
|
||||
}
|
||||
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);
|
||||
if (Long_isNegative(a)) {
|
||||
a = Long_neg(a);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.platform.plugin;
|
||||
|
||||
import org.teavm.cache.NoCache;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.javascript.spi.GeneratedBy;
|
||||
import org.teavm.model.*;
|
||||
|
@ -49,10 +50,14 @@ class MetadataProviderTransformer implements ClassHolderTransformer {
|
|||
method.getReference(), ClassScopedMetadataProvider.class.getName(),
|
||||
PlatformClass.class.getName());
|
||||
}
|
||||
|
||||
AnnotationHolder genAnnot = new AnnotationHolder(GeneratedBy.class.getName());
|
||||
genAnnot.getValues().put("value", new AnnotationValue(ValueType.object(
|
||||
ClassScopedMetadataProviderNativeGenerator.class.getName())));
|
||||
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());
|
||||
pe.setField(field.getReference(), field.getType(), pe.invoke(createMethod.getReference()));
|
||||
pe.jump(resourceFound);
|
||||
|
||||
AnnotationHolder noCacheAnnot = new AnnotationHolder(NoCache.class.getName());
|
||||
method.getAnnotations().add(noCacheAnnot);
|
||||
}
|
||||
|
||||
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