package org.h2.value;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.UUID;
import org.h2.api.ErrorCode;
import org.h2.message.DbException;
import org.h2.util.Bits;
import org.h2.util.MathUtils;
import org.h2.util.StringUtils;
public class ValueUuid extends Value {
static final int PRECISION = 16;
static final int DISPLAY_SIZE = 36;
private final long high, low;
private ValueUuid(long high, long low) {
this.high = high;
this.low = low;
}
@Override
public int hashCode() {
return (int) ((high >>> 32) ^ high ^ (low >>> 32) ^ low);
}
public static ValueUuid getNewRandom() {
long high = MathUtils.secureRandomLong();
long low = MathUtils.secureRandomLong();
high = (high & (~0xf000L)) | 0x4000L;
low = (low & 0x3fff_ffff_ffff_ffffL) | 0x8000_0000_0000_0000L;
return new ValueUuid(high, low);
}
public static ValueUuid get(byte[] binary) {
if (binary.length < 16) {
return get(StringUtils.convertBytesToHex(binary));
}
long high = Bits.readLong(binary, 0);
long low = Bits.readLong(binary, 8);
return (ValueUuid) Value.cache(new ValueUuid(high, low));
}
public static ValueUuid get(long high, long low) {
return (ValueUuid) Value.cache(new ValueUuid(high, low));
}
public static ValueUuid get(UUID uuid) {
return get(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
}
public static ValueUuid get(String s) {
long low = 0, high = 0;
for (int i = 0, j = 0, length = s.length(); i < length; i++) {
char c = s.charAt(i);
if (c >= '0' && c <= '9') {
low = (low << 4) | (c - '0');
} else if (c >= 'a' && c <= 'f') {
low = (low << 4) | (c - 'a' + 0xa);
} else if (c == '-') {
continue;
} else if (c >= 'A' && c <= 'F') {
low = (low << 4) | (c - 'A' + 0xa);
} else if (c <= ' ') {
continue;
} else {
throw DbException.get(ErrorCode.DATA_CONVERSION_ERROR_1, s);
}
if (j++ == 15) {
high = low;
low = 0;
}
}
return (ValueUuid) Value.cache(new ValueUuid(high, low));
}
@Override
public StringBuilder getSQL(StringBuilder builder) {
builder.append('\'');
return addString(builder).append('\'');
}
@Override
public TypeInfo getType() {
return TypeInfo.TYPE_UUID;
}
@Override
public int getMemory() {
return 32;
}
@Override
public int getValueType() {
return UUID;
}
@Override
public String getString() {
return addString(new StringBuilder(36)).toString();
}
private StringBuilder addString(StringBuilder builder) {
StringUtils.appendHex(builder, high >> 32, 4).append('-');
StringUtils.appendHex(builder, high >> 16, 2).append('-');
StringUtils.appendHex(builder, high, 2).append('-');
StringUtils.appendHex(builder, low >> 48, 2).append('-');
return StringUtils.appendHex(builder, low, 6);
}
@Override
public int compareTypeSafe(Value o, CompareMode mode) {
if (o == this) {
return 0;
}
ValueUuid v = (ValueUuid) o;
long v1 = high, v2 = v.high;
if (v1 == v2) {
v1 = low;
v2 = v.low;
if (mode.isUuidUnsigned()) {
v1 += Long.MIN_VALUE;
v2 += Long.MIN_VALUE;
}
return Long.compare(v1, v2);
}
if (mode.isUuidUnsigned()) {
v1 += Long.MIN_VALUE;
v2 += Long.MIN_VALUE;
}
return v1 > v2 ? 1 : -1;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof ValueUuid)) {
return false;
}
ValueUuid v = (ValueUuid) other;
return high == v.high && low == v.low;
}
@Override
public Object getObject() {
return new UUID(high, low);
}
@Override
public byte[] getBytes() {
return Bits.uuidToBytes(high, low);
}
@Override
public void set(PreparedStatement prep, int parameterIndex)
throws SQLException {
prep.setBytes(parameterIndex, getBytes());
}
public long getHigh() {
return high;
}
public long getLow() {
return low;
}
}