package org.apache.lucene.util.packed;
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import org.apache.lucene.store.IndexOutput;
import java.io.IOException;
// Packs high order byte first, to match
// IndexOutput.writeInt/Long/Short byte order
/**
* Generic writer for space-optimal packed values. The resulting bits can be
* used directly by Packed32, Packed64 and PackedDirect* and will always be
* long-aligned.
*/
class PackedWriter extends PackedInts.Writer {
private long pending;
private int pendingBitPos;
// masks[n-1] masks for bottom n bits
private final long[] masks;
private int written = 0;
public PackedWriter(IndexOutput out, int valueCount, int bitsPerValue)
throws IOException {
super(out, valueCount, bitsPerValue);
pendingBitPos = 64;
masks = new long[bitsPerValue - 1];
long v = 1;
for (int i = 0; i < bitsPerValue - 1; i++) {
v *= 2;
masks[i] = v - 1;
}
}
/**
* Do not call this after finish
*/
@Override
public void add(long v) throws IOException {
assert v <= PackedInts.maxValue(bitsPerValue) : "v=" + v
+ " maxValue=" + PackedInts.maxValue(bitsPerValue);
assert v >= 0;
//System.out.println(" packedw add v=" + v + " pendingBitPos=" + pendingBitPos);
// TODO
if (pendingBitPos >= bitsPerValue) {
// not split
// write-once, so we can |= w/o first masking to 0s
pending |= v << (pendingBitPos - bitsPerValue);
if (pendingBitPos == bitsPerValue) {
// flush
out.writeLong(pending);
pending = 0;
pendingBitPos = 64;
} else {
pendingBitPos -= bitsPerValue;
}
} else {
// split
// write top pendingBitPos bits of value into bottom bits of pending
pending |= (v >> (bitsPerValue - pendingBitPos)) & masks[pendingBitPos - 1];
//System.out.println(" part1 (v >> " + (bitsPerValue - pendingBitPos) + ") & " + masks[pendingBitPos-1]);
// flush
out.writeLong(pending);
// write bottom (bitsPerValue - pendingBitPos) bits of value into top bits of pending
pendingBitPos = 64 - bitsPerValue + pendingBitPos;
//System.out.println(" part2 v << " + pendingBitPos);
pending = (v << pendingBitPos);
}
written++;
}
@Override
public void finish() throws IOException {
while (written < valueCount) {
add(0L); // Auto flush
}
if (pendingBitPos != 64) {
out.writeLong(pending);
}
}
@Override
public String toString() {
return "PackedWriter(written " + written + "/" + valueCount + " with "
+ bitsPerValue + " bits/value)";
}
}