Untitled

 avatar
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