You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by tr...@apache.org on 2008/05/22 03:09:24 UTC

svn commit: r658963 - in /mina/branches/buffer/core/src: main/java/org/apache/mina/util/byteaccess/ test/java/org/apache/mina/common/

Author: trustin
Date: Wed May 21 18:09:24 2008
New Revision: 658963

URL: http://svn.apache.org/viewvc?rev=658963&view=rev
Log:
Applied Rich's latest patch

Added:
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java   (with props)
Modified:
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java
    mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java
    mina/branches/buffer/core/src/test/java/org/apache/mina/common/ByteAccessTest.java

Added: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java?rev=658963&view=auto
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java (added)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java Wed May 21 18:09:24 2008
@@ -0,0 +1,74 @@
+/*
+ *  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;
+
+
+abstract class AbstractByteArray implements ByteArray {
+
+    /**
+     * @inheritDoc
+     */
+    public final int length() {
+        return last() - first();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public final boolean equals(Object other) {
+        // Optimization: compare pointers.
+        if (other == this) {
+            return true;
+        }
+        // Compare types.
+        if (!(other instanceof ByteArray)) {
+            return false;
+        }
+        ByteArray otherByteArray = (ByteArray) other;
+        // Compare properties.
+        if (first() != otherByteArray.first()
+                || last() != otherByteArray.last()
+                || !order().equals(otherByteArray.order())) {
+            return false;
+        }
+        // Compare bytes.
+        Cursor cursor = cursor();
+        Cursor otherCursor = otherByteArray.cursor();
+        for (int remaining = cursor.getRemaining(); remaining > 0;) {
+            // Optimization: prefer int comparisons over byte comparisons
+            if (remaining >= 4) {
+                int i = cursor.getInt();
+                int otherI = otherCursor.getInt();
+                if (i != otherI) {
+                    return false;
+                }
+            } else {
+                byte b = cursor.get();
+                byte otherB = otherCursor.get();
+                if (b != otherB) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+}

Propchange: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/AbstractByteArray.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/BufferByteArray.java Wed May 21 18:09:24 2008
@@ -30,7 +30,7 @@
  * a <code>SimpleByteArrayFactory</code>.
  *
  */
-public abstract class BufferByteArray implements ByteArray {
+public abstract class BufferByteArray extends AbstractByteArray {
 
     /**
      * The backing <code>ByteBuffer</code>.
@@ -54,6 +54,27 @@
     public ByteBuffer getSingleByteBuffer() {
         return bb;
     }
+    
+    /**
+     * @inheritDoc
+     * 
+     * Calling <code>free()</code> on the returned slice has no effect.
+     */
+    public ByteArray slice(int index, int length) {
+        int oldLimit = bb.limit();
+        bb.position(index);
+        bb.limit(index + length);
+        ByteBuffer slice = bb.slice();
+        bb.limit(oldLimit);
+        return new BufferByteArray(slice) {
+            
+            @Override
+            public void free() {
+                // Do nothing.
+            }
+            
+        };
+    }
 
     /**
      * @inheritDoc
@@ -91,13 +112,6 @@
     /**
      * @inheritDoc
      */
-    public int length() {
-        return last() - first();
-    }
-
-    /**
-     * @inheritDoc
-     */
     public ByteOrder order() {
         return bb.order();
     }
@@ -142,6 +156,20 @@
     /**
      * @inheritDoc
      */
+    public short getShort(int index) {
+        return bb.getShort(index);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putShort(int index, short s) {
+        bb.putShort(index, s);
+    }
+
+    /**
+     * @inheritDoc
+     */
     public int getInt(int index) {
         return bb.getInt(index);
     }
@@ -153,6 +181,62 @@
         bb.putInt(index, i);
     }
 
+    /**
+     * @inheritDoc
+     */
+    public long getLong(int index) {
+        return bb.getLong(index);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putLong(int index, long l) {
+        bb.putLong(index, l);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public float getFloat(int index) {
+        return bb.getFloat(index);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putFloat(int index, float f) {
+        bb.putFloat(index, f);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public double getDouble(int index) {
+        return bb.getDouble(index);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putDouble(int index, double d) {
+        bb.putDouble(index, d);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public char getChar(int index) {
+        return bb.getChar(index);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putChar(int index, char c) {
+        bb.putChar(index, c);
+    }
+
     private class CursorImpl implements Cursor {
 
         private int index;
@@ -195,6 +279,16 @@
             }
             this.index = index;
         }
+        
+        public void skip(int length) {
+            setIndex(index + length);
+        }
+        
+        public ByteArray slice(int length) {
+            ByteArray slice = BufferByteArray.this.slice(index, length);
+            index += length;
+            return slice;
+        }
 
         /**
          * @inheritDoc
@@ -241,6 +335,23 @@
         /**
          * @inheritDoc
          */
+        public short getShort() {
+            short s = BufferByteArray.this.getShort(index);
+            index += 2;
+            return s;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putShort(short s) {
+            BufferByteArray.this.putShort(index, s);
+            index += 2;
+        }
+
+        /**
+         * @inheritDoc
+         */
         public int getInt() {
             int i = BufferByteArray.this.getInt(index);
             index += 4;
@@ -255,5 +366,72 @@
             index += 4;
         }
 
+        /**
+         * @inheritDoc
+         */
+        public long getLong() {
+            long l = BufferByteArray.this.getLong(index);
+            index += 8;
+            return l;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putLong(long l) {
+            BufferByteArray.this.putLong(index, l);
+            index += 8;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public float getFloat() {
+            float f = BufferByteArray.this.getFloat(index);
+            index += 4;
+            return f;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putFloat(float f) {
+            BufferByteArray.this.putFloat(index, f);
+            index += 4;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public double getDouble() {
+            double d = BufferByteArray.this.getDouble(index);
+            index += 8;
+            return d;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putDouble(double d) {
+            BufferByteArray.this.putDouble(index, d);
+            index += 8;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public char getChar() {
+            char c = BufferByteArray.this.getChar(index);
+            index += 2;
+            return c;
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putChar(char c) {
+            BufferByteArray.this.putChar(index, c);
+            index += 2;
+        }
     }
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/ByteArray.java Wed May 21 18:09:24 2008
@@ -70,6 +70,13 @@
     ByteBuffer getSingleByteBuffer();
 
     /**
+     * A ByteArray is equal to another ByteArray if they start and end at the
+     * same index, have the same byte order, and contain the same bytes at each
+     * index.
+     */
+    public boolean equals(Object other);
+
+    /**
      * @inheritDoc
      */
     byte get(int index);

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArray.java Wed May 21 18:09:24 2008
@@ -30,8 +30,11 @@
 /**
  * A ByteArray composed of other ByteArrays. Optimised for fast relative access
  * via cursors. Absolute access methods are provided, but may perform poorly.
+ *
+ * TODO: Write about laziness of cursor implementation - how movement doesn't
+ * happen until actual get/put.
  */
-public final class CompositeByteArray implements ByteArray {
+public final class CompositeByteArray extends AbstractByteArray {
 
     /**
      * Allows for efficient detection of component boundaries when using a cursor.
@@ -91,7 +94,7 @@
     }
 
     public void addFirst(ByteArray ba) {
-        handleAdd(ba);
+        addHook(ba);
         bas.addFirst(ba);
     }
 
@@ -128,9 +131,9 @@
                 remaining -= component.last();
             } else {
                 // Remove part of component. Do this by removing entire
-                // component
-                // then readding remaining bytes.
-                // TODO: Consider using getByteBuffers(), as more generic.
+                // component then readding remaining bytes.
+                // TODO: Consider using getByteBuffers(), as would avoid
+                // performance problems for nested ComponentByteArrays.
                 ByteBuffer bb = component.getSingleByteBuffer();
                 int originalLimit = bb.limit();
                 bb.position(0);
@@ -163,7 +166,7 @@
     }
 
     public void addLast(ByteArray ba) {
-        handleAdd(ba);
+        addHook(ba);
         bas.addLast(ba);
     }
 
@@ -280,6 +283,13 @@
     public Cursor cursor(int index, CursorListener listener) {
         return new CursorImpl(index, listener);
     }
+    
+    /**
+     * @inheritDoc
+     */
+    public ByteArray slice(int index, int length) {
+        return cursor(index).slice(length);
+    }
 
     /**
      * @inheritDoc
@@ -312,20 +322,6 @@
     /**
      * @inheritDoc
      */
-    public int getInt(int index) {
-        return cursor(index).getInt();
-    }
-
-    /**
-     * @inheritDoc
-     */
-    public void putInt(int index, int i) {
-        cursor(index).putInt(i);
-    }
-
-    /**
-     * @inheritDoc
-     */
     public int first() {
         return bas.firstByte();
     }
@@ -338,13 +334,13 @@
     }
 
     /**
-     * @inheritDoc
+     * This method should be called prior to adding any component
+     * <code>ByteArray</code> to a composite.
+     *
+     * @param ba
+     *            The component to add.
      */
-    public int length() {
-        return last() - first();
-    }
-
-    private void handleAdd(ByteArray ba) {
+    private void addHook(ByteArray ba) {
         // Check first() is zero, otherwise cursor might not work.
         // TODO: Remove this restriction?
         if (ba.first() != 0) {
@@ -387,6 +383,90 @@
         }
     }
 
+    /**
+     * @inheritDoc
+     */
+    public short getShort(int index) {
+        return cursor(index).getShort();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putShort(int index, short s) {
+        cursor(index).putShort(s);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public int getInt(int index) {
+        return cursor(index).getInt();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putInt(int index, int i) {
+        cursor(index).putInt(i);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public long getLong(int index) {
+        return cursor(index).getLong();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putLong(int index, long l) {
+        cursor(index).putLong(l);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public float getFloat(int index) {
+        return cursor(index).getFloat();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putFloat(int index, float f) {
+        cursor(index).putFloat(f);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public double getDouble(int index) {
+        return cursor(index).getDouble();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putDouble(int index, double d) {
+        cursor(index).putDouble(d);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public char getChar(int index) {
+        return cursor(index).getChar();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putChar(int index, char c) {
+        cursor(index).putChar(c);
+    }
+
     private class CursorImpl implements Cursor {
 
         private int index;
@@ -432,6 +512,30 @@
             checkBounds(index, 0);
             this.index = index;
         }
+        
+        /**
+         * @inheritDoc
+         */
+        public void skip(int length) {
+            setIndex(index + length);
+        }
+        
+        /**
+         * @inheritDoc
+         */
+        public ByteArray slice(int length) {
+            CompositeByteArray slice = new CompositeByteArray(byteArrayFactory);
+            int remaining = length;
+            while (remaining > 0) {
+                prepareForAccess(remaining);
+                int componentSliceSize = Math.min(remaining, componentCursor.getRemaining());
+                ByteArray componentSlice = componentCursor.slice(componentSliceSize);
+                slice.addLast(componentSlice);
+                index += componentSliceSize;
+                remaining -= componentSliceSize;
+            }
+            return slice;
+        }
 
         /**
          * @inheritDoc
@@ -490,7 +594,7 @@
 
             // Go forward, if necessary.
             while (index >= componentIndex + componentNode.getByteArray()
-                    .last()) {
+                    .length()) {
                 componentIndex += componentNode.getByteArray().last();
                 componentNode = componentNode.getNextNode();
                 if (listener != null) {
@@ -573,6 +677,49 @@
         /**
          * @inheritDoc
          */
+        public short getShort() {
+            prepareForAccess(2);
+            if (componentCursor.getRemaining() >= 4) {
+                short s = componentCursor.getShort();
+                index += 2;
+                return s;
+            } else {
+                byte b0 = get();
+                byte b1 = get();
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    return (short) ((b0 << 8) | (b1 << 0));
+                } else {
+                    return (short) ((b1 << 8) | (b0 << 0));
+                }
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putShort(short s) {
+            prepareForAccess(2);
+            if (componentCursor.getRemaining() >= 4) {
+                componentCursor.putShort(s);
+                index += 2;
+            } else {
+                byte b0;
+                byte b1;
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    b0 = (byte) ((s >> 8) & 0xff);
+                    b1 = (byte) ((s >> 0) & 0xff);
+                } else {
+                    b0 = (byte) ((s >> 0) & 0xff);
+                    b1 = (byte) ((s >> 8) & 0xff);
+                }
+                put(b0);
+                put(b1);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
         public int getInt() {
             prepareForAccess(4);
             if (componentCursor.getRemaining() >= 4) {
@@ -580,14 +727,14 @@
                 index += 4;
                 return i;
             } else {
+                byte b0 = get();
                 byte b1 = get();
                 byte b2 = get();
                 byte b3 = get();
-                byte b4 = get();
                 if (order.equals(ByteOrder.BIG_ENDIAN)) {
-                    return b1 << 24 & b2 << 16 & b3 << 8 & b4;
+                    return ((b0 << 24) | (b1 << 16) | (b2 << 8) | (b3 << 0));
                 } else {
-                    return b4 << 24 & b3 << 16 & b2 << 8 & b1;
+                    return ((b3 << 24) | (b2 << 16) | (b1 << 8) | (b0 << 0));
                 }
             }
         }
@@ -601,32 +748,201 @@
                 componentCursor.putInt(i);
                 index += 4;
             } else {
+                byte b0;
+                byte b1;
+                byte b2;
+                byte b3;
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    b0 = (byte) ((i >> 24) & 0xff);
+                    b1 = (byte) ((i >> 16) & 0xff);
+                    b2 = (byte) ((i >> 8) & 0xff);
+                    b3 = (byte) ((i >> 0) & 0xff);
+                } else {
+                    b0 = (byte) ((i >> 0) & 0xff);
+                    b1 = (byte) ((i >> 8) & 0xff);
+                    b2 = (byte) ((i >> 16) & 0xff);
+                    b3 = (byte) ((i >> 24) & 0xff);
+                }
+                put(b0);
+                put(b1);
+                put(b2);
+                put(b3);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public long getLong() {
+            prepareForAccess(8);
+            if (componentCursor.getRemaining() >= 4) {
+                long l = componentCursor.getLong();
+                index += 8;
+                return l;
+            } else {
+                byte b0 = get();
+                byte b1 = get();
+                byte b2 = get();
+                byte b3 = get();
+                byte b4 = get();
+                byte b5 = get();
+                byte b6 = get();
+                byte b7 = get();
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    return ((b0 & 0xffL) << 56) | ((b1 & 0xffL) << 48) | ((b2 & 0xffL) << 40) | ((b3 & 0xffL) << 32) | ((b4 & 0xffL) << 24) | ((b5 & 0xffL) << 16) | ((b6 & 0xffL) << 8) | ((b7 & 0xffL) << 0);
+                } else {
+                    return ((b7 & 0xffL) << 56) | ((b6 & 0xffL) << 48) | ((b5 & 0xffL) << 40) | ((b4 & 0xffL) << 32) | ((b3 & 0xffL) << 24) | ((b2 & 0xffL) << 16) | ((b1 & 0xffL) << 8) | ((b0 & 0xffL) << 0);
+                }
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putLong(long l) {
+            prepareForAccess(8);
+            if (componentCursor.getRemaining() >= 4) {
+                componentCursor.putLong(l);
+                index += 8;
+            } else {
+                byte b0;
                 byte b1;
                 byte b2;
                 byte b3;
                 byte b4;
+                byte b5;
+                byte b6;
+                byte b7;
                 if (order.equals(ByteOrder.BIG_ENDIAN)) {
-                    b4 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b3 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b2 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b1 = (byte) (i & 0xff);
+                    b0 = (byte) ((l >> 56) & 0xff);
+                    b1 = (byte) ((l >> 48) & 0xff);
+                    b2 = (byte) ((l >> 40) & 0xff);
+                    b3 = (byte) ((l >> 32) & 0xff);
+                    b4 = (byte) ((l >> 24) & 0xff);
+                    b5 = (byte) ((l >> 16) & 0xff);
+                    b6 = (byte) ((l >> 8) & 0xff);
+                    b7 = (byte) ((l >> 0) & 0xff);
                 } else {
-                    b1 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b2 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b3 = (byte) (i & 0xff);
-                    i >>= 8;
-                    b4 = (byte) (i & 0xff);
+                    b0 = (byte) ((l >> 0) & 0xff);
+                    b1 = (byte) ((l >> 8) & 0xff);
+                    b2 = (byte) ((l >> 16) & 0xff);
+                    b3 = (byte) ((l >> 24) & 0xff);
+                    b4 = (byte) ((l >> 32) & 0xff);
+                    b5 = (byte) ((l >> 40) & 0xff);
+                    b6 = (byte) ((l >> 48) & 0xff);
+                    b7 = (byte) ((l >> 56) & 0xff);
                 }
+                put(b0);
                 put(b1);
                 put(b2);
                 put(b3);
                 put(b4);
+                put(b5);
+                put(b6);
+                put(b7);
             }
         }
+
+        /**
+         * @inheritDoc
+         */
+        public float getFloat() {
+            prepareForAccess(4);
+            if (componentCursor.getRemaining() >= 4) {
+                float f = componentCursor.getFloat();
+                index += 4;
+                return f;
+            } else {
+                int i = getInt();
+                return Float.intBitsToFloat(i);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putFloat(float f) {
+            prepareForAccess(4);
+            if (componentCursor.getRemaining() >= 4) {
+                componentCursor.putFloat(f);
+                index += 4;
+            } else {
+                int i = Float.floatToIntBits(f);
+                putInt(i);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public double getDouble() {
+            prepareForAccess(8);
+            if (componentCursor.getRemaining() >= 4) {
+                double d = componentCursor.getDouble();
+                index += 8;
+                return d;
+            } else {
+                long l = getLong();
+                return Double.longBitsToDouble(l);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putDouble(double d) {
+            prepareForAccess(8);
+            if (componentCursor.getRemaining() >= 4) {
+                componentCursor.putDouble(d);
+                index += 8;
+            } else {
+                long l = Double.doubleToLongBits(d);
+                putLong(l);
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public char getChar() {
+            prepareForAccess(2);
+            if (componentCursor.getRemaining() >= 4) {
+                char c = componentCursor.getChar();
+                index += 2;
+                return c;
+            } else {
+                byte b0 = get();
+                byte b1 = get();
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    return (char) ((b0 << 8) | (b1 << 0));
+                } else {
+                    return (char) ((b1 << 8) | (b0 << 0));
+                }
+            }
+        }
+
+        /**
+         * @inheritDoc
+         */
+        public void putChar(char c) {
+            prepareForAccess(2);
+            if (componentCursor.getRemaining() >= 4) {
+                componentCursor.putChar(c);
+                index += 2;
+            } else {
+                byte b0;
+                byte b1;
+                if (order.equals(ByteOrder.BIG_ENDIAN)) {
+                    b0 = (byte) ((c >> 8) & 0xff);
+                    b1 = (byte) ((c >> 0) & 0xff);
+                } else {
+                    b0 = (byte) ((c >> 0) & 0xff);
+                    b1 = (byte) ((c >> 8) & 0xff);
+                }
+                put(b0);
+                put(b1);
+            }
+        }
+
     }
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeBase.java Wed May 21 18:09:24 2008
@@ -70,14 +70,23 @@
         });
     }
 
+    /**
+     * @inheritDoc
+     */
     public final int getRemaining() {
         return cursor.getRemaining();
     }
 
+    /**
+     * @inheritDoc
+     */
     public final boolean hasRemaining() {
         return cursor.hasRemaining();
     }
 
+    /**
+     * @inheritDoc
+     */
     public ByteOrder order() {
         return cba.order();
     }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeReader.java Wed May 21 18:09:24 2008
@@ -50,6 +50,20 @@
             cba.removeFirst().free();
         }
     }
+    
+    /**
+     * @inheritDoc
+     */
+    public void skip(int length) {
+        cursor.skip(length);
+    }
+    
+    /**
+     * @inheritDoc
+     */
+    public ByteArray slice(int length) {
+        return cursor.slice(length);
+    }
 
     public byte get() {
         return cursor.get();
@@ -58,9 +72,46 @@
     public void get(ByteBuffer bb) {
         cursor.get(bb);
     }
+    /**
+     * @inheritDoc
+     */
+    public short getShort() {
+        return cursor.getShort();
+    }
 
+    /**
+     * @inheritDoc
+     */
     public int getInt() {
         return cursor.getInt();
     }
 
+    /**
+     * @inheritDoc
+     */
+    public long getLong() {
+        return cursor.getLong();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public float getFloat() {
+        return cursor.getFloat();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public double getDouble() {
+        return cursor.getDouble();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public char getChar() {
+        return cursor.getChar();
+    }
+
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/CompositeByteArrayRelativeWriter.java Wed May 21 18:09:24 2008
@@ -126,11 +126,18 @@
         ByteArray removed = cba.removeTo(index);
         flusher.flush(removed);
     }
+    
+    /**
+     * @inheritDoc
+     */
+    public void skip(int length) {
+        cursor.skip(length);
+    }
 
     @Override
     protected void cursorPassedFirstComponent() {
         if (autoFlush) {
-            flushTo(cba.first() + cba.getFirst().last());
+            flushTo(cba.first() + cba.getFirst().length());
         }
     }
 
@@ -153,9 +160,48 @@
     /**
      * @inheritDoc
      */
+    public void putShort(short s) {
+        prepareForAccess(2);
+        cursor.putShort(s);
+    }
+
+    /**
+     * @inheritDoc
+     */
     public void putInt(int i) {
         prepareForAccess(4);
         cursor.putInt(i);
     }
 
+    /**
+     * @inheritDoc
+     */
+    public void putLong(long l) {
+        prepareForAccess(8);
+        cursor.putLong(l);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putFloat(float f) {
+        prepareForAccess(4);
+        cursor.putFloat(f);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putDouble(double d) {
+        prepareForAccess(8);
+        cursor.putDouble(d);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public void putChar(char c) {
+        prepareForAccess(2);
+        cursor.putChar(c);
+    }
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteReader.java Wed May 21 18:09:24 2008
@@ -43,10 +43,15 @@
     int length();
 
     /**
+     * Creates an array with a view of part of this array.
+     */
+    ByteArray slice(int index, int length);
+
+    /**
      * Gets the order of the bytes.
      */
     ByteOrder order();
-
+    
     /**
      * Gets a <code>byte</code> from the given index.
      */
@@ -58,7 +63,32 @@
     public void get(int index, ByteBuffer bb);
 
     /**
+     * Gets a <code>short</code> from the given index.
+     */
+    short getShort(int index);
+
+    /**
      * Gets an <code>int</code> from the given index.
      */
     int getInt(int index);
+
+    /**
+     * Gets a <code>long</code> from the given index.
+     */
+    long getLong(int index);
+
+    /**
+     * Gets a <code>float</code> from the given index.
+     */
+    float getFloat(int index);
+
+    /**
+     * Gets a <code>double</code> from the given index.
+     */
+    double getDouble(int index);
+
+    /**
+     * Gets a <code>char</code> from the given index.
+     */
+    char getChar(int index);
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoAbsoluteWriter.java Wed May 21 18:09:24 2008
@@ -53,7 +53,32 @@
     public void put(int index, ByteBuffer 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);
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeReader.java Wed May 21 18:09:24 2008
@@ -36,6 +36,16 @@
      * 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.
@@ -53,8 +63,32 @@
     void get(ByteBuffer 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();
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/IoRelativeWriter.java Wed May 21 18:09:24 2008
@@ -36,6 +36,11 @@
      * 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.
@@ -53,7 +58,32 @@
     void put(ByteBuffer 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);
 }

Modified: mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java (original)
+++ mina/branches/buffer/core/src/main/java/org/apache/mina/util/byteaccess/SimpleByteArrayFactory.java Wed May 21 18:09:24 2008
@@ -28,6 +28,10 @@
  */
 public class SimpleByteArrayFactory implements ByteArrayFactory {
 
+    public SimpleByteArrayFactory() {
+        super();
+    }
+
     /**
      * @inheritDoc
      */

Modified: mina/branches/buffer/core/src/test/java/org/apache/mina/common/ByteAccessTest.java
URL: http://svn.apache.org/viewvc/mina/branches/buffer/core/src/test/java/org/apache/mina/common/ByteAccessTest.java?rev=658963&r1=658962&r2=658963&view=diff
==============================================================================
--- mina/branches/buffer/core/src/test/java/org/apache/mina/common/ByteAccessTest.java (original)
+++ mina/branches/buffer/core/src/test/java/org/apache/mina/common/ByteAccessTest.java Wed May 21 18:09:24 2008
@@ -1,8 +1,28 @@
+/*
+ *  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.common;
 
-import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.createStrictControl;
 
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -29,7 +49,7 @@
  */
 public class ByteAccessTest extends TestCase {
 
-    private final List<String> operations = new ArrayList<String>();
+    private List<String> operations = new ArrayList<String>();
 
     private void resetOperations() {
         operations.clear();
@@ -308,6 +328,44 @@
             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) {
@@ -370,4 +428,84 @@
         }
     }
 
+    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 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());
+    }
+
 }