Added: mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java?rev=685367&view=auto ============================================================================== --- mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java (added) +++ mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java Tue Aug 12 16:24:26 2008 @@ -0,0 +1,101 @@ +/* + * 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. + * + */ +package org.apache.mina.util.byteaccess; + + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + + +/** + * Provides absolute write access to a sequence of bytes. + * + * @author The Apache MINA Project ([EMAIL PROTECTED]) + * @version $Rev$, $Date$ + */ +public interface IoAbsoluteWriter +{ + + /** + * Get the index of the first byte that can be accessed. + */ + int first(); + + + /** + * Gets the index after the last byte that can be accessed. + */ + int last(); + + + /** + * Gets the order of the bytes. + */ + ByteOrder order(); + + + /** + * Puts a <code>byte</code> at the given index. + */ + void put( int index, byte b ); + + + /** + * Puts bytes from the <code>IoBuffer</code> at the given index. + */ + public void put( int index, IoBuffer bb ); + + + /** + * Puts a <code>short</code> at the given index. + */ + void putShort( int index, short s ); + + + /** + * Puts an <code>int</code> at the given index. + */ + void putInt( int index, int i ); + + + /** + * Puts a <code>long</code> at the given index. + */ + void putLong( int index, long l ); + + + /** + * Puts a <code>float</code> at the given index. + */ + void putFloat( int index, float f ); + + + /** + * Puts a <code>double</code> at the given index. + */ + void putDouble( int index, double d ); + + + /** + * Puts a <code>char</code> at the given index. + */ + void putChar( int index, char c ); +}
Added: mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java?rev=685367&view=auto ============================================================================== --- mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java (added) +++ mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java Tue Aug 12 16:24:26 2008 @@ -0,0 +1,113 @@ +/* + * 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. + * + */ +package org.apache.mina.util.byteaccess; + + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + + +/** + * Provides relative read access to a sequence of bytes. + * + * @author The Apache MINA Project ([EMAIL PROTECTED]) + * @version $Rev$, $Date$ + */ +public interface IoRelativeReader +{ + + /** + * Gets the number of remaining bytes that can be read. + */ + int getRemaining(); + + + /** + * Checks if there are any remaining bytes that can be read. + */ + boolean hasRemaining(); + + + /** + * Advances the reader by the given number of bytes. + */ + void skip( int length ); + + + /** + * Creates an array with a view of part of this array. + */ + ByteArray slice( int length ); + + + /** + * Gets the order of the bytes. + */ + ByteOrder order(); + + + /** + * Gets a <code>byte</code> and advances the reader. + */ + byte get(); + + + /** + * Gets enough bytes to fill the <code>IoBuffer</code> and advances the reader. + */ + void get( IoBuffer bb ); + + + /** + * Gets a <code>short</code> and advances the reader. + */ + short getShort(); + + + /** + * Gets an <code>int</code> and advances the reader. + */ + int getInt(); + + + /** + * Gets a <code>long</code> and advances the reader. + */ + long getLong(); + + + /** + * Gets a <code>float</code> and advances the reader. + */ + float getFloat(); + + + /** + * Gets a <code>double</code> and advances the reader. + */ + double getDouble(); + + + /** + * Gets a <code>char</code> and advances the reader. + */ + char getChar(); +} Added: mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java?rev=685367&view=auto ============================================================================== --- mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java (added) +++ mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java Tue Aug 12 16:24:26 2008 @@ -0,0 +1,107 @@ +/* + * 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. + * + */ +package org.apache.mina.util.byteaccess; + + +import java.nio.ByteOrder; + +import org.apache.mina.core.buffer.IoBuffer; + + +/** + * Provides relative read access to a sequence of bytes. + * + * @author The Apache MINA Project ([EMAIL PROTECTED]) + * @version $Rev$, $Date$ + */ +public interface IoRelativeWriter +{ + + /** + * Gets the number of remaining bytes that can be read. + */ + int getRemaining(); + + + /** + * Checks if there are any remaining bytes that can be read. + */ + boolean hasRemaining(); + + + /** + * Advances the writer by the given number of bytes. + */ + void skip( int length ); + + + /** + * Gets the order of the bytes. + */ + ByteOrder order(); + + + /** + * Puts a <code>byte</code> and advances the reader. + */ + void put( byte b ); + + + /** + * Puts enough bytes to fill the <code>IoBuffer</code> and advances the reader. + */ + void put( IoBuffer bb ); + + + /** + * Puts a <code>short</code> and advances the reader. + */ + void putShort( short s ); + + + /** + * Puts an <code>int</code> and advances the reader. + */ + void putInt( int i ); + + + /** + * Puts a <code>long</code> and advances the reader. + */ + void putLong( long l ); + + + /** + * Puts a <code>float</code> and advances the reader. + */ + void putFloat( float f ); + + + /** + * Puts a <code>double</code> and advances the reader. + */ + void putDouble( double d ); + + + /** + * Puts a <code>char</code> and advances the reader. + */ + void putChar( char c ); +} Added: mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java?rev=685367&view=auto ============================================================================== --- mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java (added) +++ mina/trunk/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java Tue Aug 12 16:24:26 2008 @@ -0,0 +1,70 @@ +/* + * 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. + * + */ +package org.apache.mina.util.byteaccess; + + +import org.apache.mina.core.buffer.IoBuffer; + + +/** + * Creates <code>ByteArray</code> backed by a heap-allocated + * <code>IoBuffer</code>. The free method on returned + * <code>ByteArray</code>s is a nop. + * + * @author The Apache MINA Project ([EMAIL PROTECTED]) + * @version $Rev$, $Date$ + */ +public class SimpleByteArrayFactory implements ByteArrayFactory +{ + /** + * + * Creates a new instance of SimpleByteArrayFactory. + * + */ + public SimpleByteArrayFactory() + { + super(); + } + + + /** + * @inheritDoc + */ + public ByteArray create( int size ) + { + if ( size < 0 ) + { + throw new IllegalArgumentException( "Buffer size must not be negative:" + size ); + } + IoBuffer bb = IoBuffer.allocate( size ); + ByteArray ba = new BufferByteArray( bb ) + { + + @Override + public void free() + { + // Nothing to do. + } + + }; + return ba; + } + +} Added: mina/trunk/core/src/test/java/org/apache/mina/util/byteaccess/ByteAccessTest.java URL: http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/util/byteaccess/ByteAccessTest.java?rev=685367&view=auto ============================================================================== --- mina/trunk/core/src/test/java/org/apache/mina/util/byteaccess/ByteAccessTest.java (added) +++ mina/trunk/core/src/test/java/org/apache/mina/util/byteaccess/ByteAccessTest.java Tue Aug 12 16:24:26 2008 @@ -0,0 +1,558 @@ +/* + * 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. + * + */ +package org.apache.mina.util.byteaccess; + +import static org.easymock.EasyMock.createStrictControl; + +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.apache.mina.core.buffer.IoBuffer; +import org.apache.mina.util.byteaccess.ByteArray.Cursor; +import org.apache.mina.util.byteaccess.CompositeByteArray.CursorListener; +import org.apache.mina.util.byteaccess.CompositeByteArrayRelativeWriter.ChunkedExpander; +import org.apache.mina.util.byteaccess.CompositeByteArrayRelativeWriter.Flusher; +import org.easymock.IMocksControl; + +/** + * Tests classes in the <code>byteaccess</code> package. + * + * @author <a href="mailto:[EMAIL PROTECTED]">Apache Directory Project</a> + * @version $Rev$, $Date$ + */ +public class ByteAccessTest extends TestCase { + + private List<String> operations = new ArrayList<String>(); + + private void resetOperations() { + operations.clear(); + } + + private void assertOperationCountEquals(int expectedCount) { + assertEquals("Operations: " + operations, expectedCount, operations.size()); + } + + private void addOperation(String description) { + operations.add(description); + } + + public void testBufferByteArray() throws Exception { + ByteArray ba = getByteArrayFactory().create(1000); + testAbsoluteReaderAndWriter(0, 1000, ba, ba); + testAbsoluteReaderAndWriter(0, 1000, ba, ba); + Cursor readCursor = ba.cursor(); + Cursor writeCursor = ba.cursor(); + testRelativeReaderAndWriter(1000, readCursor, writeCursor); + } + + public void testCompositeAddAndRemove() throws Exception { + CompositeByteArray cba = new CompositeByteArray(); + assertEquals(0, cba.first()); + assertEquals(0, cba.last()); + cba.addFirst(getByteArrayFactory().create(100)); + assertEquals(-100, cba.first()); + assertEquals(0, cba.last()); + cba.addFirst(getByteArrayFactory().create(100)); + assertEquals(-200, cba.first()); + assertEquals(0, cba.last()); + cba.addLast(getByteArrayFactory().create(100)); + assertEquals(-200, cba.first()); + assertEquals(100, cba.last()); + cba.removeFirst(); + assertEquals(-100, cba.first()); + assertEquals(100, cba.last()); + cba.addLast(getByteArrayFactory().create(100)); + assertEquals(-100, cba.first()); + assertEquals(200, cba.last()); + cba.removeLast(); + assertEquals(-100, cba.first()); + assertEquals(100, cba.last()); + cba.removeFirst(); + assertEquals(0, cba.first()); + assertEquals(100, cba.last()); + cba.removeFirst(); + assertEquals(100, cba.first()); + assertEquals(100, cba.last()); + cba.addLast(getByteArrayFactory().create(100)); + assertEquals(100, cba.first()); + assertEquals(200, cba.last()); + } + + private BufferByteArray wrapString(String string) { + byte[] bytes = string.getBytes(); + IoBuffer bb = IoBuffer.wrap(bytes); + BufferByteArray ba = new BufferByteArray(bb) { + + @Override + public void free() { + addOperation(this + ".free()"); + // Nothing to do. + } + + }; + return ba; + } + + private String toString(ByteArray ba) { + IoBuffer bb = IoBuffer.allocate(ba.length()); + ba.get(0, bb); + byte[] bytes = bb.array(); + String string = new String(bytes); + return string; + } + + public void testCompositeStringJoin() throws Exception { + ByteArray ba1 = wrapString("Hello"); + ByteArray ba2 = wrapString("MINA"); + ByteArray ba3 = wrapString("World"); + + CompositeByteArray cba = new CompositeByteArray(); + cba.addLast(ba1); + cba.addLast(ba2); + cba.addLast(ba3); + + assertEquals("HelloMINAWorld", toString(cba)); + } + + public void testCompositeCursor() throws Exception { + IMocksControl mc = createStrictControl(); + + ByteArray ba1 = getByteArrayFactory().create(10); + ByteArray ba2 = getByteArrayFactory().create(10); + ByteArray ba3 = getByteArrayFactory().create(10); + + + CompositeByteArray cba = new CompositeByteArray(); + cba.addLast(ba1); + cba.addLast(ba2); + cba.addLast(ba3); + + CursorListener cl = mc.createMock(CursorListener.class); + + mc.reset(); + mc.replay(); + Cursor cursor = cba.cursor(cl); + mc.verify(); + + mc.reset(); + cl.enteredFirstComponent(0, ba1); + mc.replay(); + cursor.get(); + mc.verify(); + + mc.reset(); + mc.replay(); + cursor.setIndex(10); + mc.verify(); + + mc.reset(); + cl.enteredNextComponent(10, ba2); + mc.replay(); + cursor.put((byte) 55); + mc.verify(); + + mc.reset(); + mc.replay(); + cursor.setIndex(9); + mc.verify(); + + mc.reset(); + cl.enteredPreviousComponent(0, ba1); + cl.enteredNextComponent(10, ba2); + mc.replay(); + cursor.putInt(66); + mc.verify(); + + mc.reset(); + cl.enteredNextComponent(20, ba3); + mc.replay(); + cursor.setIndex(29); + cursor.get(); + mc.verify(); + + cba.removeLast(); // Force cursor to relocate itself. + + mc.reset(); + cl.enteredLastComponent(10, ba2); + mc.replay(); + cursor.setIndex(15); + cursor.get(); + mc.verify(); + + mc.reset(); + cl.enteredPreviousComponent(0, ba1); + mc.replay(); + cursor.setIndex(0); + cursor.get(); + mc.verify(); + } + + public void testCompositeByteArray() throws Exception { + CompositeByteArray ba = new CompositeByteArray(); + for (int i = 0; i < 1000; i += 100) { + ba.addLast(getByteArrayFactory().create(100)); + } + resetOperations(); + testAbsoluteReaderAndWriter(0, 1000, ba, ba); + testAbsoluteReaderAndWriter(0, 1000, ba, ba); + assertOperationCountEquals(0); + Cursor readCursor = ba.cursor(); + Cursor writeCursor = ba.cursor(); + testRelativeReaderAndWriter(1000, readCursor, writeCursor); + assertOperationCountEquals(0); + } + + public void testCompositeByteArrayRelativeReaderAndWriter() throws Exception { + CompositeByteArray cba = new CompositeByteArray(); + CompositeByteArrayRelativeReader cbarr = new CompositeByteArrayRelativeReader(cba, true); + CompositeByteArrayRelativeWriter cbarw = new CompositeByteArrayRelativeWriter(cba, getExpander(100), getFlusher(), false); + resetOperations(); + testRelativeReaderAndWriter(10, cbarr, cbarw); + assertOperationCountEquals(2); + resetOperations(); + testRelativeReaderAndWriter(100, cbarr, cbarw); + assertOperationCountEquals(3); + resetOperations(); + testRelativeReaderAndWriter(1000, cbarr, cbarw); + assertOperationCountEquals(30); + resetOperations(); + testRelativeReaderAndWriter(10000, cbarr, cbarw); + assertOperationCountEquals(300); + resetOperations(); + testRelativeReaderAndWriter(90, cbarr, cbarw); + assertOperationCountEquals(0); // Last free doesn't occur, since cursor only moves lazily. + } + + public void testCompositeByteArrayRelativeReaderAndWriterWithFlush() throws Exception { + CompositeByteArray cba = new CompositeByteArray(); + CompositeByteArrayRelativeReader cbarr = new CompositeByteArrayRelativeReader(cba, true); + CompositeByteArrayRelativeWriter cbarw = new CompositeByteArrayRelativeWriter(cba, getExpander(100), getFlusher(), true); + resetOperations(); + testRelativeReaderAndWriter(10, cbarr, cbarw); + assertOperationCountEquals(2); + resetOperations(); + testRelativeReaderAndWriter(100, cbarr, cbarw); + assertOperationCountEquals(4); + resetOperations(); + testRelativeReaderAndWriter(1000, cbarr, cbarw); + assertOperationCountEquals(40); + resetOperations(); + testRelativeReaderAndWriter(10000, cbarr, cbarw); + assertOperationCountEquals(400); + resetOperations(); + testRelativeReaderAndWriter(90, cbarr, cbarw); + assertOperationCountEquals(0); // Last free doesn't occur, since cursor only moves lazily. + } + + public void testCompositeRemoveTo() throws Exception { + CompositeByteArray cba = new CompositeByteArray(); + { + // Remove nothing. + resetOperations(); + ByteArray removed = cba.removeTo(0); + assertEquals(0, removed.first()); + assertEquals(0, removed.last()); + assertEquals(0, cba.first()); + assertEquals(0, cba.last()); + removed.free(); + assertOperationCountEquals(0); + } + cba.addLast(getByteArrayFactory().create(100)); + { + // Remove nothing. + resetOperations(); + ByteArray removed = cba.removeTo(0); + assertEquals(0, removed.first()); + assertEquals(0, removed.last()); + assertEquals(0, cba.first()); + assertEquals(100, cba.last()); + removed.free(); + assertOperationCountEquals(0); + } + { + // Remove entire component. + resetOperations(); + ByteArray removed = cba.removeTo(100); + assertEquals(0, removed.first()); + assertEquals(100, removed.last()); + assertEquals(100, cba.first()); + assertEquals(100, cba.last()); + removed.free(); + assertOperationCountEquals(1); + } + { + // Remove nothing. + resetOperations(); + ByteArray removed = cba.removeTo(100); + assertEquals(0, removed.first()); + assertEquals(0, removed.last()); + assertEquals(100, cba.first()); + assertEquals(100, cba.last()); + removed.free(); + assertOperationCountEquals(0); + } + cba.addLast(getByteArrayFactory().create(100)); + { + // Remove nothing. + resetOperations(); + ByteArray removed = cba.removeTo(100); + assertEquals(0, removed.first()); + assertEquals(0, removed.last()); + assertEquals(100, cba.first()); + assertEquals(200, cba.last()); + removed.free(); + assertOperationCountEquals(0); + } + { + // Remove half a component. + resetOperations(); + ByteArray removed = cba.removeTo(150); + assertEquals(0, removed.first()); + assertEquals(50, removed.last()); + assertEquals(150, cba.first()); + assertEquals(200, cba.last()); + removed.free(); + assertOperationCountEquals(0); // Doesn't free until component finished. + } + { + // Remove nothing. + resetOperations(); + ByteArray removed = cba.removeTo(150); + assertEquals(0, removed.first()); + assertEquals(0, removed.last()); + assertEquals(150, cba.first()); + assertEquals(200, cba.last()); + removed.free(); + assertOperationCountEquals(0); + } + { + // Remove other half. + resetOperations(); + ByteArray removed = cba.removeTo(200); + assertEquals(0, removed.first()); + assertEquals(50, removed.last()); + assertEquals(200, cba.first()); + assertEquals(200, cba.last()); + removed.free(); + assertOperationCountEquals(1); // Frees ByteArray behind both buffers. + } + } + + public void testCompositeByteArraySlicing() { + CompositeByteArray cba = new CompositeByteArray(); + cba.addLast(getByteArrayFactory().create(10)); + cba.addLast(getByteArrayFactory().create(10)); + cba.addLast(getByteArrayFactory().create(10)); + testByteArraySlicing(cba, 0, 30); + testByteArraySlicing(cba, 5, 10); + testByteArraySlicing(cba, 10, 20); + testByteArraySlicing(cba, 1, 28); + testByteArraySlicing(cba, 19, 2); + } + + public void testBufferByteArraySlicing() { + ByteArray bba = getByteArrayFactory().create(30); + testByteArraySlicing(bba, 0, 30); + testByteArraySlicing(bba, 5, 10); + testByteArraySlicing(bba, 10, 20); + testByteArraySlicing(bba, 1, 28); + testByteArraySlicing(bba, 19, 2); + + } + + private void testByteArraySlicing(ByteArray ba, int start, int length) { + ByteArray slice = ba.slice(start, length); + for (int i = 0; i < length; i++) { + byte b1 = (byte) (i % 67); + byte b2 = (byte) (i % 36); + int sourceIndex = i + start; + int sliceIndex = i; + ba.put(sourceIndex, b1); + assertEquals(b1, ba.get(sourceIndex)); + assertEquals(b1, slice.get(sliceIndex)); + slice.put(sliceIndex, b2); + assertEquals(b2, ba.get(sourceIndex)); + assertEquals(b2, slice.get(sliceIndex)); + } + } + + private ChunkedExpander getExpander(final int chunkSize) { + return new ChunkedExpander(getByteArrayFactory(), chunkSize) { + @Override + public void expand(CompositeByteArray cba, int minSize) { + addOperation("ChunkedExpander(" + chunkSize + ").expand(" + cba + "," + minSize + ")"); + super.expand(cba, minSize); + } + }; + } + + private Flusher getFlusher() { + return new CompositeByteArrayRelativeWriter.Flusher() { + + public void flush(ByteArray ba) { + addOperation("Flusher().flush(" + ba + ")"); + ba.free(); + } + + }; + } + + private SimpleByteArrayFactory getByteArrayFactory() { + return new SimpleByteArrayFactory() { + @Override + public ByteArray create(final int size) { + if (size < 0) { + throw new IllegalArgumentException( + "Buffer size must not be negative:" + size); + } + IoBuffer bb = IoBuffer.allocate(size); + ByteArray ba = new BufferByteArray(bb) { + + @Override + public void free() { + addOperation(this + ".free()"); + // Nothing to do. + } + + }; + addOperation("SimpleByteArrayFactory().create(" + size + ") = " + ba); + return ba; + } + }; + } + + private void testRelativeReaderAndWriter(int length, IoRelativeReader reader, IoRelativeWriter writer) { + for (int i = 0; i < length; i++) { + byte b = (byte) (i % 67); + writer.put(b); + assertEquals(b, reader.get()); + } + } + + private void testAbsoluteReaderAndWriter(int start, int length, IoAbsoluteReader reader, IoAbsoluteWriter writer) { + for (int i = start; i < length; i++) { + byte b = (byte) (i % 67); + writer.put(i, b); + assertEquals(b, reader.get(i)); + } + } + + public void testByteArrayPrimitiveAccess() { + ByteArray bbaBig = getByteArrayFactory().create(1000); + bbaBig.order(ByteOrder.BIG_ENDIAN); + testPrimitiveAccess(bbaBig.cursor(), bbaBig.cursor()); + + ByteArray bbaLittle = getByteArrayFactory().create(1000); + bbaLittle.order(ByteOrder.LITTLE_ENDIAN); + testPrimitiveAccess(bbaLittle.cursor(), bbaLittle.cursor()); + } + + public void testByteArrayBufferAccess() { + ByteArray ba = getByteArrayFactory().create(1); + ba.put(0, (byte) 99); + IoBuffer bb = IoBuffer.allocate(2); + + bb.clear(); + Cursor cursor = ba.cursor(); + assertEquals(0, cursor.getIndex()); + assertEquals(1, cursor.getRemaining()); + assertEquals(0, bb.position()); + assertEquals(2, bb.remaining()); + cursor.get(bb); + assertEquals(1, cursor.getIndex()); + assertEquals(0, cursor.getRemaining()); + assertEquals(1, bb.position()); + assertEquals(1, bb.remaining()); + } + + public void testCompositeByteArrayPrimitiveAccess() { + CompositeByteArray cbaBig = new CompositeByteArray(); + cbaBig.order(ByteOrder.BIG_ENDIAN); + for (int i = 0; i < 1000; i++) { + ByteArray component = getByteArrayFactory().create(1); + component.order(ByteOrder.BIG_ENDIAN); + cbaBig.addLast(component); + } + testPrimitiveAccess(cbaBig.cursor(), cbaBig.cursor()); + + CompositeByteArray cbaLittle = new CompositeByteArray(); + cbaLittle.order(ByteOrder.LITTLE_ENDIAN); + for (int i = 0; i < 1000; i++) { + ByteArray component = getByteArrayFactory().create(1); + component.order(ByteOrder.LITTLE_ENDIAN); + cbaLittle.addLast(component); + } + testPrimitiveAccess(cbaLittle.cursor(), cbaLittle.cursor()); + } + + public void testCompositeByteArrayWrapperPrimitiveAccess() { + CompositeByteArray cbaBig = new CompositeByteArray(); + cbaBig.order(ByteOrder.BIG_ENDIAN); + for (int i = 0; i < 1000; i++) { + ByteArray component = getByteArrayFactory().create(1); + component.order(ByteOrder.BIG_ENDIAN); + cbaBig.addLast(component); + } + testPrimitiveAccess(new CompositeByteArrayRelativeWriter(cbaBig, getExpander(10), getFlusher(), false), new CompositeByteArrayRelativeReader(cbaBig, true)); + + CompositeByteArray cbaLittle = new CompositeByteArray(); + cbaLittle.order(ByteOrder.LITTLE_ENDIAN); + for (int i = 0; i < 1000; i++) { + ByteArray component = getByteArrayFactory().create(1); + component.order(ByteOrder.LITTLE_ENDIAN); + cbaLittle.addLast(component); + } + testPrimitiveAccess(new CompositeByteArrayRelativeWriter(cbaLittle, getExpander(10), getFlusher(), false), new CompositeByteArrayRelativeReader(cbaLittle, true)); + } + + private void testPrimitiveAccess(IoRelativeWriter write, IoRelativeReader read) { + byte b = (byte) 0x12; + write.put(b); + assertEquals(b, read.get()); + + short s = (short) 0x12; + write.putShort(s); + assertEquals(s, read.getShort()); + + int i = 0x12345678; + write.putInt(i); + assertEquals(i, read.getInt()); + + long l = 0x1234567890123456L; + write.putLong(l); + assertEquals(l, read.getLong()); + + float f = Float.intBitsToFloat(i); + write.putFloat(f); + assertEquals(f, read.getFloat()); + + double d = Double.longBitsToDouble(l); + write.putDouble(d); + assertEquals(d, read.getDouble()); + + char c = (char) 0x1234; + write.putChar(c); + assertEquals(c, read.getChar()); + } + +}
