Untitled
unknown
plain_text
a year ago
3.0 kB
4
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