Untitled
unknown
plain_text
2 years ago
3.0 kB
5
Indexable
public static Query<Integer, Integer> pack() {
return new Query<Integer, Integer>() {
private List<Integer> buffer = new ArrayList<>();
private int maxBits = 0;
@Override
public void start(Sink<Integer> sink) {
buffer.clear();
maxBits = 0;
}
@Override
public void next(Integer item, Sink<Integer> sink) {
buffer.add(item);
int bitsNeeded = Integer.SIZE - Integer.numberOfLeadingZeros(item | 1);
maxBits = Math.max(maxBits, bitsNeeded);
if (buffer.size() % BLOCK_SIZE == 0) {
flush(sink);
}
}
@Override
public void end(Sink<Integer> sink) {
if (!buffer.isEmpty()) {
flush(sink);
}
sink.end();
}
private void flush(Sink<Integer> sink) {
sink.next(maxBits); // Assume maxBits fits in a single byte
int currentByte = 0, bitsFilled = 0;
for (Integer value : buffer) {
int valueBits = maxBits;
int bitsRemaining = valueBits;
while (bitsRemaining > 0) {
if (bitsFilled + bitsRemaining < 8) {
currentByte |= (value << bitsFilled);
bitsFilled += bitsRemaining;
break;
} else {
int spaceLeft = 8 - bitsFilled;
currentByte |= (value & ((1 << spaceLeft) - 1)) << bitsFilled;
sink.next(currentByte);
value >>>= spaceLeft;
bitsRemaining -= spaceLeft;
currentByte = 0;
bitsFilled = 0;
}
}
}
if (bitsFilled > 0) {
sink.next(currentByte); // Send the last byte if it's not empty
}
buffer.clear();
maxBits = 0;
}
};
}
public static Query<Integer, Integer> unpack() {
return new Query<Integer, Integer>() {
private int currentByte = 0;
private int bitsInCurrentByte = 0;
private int bitsPerValue = 0;
private int valuesRemaining = BLOCK_SIZE;
@Override
public void start(Sink<Integer> sink) {
valuesRemaining = 0;
}
@Override
public void next(Integer packedData, Sink<Integer> sink) {
if (valuesRemaining == 0) {
bitsPerValue = packedData;
valuesRemaining = BLOCK_SIZE;
currentByte = 0;
bitsInCurrentByte = 0;
} else {
int availableBits = 8;
while (availableBits > 0 && valuesRemaining > 0) {
if (bitsInCurrentByte < bitsPerValue) {
int bitsNeeded = bitsPerValue - bitsInCurrentByte;
int bitsToTake = Math.min(bitsNeeded, availableBits);
int mask = (1 << bitsToTake) - 1;
int newData = (packedData & mask) << bitsInCurrentByte;
currentByte |= newData;
packedData >>>= bitsToTake;
availableBits -= bitsToTake;
bitsInCurrentByte += bitsToTake;
}
if (bitsInCurrentByte == bitsPerValue) {
sink.next(currentByte);
valuesRemaining--;
currentByte = 0;
bitsInCurrentByte = 0;
}
}
}
}
@Override
public void end(Sink<Integer> sink) {
sink.end();
}
};
}Editor is loading...
Leave a Comment