package org.mapdb.serializer;
import org.mapdb.DataInput2;
import org.mapdb.DataOutput2;
import java.io.IOException;
/**
* Serializes group of {@code byte[]} with delta compression.
*/
public class SerializerByteArrayDelta extends SerializerByteArray {
//TODO PERF char[][] versus Object[]
@Override
public void valueArraySerialize(DataOutput2 out, Object vals) throws IOException {
byte[][] chars = (byte[][]) vals;
//write lengths
for(byte[] b:chars){
out.packInt(b.length);
}
//$DELAY$
//find common prefix
int prefixLen = commonPrefixLen(chars);
out.packInt(prefixLen);
out.write(chars[0], 0, prefixLen);
//$DELAY$
for(byte[] b:chars){
out.write(b,prefixLen,b.length-prefixLen);
}
}
@Override
public byte[][] valueArrayDeserialize(DataInput2 in, int size) throws IOException {
byte[][] ret = new byte[size][];
//read lengths and init arrays
for(int i=0;i<ret.length;i++){
ret[i] = new byte[in.unpackInt()];
}
//$DELAY$
//read and distribute common prefix
int prefixLen = in.unpackInt();
in.readFully(ret[0],0,prefixLen);
for(int i=1;i<ret.length;i++){
System.arraycopy(ret[0],0,ret[i],0,prefixLen);
}
//$DELAY$
//read suffixes
for (byte[] aRet : ret) {
in.readFully(aRet, prefixLen, aRet.length - prefixLen);
}
return ret;
}
protected static int commonPrefixLen(byte[][] bytes) {
//TODO PERF refactor to calculate minimal length first, to save comparations.
for(int ret=0;;ret++){
if(bytes[0].length==ret) {
return ret;
}
byte byt = bytes[0][ret];
for(int i=1;i<bytes.length;i++){
if(bytes[i].length==ret || byt!=bytes[i][ret])
return ret;
}
}
}
}