public final class HexMath
{
private static final String NUMBERS = "0123456789abcdefABCDEF";
private static final int RADIX = 0x10; // Basis 16
public static class MD5String
extends HexString
{
private static final long serialVersionUID = 8423109029732380666L;
public MD5String(String value)
{
super((value != null && value.length() >= 32)? value.substring(value.length() - 32) : "");
}
}
public static class HexString
extends Number
implements Cloneable
{
private static final long serialVersionUID = 6216050881224903751L;
private final String value;
public HexString(long value)
{
this(Long.valueOf(value).toString());
}
public HexString(double value)
{
this(Double.doubleToLongBits(value));
}
public HexString(float value)
{
this(Float.floatToIntBits(value));
}
public HexString(String value)
{
if(!check(value)) throw new NumberFormatException("illegal value" + value);
this.value = value;
}
private boolean check(String value)
{
if(value == null || value.length() == 0) return false;
boolean rc = true;
for(int n = 0; n < value.length() && rc; n++) rc &= NUMBERS.contains(String.valueOf(value.charAt(n)));
return rc;
}
public HexString expand(int times)
{
return expand(times, true);
}
public HexString expand(int times, boolean ignorenflag)
{
if(times < 1) throw new IllegalArgumentException("parameter 'times' has to be larger than 0");
StringBuffer tmp = new StringBuffer();
int flag = (!ignorenflag)? Integer.parseInt(String.valueOf(value.charAt(0)), RADIX) : 0;
tmp.append(NUMBERS.charAt(((flag & RADIX) != 0)? 8 : 0));
times--;
for(; times > 0; times--) tmp.append(NUMBERS.charAt(0));
if(!ignorenflag) {
tmp.append(NUMBERS.charAt(flag | (RADIX - 1)));
flag = 1;
}
tmp.append(value.substring(flag));
return new HexString(tmp.toString());
}
public static HexString parseHex(String value)
{
return new HexString(value);
}
public static HexString parseHex(double value)
{
return new HexString(value);
}
public static HexString parseHex(float value)
{
return new HexString(value);
}
public static HexString parseHex(long value)
{
return new HexString(value);
}
public final double doubleValue()
{
return Double.longBitsToDouble(longValue());
}
public final float floatValue()
{
return Float.intBitsToFloat(intValue());
}
public final int intValue()
{
int start = (value.length() > 8)? value.length() - 8 : 0;
return Integer.parseInt(value.substring(start), 16);
}
public final long longValue()
{
int start = (value.length() > 16)? value.length() - 16 : 0;
return Long.parseLong(value.substring(start), 16);
}
public final String toString()
{
return value;
}
public final int length()
{
return value.length();
}
public final Object clone()
{
return new HexString(value);
}
public final boolean equals(Object obj)
{
if(this == obj) return true;
try {
HexString tmp = (HexString) obj;
return tmp.value.equalsIgnoreCase(value);
} catch(ClassCastException e) {
return false;
}
}
}
private HexMath()
{
}
public static HexString xor(HexString a, HexString b)
{
return eor(a, b);
}
public static HexString eor(HexString a, HexString b)
{
if(a == null || b == null) throw new NullPointerException();
int length = Math.max(a.length(), b.length());
if(a.length() < length) a = a.expand(length - a.length());
if(b.length() < length) b = b.expand(length - b.length());
StringBuffer rc = new StringBuffer();
int tmp;
for(int i = 0; i < a.length(); i++) {
tmp = Integer.parseInt(String.valueOf(a.value.charAt(i)), RADIX)
^ Integer.parseInt(String.valueOf(b.value.charAt(i)), RADIX);
rc.append(NUMBERS.charAt(tmp));
}
return new HexString(rc.toString());
}
public static HexString and(HexString a, HexString b)
{
if(a == null || b == null) throw new NullPointerException();
int length = Math.max(a.length(), b.length());
if(a.length() < length) a = a.expand(length - a.length());
if(b.length() < length) b = b.expand(length - b.length());
StringBuffer rc = new StringBuffer();
int tmp;
for(int i = 0; i < a.length(); i++) {
tmp = Integer.parseInt(String.valueOf(a.value.charAt(i)), RADIX)
& Integer.parseInt(String.valueOf(b.value.charAt(i)), RADIX);
rc.append(NUMBERS.charAt(tmp));
}
return new HexString(rc.toString());
}
public static HexString or(HexString a, HexString b)
{
if(a == null || b == null) throw new NullPointerException();
int length = Math.max(a.length(), b.length());
if(a.length() < length) a = a.expand(length - a.length());
if(b.length() < length) b = b.expand(length - b.length());
StringBuffer rc = new StringBuffer();
int tmp;
for(int i = 0; i < a.length(); i++) {
tmp = Integer.parseInt(String.valueOf(a.value.charAt(i)), RADIX)
| Integer.parseInt(String.valueOf(b.value.charAt(i)), RADIX);
rc.append(NUMBERS.charAt(tmp));
}
return new HexString(rc.toString());
}
public static HexString eand(HexString a, HexString b)
{
return xand(a, b);
}
public static HexString xand(HexString a, HexString b)
{
a = eor(a, b);
return not(a);
}
public static HexString nor(HexString a, HexString b)
{
a = or(a, b);
return not(a);
}
public static HexString nand(HexString a, HexString b)
{
a = and(a, b);
return not(a);
}
public static HexString not(HexString a)
{
if(a == null) throw new NullPointerException();
StringBuffer tmp = new StringBuffer();
int cnt = 0;
while(cnt++ < a.length()) tmp.append("f");
return eor(a, new HexString(tmp.toString()));
}
}