package php.runtime.memory;
import php.runtime.Memory;
import php.runtime.memory.support.MemoryStringUtils;
import java.nio.charset.Charset;
public class LongMemory extends Memory {
protected final static int MAX_CACHE_STRING = 10000;
protected final static int MAX_NEG_CACHE = Short.MAX_VALUE / 7;
protected final static int MAX_POS_CACHE = Short.MAX_VALUE - MAX_NEG_CACHE;
protected final static String[] STRING_VALUES;
protected final static LongMemory[] CACHE;
static {
STRING_VALUES = new String[MAX_CACHE_STRING];
for(int i = 0; i < MAX_CACHE_STRING; i++){
STRING_VALUES[i] = String.valueOf(i);
}
CACHE = new LongMemory[MAX_POS_CACHE + MAX_NEG_CACHE];
for(int i = -MAX_NEG_CACHE; i < MAX_POS_CACHE; i++){
CACHE[i + MAX_NEG_CACHE] = new LongMemory(i);
}
}
public long value;
public LongMemory(long value) {
super(Type.INT);
this.value = value;
}
public static Memory valueOf(long value){
if (value >= -MAX_NEG_CACHE && value < MAX_POS_CACHE)
return CACHE[(int)value + MAX_NEG_CACHE];
else
return new LongMemory(value);
}
public static Memory valueOf(int value){
if (value >= -MAX_NEG_CACHE && value <= MAX_NEG_CACHE)
return CACHE[value + MAX_NEG_CACHE];
else
return new LongMemory(value);
}
public static Memory valueOf(byte value){
return valueOf((int)value);
}
public static Memory valueOf(short value){
return valueOf((int)value);
}
public static Memory valueOf(boolean value){
return value ? TRUE : FALSE;
}
@Override
public long toLong() {
return value;
}
@Override
public double toDouble() {
return value;
}
@Override
public boolean toBoolean() {
return value != 0;
}
@Override
public Memory toNumeric() {
return this;
}
@Override
public String toString() {
if (value >= 0 && value < MAX_CACHE_STRING)
return STRING_VALUES[(int)value];
return String.valueOf(value);
}
@Override
public Memory inc() {
return new LongMemory(value + 1);
}
@Override
public Memory dec() {
return new LongMemory(value - 1);
}
@Override
public Memory negative() {
return new LongMemory(- value);
}
@Override
public Memory plus(Memory memory) {
switch (memory.type){
case INT: return LongMemory.valueOf(value + ((LongMemory) memory).value);
case DOUBLE: return new DoubleMemory(value + ((DoubleMemory)memory).value);
case REFERENCE: return plus(memory.toValue());
default: return plus(memory.toNumeric());
}
}
@Override
public Memory minus(Memory memory) {
switch (memory.type){
case INT: return LongMemory.valueOf(value - ((LongMemory) memory).value);
case DOUBLE: return new DoubleMemory(value - ((DoubleMemory)memory).value);
case REFERENCE: return minus(memory.toValue());
default: return minus(memory.toNumeric());
}
}
@Override
public Memory mul(Memory memory) {
switch (memory.type){
case INT: return LongMemory.valueOf(value * ((LongMemory) memory).value);
case DOUBLE: return new DoubleMemory(value * ((DoubleMemory)memory).value);
case REFERENCE: return mul(memory.toValue());
default: return mul(memory.toNumeric());
}
}
@Override
public Memory pow(Memory memory) {
switch (memory.type){
case INT: return pow(((LongMemory) memory).value);
case DOUBLE: return pow(((DoubleMemory) memory).value);
case REFERENCE: return pow(memory.toImmutable());
default: return pow(memory.toNumeric());
}
}
@Override
public Memory div(Memory memory) {
switch (memory.type){
case INT: {
long tmp = ((LongMemory)memory).value;
if (tmp == 0) return FALSE;
if (value % tmp == 0)
return LongMemory.valueOf(value / tmp);
else
return new DoubleMemory(value / (double)tmp);
}
case DOUBLE:
if (((DoubleMemory)memory).value == 0) return FALSE;
return new DoubleMemory(value / ((DoubleMemory)memory).value);
case REFERENCE: return div(memory.toValue());
default: return div(memory.toNumeric());
}
}
@Override
public Memory div(long value) {
if (value == 0)
return FALSE;
if (this.value % value == 0)
return LongMemory.valueOf(this.value / value);
else
return new DoubleMemory(this.value / (double)value);
}
@Override
public boolean identical(Memory memory) {
return memory.getRealType() == Type.INT && ((LongMemory)memory).value == value;
}
@Override
public boolean equal(Memory memory) {
switch (memory.type){
case INT: return ((LongMemory)memory).value == value;
case DOUBLE: return ((DoubleMemory)memory).value == value;
case STRING: return equal(memory.toNumeric());
case REFERENCE: return equal(memory.toValue());
default:
return value == toLong();
}
}
@Override
public boolean equal(long value) {
return this.value == value;
}
@Override
public boolean equal(double value) {
return this.value == value;
}
@Override
public boolean notEqual(Memory memory) {
switch (memory.type){
case INT: return ((LongMemory)memory).value != value;
case DOUBLE: return ((DoubleMemory)memory).value != value;
case STRING: return notEqual(memory.toNumeric());
case REFERENCE: return smaller(memory.toValue());
default:
return value != toLong();
}
}
@Override
public String concat(Memory memory) {
return toString().concat(memory.toString());
}
@Override
public boolean smaller(Memory memory) {
switch (memory.type){
case DOUBLE: return value < ((DoubleMemory)memory).value;
case INT: return value < ((LongMemory)memory).value;
case STRING: return smaller(memory.toNumeric());
case REFERENCE: return smaller(memory.toValue());
default:
return value < toLong();
}
}
@Override
public boolean smallerEq(Memory memory) {
switch (memory.type){
case DOUBLE: return value <= ((DoubleMemory)memory).value;
case INT: return value <= ((LongMemory)memory).value;
case STRING: return smallerEq(memory.toNumeric());
case REFERENCE: return smallerEq(memory.toValue());
default:
return value <= toLong();
}
}
@Override
public boolean greater(Memory memory) {
return memory.smaller(this);
}
@Override
public boolean greaterEq(Memory memory) {
return memory.smallerEq(this);
}
@Override
public Memory minus(long value) {
return LongMemory.valueOf(this.value - value);
}
@Override
public Memory plus(long value) {
return LongMemory.valueOf(this.value + value);
}
@Override
public Memory div(boolean value) {
if (!value)
return FALSE;
return this;
}
@Override
public int hashCode() {
return (int) (value ^ (value >>> 32));
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof LongMemory)) return false;
LongMemory that = (LongMemory) o;
return value == that.value;
}
@Override
public byte[] getBinaryBytes(Charset charset) {
return MemoryStringUtils.getBinaryBytes(this);
}
}