Completes java.lang.Long

This commit is contained in:
konsoletyper 2014-03-12 16:57:34 +04:00
parent 134196d401
commit ad1d231094
6 changed files with 305 additions and 33 deletions

View File

@ -92,6 +92,9 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
case "intClass":
context.getWriter().append("$rt_cls($rt_intcls())");
break;
case "longClass":
context.getWriter().append("$rt_cls($rt_longcls())");
break;
case "floatClass":
context.getWriter().append("$rt_cls($rt_floatcls())");
break;
@ -191,6 +194,7 @@ public class ClassNativeGenerator implements Generator, Injector, DependencyPlug
case "shortClass":
case "charClass":
case "intClass":
case "longClass":
case "floatClass":
case "doubleClass":
case "wrapClass":

View File

@ -33,6 +33,10 @@ public class LongNativeGenerator implements Generator {
writer.append("Long_compare(").append(context.getParameterName(1)).append(", ")
.append(context.getParameterName(2)).append(");").softNewLine();
break;
case "hashCode":
writer.append("return ").append(context.getParameterName(1)).append(".hi ^ ")
.append(context.getParameterName(1)).append(".lo;").softNewLine();
break;
}
}
}

View File

@ -152,43 +152,30 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
}
protected TAbstractStringBuilder insert(int target, long value) {
return insert(target, value, 10);
}
protected TAbstractStringBuilder insert(int target, long value, int radix) {
boolean positive = true;
if (value < 0) {
positive = false;
value = -value;
}
if (value < 10) {
if (value < radix) {
if (!positive) {
insertSpace(target, target + 2);
buffer[target++] = '-';
} else {
insertSpace(target, target + 1);
}
buffer[target++] = (char)('0' + value);
buffer[target++] = Character.forDigit((int)value, radix);
} else {
int sz = 0;
int sz = 1;
long pos = 1;
if (pos * 10000000000000000L <= value) {
pos *= 10000000000000000L;
sz |= 16;
while (pos * radix > pos && pos * radix <= value) {
pos *= radix;
++sz;
}
if ((sz | 8) <= 18 && pos * 100000000L <= value) {
pos *= 100000000L;
sz |= 8;
}
if ((sz | 4) <= 18 && pos * 10000L <= value) {
pos *= 10000L;
sz |= 4;
}
if ((sz | 2) <= 18 && pos * 100L <= value) {
pos *= 100L;
sz |= 2;
}
if ((sz | 1) <= 18 && pos * 10L <= value) {
pos *= 10L;
sz |= 1;
}
++sz;
if (!positive) {
++sz;
}
@ -197,9 +184,9 @@ class TAbstractStringBuilder extends TObject implements TSerializable, TCharSequ
buffer[target++] = '-';
}
while (pos > 0) {
buffer[target++] = (char)('0' + value / pos);
buffer[target++] = TCharacter.forDigit((int)(value / pos), radix);
value %= pos;
pos /= 10;
pos /= radix;
}
}
return this;

View File

@ -93,6 +93,10 @@ public class TClass<T> extends TObject {
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TInteger> intClass();
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TLong> longClass();
@InjectedBy(ClassNativeGenerator.class)
@PluggableDependency(ClassNativeGenerator.class)
static native TClass<TFloat> floatClass();

View File

@ -172,7 +172,7 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
}
public static TInteger getInteger(TString nm, int val) {
return getInteger(nm, val);
return getInteger(nm, TInteger.valueOf(val));
}
public static TInteger getInteger(TString nm, TInteger val) {
@ -336,16 +336,16 @@ public class TInteger extends TNumber implements TComparable<TInteger> {
}
public static int reverse(int i) {
i = (i & 0xAAAAAAAA) >> 1 + (i & 0x55555555) << 1;
i = (i & 0xCCCCCCCC) >> 2 + (i & 0x33333333) << 2;
i = (i & 0xF0F0F0F0) >> 4 + (i & 0x0F0F0F0F) << 4;
i = (i & 0xFF00FF00) >> 8 + (i & 0x00FF00FF) << 8;
i = (i & 0xFFFF0000) >> 16 + (i & 0x0000FFFF) << 16;
i = (i & 0xAAAAAAAA) >> 1 | (i & 0x55555555) << 1;
i = (i & 0xCCCCCCCC) >> 2 | (i & 0x33333333) << 2;
i = (i & 0xF0F0F0F0) >> 4 | (i & 0x0F0F0F0F) << 4;
i = (i & 0xFF00FF00) >> 8 | (i & 0x00FF00FF) << 8;
i = (i & 0xFFFF0000) >> 16 | (i & 0x0000FFFF) << 16;
return i;
}
public static int reverseBytes(int i) {
i = (i & 0xFF00FF00) >> 8 + (i & 0x00FF00FF) << 8;
i = (i & 0xFF00FF00) >> 8 | (i & 0x00FF00FF) << 8;
i = i >> 16 + i << 16;
return i;
}

View File

@ -22,17 +22,138 @@ import org.teavm.javascript.ni.Rename;
*
* @author Alexey Andreev <konsoletyper@gmail.com>
*/
public class TLong extends TNumber {
public class TLong extends TNumber implements TComparable<TLong> {
public static final long MIN_VALUE = -0x8000000000000000L;
public static final long MAX_VALUE = 0x7FFFFFFFFFFFFFFFL;
public static final TClass<TLong> TYPE = TClass.longClass();
public static final int SIZE = 64;
private long value;
public TLong(long value) {
this.value = value;
}
public TLong(TString value) throws TNumberFormatException {
this(parseLong(value));
}
public static TLong valueOf(long value) {
return new TLong(value);
}
public static long parseLong(TString s, int radix) throws TNumberFormatException {
if (radix < TCharacter.MIN_RADIX || radix > TCharacter.MAX_RADIX) {
throw new TNumberFormatException(TString.wrap("Illegal radix: " + radix));
}
if (s == null || s.isEmpty()) {
throw new TNumberFormatException(TString.wrap("String is null or empty"));
}
boolean negative = false;
int index = 0;
switch (s.charAt(0)) {
case '-':
negative = true;
index = 1;
break;
case '+':
index = 1;
break;
}
long value = 0;
while (index < s.length()) {
int digit = TCharacter.getNumericValue(s.charAt(index++));
if (digit < 0) {
throw new TNumberFormatException(TString.wrap("String contains invalid digits: " + s));
}
if (digit >= radix) {
throw new TNumberFormatException(TString.wrap("String contains digits out of radix " + radix +
": " + s));
}
value = radix * value + digit;
if (value < 0) {
if (index == s.length() && value == MIN_VALUE && negative) {
return MIN_VALUE;
}
throw new TNumberFormatException(TString.wrap("The value is too big for int type: " + s));
}
}
return negative ? -value : value;
}
public static long parseLong(TString s) throws TNumberFormatException {
return parseLong(s, 10);
}
public static TLong valueOf(TString s, int radix) throws TNumberFormatException {
return valueOf(parseLong(s, radix));
}
public static TLong valueOf(TString s) throws TNumberFormatException {
return valueOf(parseLong(s));
}
public static TLong decode(TString nm) throws TNumberFormatException {
if (nm == null || nm.isEmpty()) {
throw new TNumberFormatException(TString.wrap("Can't parse empty or null string"));
}
int index = 0;
boolean negaive = false;
if (nm.charAt(index) == '+') {
++index;
} else if (nm.charAt(index) == '-') {
++index;
negaive = true;
}
if (index >= nm.length()) {
throw new TNumberFormatException(TString.wrap("The string does not represent a number"));
}
int radix = 10;
if (nm.charAt(index) == '#') {
radix = 16;
++index;
} else if (nm.charAt(index) == '0') {
++index;
if (index == nm.length()) {
return TLong.valueOf(0);
}
if (nm.charAt(index) == 'x' || nm.charAt(index) == 'X') {
radix = 16;
++index;
} else {
radix = 8;
}
}
if (index >= nm.length()) {
throw new TNumberFormatException(TString.wrap("The string does not represent a number"));
}
long value = 0;
while (index < nm.length()) {
int digit = decodeDigit(nm.charAt(index++));
if (digit >= radix) {
throw new TNumberFormatException(TString.wrap("The string does not represent a number"));
}
value = value * radix + digit;
if (value < 0) {
if (negaive && value == MIN_VALUE && index == nm.length()) {
return TLong.valueOf(MIN_VALUE);
}
throw new TNumberFormatException(TString.wrap("The string represents a too big number"));
}
}
return TLong.valueOf(negaive ? -value : value);
}
private static int decodeDigit(char c) {
if (c >= '0' && c <= '9') {
return c - '0';
} else if (c >= 'a' && c <= 'z') {
return c - 'a' + 10;
} else if (c >= 'A' && c <= 'Z') {
return c - 'A' + 10;
} else {
return 255;
}
}
@Override
public int intValue() {
return (int)value;
@ -53,6 +174,22 @@ public class TLong extends TNumber {
return value;
}
public static TString toString(long i, int radix) {
return TString.wrap(new TStringBuilder().insert(0, i, radix).toString());
}
public static TString toHexString(long i) {
return toString(i, 16);
}
public static TString toOctalString(long i) {
return toString(i, 8);
}
public static TString toBinaryString(long i) {
return toString(i, 2);
}
public TString toString(long value) {
return TString.wrap(new TStringBuilder().append(value).toString());
}
@ -63,6 +200,10 @@ public class TLong extends TNumber {
return toString(value);
}
@Override
@GeneratedBy(LongNativeGenerator.class)
public native int hashCode();
@Override
public boolean equals(TObject other) {
if (this == other) {
@ -73,4 +214,136 @@ public class TLong extends TNumber {
@GeneratedBy(LongNativeGenerator.class)
public static native int compare(long a, long b);
@Override
public int compareTo(TLong other) {
return compare(value, other.value);
}
public static TLong getLong(TString nm) {
return getLong(nm, null);
}
public static TLong getLong(TString nm, long val) {
return getLong(nm, TLong.valueOf(val));
}
public static TLong getLong(TString nm, TLong val) {
TString result = TSystem.getProperty(nm);
return result != null ? TLong.valueOf(result) : val;
}
public static long highestOneBit(long i) {
return 0x8000000000000000L >>> numberOfLeadingZeros(i);
}
public static int numberOfLeadingZeros(long i) {
if (i == 0) {
return SIZE;
}
int n = 0;
if (i >>> 32 != 0) {
i >>>= 32;
n |= 32;
}
if (i >>> 16 != 0) {
i >>>= 16;
n |= 16;
}
if (i >>> 8 != 0) {
i >>>= 8;
n |= 8;
}
if (i >>> 4 != 0) {
i >>>= 4;
n |= 4;
}
if (i >>> 2 != 0) {
i >>>= 2;
n |= 2;
}
if (i >>> 1 != 0) {
i >>>= 1;
n |= 1;
}
return SIZE - n - 1;
}
public static int numberOfTrailingZeros(long i) {
if (i == 0) {
return SIZE;
}
int n = 0;
if (i << 32 != 0) {
i <<= 32;
n |= 32;
}
if (i << 16 != 0) {
i <<= 16;
n |= 16;
}
if (i << 8 != 0) {
i <<= 8;
n |= 8;
}
if (i << 4 != 0) {
i <<= 4;
n |= 4;
}
if (i << 2 != 0) {
i <<= 2;
n |= 2;
}
if (i << 1 != 0) {
i <<= 1;
n |= 1;
}
return SIZE - n - 1;
}
public static long lowestOneBit(long i) {
return 1L << numberOfTrailingZeros(i);
}
public static int bitCount(long i) {
i = (i & 0xAAAAAAAAAAAAAAAAL) >> 1 + i & 0x5555555555555555L;
i = (i & 0xCCCCCCCCCCCCCCCCL) >> 2 + i & 0x3333333333333333L;
i = (i & 0x3030303030303030L) >> 4 + i & 0x0303030303030303L;
i = (i & 0x0700070007000700L) >> 8 + i & 0x0007000700070007L;
i = (i & 0x000F0000000F0000L) >> 16 + i & 0x0000000F0000000FL;
i = (i & 0x0000001F00000000L) >> 32 + i & 0x000000000000001FL;
return (int)i;
}
public static long rotateLeft(long i, int distance) {
distance &= 0x3F;
return (i << distance) | (i >>> (64 - distance));
}
public static long rotateRight(long i, int distance) {
distance &= 0x3F;
return (i >>> distance) | (i << (64 - distance));
}
public static long reverse(long i) {
i = (i & 0xAAAAAAAAAAAAAAAAL) >> 1 | (i & 0x5555555555555555L) << 1;
i = (i & 0xCCCCCCCCCCCCCCCCL) >> 2 | (i & 0x3333333333333333L) << 2;
i = (i & 0xF0F0F0F0F0F0F0F0L) >> 4 | (i & 0x0F0F0F0F0F0F0F0FL) << 4;
i = (i & 0xFF00FF00FF00FF00L) >> 8 | (i & 0x00FF00FF00FF00FFL) << 8;
i = (i & 0xFFFF0000FFFF0000L) >> 16 | (i & 0x0000FFFF0000FFFFL) << 16;
i = (i & 0xFFFF0000FFFF0000L) >> 32 | (i & 0x0000FFFF0000FFFFL) << 32;
return i;
}
public static long reverseBytes(long i) {
i = (i & 0xFF00FF00FF00FF00L) >> 8 | (i & 0x00FF00FF00FF00FFL) << 8;
i = (i & 0xFFFF0000FFFF0000L) >> 16 | (i & 0x0000FFFF0000FFFFL) << 16;
i = i >> 32 | i << 32;
return i;
}
public static int signum(long i) {
return (int)((i >> 63) | (-i >>> 63));
}
}