package org.apache.lucene.util.bkd;
import java.io.IOException;
import org.apache.lucene.index.PointValues.IntersectVisitor;
import org.apache.lucene.store.DataOutput;
import org.apache.lucene.store.IndexInput;
class DocIdsWriter {
private DocIdsWriter() {}
static void writeDocIds(int[] docIds, int start, int count, DataOutput out) throws IOException {
boolean sorted = true;
for (int i = 1; i < count; ++i) {
if (docIds[start + i - 1] > docIds[start + i]) {
sorted = false;
break;
}
}
if (sorted) {
out.writeByte((byte) 0);
int previous = 0;
for (int i = 0; i < count; ++i) {
int doc = docIds[start + i];
out.writeVInt(doc - previous);
previous = doc;
}
} else {
long max = 0;
for (int i = 0; i < count; ++i) {
max |= Integer.toUnsignedLong(docIds[start + i]);
}
if (max <= 0xffffff) {
out.writeByte((byte) 24);
for (int i = 0; i < count; ++i) {
out.writeShort((short) (docIds[start + i] >>> 8));
out.writeByte((byte) docIds[start + i]);
}
} else {
out.writeByte((byte) 32);
for (int i = 0; i < count; ++i) {
out.writeInt(docIds[start + i]);
}
}
}
}
static void readInts(IndexInput in, int count, int[] docIDs) throws IOException {
final int bpv = in.readByte();
switch (bpv) {
case 0:
readDeltaVInts(in, count, docIDs);
break;
case 32:
readInts32(in, count, docIDs);
break;
case 24:
readInts24(in, count, docIDs);
break;
default:
throw new IOException("Unsupported number of bits per value: " + bpv);
}
}
private static void readDeltaVInts(IndexInput in, int count, int[] docIDs) throws IOException {
int doc = 0;
for (int i = 0; i < count; i++) {
doc += in.readVInt();
docIDs[i] = doc;
}
}
static <T> void readInts32(IndexInput in, int count, int[] docIDs) throws IOException {
for (int i = 0; i < count; i++) {
docIDs[i] = in.readInt();
}
}
private static void readInts24(IndexInput in, int count, int[] docIDs) throws IOException {
int i;
for (i = 0; i < count - 7; i += 8) {
long l1 = in.readLong();
long l2 = in.readLong();
long l3 = in.readLong();
docIDs[i] = (int) (l1 >>> 40);
docIDs[i+1] = (int) (l1 >>> 16) & 0xffffff;
docIDs[i+2] = (int) (((l1 & 0xffff) << 8) | (l2 >>> 56));
docIDs[i+3] = (int) (l2 >>> 32) & 0xffffff;
docIDs[i+4] = (int) (l2 >>> 8) & 0xffffff;
docIDs[i+5] = (int) (((l2 & 0xff) << 16) | (l3 >>> 48));
docIDs[i+6] = (int) (l3 >>> 24) & 0xffffff;
docIDs[i+7] = (int) l3 & 0xffffff;
}
for (; i < count; ++i) {
docIDs[i] = (Short.toUnsignedInt(in.readShort()) << 8) | Byte.toUnsignedInt(in.readByte());
}
}
static void readInts(IndexInput in, int count, IntersectVisitor visitor) throws IOException {
final int bpv = in.readByte();
switch (bpv) {
case 0:
readDeltaVInts(in, count, visitor);
break;
case 32:
readInts32(in, count, visitor);
break;
case 24:
readInts24(in, count, visitor);
break;
default:
throw new IOException("Unsupported number of bits per value: " + bpv);
}
}
private static void readDeltaVInts(IndexInput in, int count, IntersectVisitor visitor) throws IOException {
int doc = 0;
for (int i = 0; i < count; i++) {
doc += in.readVInt();
visitor.visit(doc);
}
}
private static void readInts32(IndexInput in, int count, IntersectVisitor visitor) throws IOException {
for (int i = 0; i < count; i++) {
visitor.visit(in.readInt());
}
}
private static void readInts24(IndexInput in, int count, IntersectVisitor visitor) throws IOException {
int i;
for (i = 0; i < count - 7; i += 8) {
long l1 = in.readLong();
long l2 = in.readLong();
long l3 = in.readLong();
visitor.visit((int) (l1 >>> 40));
visitor.visit((int) (l1 >>> 16) & 0xffffff);
visitor.visit((int) (((l1 & 0xffff) << 8) | (l2 >>> 56)));
visitor.visit((int) (l2 >>> 32) & 0xffffff);
visitor.visit((int) (l2 >>> 8) & 0xffffff);
visitor.visit((int) (((l2 & 0xff) << 16) | (l3 >>> 48)));
visitor.visit((int) (l3 >>> 24) & 0xffffff);
visitor.visit((int) l3 & 0xffffff);
}
for (; i < count; ++i) {
visitor.visit((Short.toUnsignedInt(in.readShort()) << 8) | Byte.toUnsignedInt(in.readByte()));
}
}
}