package org.basex.query.item;
import static org.basex.query.util.Err.*;
import org.basex.query.QueryException;
import org.basex.util.InputInfo;
import org.basex.util.Token;
import org.basex.util.TokenBuilder;
/**
* HexBinary item.
*
* @author BaseX Team 2005-12, BSD License
* @author Christian Gruen
*/
public final class Hex extends Bin {
/**
* Constructor.
* @param b bytes
*/
public Hex(final byte[] b) {
super(b, AtomType.HEX);
}
/**
* Constructor.
* @param v textual representation
* @param ii input info
* @throws QueryException query exception
*/
public Hex(final byte[] v, final InputInfo ii) throws QueryException {
super(decode(Token.trim(v), ii), AtomType.HEX);
}
/**
* Constructor.
* @param b binary data
* @param ii input info
* @throws QueryException query exception
*/
Hex(final Bin b, final InputInfo ii) throws QueryException {
this(b.val(ii));
}
@Override
public byte[] string(final InputInfo ii) throws QueryException {
return Token.hex(val(ii), true);
}
@Override
public boolean eq(final InputInfo ii, final Item it)
throws QueryException {
return Token.eq(val(ii), it instanceof Bin ? ((Bin) it).val(ii) :
decode(it.string(ii), ii));
}
/**
* Converts the input into a byte array.
* @param d textual data
* @param ii input info
* @return decoded string
* @throws QueryException query exception
*/
private static byte[] decode(final byte[] d, final InputInfo ii)
throws QueryException {
if((d.length & 1) != 0) throw FUNCAST.thrw(ii, AtomType.HEX, (char) d[0]);
final int l = d.length >>> 1;
final byte[] v = new byte[l];
for(int i = 0; i < l; ++i) {
v[i] = (byte) ((dec(d[i << 1], ii) << 4) + dec(d[(i << 1) + 1], ii));
}
return v;
}
/**
* Converts a single character into a byte value.
* @param b character
* @param ii input info
* @return byte value
* @throws QueryException query exception
*/
private static int dec(final byte b, final InputInfo ii)
throws QueryException {
if(b >= '0' && b <= '9') return b - '0';
if(b >= 'a' && b <= 'f' || b >= 'A' && b <= 'F') return (b & 0x0F) + 9;
throw FUNCAST.thrw(ii, AtomType.HEX, (char) b);
}
@Override
public String toString() {
return new TokenBuilder().add('"').add(Token.hex(data, true)).
add('"').toString();
}
}