package org.basex.query.item;
import static org.basex.query.util.Err.*;
import static org.basex.util.Token.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import org.basex.query.QueryException;
import org.basex.query.util.Err;
import org.basex.util.InputInfo;
import org.basex.util.Token;
/**
* Decimal item.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class Dec extends Num {
/** Zero value. */
private static final Dec ZERO = new Dec(BigDecimal.ZERO);
/** Decimal value. */
private final BigDecimal val;
/**
* Constructor.
* @param t string representation
*/
public Dec(final byte[] t) {
super(AtomType.DEC);
val = new BigDecimal(Token.string(trim(t)));
}
/**
* Constructor.
* @param d decimal value
* @param t string representation
*/
public Dec(final BigDecimal d, final Type t) {
super(t);
val = d;
}
/**
* Constructor.
* @param d decimal value
*/
private Dec(final BigDecimal d) {
super(AtomType.DEC);
val = d;
}
/**
* Constructor.
* @param d big decimal value
* @return value
*/
public static Dec get(final BigDecimal d) {
return d.signum() == 0 ? ZERO : new Dec(d);
}
/**
* Constructor.
* @param d big decimal value
* @return value
*/
public static Dec get(final double d) {
return get(BigDecimal.valueOf(d));
}
@Override
public byte[] string(final InputInfo ii) {
return chopNumber(token(val.toPlainString()));
}
@Override
public boolean bool(final InputInfo ii) {
return val.signum() != 0;
}
@Override
public long itr(final InputInfo ii) {
return val.longValue();
}
@Override
public float flt(final InputInfo ii) {
return val.floatValue();
}
@Override
public double dbl(final InputInfo ii) {
return val.doubleValue();
}
@Override
public BigDecimal dec(final InputInfo ii) {
return val;
}
@Override
public boolean eq(final InputInfo ii, final Item it) throws QueryException {
return it.type == AtomType.DBL || it.type == AtomType.FLT ?
it.eq(ii, this) : val.compareTo(it.dec(ii)) == 0;
}
@Override
public int diff(final InputInfo ii, final Item it) throws QueryException {
final double d = it.dbl(ii);
return d == 1 / 0.0 ? -1 : d == -1 / 0.0 ? 1 :
Double.isNaN(d) ? UNDEF : val.compareTo(it.dec(ii));
}
@Override
public Object toJava() {
return type == AtomType.ULN ? new BigInteger(val.toString()) : val;
}
/**
* Converts the given double into a decimal value.
* @param val value to be converted
* @param ii input info
* @return double value
* @throws QueryException query exception
*/
static BigDecimal parse(final double val, final InputInfo ii)
throws QueryException {
if(Double.isNaN(val) || val == 1 / 0d || val == -1 / 0d)
Err.value(ii, AtomType.DEC, val);
return BigDecimal.valueOf(val);
}
/**
* Converts the given token into a decimal value.
* @param val value to be converted
* @param ii input info
* @return double value
* @throws QueryException query exception
*/
static BigDecimal parse(final byte[] val, final InputInfo ii)
throws QueryException {
if(contains(val, 'e') || contains(val, 'E'))
FUNCAST.thrw(ii, AtomType.DEC, val);
try {
return new BigDecimal(Token.string(val).trim());
} catch(final NumberFormatException ex) {
throw ZERO.castErr(val, ii);
}
}
}