blob: 2d617da0afb55be5df1ce913557d9dfb51eb487e [file] [log] [blame]
package com.gemstone.gemfire.internal.redis;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import com.gemstone.gemfire.DataSerializable;
import com.gemstone.gemfire.DataSerializer;
/**
* This class is a wrapper for the any Regions that need to store a
* byte[]. The only data this an instance will store is a byte[]
* for the data but it is also serializable and comparable so it is able to be used
* in querying. The hash code and to string variant are created lazily
*
* @author Vitaliy Gavrilov
*
*/
public class ByteArrayWrapper implements DataSerializable, Comparable<ByteArrayWrapper> {
/**
* Generated serialVerionUID
*/
private static final long serialVersionUID = 9066391742266642992L;
/**
* The data portion of ValueWrapper
*/
private byte[] value;
/**
* Hash of {@link #value}, this value is cached for performance
*/
private transient int hashCode;
private transient String toString;
/**
* Empty constructor for serialization
*/
public ByteArrayWrapper() {
}
/**
* Default constructor constructs a ValueWrapper
* and initialize the {@link #value}
*
* @param value
*/
public ByteArrayWrapper(byte[] value) {
this.value = value;
this.hashCode = Arrays.hashCode(value);
}
@Override
public void toData(DataOutput out) throws IOException {
DataSerializer.writeByteArray(value, out);
}
@Override
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
this.value = DataSerializer.readByteArray(in);;
this.hashCode = Arrays.hashCode(this.value);
}
@Override
public String toString() {
if (toString == null)
toString = Coder.bytesToString(this.value);
return toString;
}
public byte[] toBytes() {
return this.value;
}
public void setBytes(byte[] bytes) {
this.value = bytes;
this.toString = null;
this.hashCode = Arrays.hashCode(bytes);
}
/**
* Getter for the length of the {@link #value} array
* @return The length of the value array
*/
public int length() {
return value.length;
}
/**
* Hash code for byte[] wrapped by this object,
* the actual hashcode is determined by Arrays.hashCode(byte[])
*/
@Override
public int hashCode() {
return this.hashCode;
}
@Override
public boolean equals(Object other) {
if (other instanceof ByteArrayWrapper)
return Arrays.equals(value, ((ByteArrayWrapper) other).value);
else if (other instanceof String) {
return Arrays.equals(value, Coder.stringToBytes((String) other));
}
return false;
}
/**
* This is a byte to byte comparator, it is not lexicographical but purely compares
* byte values
*/
@Override
public int compareTo(ByteArrayWrapper other) {
return arrayCmp(value, other.value);
}
/**
* Private helper method to compare two byte arrays, A.compareTo(B). The comparison
* is basically numerical, for each byte index, the byte representing the greater
* value will be the greater
*
* @param A byte[]
* @param B byte[]
* @return 1 if A > B, -1 if B > A, 0 if A == B
*/
private int arrayCmp(byte[] A, byte[] B) {
if (A == B)
return 0;
if (A == null) {
return -1;
} else if (B == null) {
return 1;
}
int len = Math.min(A.length, B.length);
for (int i = 0; i < len; i++) {
byte a = A[i];
byte b = B[i];
int diff = a - b;
if (diff > 0)
return 1;
else if (diff < 0)
return -1;
}
if (A.length > B.length)
return 1;
else if (B.length > A.length)
return -1;
return 0;
}
}