@Override public void write(Buffer source, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (source.size() < byteCount) { throw new IllegalArgumentException("size=" + source.size() + " byteCount=" + byteCount); } if (byteCount == 0) return; source.readUnsafe(cursor); try { long remaining = byteCount; for (int length = cursor.seek(0); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } super.write(source, byteCount); }
@Override public long read(Buffer sink, long byteCount) throws IOException { if (byteCount < 0) throw new IllegalArgumentException("byteCount < 0: " + byteCount); if (byteCount == 0) return 0; long result = super.read(sink, byteCount); if (result == -1L) return result; sink.readUnsafe(cursor); try { long remaining = result; for (int length = cursor.seek(sink.size() - result); remaining > 0 && length > 0; length = cursor.next()) { int toIntercept = (int) Math.min(length, remaining); intercept(cursor.data, cursor.start, toIntercept); remaining -= toIntercept; } } finally { cursor.close(); } return result; }
@Test public void accessSegmentBySegment() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { Buffer actual = new Buffer(); while (cursor.next() != -1L) { actual.write(cursor.data, cursor.start, cursor.end - cursor.start); } assertEquals(buffer, actual); } }
static void toggleMask(Buffer.UnsafeCursor cursor, byte[] key) { int keyIndex = 0; int keyLength = key.length; do { byte[] buffer = cursor.data; for (int i = cursor.start, end = cursor.end; i < end; i++, keyIndex++) { keyIndex %= keyLength; // Reassign to prevent overflow breaking counter. buffer[i] = (byte) (buffer[i] ^ key[keyIndex]); } } while (cursor.next() != -1); }
@Test public void segmentBySegmentNavigation() throws Exception { Buffer buffer = bufferFactory.newBuffer(); UnsafeCursor cursor = buffer.readUnsafe(); assertEquals(-1, cursor.offset); try { long lastOffset = cursor.offset; while (cursor.next() != -1L) { assertTrue(cursor.offset > lastOffset); lastOffset = cursor.offset; } assertEquals(buffer.size(), cursor.offset); assertNull(cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); } finally { cursor.close(); } }
static void toggleMask(Buffer.UnsafeCursor cursor, byte[] key) { int keyIndex = 0; int keyLength = key.length; do { byte[] buffer = cursor.data; for (int i = cursor.start, end = cursor.end; i < end; i++, keyIndex++) { keyIndex %= keyLength; // Reassign to prevent overflow breaking counter. buffer[i] = (byte) (buffer[i] ^ key[keyIndex]); } } while (cursor.next() != -1); }
@Test public void seekToNegativeOneSeeksBeforeFirstSegment() throws Exception { Buffer buffer = bufferFactory.newBuffer(); try (UnsafeCursor cursor = buffer.readUnsafe()) { cursor.seek(-1L); assertEquals(-1, cursor.offset); assertEquals(null, cursor.data); assertEquals(-1, cursor.start); assertEquals(-1, cursor.end); cursor.next(); assertEquals(0, cursor.offset); } }
static void toggleMask(Buffer.UnsafeCursor cursor, byte[] key) { int keyIndex = 0; int keyLength = key.length; do { byte[] buffer = cursor.data; for (int i = cursor.start, end = cursor.end; i < end; i++, keyIndex++) { keyIndex %= keyLength; // Reassign to prevent overflow breaking counter. buffer[i] = (byte) (buffer[i] ^ key[keyIndex]); } } while (cursor.next() != -1); }