directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From akaras...@apache.org
Subject svn commit: rev 9745 - in incubator/directory/snickers/branches/buffer-branch/ber/src: java/org/apache/snickers/ber test/org/apache/snickers/ber
Date Thu, 25 Mar 2004 23:02:33 GMT
Author: akarasulu
Date: Thu Mar 25 15:02:31 2004
New Revision: 9745

Added:
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractBufferedDecoderTestCase.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractChunkingBERDecoderTestCase.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERBufferedDecoder.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingBERDecoder.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingTuple.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERBufferedDecoderTest.java
Modified:
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallbackAdapter.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/Tuple.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERDecoderTest.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTest.java
   incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTreeDecoderTest.java
Log:
Lots of little experiments here but we're starting to see the light with 
chunking in the picture.


Added: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractBufferedDecoderTestCase.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractBufferedDecoderTestCase.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,411 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.util.Stack ;
+import java.nio.ByteBuffer ;
+import java.util.ArrayList ;
+
+import org.apache.commons.codec.binary.Binary ;
+import org.apache.commons.codec.DecoderException ;
+import org.apache.commons.codec.stateful.DecoderMonitor ;
+import org.apache.commons.codec.stateful.DecoderCallback ;
+import org.apache.commons.codec.stateful.StatefulDecoder ;
+
+import org.apache.commons.lang.exception.ExceptionUtils ;
+
+import org.apache.ldap.common.message.Message ;
+import org.apache.ldap.common.message.MessageEncoder ;
+
+import junit.framework.TestCase ;
+
+
+/**
+ * Tests the BER decoder.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev: 9743 $
+ */
+public abstract class AbstractBufferedDecoderTestCase extends TestCase 
+    implements BERDecoderCallback, DecoderMonitor
+{
+    /** list of encountered TLV's as we recieve completed decode callbacks */
+    protected ArrayList tlvList = new ArrayList() ;
+    /** the decoder that is constructed every time */
+    protected BERBufferedDecoder decoder = null ;
+    
+
+    /*
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception
+    {
+        super.setUp() ;
+        decoder = new BERBufferedDecoder( 1024 ) ;
+        decoder.setCallback( this ) ;
+        decoder.setDecoderMonitor( this ) ;
+    }
+
+    
+    /*
+     * @see TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception
+    {
+        super.tearDown() ;
+        tlvList.clear() ;
+        decoder = null ;
+    }
+
+    
+    /**
+     * Constructor for BERDecoderTest.
+     * @param arg0
+     */
+    public AbstractBufferedDecoderTestCase( String arg0 )
+    {
+        super( arg0 ) ;
+    }
+    
+    
+    /**
+     * Fragments an array of bytes into multiple arrays 'attempting' to keep 
+     * them the same size however the last fragment will be an array 
+     * bites.length%size which may or may not be of the requested fragment size.
+     * However it will never be greater.  Use this method to break appart TLV 
+     * byte arrays to feed them into the decoder for testing.
+     * 
+     * @param bites the bites to fragment
+     * @param size the maximum size of a fragment
+     * @return the array of byte[] fragments
+     */
+    public byte[][] fragment( byte[] bites, int size )
+    {
+        byte[][] fragments = null ;
+        
+        if ( size <= 0 )
+        {    
+            throw new IllegalArgumentException( 
+                    "fragment size should be 1 or more but was " + size ) ;
+        }
+        
+        int wholeFrags = bites.length/size ;
+        int partialFragSize = bites.length % size ; 
+
+        /*
+         * Allocate what we need depending on the size of our remainder
+         */
+        if ( partialFragSize == 0 ) 
+        {
+            fragments = new byte[wholeFrags][] ;
+        }
+        else
+        {
+            fragments = new byte[wholeFrags+1][] ;
+            fragments[wholeFrags] = new byte[partialFragSize] ;
+        }
+        
+        for ( int ii = 0; ii < wholeFrags; ii++ )
+        {
+            fragments[ii] = new byte[size] ;
+            System.arraycopy( bites, ii * size, fragments[ii], 0, size ) ;
+        }
+        
+        if ( partialFragSize != 0 )
+        {
+            int srcPos = wholeFrags * size ;
+            byte[] src = fragments[wholeFrags] ;
+            System.arraycopy( bites, srcPos, src, 0, partialFragSize ) ;
+        }
+        
+        return fragments ;
+    }
+    
+    
+    /**
+     * BER decodes a string of 0's and 1's.
+     * 
+     * @param bitString a string of ascii 0's and 1's
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( String bitString ) throws DecoderException
+    {
+        byte [] bites = Binary.fromAscii( bitString.getBytes() ) ;
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * BER decodes a single byte.
+     * 
+     * @param bite a single byte to decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( byte bite ) throws DecoderException
+    {
+        byte [] bites = { bite } ;
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * BER decodes a byte array.
+     * 
+     * @param bites a byte array to decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( byte[] bites ) throws DecoderException
+    {
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * First BER encodes then BER decodes a Tuple.
+     * 
+     * @param tlv a tuple to encode then decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding
+     */
+    public Tuple decode( Tuple tlv ) throws DecoderException
+    {
+        ByteBuffer buf = ByteBuffer.wrap( tlv.toEncodedArray() ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            Stack stack = decoder.getTupleStack() ;
+            
+            if ( stack.isEmpty() )
+            {    
+                return decoder.getCurrentTuple() ;
+            }
+            else
+            {
+                return ( Tuple ) stack.peek() ;
+            }
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * First BER encodes then BER decodes a train of Tuples.
+     * 
+     * @param tlvs a tuple array to encode then decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding
+     */
+    public Tuple decode( Tuple[] tlvs ) throws DecoderException
+    {
+        int lastSize = tlvList.size() ;
+
+        for ( int ii = 0; ii < tlvs.length; ii++ )
+        {
+            decode( tlvs[ii] ) ;
+        }
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+    
+    
+    /**
+     * Encodes a message using the message framework and the default BERLib
+     * provider which is snacc for now.  Later we shall remove this dependency.
+     * It then decodes encoded output generated.
+     * 
+     * @param msg the BER encoded message
+     * @return the last tuple generated by decoding the encoded message
+     * @throws DecoderException if there are any failures
+     */
+    public Tuple decode( Message msg ) throws DecoderException
+    {
+        MessageEncoder encoder = new MessageEncoder() ;
+        decode( encoder.encode( msg ) ) ;
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+    
+    
+    /**
+     * Convenience method used to encode a msg using the Snacc libraries for
+     * the time being.
+     * 
+     * @param msg the message to encode
+     * @return a byte buffer with the encoded message
+     */
+    public ByteBuffer encode( Message msg )
+    {
+        MessageEncoder encoder = new MessageEncoder() ;
+        return ByteBuffer.wrap( encoder.encode( msg ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#tagDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void tagDecoded( Tuple tlv )
+    {
+        assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
+        assertEquals( BERDecoderState.TAG, decoder.getState() ) ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#lengthDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void lengthDecoded( Tuple tlv )
+    {
+        assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
+        assertEquals( BERDecoderState.LENGTH, decoder.getState() ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#partialValueDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void partialValueDecoded( Tuple tlv )
+    {
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object)
+     */
+    public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+    {
+        Tuple t = ( Tuple ) decoded ;
+        tlvList.add( t.clone() ) ;
+        assertEquals( BERDecoderState.VALUE, this.decoder.getState() ) ;
+    }
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#callbackOccured(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderCallback, java.lang.Object)
+     */
+    public void callbackOccured( StatefulDecoder decoder, DecoderCallback cb,
+								 Object decoded )
+    {
+        assertEquals( this, cb ) ;
+        assertEquals( this.decoder, decoder ) ;
+        Tuple t = ( Tuple ) decoded ;
+        assertNotNull( t ) ;
+        if ( t.isPrimitive )
+        {    
+            assertTrue( this.decoder.getCurrentTuple().equals( decoded ) ) ;
+        }
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#callbackSet(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderCallback, 
+     * org.apache.commons.codec.stateful.DecoderCallback)
+     */
+    public void callbackSet( StatefulDecoder decoder, DecoderCallback oldcb,
+							 DecoderCallback newcb )
+    {
+        assertEquals( this, newcb ) ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#error(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void error( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#fatalError(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void fatalError( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#monitorSet(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderMonitor)
+     */
+    public void monitorSet( StatefulDecoder decoder, DecoderMonitor oldmon )
+    {
+        assertEquals( this, oldmon ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#warning(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void warning( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+}

Added: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractChunkingBERDecoderTestCase.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractChunkingBERDecoderTestCase.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,411 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.util.Stack ;
+import java.nio.ByteBuffer ;
+import java.util.ArrayList ;
+
+import org.apache.commons.codec.binary.Binary ;
+import org.apache.commons.codec.DecoderException ;
+import org.apache.commons.codec.stateful.DecoderMonitor ;
+import org.apache.commons.codec.stateful.DecoderCallback ;
+import org.apache.commons.codec.stateful.StatefulDecoder ;
+
+import org.apache.commons.lang.exception.ExceptionUtils ;
+
+import org.apache.ldap.common.message.Message ;
+import org.apache.ldap.common.message.MessageEncoder ;
+
+import junit.framework.TestCase ;
+
+
+/**
+ * Tests the BER decoder.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev: 9743 $
+ */
+public abstract class AbstractChunkingBERDecoderTestCase extends TestCase 
+    implements BERDecoderCallback, DecoderMonitor
+{
+    /** list of encountered TLV's as we recieve completed decode callbacks */
+    protected ArrayList tlvList = new ArrayList() ;
+    /** the decoder that is constructed every time */
+    protected ChunkingBERDecoder decoder = null ;
+    
+
+    /*
+     * @see TestCase#setUp()
+     */
+    protected void setUp() throws Exception
+    {
+        super.setUp() ;
+        decoder = new ChunkingBERDecoder( 1024 ) ;
+        decoder.setCallback( this ) ;
+        decoder.setDecoderMonitor( this ) ;
+    }
+
+    
+    /*
+     * @see TestCase#tearDown()
+     */
+    protected void tearDown() throws Exception
+    {
+        super.tearDown() ;
+        tlvList.clear() ;
+        decoder = null ;
+    }
+
+    
+    /**
+     * Constructor for BERDecoderTest.
+     * @param arg0
+     */
+    public AbstractChunkingBERDecoderTestCase( String arg0 )
+    {
+        super( arg0 ) ;
+    }
+    
+    
+    /**
+     * Fragments an array of bytes into multiple arrays 'attempting' to keep 
+     * them the same size however the last fragment will be an array 
+     * bites.length%size which may or may not be of the requested fragment size.
+     * However it will never be greater.  Use this method to break appart TLV 
+     * byte arrays to feed them into the decoder for testing.
+     * 
+     * @param bites the bites to fragment
+     * @param size the maximum size of a fragment
+     * @return the array of byte[] fragments
+     */
+    public byte[][] fragment( byte[] bites, int size )
+    {
+        byte[][] fragments = null ;
+        
+        if ( size <= 0 )
+        {    
+            throw new IllegalArgumentException( 
+                    "fragment size should be 1 or more but was " + size ) ;
+        }
+        
+        int wholeFrags = bites.length/size ;
+        int partialFragSize = bites.length % size ; 
+
+        /*
+         * Allocate what we need depending on the size of our remainder
+         */
+        if ( partialFragSize == 0 ) 
+        {
+            fragments = new byte[wholeFrags][] ;
+        }
+        else
+        {
+            fragments = new byte[wholeFrags+1][] ;
+            fragments[wholeFrags] = new byte[partialFragSize] ;
+        }
+        
+        for ( int ii = 0; ii < wholeFrags; ii++ )
+        {
+            fragments[ii] = new byte[size] ;
+            System.arraycopy( bites, ii * size, fragments[ii], 0, size ) ;
+        }
+        
+        if ( partialFragSize != 0 )
+        {
+            int srcPos = wholeFrags * size ;
+            byte[] src = fragments[wholeFrags] ;
+            System.arraycopy( bites, srcPos, src, 0, partialFragSize ) ;
+        }
+        
+        return fragments ;
+    }
+    
+    
+    /**
+     * BER decodes a string of 0's and 1's.
+     * 
+     * @param bitString a string of ascii 0's and 1's
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( String bitString ) throws DecoderException
+    {
+        byte [] bites = Binary.fromAscii( bitString.getBytes() ) ;
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * BER decodes a single byte.
+     * 
+     * @param bite a single byte to decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( byte bite ) throws DecoderException
+    {
+        byte [] bites = { bite } ;
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * BER decodes a byte array.
+     * 
+     * @param bites a byte array to decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding.
+     */
+    public Tuple decode( byte[] bites ) throws DecoderException
+    {
+        ByteBuffer buf = ByteBuffer.wrap( bites ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * First BER encodes then BER decodes a Tuple.
+     * 
+     * @param tlv a tuple to encode then decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding
+     */
+    public Tuple decode( Tuple tlv ) throws DecoderException
+    {
+        ByteBuffer buf = ByteBuffer.wrap( tlv.toEncodedArray() ) ;
+        int lastSize = tlvList.size() ;
+        decoder.decode( buf ) ;
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            Stack stack = decoder.getTupleStack() ;
+            
+            if ( stack.isEmpty() )
+            {    
+                return decoder.getCurrentTuple() ;
+            }
+            else
+            {
+                return ( Tuple ) stack.peek() ;
+            }
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+
+    
+    /**
+     * First BER encodes then BER decodes a train of Tuples.
+     * 
+     * @param tlvs a tuple array to encode then decode
+     * @return a copy of the decoded tuple or the partially decoded current tlv
+     * @throws DecoderException if there are errors while decoding
+     */
+    public Tuple decode( Tuple[] tlvs ) throws DecoderException
+    {
+        int lastSize = tlvList.size() ;
+
+        for ( int ii = 0; ii < tlvs.length; ii++ )
+        {
+            decode( tlvs[ii] ) ;
+        }
+        
+        if ( tlvList.isEmpty() || tlvList.size() == lastSize )
+        {
+            return decoder.getCurrentTuple() ;
+        }
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+    
+    
+    /**
+     * Encodes a message using the message framework and the default BERLib
+     * provider which is snacc for now.  Later we shall remove this dependency.
+     * It then decodes encoded output generated.
+     * 
+     * @param msg the BER encoded message
+     * @return the last tuple generated by decoding the encoded message
+     * @throws DecoderException if there are any failures
+     */
+    public Tuple decode( Message msg ) throws DecoderException
+    {
+        MessageEncoder encoder = new MessageEncoder() ;
+        decode( encoder.encode( msg ) ) ;
+        
+        return ( Tuple ) tlvList.get( tlvList.size() - 1 ) ;
+    }
+    
+    
+    /**
+     * Convenience method used to encode a msg using the Snacc libraries for
+     * the time being.
+     * 
+     * @param msg the message to encode
+     * @return a byte buffer with the encoded message
+     */
+    public ByteBuffer encode( Message msg )
+    {
+        MessageEncoder encoder = new MessageEncoder() ;
+        return ByteBuffer.wrap( encoder.encode( msg ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#tagDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void tagDecoded( Tuple tlv )
+    {
+        assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
+        assertEquals( BERDecoderState.TAG, decoder.getState() ) ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#lengthDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void lengthDecoded( Tuple tlv )
+    {
+        assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
+        assertEquals( BERDecoderState.LENGTH, decoder.getState() ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#partialValueDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void partialValueDecoded( Tuple tlv )
+    {
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object)
+     */
+    public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+    {
+        Tuple t = ( Tuple ) decoded ;
+        tlvList.add( t.clone() ) ;
+        assertEquals( BERDecoderState.VALUE, this.decoder.getState() ) ;
+    }
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#callbackOccured(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderCallback, java.lang.Object)
+     */
+    public void callbackOccured( StatefulDecoder decoder, DecoderCallback cb,
+								 Object decoded )
+    {
+        assertEquals( this, cb ) ;
+        assertEquals( this.decoder, decoder ) ;
+        Tuple t = ( Tuple ) decoded ;
+        assertNotNull( t ) ;
+        if ( t.isPrimitive )
+        {    
+            assertTrue( this.decoder.getCurrentTuple().equals( decoded ) ) ;
+        }
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#callbackSet(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderCallback, 
+     * org.apache.commons.codec.stateful.DecoderCallback)
+     */
+    public void callbackSet( StatefulDecoder decoder, DecoderCallback oldcb,
+							 DecoderCallback newcb )
+    {
+        assertEquals( this, newcb ) ;
+    }
+
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#error(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void error( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#fatalError(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void fatalError( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#monitorSet(
+     * org.apache.commons.codec.stateful.StatefulDecoder, 
+     * org.apache.commons.codec.stateful.DecoderMonitor)
+     */
+    public void monitorSet( StatefulDecoder decoder, DecoderMonitor oldmon )
+    {
+        assertEquals( this, oldmon ) ;
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderMonitor#warning(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Exception)
+     */
+    public void warning( StatefulDecoder decoder, Exception exception )
+    {
+        fail( ExceptionUtils.getFullStackTrace( exception ) ) ;
+    }
+}

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/AbstractDecoderTestCase.java	Thu Mar 25 15:02:31 2004
@@ -215,7 +215,7 @@
      */
     public Tuple decode( Tuple tlv ) throws DecoderException
     {
-        ByteBuffer buf = ByteBuffer.wrap( tlv.encode() ) ;
+        ByteBuffer buf = ByteBuffer.wrap( tlv.toEncodedArray() ) ;
         int lastSize = tlvList.size() ;
         decoder.decode( buf ) ;
         
@@ -302,6 +302,15 @@
     {
         assertTrue( decoder.getCurrentTuple().equals( tlv ) ) ;
         assertEquals( BERDecoderState.TAG, decoder.getState() ) ;
+    }
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#partialValueDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void partialValueDecoded( Tuple tlv )
+    {
     }
 
 

Added: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERBufferedDecoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERBufferedDecoder.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,531 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.util.Stack ;
+
+import java.nio.ByteBuffer ;
+
+import org.apache.commons.lang.ArrayUtils ;
+
+import org.apache.commons.codec.DecoderException ;
+import org.apache.commons.codec.stateful.DecoderMonitor ;
+import org.apache.commons.codec.stateful.DecoderCallback ;
+import org.apache.commons.codec.stateful.StatefulDecoder ;
+import org.apache.commons.codec.stateful.DecoderMonitorAdapter ;
+
+
+/**
+ * Low level BER encoded bytes to Tag Value Length (TLV) tuple decoder.  
+ * This decoder is a low level event based parser which operates in a fashion 
+ * similar to the way SAX works except the elements of concern are the tag, 
+ * length, and value entities.
+ * <p>
+ * Instance variables and a Stack is used to track the state of the decoder 
+ * between decode calls.  The stack maintains the nesting of TLV tuples.  Rather
+ * than creating new TLV tuple instances every time a single tuple is reused for
+ * primitive types and new tlv tuples are cloned for constructed types.  The 
+ * tuple fed to the callback must therefore be used very carefully - its values
+ * must be copied to prevent their loss.
+ * </p>
+ * <p>
+ * Note that all tuples are not created equal.  Constructed TLVs nesting others
+ * will have null value members.  Only TLV tuples of primitive types or the 
+ * leaf TLV tuples of the TLV tuple tree will only contain non null values.  
+ * Therefore the nature of a TLV tuple should be investigated by callbacks 
+ * before attempting to interpret their values.
+ * </p>
+ * 
+ * @see Tuple for TLV tuple value size limitations
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev: 9743 $
+ */
+public class BERBufferedDecoder implements StatefulDecoder, DecoderCallback
+{
+    private static final ByteBuffer EMPTY_BUFFER = 
+        ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+    private static final BERDecoderCallback DEFAULT_CALLBACK = 
+        new BERDecoderCallbackAdapter() ;
+    private static final DecoderMonitor DEFAULT_MONITOR =
+        new DecoderMonitorAdapter() ;
+    
+    /** this decoder's callback */
+    private BERDecoderCallback cb = DEFAULT_CALLBACK ;
+    /** the monitor used by this decoder */
+    private DecoderMonitor monitor = DEFAULT_MONITOR ;
+    
+    /** the single TLV tuple used by this decoder */
+    private final Tuple tlv = new Tuple() ;
+
+    /** a decoder used to decode tag octets */ 
+    private final TagDecoder tagDecoder = new TagDecoder() ;
+    /** a decoder used to decode length octets */ 
+    private final LengthDecoder lengthDecoder = new LengthDecoder() ;
+    
+    /** a buffer wrapper around the value backing store */
+    private final ByteBuffer valueBuffer ;
+    
+    /** stack of nested/constructed TLV tuples */
+    private final Stack tlvStack = new Stack() ;
+
+    /** the state of this decoder */
+    private BERDecoderState state = BERDecoderState.getStartState() ;
+    
+    
+    /**
+     * Creates a stateful BER decoder which limits the tuple's value size.
+     * 
+     * @param valueMax the maximum tuple value size handled by this decoder
+     */
+    public BERBufferedDecoder( int valueMax )
+    {
+        tagDecoder.setCallback( this ) ;
+        lengthDecoder.setCallback( this ) ;
+        valueBuffer = ByteBuffer.allocate( valueMax ) ;
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // StatefulDecoder Methods
+    // ------------------------------------------------------------------------
+
+    
+    /**
+     * Expects a ByteBuffer containing BER encoded data.
+     * 
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#decode(
+     * java.lang.Object)
+     * @throws ClassCastException if the encoded argument is not a ByteBuffer
+     * @throws IllegalArgumentException if the buffer is null or empty
+     */
+    public void decode( Object encoded ) throws DecoderException
+    {
+        ByteBuffer buf = ( ByteBuffer ) encoded ;
+        
+        /* --------------------------------------------------------------------
+           Handle any unusual input by informing the monitor. 
+           ------------------------------------------------------------------ */
+        
+        if ( buf == null && monitor != null )
+        {
+            String msg = "ignoring null argument to decode()" ;
+            monitor.warning( this, new IllegalArgumentException( msg ) ) ;
+            return ;
+        }
+
+        if ( buf.remaining() == 0 && monitor != null )
+        {
+            String msg = "ignoring empty buffer" ;
+            monitor.warning( this, new IllegalArgumentException( msg ) ) ;
+            return ;
+        }
+        
+        /*
+         * This loop is used instead of costly recursion.  This requires each
+         * of the statewise decode methods to process bytes from the buffer.  If
+         * they can process enough to switch state they do and return 
+         * immediately.  This loop makes sure the next processing state is 
+         * handled if there is more data for that state.
+         */
+        while ( buf.hasRemaining() )
+        {    
+            switch( state.getValue() )
+            {
+                case( BERDecoderState.TAG_VAL ):
+                    tagDecoder.decode( buf ) ;
+                    break ;
+                case( BERDecoderState.LENGTH_VAL ):
+                    lengthDecoder.decode( buf ) ;
+                    break ;
+                case( BERDecoderState.VALUE_VAL ):
+                    decodeValue( buf ) ;
+                    break ;
+            }
+        }
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#setCallback(
+     * org.apache.commons.codec.stateful.DecoderCallback)
+     */
+    public void setCallback( DecoderCallback cb )
+    {
+        this.cb = ( BERDecoderCallback ) cb ;
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#setDecoderMonitor(
+     * org.apache.commons.codec.stateful.DecoderMonitor)
+     */
+    public void setDecoderMonitor( DecoderMonitor monitor )
+    {
+        this.monitor = monitor ;
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // State Based Decode Methods
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Extracts the value portion from the buffer for a primitive type.
+     * 
+     * @param buf the byte byffer containing BER encoded data 
+     */
+    private void decodeValue( ByteBuffer buf ) throws DecoderException
+    {
+        int needToRead = Length.UNDEFINED ;
+        tlv.value = valueBuffer ;
+
+        /*
+         * setup to start decoding the value by figuring how much we need to
+         * read at this point - previous reads of the value may have already
+         * occurred.
+         */
+        if ( tlv.valueIndex == Length.UNDEFINED )
+        {
+            needToRead = tlv.length ;
+        }
+        else
+        {
+            needToRead = tlv.length - tlv.valueIndex ;
+        }
+        
+        /*
+         * check if we have the remainder of the value to complete the 
+         * TLV within the current buffer - if so we read all of it
+         */
+        if ( buf.remaining() >= needToRead )
+        {
+            /*
+             * since the value is contained within this chunk we can return
+             * a slice of the buffer rather than copying the section of the 
+             * buffer. This will only work if the entire value is in this 
+             * buffer.  The only way to determin that is if the tlv.length
+             * value equals the needToRead value.
+             */
+            if ( needToRead == tlv.length )
+            {    
+                tlv.value = buf.slice().limit( needToRead ) ;
+                buf.position( buf.position() + needToRead ) ;
+            }
+            else
+            {
+                int oldLimit = buf.limit() ;
+                buf.limit( needToRead ) ;
+                valueBuffer.put( buf ) ;
+                valueBuffer.flip() ;
+                buf.limit( oldLimit ) ;
+            }
+            
+            tlv.valueIndex = tlv.length ;
+            tlv.index += tlv.length ;
+            
+            fireDecodeOccurred( tlv ) ;
+            updateStack( needToRead ) ;
+            tlv.clear() ;
+            state = BERDecoderState.TAG ;
+        }
+        
+        /*
+         * the buffer does not contain the rest of the value we need in order
+         * to complete the current TLV - the value is fragmented so we read
+         * what we can and update indices by that amount.
+         */
+        else
+        {
+            if ( tlv.valueIndex == Length.UNDEFINED )
+            {
+                tlv.valueIndex = 0 ;
+            }
+            
+            int remaining = buf.remaining() ;
+            valueBuffer.put( buf ) ;
+            tlv.valueIndex += remaining ;
+            tlv.index +=remaining ;
+            updateStack( remaining ) ;
+        }
+    }
+    
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object)
+     */
+    public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+    {
+        if ( decoder == tagDecoder )
+        {
+            Tag tag = ( Tag ) decoded ;
+            tlv.id = tag.getId() ;
+            tlv.isPrimitive = tag.isPrimitive() ;
+            tlv.typeClass = tag.getTypeClass() ;
+            tlv.index = tag.size() ;
+
+            fireTagDecoded() ;
+            updateStack( tag.size() ) ;
+            state = state.getNext( tag.isPrimitive() ) ;
+        }
+        else if ( decoder == lengthDecoder )
+        {
+            Length length = ( Length ) decoded ;
+            tlv.length = length.getLength() ;
+            
+            if ( tlv.length == Length.INDEFINATE )
+            {
+                tlv.index = Length.INDEFINATE ;
+                tlv.valueIndex = Length.INDEFINATE ;
+            }
+            else
+            {    
+                tlv.index += length.size() ;
+            }
+            
+            fireLengthDecoded() ;
+            updateStack( length.size() ) ;
+            
+            if ( ! tlv.isPrimitive )
+            {
+                if ( tlv.isIndefinate() || tlv.length > 0 )
+                {    
+                    tlvStack.push( tlv.clone() ) ;
+                }
+                else
+                {
+                    state = BERDecoderState.VALUE ;
+                    fireDecodeOccurred( tlv ) ;
+                }
+                
+                state = BERDecoderState.TAG ;
+                tlv.clear() ;
+            }
+            else if ( tlv.isIndefinateTerminator() )
+            {
+                return ;
+            }
+            else if ( tlv.length > valueBuffer.capacity() )
+            {
+                throw new IllegalArgumentException( 
+                        "value too large - limit of " + valueBuffer.capacity()
+                        + " bytes for the value surpassed by TLV with length "
+                        + tlv.length ) ;
+            }
+            else if ( tlv.length > 0 )
+            {
+                valueBuffer.clear() ;
+                tlv.value = valueBuffer ;
+                state = BERDecoderState.VALUE ;
+            }
+            else
+            {
+                state = BERDecoderState.VALUE ;
+                fireDecodeOccurred( tlv ) ;
+                state = BERDecoderState.TAG ;
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( "unrecognized decoder" ) ;
+        }
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // private utility methods
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Fires a tag decoded event by making the appropriate calls to the 
+     * callback and the monitor.   If the monitor is a BERDecoderMonitor with
+     * extended reporting, then those methods are invoked.
+     * 
+     * Also as a side-effect this method clears the tag buffer once it has 
+     * finished notifying the monitor and calling the callback. 
+     */
+    private void fireTagDecoded()
+    {
+        if ( cb != null )
+        {
+            cb.tagDecoded( tlv ) ;
+        }
+        
+        if ( monitor != null && monitor instanceof BERDecoderMonitor )
+        {
+            BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ;
+            //berMonitor.tagDecoded( tlv, tagDecoder.getOctets() ) ;
+        }
+    }
+    
+    
+    /**
+     * Fires a length decoded event by making the appropriate calls to the 
+     * callback and the monitor.   If the monitor is a BERDecoderMonitor with
+     * extended reporting, then those methods are invoked.
+     * 
+     * Also as a side-effect this method clears the length buffer once it has 
+     * finished notifying the monitor and calling the callback. 
+     */
+    private void fireLengthDecoded()
+    {
+        if ( cb != null )
+        {
+            cb.lengthDecoded( tlv ) ;
+        }
+        
+        if ( monitor != null && monitor instanceof BERDecoderMonitor )
+        {
+            BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ;
+            //berMonitor.lengthDecoded( tlv, lengthBuffer.toArray() ) ;
+        }
+    }
+    
+    
+    /**
+     * Fires a complete TLV decoded event by making the appropriate calls to 
+     * the callback and the monitor.
+     */
+    private void fireDecodeOccurred( Tuple tlv )
+    {
+        if ( cb != null )
+        {
+            cb.decodeOccurred( this, tlv ) ;
+        }
+        
+        if ( monitor != null )
+        {
+            monitor.callbackOccured( this, cb, tlv ) ;
+        }
+    }
+
+    
+    /**
+     * Increments the indices of constructed TLV's within the TLV Stack.
+     * 
+     * @param increment the amount to increment indices by.
+     */
+    private void updateStack( int increment )
+    {
+        for ( int ii = 0; ii < tlvStack.size(); ii++ )
+        {
+            Tuple t = ( Tuple ) tlvStack.get( ii ) ;
+            
+            if ( t.isIndefinate() )
+            {
+                continue ;
+            }
+                
+            t.index += increment ;
+                
+            if ( t.valueIndex == Length.UNDEFINED )
+            {
+                t.valueIndex = 0 ;
+            }
+                
+            t.valueIndex += increment ;
+        }
+        
+        if ( tlvStack.isEmpty() )
+        {
+            return ;
+        }
+        
+        do
+        {
+            Tuple top = ( Tuple ) tlvStack.peek() ;
+            
+            if ( top.isIndefinate() && tlv.isIndefinateTerminator() )
+            {
+                tlvStack.pop() ;
+                state = BERDecoderState.VALUE ;
+                fireDecodeOccurred( top ) ;
+                state = BERDecoderState.TAG ;
+            }
+            else if ( top.isIndefinate() )
+            {
+                break ;
+            }
+            else if ( top.valueIndex >= top.length )
+            {
+                tlvStack.pop() ;
+                state = BERDecoderState.VALUE ;
+                fireDecodeOccurred( top ) ;
+                state = BERDecoderState.TAG ;
+            }
+            else
+            {
+                break ;
+            }
+            
+        } while( tlvStack.size() > 0 ) ;
+    }
+
+    
+    // ------------------------------------------------------------------------
+    // Methods used for testing
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Gets the current state of this BERDecoder.  Used only for debugging and 
+     * testing.
+     * 
+     * @return the state enum
+     */
+    BERDecoderState getState()
+    {
+        return state ;
+    }
+    
+    
+    /**
+     * Gets a cloned copy of the current tuple.  Used only for debugging and 
+     * testing.
+     * 
+     * @return a clone of the current tlv 
+     */
+    Tuple getCurrentTuple()
+    {
+        return ( Tuple ) tlv.clone() ;
+    }
+    
+    
+    /**
+     * Gets a deep copy of the constructed tuple stack.  Used only for debugging
+     * and testing.
+     * 
+     * @return a deep copy of the tuple stack
+     */
+    Stack getTupleStack()
+    {
+        Stack stack = new Stack() ;
+        
+        for ( int ii = 0; ii < tlvStack.size(); ii++ )
+        {
+            Tuple t = ( Tuple ) tlvStack.get( ii ) ;
+            stack.add( t.clone() ) ;
+        }
+        
+        return stack ;
+    }
+}

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallback.java	Thu Mar 25 15:02:31 2004
@@ -55,4 +55,11 @@
      * @param tlv the TLV tuple
      */
     void lengthDecoded( Tuple tlv ) ;
+    
+    /**
+     * Method used to recieve notification that a part of the value was decoded.
+     * 
+     * @param tlv the TLV tuple 
+     */
+    void partialValueDecoded( Tuple tlv ) ;
 }

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallbackAdapter.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallbackAdapter.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/BERDecoderCallbackAdapter.java	Thu Mar 25 15:02:31 2004
@@ -48,6 +48,15 @@
 
     
     /* (non-Javadoc)
+     * @see org.apache.snickers.ber.BERDecoderCallback#partialValueDecoded(
+     * org.apache.snickers.ber.Tuple)
+     */
+    public void partialValueDecoded(Tuple tlv)
+    {
+    }
+
+    
+    /* (non-Javadoc)
      * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred(
      * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object)
      */

Added: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingBERDecoder.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingBERDecoder.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,510 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.util.Stack ;
+
+import java.nio.ByteBuffer ;
+
+import org.apache.commons.lang.ArrayUtils ;
+
+import org.apache.commons.codec.DecoderException ;
+import org.apache.commons.codec.stateful.DecoderMonitor ;
+import org.apache.commons.codec.stateful.DecoderCallback ;
+import org.apache.commons.codec.stateful.StatefulDecoder ;
+import org.apache.commons.codec.stateful.DecoderMonitorAdapter ;
+
+
+/**
+ * A decoder that decodes BER encoded bytes to Tag Value Length (TLV) tuples.  
+ * This decoder is a low level event based parser which operates in a fashion 
+ * similar to the way SAX works except the elements of concern are the tag, 
+ * length, and value entities.  The decoder is a state machine which processes
+ * input as it is made available.
+ * <p>
+ * A Stack is used to track the state of the decoder between decode calls.  It 
+ * maintains the nesting of TLV tuples.  Rather than creating new TLV tuple 
+ * instances every time a single tuple is reused for primitive types and new 
+ * tlv tuples are cloned for constructed types which are pushed onto the stack.
+ * The tuple fed to the callback must therefore be used very carefully - its 
+ * values must be copied to prevent their loss if they are to be used later 
+ * after the callback invokation has returned.
+ * </p>
+ * <p>
+ * Note that all tuples are not created equal.  Constructed TLVs nesting others
+ * will have null value members or empty buffers.  Only TLV tuples of primitive 
+ * types or the leaf TLV tuples of the TLV tuple tree will contain non null 
+ * values.  Therefore the nature of a TLV tuple should be investigated by 
+ * callbacks before attempting to interpret their values.  Also this decoder
+ * chunks value data returning it in parts rather than in one complete peice
+ * in the end.  The value of the TLV Tuple returned is the part of the value
+ * that was read from the input fed into the decoder.  These 'chuncks' returned
+ * by callback makes it so there are no size limits to the value of a TLV. Again
+ * to reiterate chunking on values is only performed on primitive TLV Tuple 
+ * types. 
+ * </p>
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev: 9743 $
+ */
+public class ChunkingBERDecoder implements StatefulDecoder, DecoderCallback
+{
+    private static final ByteBuffer EMPTY_BUFFER = 
+        ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+    private static final BERDecoderCallback DEFAULT_CALLBACK = 
+        new BERDecoderCallbackAdapter() ;
+    private static final DecoderMonitor DEFAULT_MONITOR =
+        new DecoderMonitorAdapter() ;
+    
+    /** this decoder's callback */
+    private BERDecoderCallback cb = DEFAULT_CALLBACK ;
+    /** the monitor used by this decoder */
+    private DecoderMonitor monitor = DEFAULT_MONITOR ;
+    
+    /** the single TLV tuple used by this decoder */
+    private final Tuple tlv = new Tuple() ;
+
+    /** a decoder used to decode tag octets */ 
+    private final TagDecoder tagDecoder = new TagDecoder() ;
+    /** a decoder used to decode length octets */ 
+    private final LengthDecoder lengthDecoder = new LengthDecoder() ;
+    
+    /** stack of nested/constructed TLV tuples */
+    private final Stack tlvStack = new Stack() ;
+
+    /** the state of this decoder */
+    private BERDecoderState state = BERDecoderState.getStartState() ;
+    
+    
+    /**
+     * Creates a stateful BER decoder which limits the tuple's value size.
+     * 
+     * @param valueMax the maximum tuple value size handled by this decoder
+     */
+    public ChunkingBERDecoder( int valueMax )
+    {
+        tagDecoder.setCallback( this ) ;
+        lengthDecoder.setCallback( this ) ;
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // StatefulDecoder Methods
+    // ------------------------------------------------------------------------
+
+    
+    /**
+     * Expects a ByteBuffer containing BER encoded data.
+     * 
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#decode(
+     * java.lang.Object)
+     * @throws ClassCastException if the encoded argument is not a ByteBuffer
+     * @throws IllegalArgumentException if the buffer is null or empty
+     */
+    public void decode( Object encoded ) throws DecoderException
+    {
+        ByteBuffer buf = ( ByteBuffer ) encoded ;
+        
+        /* --------------------------------------------------------------------
+           Handle any unusual input by informing the monitor. 
+           ------------------------------------------------------------------ */
+        
+        if ( buf == null && monitor != null )
+        {
+            String msg = "ignoring null argument to decode()" ;
+            monitor.warning( this, new IllegalArgumentException( msg ) ) ;
+            return ;
+        }
+
+        if ( buf.remaining() == 0 && monitor != null )
+        {
+            String msg = "ignoring empty buffer" ;
+            monitor.warning( this, new IllegalArgumentException( msg ) ) ;
+            return ;
+        }
+        
+        /*
+         * This loop is used instead of costly recursion.  This requires each
+         * of the statewise decode methods to process bytes from the buffer.  If
+         * they can process enough to switch state they do and return 
+         * immediately.  This loop makes sure the next processing state is 
+         * handled if there is more data for that state.
+         */
+        while ( buf.hasRemaining() )
+        {    
+            switch( state.getValue() )
+            {
+                case( BERDecoderState.TAG_VAL ):
+                    tagDecoder.decode( buf ) ;
+                    break ;
+                case( BERDecoderState.LENGTH_VAL ):
+                    lengthDecoder.decode( buf ) ;
+                    break ;
+                case( BERDecoderState.VALUE_VAL ):
+                    decodeValue( buf ) ;
+                    break ;
+            }
+        }
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#setCallback(
+     * org.apache.commons.codec.stateful.DecoderCallback)
+     */
+    public void setCallback( DecoderCallback cb )
+    {
+        this.cb = ( BERDecoderCallback ) cb ;
+    }
+    
+
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.StatefulDecoder#setDecoderMonitor(
+     * org.apache.commons.codec.stateful.DecoderMonitor)
+     */
+    public void setDecoderMonitor( DecoderMonitor monitor )
+    {
+        this.monitor = monitor ;
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // State Based Decode Methods
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Extracts the value portion from the buffer for a primitive type.
+     * 
+     * @param buf the byte byffer containing BER encoded data 
+     */
+    private void decodeValue( ByteBuffer buf ) throws DecoderException
+    {
+        int needToRead = Length.UNDEFINED ;
+
+        /*
+         * setup to start decoding the value by figuring how much we need to
+         * read at this point - previous reads of the value may have already
+         * occurred.
+         */
+        if ( tlv.valueIndex == Length.UNDEFINED )
+        {
+            needToRead = tlv.length ;
+        }
+        else
+        {
+            needToRead = tlv.length - tlv.valueIndex ;
+        }
+        
+        /*
+         * check if we have the remainder of the value to complete the 
+         * TLV within the current buffer - if so we read all of it
+         */
+        if ( buf.remaining() >= needToRead )
+        {
+            tlv.value = buf.slice().limit( needToRead ) ;
+            buf.position( buf.position() + needToRead ) ;
+            tlv.valueIndex = tlv.length ;
+            tlv.index += tlv.length ;
+            
+            cb.partialValueDecoded( tlv ) ;
+            fireDecodeOccurred( tlv ) ;
+            updateStack( needToRead ) ;
+            tlv.clear() ;
+            state = BERDecoderState.TAG ;
+        }
+        
+        /*
+         * the buffer does not contain the rest of the value we need in order
+         * to complete the current TLV - the value is fragmented so we read
+         * what we can and update indices by that amount.
+         */
+        else
+        {
+            if ( tlv.valueIndex == Length.UNDEFINED )
+            {
+                tlv.valueIndex = 0 ;
+            }
+            
+            int remaining = buf.remaining() ;
+            tlv.value = buf.slice() ;
+            tlv.valueIndex += remaining ;
+            tlv.index +=remaining ;
+            
+            cb.partialValueDecoded( tlv ) ;
+            updateStack( remaining ) ;
+        }
+    }
+    
+    
+    
+    /* (non-Javadoc)
+     * @see org.apache.commons.codec.stateful.DecoderCallback#decodeOccurred(
+     * org.apache.commons.codec.stateful.StatefulDecoder, java.lang.Object)
+     */
+    public void decodeOccurred( StatefulDecoder decoder, Object decoded )
+    {
+        if ( decoder == tagDecoder )
+        {
+            Tag tag = ( Tag ) decoded ;
+            tlv.id = tag.getId() ;
+            tlv.isPrimitive = tag.isPrimitive() ;
+            tlv.typeClass = tag.getTypeClass() ;
+            tlv.index = tag.size() ;
+
+            fireTagDecoded() ;
+            updateStack( tag.size() ) ;
+            state = state.getNext( tag.isPrimitive() ) ;
+        }
+        else if ( decoder == lengthDecoder )
+        {
+            Length length = ( Length ) decoded ;
+            tlv.length = length.getLength() ;
+            
+            if ( tlv.length == Length.INDEFINATE )
+            {
+                tlv.index = Length.INDEFINATE ;
+                tlv.valueIndex = Length.INDEFINATE ;
+            }
+            else
+            {    
+                tlv.index += length.size() ;
+            }
+            
+            fireLengthDecoded() ;
+            updateStack( length.size() ) ;
+            
+            if ( ! tlv.isPrimitive )
+            {
+                if ( tlv.isIndefinate() || tlv.length > 0 )
+                {    
+                    tlvStack.push( tlv.clone() ) ;
+                }
+                else
+                {
+                    state = BERDecoderState.VALUE ;
+                    fireDecodeOccurred( tlv ) ;
+                }
+                
+                state = BERDecoderState.TAG ;
+                tlv.clear() ;
+            }
+            else if ( tlv.isIndefinateTerminator() )
+            {
+                return ;
+            }
+            else if ( tlv.length > 0 )
+            {
+                state = BERDecoderState.VALUE ;
+            }
+            else
+            {
+                state = BERDecoderState.VALUE ;
+                tlv.value = EMPTY_BUFFER ;
+                cb.partialValueDecoded( tlv ) ;
+                fireDecodeOccurred( tlv ) ;
+                state = BERDecoderState.TAG ;
+            }
+        }
+        else
+        {
+            throw new IllegalArgumentException( "unrecognized decoder" ) ;
+        }
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // private utility methods
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Fires a tag decoded event by making the appropriate calls to the 
+     * callback and the monitor.   If the monitor is a BERDecoderMonitor with
+     * extended reporting, then those methods are invoked.
+     * 
+     * Also as a side-effect this method clears the tag buffer once it has 
+     * finished notifying the monitor and calling the callback. 
+     */
+    private void fireTagDecoded()
+    {
+        if ( cb != null )
+        {
+            cb.tagDecoded( tlv ) ;
+        }
+        
+        if ( monitor != null && monitor instanceof BERDecoderMonitor )
+        {
+            BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ;
+            //berMonitor.tagDecoded( tlv, tagDecoder.getOctets() ) ;
+        }
+    }
+    
+    
+    /**
+     * Fires a length decoded event by making the appropriate calls to the 
+     * callback and the monitor.   If the monitor is a BERDecoderMonitor with
+     * extended reporting, then those methods are invoked.
+     * 
+     * Also as a side-effect this method clears the length buffer once it has 
+     * finished notifying the monitor and calling the callback. 
+     */
+    private void fireLengthDecoded()
+    {
+        if ( cb != null )
+        {
+            cb.lengthDecoded( tlv ) ;
+        }
+        
+        if ( monitor != null && monitor instanceof BERDecoderMonitor )
+        {
+            BERDecoderMonitor berMonitor = ( BERDecoderMonitor ) monitor ;
+            //berMonitor.lengthDecoded( tlv, lengthBuffer.toArray() ) ;
+        }
+    }
+    
+    
+    /**
+     * Fires a complete TLV decoded event by making the appropriate calls to 
+     * the callback and the monitor.
+     */
+    private void fireDecodeOccurred( Tuple tlv )
+    {
+        if ( cb != null )
+        {
+            cb.decodeOccurred( this, tlv ) ;
+        }
+        
+        if ( monitor != null )
+        {
+            monitor.callbackOccured( this, cb, tlv ) ;
+        }
+    }
+
+    
+    /**
+     * Increments the indices of constructed TLV's within the TLV Stack.
+     * 
+     * @param increment the amount to increment indices by.
+     */
+    private void updateStack( int increment )
+    {
+        for ( int ii = 0; ii < tlvStack.size(); ii++ )
+        {
+            Tuple t = ( Tuple ) tlvStack.get( ii ) ;
+            
+            if ( t.isIndefinate() )
+            {
+                continue ;
+            }
+                
+            t.index += increment ;
+                
+            if ( t.valueIndex == Length.UNDEFINED )
+            {
+                t.valueIndex = 0 ;
+            }
+                
+            t.valueIndex += increment ;
+        }
+        
+        if ( tlvStack.isEmpty() )
+        {
+            return ;
+        }
+        
+        do
+        {
+            Tuple top = ( Tuple ) tlvStack.peek() ;
+            
+            if ( top.isIndefinate() && tlv.isIndefinateTerminator() )
+            {
+                tlvStack.pop() ;
+                state = BERDecoderState.VALUE ;
+                fireDecodeOccurred( top ) ;
+                state = BERDecoderState.TAG ;
+            }
+            else if ( top.isIndefinate() )
+            {
+                break ;
+            }
+            else if ( top.valueIndex >= top.length )
+            {
+                tlvStack.pop() ;
+                state = BERDecoderState.VALUE ;
+                fireDecodeOccurred( top ) ;
+                state = BERDecoderState.TAG ;
+            }
+            else
+            {
+                break ;
+            }
+            
+        } while( tlvStack.size() > 0 ) ;
+    }
+
+    
+    // ------------------------------------------------------------------------
+    // Methods used for testing
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Gets the current state of this BERDecoder.  Used only for debugging and 
+     * testing.
+     * 
+     * @return the state enum
+     */
+    BERDecoderState getState()
+    {
+        return state ;
+    }
+    
+    
+    /**
+     * Gets a cloned copy of the current tuple.  Used only for debugging and 
+     * testing.
+     * 
+     * @return a clone of the current tlv 
+     */
+    Tuple getCurrentTuple()
+    {
+        return ( Tuple ) tlv.clone() ;
+    }
+    
+    
+    /**
+     * Gets a deep copy of the constructed tuple stack.  Used only for debugging
+     * and testing.
+     * 
+     * @return a deep copy of the tuple stack
+     */
+    Stack getTupleStack()
+    {
+        Stack stack = new Stack() ;
+        
+        for ( int ii = 0; ii < tlvStack.size(); ii++ )
+        {
+            Tuple t = ( Tuple ) tlvStack.get( ii ) ;
+            stack.add( t.clone() ) ;
+        }
+        
+        return stack ;
+    }
+}

Added: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingTuple.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/ChunkingTuple.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,646 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.nio.ByteBuffer ;
+
+import org.apache.commons.lang.ArrayUtils ;
+
+
+/**
+ * TLV Tuple used by the value chunking decoder.  Because the length field is 
+ * a primitive int it's maximum value is 2,147,483,647 a single TLV's tuple 
+ * cannot have a length over this amount or a value size over 2 GB.
+ * 
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class ChunkingTuple 
+{
+    private static final ByteBuffer EMPTY_BUFFER =
+        ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+    
+    /** mask for bit 5 with 0-based index */
+    private static final int BIT_5 = 0x20 ;
+    /** mask for bit 6 with 0-based index */
+    private static final int BIT_6 = 0x40 ;
+    /** mask for bit 7 with 0-based index */
+    private static final int BIT_7 = 0x80 ;
+    
+    /** precalculated left shift of 1 by 14 places */
+    static final int BIT_13 = 1 << 14 ;
+    /** precalculated left shift of 1 by 16 places */
+    static final int BIT_15 = 1 << 16 ;
+    /** precalculated left shift of 1 by 21 places */
+    static final int BIT_20 = 1 << 21 ;
+    /** precalculated left shift of 1 by 24 places */
+    static final int BIT_23 = 1 << 24 ;
+    /** precalculated left shift of 1 by 28 places */
+    static final int BIT_27 = 1 << 28 ;
+    
+    /** the tag id for this TLV tuple */
+    int id = 0 ;
+    /** the flag for whether or not this TLV is constructed or primitive */
+    boolean isPrimitive = true ;
+    /** the type class for this TLV */
+    TypeClass typeClass = TypeClass.APPLICATION ;
+    /** the length for this TLV tuple */
+    int length = 0 ;
+    /** the value for this TLV tuple */
+    ByteBuffer value = EMPTY_BUFFER ;
+    
+    /** tlv byte index */
+    int index = Length.UNDEFINED ;
+    /** tlv value index for how far into the value we have read */
+    int valueIndex = Length.UNDEFINED ;
+    
+    
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+    
+
+    /**
+     * Empty do nothing tuple.
+     */
+    ChunkingTuple() 
+    {
+    }
+    
+    
+    /**
+     * Creates constructed application type tlv tuples.  Constructed TLV's with
+     * a definate length will use this constructor predominantly.  The TypeClass
+     * defualts to APPLICATION.
+     * 
+     * @param id the tag id of the tlv
+     * @param length the length of the value which is the length of all the 
+     *      nested tuples.
+     */
+    public ChunkingTuple( int id, int length )
+    {
+        this( id, length, TypeClass.APPLICATION ) ;
+    }
+    
+    
+    /**
+     * Creates constructed application type tlv tuples.  Constructed TLV's with
+     * a definate length will use this constructor predominantly.
+     * 
+     * @param id the tag id of the tlv
+     * @param length the length of the value which is the length of all the 
+     *      nested tuples.
+     * @param typeClass the type class of this tlv tuple
+     */
+    public ChunkingTuple( int id, int length, TypeClass typeClass )
+    {
+        this.id = id ;
+        this.length = length ;
+        value = EMPTY_BUFFER ;
+        isPrimitive = false ;
+        
+        if ( typeClass != null )
+        {
+            this.typeClass = typeClass ;
+        }
+    }
+    
+    
+    /**
+     * Creates a tuple where the length is indefinate.  The tuple according to
+     * the BER encoding must be of the constructed type.
+     * 
+     * @param id the tag id of the tlv
+     * @param typeClass the type class for the tlv
+     */
+    public ChunkingTuple( int id, TypeClass typeClass )
+    {
+        this.id = id ;
+        this.isPrimitive = false ;
+        value = EMPTY_BUFFER ;
+        length = Length.INDEFINATE ;
+        
+        if ( typeClass != null )
+        {
+            this.typeClass = typeClass ;
+        }
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // Public Accessors
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Gets the tag id (T-part) for this TLV Tuple.
+     * 
+     * @return the tag id
+     */
+    public int getId()
+    {
+        return id ;
+    }
+    
+    
+    /**
+     * Get's whether or not this tuples's length is indefinate.
+     * 
+     * @return whether or not this tuple's length is indefinate
+     */
+    public boolean isIndefinate()
+    {
+        return length == Length.INDEFINATE ;
+    }
+    
+
+    /**
+     * Get's whether or not this tuple terminates an indefinate constructed 
+     * tuple.  This means that length == 0 && isPrimitive = true && id == 0
+     * and the type class is universal.
+     * 
+     * @return whether or not this node's length is indefinate
+     */
+    public boolean isIndefinateTerminator()
+    {
+        return isPrimitive && ( id + length ) == 0 && 
+            typeClass.equals( TypeClass.UNIVERSAL ) ;
+    }
+    
+
+    /**
+     * Gets whether or not this TLV tuple is primitive or constructed.
+     * 
+     * @return true if it is primitive, false if it is constructed
+     */
+    public boolean isPrimitive()
+    {
+        return isPrimitive ;
+    }
+
+    
+    /**
+     * Gets the value length for this TLV Tuple.
+     * 
+     * @return the length in bytes of the value field for this TLV tuple
+     */
+    public int getLength()
+    {
+        return length ;
+    }
+
+    
+    /**
+     * Gets the BER TLV TypeClass for this TLV Tuple.
+     * 
+     * @return the BER TLV TypeClass for this TLV Tuple
+     */
+    public TypeClass getTypeClass()
+    {
+        return typeClass ;
+    }
+
+    
+    /**
+     * Gets the value field (V-part) for this TLV Tuple.
+     * 
+     * @return the value field for this TLV Tuple
+     */
+    public Object getValue()
+    {
+        return value ;
+    }
+    
+    
+    /**
+     * Gets the total size of this TLV tuple in bytes.  This includes the
+     * length of the tag field, the length of the length field and the length
+     * of the value filed.
+     * 
+     * @return the total TLV size in bytes
+     */
+    public int size()
+    {
+        if ( this.length == Length.INDEFINATE )
+        {    
+            return getTagLength() + getLengthLength() ;
+        }
+        else
+        {
+            return getTagLength() + getLengthLength() + length ;
+        }
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // Utility methods and java.lang.Object overrides
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * Clears the values of this tuple.
+     */
+    void clear()
+    {
+        this.id = 0 ;
+        this.index = 0 ;
+        this.isPrimitive = true ;
+        this.length = Length.UNDEFINED ;
+        this.typeClass = TypeClass.APPLICATION ;
+        this.value = EMPTY_BUFFER ;
+        this.valueIndex = Length.UNDEFINED ;
+    }
+
+    
+    /**
+     * Does not take into account the value, index or the valueIndex values when
+     * checking for equality.  Technically if both are being constructed by
+     * the decoder then they should only be equal when these values are equal
+     * because the tag, length or value would not be correct.  Plus since this
+     * is a chunking tuple the value may only be a part of the final value.
+     *
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    public boolean equals( Object o )
+    {
+        if ( o == this )
+        {
+            return true ;
+        }
+        
+        if ( o instanceof ChunkingTuple )
+        {
+            ChunkingTuple t = ( ChunkingTuple ) o ;
+            
+            if ( t.id != id )
+            {
+                return false ;
+            }
+            
+            if ( t.isPrimitive != isPrimitive )
+            {
+                return false ;
+            }
+            
+            if ( t.length != length )
+            {
+                return false ;
+            }
+            
+            if ( t.typeClass != typeClass )
+            {
+                return false ;
+            }
+        }
+        
+        return false ;
+    }
+    
+
+    /*
+     * (non-Javadoc)
+     * @see java.lang.Object#clone()
+     */
+    public Object clone()
+    {
+        ChunkingTuple t = new ChunkingTuple() ;
+        t.id = id ;
+        t.isPrimitive = isPrimitive ;
+        t.typeClass = typeClass ;
+        t.length = length ;
+        
+        ByteBuffer bb = ( ByteBuffer ) value ;
+        ByteBuffer cloned = ByteBuffer.allocate( bb.capacity() ) ;
+        int oldPos = bb.position() ;
+        bb.rewind() ;
+        cloned.put( bb ) ;
+        cloned.limit( bb.limit() ) ;
+        bb.position( oldPos ) ;
+        cloned.rewind() ;
+        t.value = cloned ;
+        
+        t.index = index ;
+        t.valueIndex = valueIndex ;
+        
+        return t ;
+    }
+    
+    
+    // ------------------------------------------------------------------------
+    // Tuple encoding operations
+    // ------------------------------------------------------------------------
+    
+    
+    /**
+     * If this is a primitive TLV then the valueBytes argument is used to 
+     * produce an encoded image of this TLV.  If it is constructed then
+     * only the TL part of the tuple is encoded leaving the value to be encoded
+     * by the set of child TLVs.
+     * 
+     * @return partial encoded image if constructed or complete TLV if primitive
+     */
+    public ByteBuffer toEncodedBuffer( ByteBuffer valueBytes )
+    {
+        ByteBuffer octets = null ;
+        int tagLength = getTagLength() ;
+        int lengthLength = getLengthLength() ;
+        int total = tagLength + lengthLength ;
+
+        if ( isPrimitive )
+        {
+            total += ( ( ByteBuffer ) valueBytes ).remaining() ;
+        }
+        
+        octets = ByteBuffer.allocate( total ) ;
+        setTag( octets, tagLength ) ;
+        setLength( octets, lengthLength ) ;
+        
+        if ( isPrimitive )
+        {
+            octets.put( valueBytes ) ;
+        }
+        
+        return ( ByteBuffer ) octets.flip() ;
+    }
+    
+    
+    /**
+     * Sets the tag section within the buffer.
+     * 
+     * @param octets the buffer to set the tag in
+     * @param tagLength the length of the tag section
+     */
+    void setTag( ByteBuffer octets, int tagLength )
+    {
+        octets.put( ( byte ) typeClass.getValue() ) ;
+        
+        if ( ! isPrimitive )
+        {
+            octets.put( 0, ( byte ) ( octets.get( 0 ) | BIT_5 ) ) ;
+        }
+        
+        if ( tagLength == 1 )
+        {
+            octets.put( 0, ( byte ) ( octets.get( 0 ) | id ) ) ;
+            return ;
+        }
+        
+        octets.put( 0, ( byte ) ( octets.get( 0 ) | Tag.SHORT_MASK ) ) ;
+        
+        if ( tagLength >= 2 )
+        {
+            octets.put( ( byte ) ( ( int ) 0x7f & id ) ) ;
+            
+            if ( tagLength > 2 )
+            {
+                octets.put( 1, ( byte ) ( octets.get( 1 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [8-14] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 7 positions so
+         * we need the following mask:
+         * 
+         * 0011 1111 1000 0000 => 0x3f80
+         * 
+         */
+        if ( tagLength >= 3 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x3f80 & id ) >> 7 ) ) ;
+            
+            if ( tagLength > 3 )
+            {
+                octets.put( 2, ( byte ) ( octets.get( 2 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [15-21] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 14 positions so
+         * we need the following mask:
+         * 
+         * 0001 1111 1100 0000 0000 0000 => 0x1fc000
+         * 
+         */
+        if ( tagLength >= 4 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x1fc000 & id ) >> 14 ) ) ;
+            
+            if ( tagLength > 4 )
+            {
+                octets.put( 3, ( byte ) ( octets.get( 3 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [22-28] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 21 positions so
+         * we need the following mask:
+         * 
+         * 0000 1111 1110 0000 0000 0000 0000 0000 => 0x0fe00000
+         * 
+         */
+        if ( tagLength >= 5 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x0fe00000 & id ) >> 21 ) ) ;
+            
+            if ( tagLength > 5 )
+            {
+                octets.put( 4, ( byte ) ( octets.get( 4 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( tagLength >= 6 )
+        {    
+            throw new IllegalArgumentException( "cannot support id's as large "
+                    + "as " + id + " unless we start using longs for the id" ) ;
+        }
+    }
+
+
+    /**
+     * Sets the length bytes.
+     * 
+     * @param octets the byte [] to set length in
+     * @param offset the offset in the array to start the length section in
+     * @param lengthBytes the number bytes for the length section
+     */
+    void setLength( ByteBuffer octets, int lengthBytes )
+    {
+        if ( length == Length.INDEFINATE )
+        {
+            octets.put( ( byte ) BIT_7 ) ;
+            return ;
+        }
+        else if ( lengthBytes == 1 )
+        {
+            octets.put( ( byte ) length ) ;
+            return ;
+        }
+        else
+        {
+            /*
+             * the lengthBytes argument is the number of octets for the L field
+             * total which for the long form includes the first octet for the 
+             * length of length (N) value where N < 127.  Technically with the 
+             * 7 bits we can specify an N of up to 127 but this value of N is 
+             * reserved.  Anyway below we subtract one from lengthBytes to get
+             * N which is set as the last 7 bits of the first octet of the L
+             * field. 
+             */
+            octets.put( ( byte ) ( BIT_7 | ( lengthBytes - 1 ) ) ) ;
+        }
+        
+        if ( lengthBytes >= 2 )
+        {
+            octets.put( ( byte ) ( 0xff & length ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 3 )
+        {
+            octets.put( ( byte ) ( ( 0xff00 & length ) >> 8 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 4 )
+        {
+            octets.put( ( byte ) ( ( 0xff0000 & length ) >> 16 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 5 )
+        {
+            octets.put( ( byte ) ( ( 0xff000000 & length ) >> 24 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 6 )
+        {    
+            throw new IllegalArgumentException( "cannot support lengths as "
+                    + "large as " + length 
+                    + " unless we start using longs for the length" ) ;
+        }
+    }
+
+
+    /**
+     * Gets the length in bytes of the tag section for this TLV tuple.
+     * 
+     * @return the length in bytes of the tag section for this TLV tuple
+     */
+    public int getTagLength()
+    {
+        if ( id < 31 )
+        {
+            return 1 ;
+        }
+        else if ( id < BIT_6 )
+        {
+            return 2 ;
+        }
+        
+        else if ( id < BIT_13 )
+        {
+            return 3 ;
+        }
+        else if ( id < BIT_20 )
+        {
+            return 4 ;
+        }
+        else if ( id < BIT_27 )
+        {
+            return 5 ;
+        }
+        
+        throw new IllegalArgumentException( "cannot support id's larger than " 
+                + id + " unless we start using longs for the id" ) ;
+    }
+    
+    
+    /**
+     * Gets the length in bytes of the length section of this TLV Tuple.
+     * 
+     * @return the length in bytes of the length section
+     */
+    public int getLengthLength()
+    {
+        if ( length == Length.INDEFINATE )
+        {
+            return 1 ;
+        }
+        
+        if ( length < 0 )
+        {
+            throw new IllegalArgumentException( "integer overflow makes id " 
+                    + "negative with a value of " + id 
+                    + " - unless we start using longs for"
+                    + " the id there you've hit a limitation" ) ;
+        }
+        else if ( length < BIT_7 )
+        {
+            return 1 ;
+        }
+        else if ( length < 256 )
+        {
+            return 2 ;
+        }
+        else if ( length < BIT_15 )
+        {
+            return 3 ;
+        }
+        else if ( length < BIT_23 )
+        {
+            return 4 ;
+        }
+        else 
+        {
+            return 5 ;
+        }
+    }
+}

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/DefaultMutableTupleNode.java	Thu Mar 25 15:02:31 2004
@@ -262,7 +262,7 @@
      */
     public void encode( ByteBuffer dest )
     {
-        dest.put( tuple.encode() ) ;
+        dest.put( tuple.toEncodedArray() ) ;
         
         if ( tuple.isPrimitive() )
         {

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/Tuple.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/Tuple.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/Tuple.java	Thu Mar 25 15:02:31 2004
@@ -17,15 +17,15 @@
 package org.apache.snickers.ber ;
 
 
+import java.nio.ByteBuffer ;
+
 import org.apache.commons.lang.ArrayUtils ;
-import org.apache.commons.codec.binary.Binary ;
 
 
 /**
- * Simple TLV Tuple.  Because the length fields is a primitive int it's maximum
+ * Simple TLV Tuple.  Because the length field is a primitive int it's maximum
  * value is 2,147,483,647 a single TLV's tuple cannot have a length over this
- * amount or a value size over 2 GB.  I don't think we'll be hitting this soon
- * especially with the value size protection feature planned for the decoder.
+ * amount or a value size over 2 GB.
  * 
  * @author <a href="mailto:directory-dev@incubator.apache.org">
  * Apache Directory Project</a>
@@ -33,10 +33,16 @@
  */
 public class Tuple
 {
-    /** precalculated left shift of 1 by 7 places */
-    static final int BIT_6 = 1 << 7 ;
-    /** precalculated left shift of 1 by 8 places */
-    static final int BIT_7 = 1 << 8 ;
+    private static final ByteBuffer EMPTY_BUFFER =
+        ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+    
+    /** mask for bit 5 with 0-based index */
+    private static final int BIT_5 = 0x20 ;
+    /** mask for bit 6 with 0-based index */
+    private static final int BIT_6 = 0x40 ;
+    /** mask for bit 7 with 0-based index */
+    private static final int BIT_7 = 0x80 ;
+    
     /** precalculated left shift of 1 by 14 places */
     static final int BIT_13 = 1 << 14 ;
     /** precalculated left shift of 1 by 16 places */
@@ -57,7 +63,7 @@
     /** the length for this TLV tuple */
     int length = 0 ;
     /** the value for this TLV tuple */
-    Object value = ArrayUtils.EMPTY_BYTE_ARRAY ;
+    Object value ;
     
     /** tlv byte index */
     int index = Length.UNDEFINED ;
@@ -74,7 +80,8 @@
      * Empty do nothing tuple.
      */
     Tuple() 
-    { 
+    {
+        value = ArrayUtils.EMPTY_BYTE_ARRAY ;
     }
     
     
@@ -130,6 +137,19 @@
     
     
     /**
+     * Creates primitive application type tlv tuples.  This will be the primary
+     * constructor used to build primitives.
+     * 
+     * @param id the tag id of the tlv
+     * @param value the value portion for this Tuple
+     */
+    public Tuple( int id, ByteBuffer value )
+    {
+        this( id, TypeClass.APPLICATION, true, value ) ;
+    }
+    
+    
+    /**
      * Creates an application type tlv with a set value and length.  
      * 
      * @param id the tag id of the tlv
@@ -143,6 +163,19 @@
     
     
     /**
+     * Creates an application type tlv with a set value and length.  
+     * 
+     * @param id the tag id of the tlv
+     * @param isPrimitive whether or not the tlv is primitive or constructed
+     * @param value the value portion for this Tuple
+     */
+    public Tuple( int id, boolean isPrimitive, ByteBuffer value )
+    {
+        this( id, TypeClass.APPLICATION, isPrimitive, value ) ;
+    }
+    
+    
+    /**
      * Creates a tuple where the length is indefinate.  The tuple according to
      * the BER encoding must be of the constructed type.
      * 
@@ -185,6 +218,42 @@
             this.value = value ;
             this.length = value.length ;
         }
+        else
+        {
+            this.value = ArrayUtils.EMPTY_BYTE_ARRAY ;
+        }
+        
+        if ( typeClass != null )
+        {
+            this.typeClass = typeClass ;
+        }
+    }
+    
+    
+    /**
+     * Creates a tuple where every member is specified including the length 
+     * which is taken from the value array.
+     * 
+     * @param id the tag id of the tlv
+     * @param typeClass the type class for the tlv
+     * @param isPrimitive whether or not the tlv is primitive or constructed
+     * @param value the value portion for this Tuple
+     */
+    public Tuple( int id, TypeClass typeClass, boolean isPrimitive, 
+                  ByteBuffer value )
+    {
+        this.id = id ;
+        this.isPrimitive = isPrimitive ;
+        
+        if ( value != null )
+        {
+            this.value = value ;
+            this.length = value.remaining() ;
+        }
+        else
+        {
+            this.value = EMPTY_BUFFER ;
+        }
         
         if ( typeClass != null )
         {
@@ -359,14 +428,39 @@
             
             if ( t.value == null && value == null )
             {
-                
+                return true ;
+            }
+            else if ( t.value == null || value == null )
+            {
+                return false ;
             }
-            else if ( ! ArrayUtils.isEquals( t.value, value ) )
+            else if ( t.value == value )
             {
+                return true ;
+            }
+            else if ( t.value.getClass() != value.getClass() )
+            {
+                if ( t.value instanceof ByteBuffer && value instanceof byte[] )
+                {
+                    ByteBuffer bb = ByteBuffer.wrap( ( byte[] ) value ) ;
+                    return bb.equals( t.value ) ;
+                }
+                else if ( value instanceof ByteBuffer && 
+                            t.value instanceof byte[] )
+                {
+                    ByteBuffer bb = ByteBuffer.wrap( ( byte[] ) t.value ) ;
+                    return bb.equals( value ) ;
+                }
+                
                 return false ;
             }
+            else if ( t.value instanceof byte[] &&
+                        ArrayUtils.isEquals( t.value, value ) )
+            {  
+                return true ;
+            }
             
-            return true ;
+            return t.value.equals( value ) ;
         }
         
         return false ;
@@ -384,7 +478,29 @@
         t.isPrimitive = isPrimitive ;
         t.typeClass = typeClass ;
         t.length = length ;
-        t.value = value ;
+        
+        if ( value instanceof byte[] )
+        {
+            byte[] bites = ( byte[] ) value ;
+            t.value = bites.clone() ;
+        }
+        else if ( value instanceof ByteBuffer )
+        {
+            ByteBuffer bb = ( ByteBuffer ) value ;
+            ByteBuffer cloned = ByteBuffer.allocate( bb.capacity() ) ;
+            int oldPos = bb.position() ;
+            bb.rewind() ;
+            cloned.put( bb ) ;
+            cloned.limit( bb.limit() ) ;
+            bb.position( oldPos ) ;
+            cloned.rewind() ;
+            t.value = cloned ;
+        }
+        else
+        {    
+            t.value = value ;
+        }
+        
         t.index = index ;
         t.valueIndex = valueIndex ;
         
@@ -404,7 +520,7 @@
      * 
      * @return partial encoded image if constructed or complete TLV if primitive
      */
-    public byte[] encode()
+    public byte[] toEncodedArray()
     {
         byte[] octets = null ;
         int tagLength = getTagLength() ;
@@ -433,6 +549,57 @@
     
     
     /**
+     * If this is a primitive TLV then it is encoded fully.  If it is not then
+     * only the TL part of the tuple is encoded leaving the value to be encoded
+     * by the set of child TLVs.
+     * 
+     * @return partial encoded image if constructed or complete TLV if primitive
+     */
+    public ByteBuffer toEncodedBuffer()
+    {
+        ByteBuffer octets = null ;
+        int tagLength = getTagLength() ;
+        int lengthLength = getLengthLength() ;
+        int valueLength = 0 ;
+        int total = tagLength + lengthLength ;
+
+        if ( isPrimitive )
+        {
+            if ( value instanceof ByteBuffer )
+            {
+                valueLength = ( ( ByteBuffer ) value ).remaining() ;
+            }
+            else if ( value instanceof byte[] )
+            {    
+                valueLength = ( ( byte[] ) value ).length ;
+            }
+            
+            total += valueLength ;
+        }
+        
+        octets = ByteBuffer.allocate( total ) ;
+        setTag( octets, tagLength ) ;
+        setLength( octets, lengthLength ) ;
+        
+        if ( isPrimitive )
+        {
+            int destPos = tagLength + lengthLength ;
+            
+            if ( value instanceof ByteBuffer )
+            {    
+                octets.put( ( ByteBuffer ) value ) ;
+            }
+            else if ( value instanceof byte[] )
+            {    
+                octets.put( ( byte [] ) value ) ;
+            }
+        }
+        
+        return ( ByteBuffer ) octets.flip() ;
+    }
+    
+    
+    /**
      * Sets the tag section within the array at the start of the array.
      * 
      * @param octets the array of bytes to set the tag in
@@ -444,7 +611,7 @@
         
         if ( ! isPrimitive )
         {
-            octets[0] |= Binary.BIT_5 ;
+            octets[0] |= BIT_5 ;
         }
         
         if ( tagLength == 1 )
@@ -458,11 +625,11 @@
         
         if ( tagLength >= 2 )
         {
-            octets[1] = ( byte ) ( ( int ) 0x0000007f & id ) ;
+            octets[1] = ( byte ) ( ( int ) 0x7f & id ) ;
             
             if ( tagLength > 2 )
             {
-                octets[1] |= Binary.BIT_7 ;
+                octets[1] |= BIT_7 ;
             }
         }
         else
@@ -484,7 +651,7 @@
             
             if ( tagLength > 3 )
             {
-                octets[2] |= Binary.BIT_7 ;
+                octets[2] |= BIT_7 ;
             }
         }
         else
@@ -506,7 +673,7 @@
             
             if ( tagLength > 4 )
             {
-                octets[3] |= Binary.BIT_7 ;
+                octets[3] |= BIT_7 ;
             }
         }
         else
@@ -528,7 +695,118 @@
             
             if ( tagLength > 5 )
             {
-                octets[4] |= Binary.BIT_7 ;
+                octets[4] |= BIT_7 ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( tagLength >= 6 )
+        {    
+            throw new IllegalArgumentException( "cannot support id's as large "
+                    + "as " + id + " unless we start using longs for the id" ) ;
+        }
+    }
+
+
+    /**
+     * Sets the tag section within the buffer.
+     * 
+     * @param octets the buffer to set the tag in
+     * @param tagLength the length of the tag section
+     */
+    void setTag( ByteBuffer octets, int tagLength )
+    {
+        octets.put( ( byte ) typeClass.getValue() ) ;
+        
+        if ( ! isPrimitive )
+        {
+            octets.put( 0, ( byte ) ( octets.get( 0 ) | BIT_5 ) ) ;
+        }
+        
+        if ( tagLength == 1 )
+        {
+            octets.put( 0, ( byte ) ( octets.get( 0 ) | id ) ) ;
+            return ;
+        }
+        
+        octets.put( 0, ( byte ) ( octets.get( 0 ) | Tag.SHORT_MASK ) ) ;
+        
+        if ( tagLength >= 2 )
+        {
+            octets.put( ( byte ) ( ( int ) 0x7f & id ) ) ;
+            
+            if ( tagLength > 2 )
+            {
+                octets.put( 1, ( byte ) ( octets.get( 1 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [8-14] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 7 positions so
+         * we need the following mask:
+         * 
+         * 0011 1111 1000 0000 => 0x3f80
+         * 
+         */
+        if ( tagLength >= 3 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x3f80 & id ) >> 7 ) ) ;
+            
+            if ( tagLength > 3 )
+            {
+                octets.put( 2, ( byte ) ( octets.get( 2 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [15-21] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 14 positions so
+         * we need the following mask:
+         * 
+         * 0001 1111 1100 0000 0000 0000 => 0x1fc000
+         * 
+         */
+        if ( tagLength >= 4 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x1fc000 & id ) >> 14 ) ) ;
+            
+            if ( tagLength > 4 )
+            {
+                octets.put( 3, ( byte ) ( octets.get( 3 ) | BIT_7 ) ) ;
+            }
+        }
+        else
+        {
+            return ;
+        }
+        
+        /* 
+         * Take bits [22-28] (1 based bit indexing) inclusive in id and set the
+         * value for the second byte to this when shifted down 21 positions so
+         * we need the following mask:
+         * 
+         * 0000 1111 1110 0000 0000 0000 0000 0000 => 0x0fe00000
+         * 
+         */
+        if ( tagLength >= 5 )
+        {
+            octets.put( ( byte ) ( ( ( int ) 0x0fe00000 & id ) >> 21 ) ) ;
+            
+            if ( tagLength > 5 )
+            {
+                octets.put( 4, ( byte ) ( octets.get( 4 ) | BIT_7 ) ) ;
             }
         }
         else
@@ -551,20 +829,108 @@
      * @param offset the offset in the array to start the length section in
      * @param lengthBytes the number bytes for the length section
      */
+    void setLength( ByteBuffer octets, int lengthBytes )
+    {
+        if ( length == Length.INDEFINATE )
+        {
+            octets.put( ( byte ) BIT_7 ) ;
+            return ;
+        }
+        else if ( lengthBytes == 1 )
+        {
+            octets.put( ( byte ) length ) ;
+            return ;
+        }
+        else
+        {
+            /*
+             * the lengthBytes argument is the number of octets for the L field
+             * total which for the long form includes the first octet for the 
+             * length of length (N) value where N < 127.  Technically with the 
+             * 7 bits we can specify an N of up to 127 but this value of N is 
+             * reserved.  Anyway below we subtract one from lengthBytes to get
+             * N which is set as the last 7 bits of the first octet of the L
+             * field. 
+             */
+            octets.put( ( byte ) ( BIT_7 | ( lengthBytes - 1 ) ) ) ;
+        }
+        
+        if ( lengthBytes >= 2 )
+        {
+            octets.put( ( byte ) ( 0xff & length ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 3 )
+        {
+            octets.put( ( byte ) ( ( 0xff00 & length ) >> 8 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 4 )
+        {
+            octets.put( ( byte ) ( ( 0xff0000 & length ) >> 16 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 5 )
+        {
+            octets.put( ( byte ) ( ( 0xff000000 & length ) >> 24 ) ) ;
+        }
+        else
+        {
+            return ;
+        }
+        
+        if ( lengthBytes >= 6 )
+        {    
+            throw new IllegalArgumentException( "cannot support lengths as "
+                    + "large as " + length 
+                    + " unless we start using longs for the length" ) ;
+        }
+    }
+
+
+    /**
+     * Sets the length bytes.
+     * 
+     * @param octets the byte [] to set length in
+     * @param offset the offset in the array to start the length section in
+     * @param lengthBytes the number bytes for the length section
+     */
     void setLength( byte[] octets, int offset, int lengthBytes )
     {
         if ( length == Length.INDEFINATE )
         {
-            octets[offset] |= BIT_6 ;
+            octets[offset] = ( byte ) BIT_7 ;
             return ;
         }
         else if ( lengthBytes == 1 )
         {
-            octets[offset] |= length ;
+            octets[offset] = ( byte ) length ;
+            return ;
         }
         else
         {
-            octets[offset] |= Binary.BIT_7 | lengthBytes - 1 ;
+            /*
+             * the lengthBytes argument is the number of octets for the L field
+             * total which for the long form includes the first octet for the 
+             * length of length (N) value where N < 127.  Technically with the 
+             * 7 bits we can specify an N of up to 127 but this value of N is 
+             * reserved.  Anyway below we subtract one from lengthBytes to get
+             * N which is set as the last 7 bits of the first octet of the L
+             * field. 
+             */
+            octets[offset] |= BIT_7 | lengthBytes - 1 ;
         }
         
         if ( lengthBytes >= 2 )
@@ -665,12 +1031,12 @@
                     + " - unless we start using longs for"
                     + " the id there you've hit a limitation" ) ;
         }
-        else if ( length < BIT_6 )
+        else if ( length < BIT_7 )
         {
             return 1 ;
         }
-        else if ( length < BIT_7 )
-        {    
+        else if ( length < 256 )
+        {
             return 2 ;
         }
         else if ( length < BIT_15 )

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/java/org/apache/snickers/ber/TupleTreeDecoder.java	Thu Mar 25 15:02:31 2004
@@ -57,6 +57,8 @@
         BERDecoderCallback berCallback = new BERDecoderCallback()
         {
             public void tagDecoded( Tuple tlv ) { }
+            
+            public void partialValueDecoded( Tuple tlv ) { }
         
             public void lengthDecoded( Tuple tlv )
             {

Added: incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERBufferedDecoderTest.java
==============================================================================
--- (empty file)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERBufferedDecoderTest.java	Thu Mar 25 15:02:31 2004
@@ -0,0 +1,277 @@
+/*
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.snickers.ber ;
+
+
+import java.nio.ByteBuffer ;
+
+import org.apache.commons.lang.ArrayUtils ;
+import org.apache.commons.lang.RandomStringUtils ;
+
+import org.apache.commons.codec.stateful.DecoderCallback ;
+import org.apache.commons.codec.stateful.StatefulDecoder ;
+import org.apache.commons.codec.stateful.DecoderMonitorAdapter ;
+
+
+/**
+ * Tests the decoder using various complext TLV decoding scenarios and performs
+ * round trip encode - decode functionality.
+ *
+ * @author <a href="mailto:directory-dev@incubator.apache.org">
+ * Apache Directory Project</a>
+ * @version $Rev: 9743 $
+ */
+public class BERBufferedDecoderTest extends AbstractBufferedDecoderTestCase
+{
+    public BERBufferedDecoderTest()
+    {
+        super( BERBufferedDecoderTest.class.getName() ) ;
+    }
+    
+    
+    public void testBasisCases() throws Exception
+    {
+        decoder.setDecoderMonitor( new DecoderMonitorAdapter() ) ;
+        decoder.decode( null ) ;
+        decoder.decode( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ) ;
+    }
+    
+    
+    String toString( Object obj ) 
+    {
+        if ( obj instanceof ByteBuffer )
+        {
+            ByteBuffer buf = ( ByteBuffer ) obj ;
+            byte[] bites = new byte[buf.remaining()] ;
+            ( ( ByteBuffer ) buf.duplicate().rewind() ).get( bites ) ;
+            return new String( bites ) ;
+        }
+        else if ( obj instanceof byte[] )
+        {
+            return new String( (byte[]) obj ) ;
+        }
+        
+        return obj.toString() ;
+    }
+    
+    public void testPrimitives() throws Exception
+    {
+        byte[] bites = null ;
+        Tuple decoded = null ;
+        Tuple t = new Tuple( 45, ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+        assertTrue( decode( t ).equals( t ) ) ; 
+        
+        t = new Tuple( 45, "Hello world!".getBytes() ) ;
+        decoded = decode( t ) ;
+        assertTrue( decoded.equals( t ) ) ;
+        assertEquals( "Hello world!", toString( decoded.getValue() ) ) ;
+
+        String mesg = RandomStringUtils.randomAlphanumeric(1000) ;
+        t = new Tuple( 1234233, mesg.getBytes() ) ;
+        decoded = decode( t ) ;
+        assertTrue( decoded.equals( t ) ) ;
+        assertEquals( mesg, toString( decoded.getValue() ) ) ;
+    }
+    
+    
+    public void testConstructedIndefinate() throws Exception
+    {
+        Tuple top = new Tuple( 1, TypeClass.APPLICATION ) ;
+        Tuple t0 = new Tuple( 2, "Hello".getBytes() ) ;
+        Tuple t1 = new Tuple( 3, "World".getBytes() ) ;
+        Tuple terminator = new Tuple( 0, TypeClass.UNIVERSAL, true, 
+                ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+        assertTrue( decode( top ).equals( top ) ) ;
+
+        Tuple decoded = decode( t0 ) ; 
+        assertTrue( decoded.equals( t0 ) ) ;
+        assertEquals( "Hello", toString( decoded.getValue() ) ) ;
+        
+        decoded = decode( t1 ) ; 
+        assertTrue( decoded.equals( t1 ) ) ;
+        assertEquals( "World", toString( decoded.getValue() ) ) ;
+        
+        decoded = decode( terminator ) ;
+        assertTrue( decoded.equals( top ) ) ;
+    }
+    
+    
+    public void testConstructedLongLengthForm() throws Exception
+    {
+        String str0 = RandomStringUtils.randomAlphanumeric(1000) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(1000) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        assertTrue( decode( top ).equals( top ) ) ;
+
+        Tuple decoded = decode( t0 ) ; 
+        assertTrue( decoded.equals( t0 ) ) ;
+        assertEquals( str0, toString( decoded.getValue() ) ) ;
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decoded.equals( top ) ) ;
+    }
+
+
+    public void testConstructedShortLengthForm() throws Exception
+    {
+        Tuple t0 = new Tuple( 2, "Hello".getBytes() ) ;
+        Tuple t1 = new Tuple( 3, "World".getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        assertTrue( decode( top ).equals( top ) ) ;
+
+        Tuple decoded = decode( t0 ) ; 
+        assertTrue( decoded.equals( t0 ) ) ;
+        assertEquals( "Hello", toString( decoded.getValue() ) ) ;
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decoded.equals( top ) ) ;
+    }
+    
+    
+    public void testFragmentedValue() throws Exception
+    {
+        String str0 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        assertTrue( decode( top ).equals( top ) ) ;
+
+        byte[] all = t0.toEncodedArray() ;
+        byte[][] fragments = fragment( all, 10 ) ;
+        Tuple decoded = null ;
+        
+        for ( int ii = 0; ii < fragments.length; ii++ )
+        {
+            decoded = decode( fragments[ii] ) ;
+        }
+        
+        assertTrue( decoded.equals( t0 ) ) ;
+        assertEquals( str0, toString( decoded.getValue() ) ) ;
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decoded.equals( top ) ) ;
+    }
+    
+    
+    public void testDecodeOccurred()
+    {
+        try
+        {
+            decoder.decodeOccurred( null, null ) ;
+            fail( "should never get here due to exception being thrown" ) ;
+        }
+        catch ( IllegalArgumentException e )
+        {
+            assertNotNull( e ) ;
+        }
+    }
+    
+    
+    public void testFireTagDecoded() throws Exception
+    {
+        decoder.setDecoderMonitor( new BERMonitor() ) ;
+        String str0 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        Tuple decoded = decode( t0 ) ; 
+        assertTrue( decoded.equals( t0 ) ) ;
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        
+        assertTrue( decode( top ).equals( top ) ) ;
+    }
+
+
+    public void testFireTagDecoded2() throws Exception
+    {
+        decoder.setDecoderMonitor( null ) ;
+        String str0 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        Tuple decoded = decode( t0 ) ; 
+        assertTrue( decoded.equals( t0 ) ) ;
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decode( top ).equals( top ) ) ;
+    }
+
+
+    public void testFireTagDecoded3() throws Exception
+    {
+        decoder.setDecoderMonitor( new BERMonitor() ) ;
+        decoder.setCallback( null ) ;
+        String str0 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        Tuple decoded = decode( t0 ) ; 
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decode( top ).equals( top ) ) ;
+    }
+
+
+    public void testFireTagDecoded4() throws Exception
+    {
+        decoder.setDecoderMonitor( null ) ;
+        decoder.setCallback( null ) ;
+        String str0 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t0 = new Tuple( 2, str0.getBytes() ) ;
+        String str1 = RandomStringUtils.randomAlphanumeric(20) ;
+        Tuple t1 = new Tuple( 3, str1.getBytes() ) ;
+        Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
+        Tuple decoded = decode( t0 ) ; 
+        
+        // automatically set to top because after t1 is delivered top is 
+        decoded = decode( t1 ) ; 
+        assertTrue( decode( top ).equals( top ) ) ;
+    }
+
+
+    class BERMonitor implements BERDecoderMonitor
+    {
+        public void callbackOccured(StatefulDecoder decoder,
+                DecoderCallback cb, Object decoded) { }
+        
+        public void error(StatefulDecoder decoder, Exception exception) { }
+        
+        public void callbackSet(StatefulDecoder decoder, DecoderCallback oldcb,
+                DecoderCallback newcb) { }
+        
+        public void fatalError(StatefulDecoder decoder, Exception exception){}
+        
+        public void lengthDecoded(Tuple tlv, byte[] lengthData) { }
+        
+        public void tagDecoded(Tuple tlv, byte[] tagData) { }
+        
+        public void warning(StatefulDecoder decoder, Exception exception) { }
+    }
+}

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERDecoderTest.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERDecoderTest.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/BERDecoderTest.java	Thu Mar 25 15:02:31 2004
@@ -140,7 +140,7 @@
         Tuple top = new Tuple( 1, t0.size() + t1.size() ) ;
         assertTrue( decode( top ).equals( top ) ) ;
 
-        byte[] all = t0.encode() ;
+        byte[] all = t0.toEncodedArray() ;
         byte[][] fragments = fragment( all, 10 ) ;
         Tuple decoded = null ;
         

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTest.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTest.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTest.java	Thu Mar 25 15:02:31 2004
@@ -17,6 +17,8 @@
 package org.apache.snickers.ber ;
 
 
+import java.nio.ByteBuffer;
+
 import org.apache.commons.lang.ArrayUtils ;
 import org.apache.commons.codec.binary.Binary ;
 
@@ -126,7 +128,7 @@
         assertEquals( 0, t.getLength() ) ;
         assertEquals( ArrayUtils.EMPTY_BYTE_ARRAY, t.getValue() ) ;
 
-        t = new Tuple( 2, TypeClass.PRIVATE, true, null ) ;
+        t = new Tuple( 2, TypeClass.PRIVATE, true, (byte[]) null ) ;
         assertEquals( 2, t.getId() ) ;
         assertEquals( TypeClass.PRIVATE, t.getTypeClass() ) ;
         assertEquals( true, t.isPrimitive() ) ;
@@ -141,7 +143,7 @@
         assertEquals( 7, t.getLength() ) ;
         assertEquals( bites, t.getValue() ) ;
         
-        t = new Tuple( 2, null, false,  null ) ; 
+        t = new Tuple( 2, null, false, (byte[]) null ) ; 
         assertEquals( 2, t.getId() ) ;
         assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
         assertEquals( false, t.isPrimitive() ) ;
@@ -152,6 +154,45 @@
     /*
      * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
      */
+    public void testTupleintTypeClassbooleanBuffer()
+    {
+        Tuple t = new Tuple( 2, TypeClass.PRIVATE, true, 
+                ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.PRIVATE, t.getTypeClass() ) ;
+        assertEquals( true, t.isPrimitive() ) ;
+        assertEquals( 0, t.getLength() ) ;
+        assertEquals( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ), 
+                t.getValue() ) ;
+
+        t = new Tuple( 2, TypeClass.PRIVATE, true, (ByteBuffer) null ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.PRIVATE, t.getTypeClass() ) ;
+        assertEquals( true, t.isPrimitive() ) ;
+        assertEquals( 0, t.getLength() ) ;
+        assertEquals( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ), 
+                t.getValue() ) ;
+
+        ByteBuffer bites = ByteBuffer.allocate( 7 ) ;
+        t = new Tuple( 2, (TypeClass) null, false, bites ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( false, t.isPrimitive() ) ;
+        assertEquals( 7, t.getLength() ) ;
+        assertEquals( bites, t.getValue() ) ;
+        
+        t = new Tuple( 2, null, false, (ByteBuffer) null ) ; 
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( false, t.isPrimitive() ) ;
+        assertEquals( 0, t.getLength() ) ;
+        assertEquals( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ), 
+                t.getValue() ) ;
+    }
+
+    /*
+     * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
+     */
     public void testTupleintbyteArray()
     {
         Tuple t = new Tuple( 2, ArrayUtils.EMPTY_BYTE_ARRAY ) ;
@@ -173,6 +214,29 @@
     /*
      * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
      */
+    public void testTupleintBuffer()
+    {
+        Tuple t = new Tuple( 2, 
+                ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( true, t.isPrimitive() ) ;
+        assertEquals( 0, t.getLength() ) ;
+        assertEquals( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ), 
+                t.getValue() ) ;
+        
+        ByteBuffer bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( 2, bites ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( true, t.isPrimitive() ) ;
+        assertEquals( 5, t.getLength() ) ;
+        assertEquals( bites, t.getValue() ) ;
+    }
+
+    /*
+     * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
+     */
     public void testTupleintbooleanbyteArray()
     {
         Tuple t = new Tuple( 2, false, ArrayUtils.EMPTY_BYTE_ARRAY ) ;
@@ -194,6 +258,29 @@
     /*
      * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
      */
+    public void testTupleintbooleanBuffer()
+    {
+        Tuple t = new Tuple( 2, false, 
+                ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( false, t.isPrimitive() ) ;
+        assertEquals( 0, t.getLength() ) ;
+        assertEquals( ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ), 
+                t.getValue() ) ;
+        
+        ByteBuffer bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( 2, false, bites ) ;
+        assertEquals( 2, t.getId() ) ;
+        assertEquals( TypeClass.APPLICATION, t.getTypeClass() ) ;
+        assertEquals( false, t.isPrimitive() ) ;
+        assertEquals( 5, t.getLength() ) ;
+        assertEquals( bites, t.getValue() ) ;
+    }
+
+    /*
+     * Class to test for void Tuple(int, int, TypeClass, boolean, byte[])
+     */
     public void testTupleintTypeClass()
     {
         Tuple t = new Tuple( 2, TypeClass.PRIVATE ) ;
@@ -229,7 +316,7 @@
         t.id = 32 ;
         assertEquals( 3, t.size() ) ;
         t.id = 127 ;
-        assertEquals( 3, t.size() ) ;
+        assertEquals( 4, t.size() ) ;
         t.id = 128 ;
         assertEquals( 4, t.size() ) ;
         t.id = 1 << 14 ;
@@ -422,14 +509,14 @@
         assertTrue( t.equals( t.clone() ) ) ;
     }
 
-    public void testEncodeConstructed()
+    public void testToEncodedArrayConstructed()
     {
         Tuple t = null ;
         byte[] encoded ;
         String binary ;
         
         t = new Tuple( 0, 0 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -437,7 +524,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 2, 0 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -445,7 +532,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 30, 0 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -453,7 +540,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 31, 0 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -462,7 +549,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 128, 0 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -472,7 +559,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 128, 127 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "01111111" +
@@ -482,7 +569,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 128, 128 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "10000000" +
@@ -493,7 +580,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 128, 255 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "11111111" +
@@ -504,7 +591,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( 128, 256 ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000001" +
@@ -516,7 +603,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
 
         t = new Tuple( Tuple.BIT_27-1, Integer.MAX_VALUE ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( Binary.toAsciiString( Integer.MAX_VALUE ) + 
                 "10000100" +
@@ -528,7 +615,7 @@
                 , Binary.toAsciiString( encoded ) ) ;
     }
 
-    public void testEncodePrimitive()
+    public void testToEncodedArrayPrimitive()
     {
         Tuple t = null ;
         byte[] encoded ;
@@ -537,7 +624,7 @@
         
         data = new byte[0] ;
         t = new Tuple( 0, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -546,7 +633,7 @@
 
         data = new byte[0] ;
         t = new Tuple( 2, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -555,7 +642,7 @@
 
         data = new byte[0] ;
         t = new Tuple( 30, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -564,7 +651,7 @@
 
         data = new byte[0] ;
         t = new Tuple( 31, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -574,7 +661,7 @@
 
         data = new byte[0] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -585,7 +672,7 @@
 
         data = new byte[1] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( 
                 "00000000" +
@@ -597,7 +684,7 @@
 
         data = new byte[127] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( Binary.toAsciiString( data ) +
                 "01111111" +
@@ -608,7 +695,7 @@
 
         data = new byte[128] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( Binary.toAsciiString( data ) +
                 "10000000" +
@@ -620,7 +707,7 @@
 
         data = new byte[255] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( Binary.toAsciiString( data ) +
                 "11111111" +
@@ -632,7 +719,7 @@
 
         data = new byte[256] ;
         t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
-        encoded = t.encode() ;
+        encoded = t.toEncodedArray() ;
         binary = Binary.toAsciiString( encoded ) ;
         assertEquals( Binary.toAsciiString( data ) + 
                 "00000001" +
@@ -644,7 +731,355 @@
                 , Binary.toAsciiString( encoded ) ) ;
     }
 
-    public void testSetTag()
+    
+    public void testToEncodedBufferConstructed()
+    {
+        Tuple t = null ;
+        ByteBuffer encoded ;
+        String binary ;
+        
+        t = new Tuple( 0, 0 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01100000"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 2, 0 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01100010"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 30, 0 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01111110"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 31, 0 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "00011111" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 128, 0 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "00000001" +
+                "10000000" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 128, 127 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "01111111" +
+                "00000001" +
+                "10000000" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 128, 128 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "10000000" +
+                "10000001" +
+                "00000001" +
+                "10000000" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 128, 255 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "11111111" +
+                "10000001" +
+                "00000001" +
+                "10000000" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( 128, 256 ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000001" +
+                "00000000" +
+                "10000010" +
+                "00000001" +
+                "10000000" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+
+        t = new Tuple( Tuple.BIT_27-1, Integer.MAX_VALUE ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( Binary.toAsciiString( Integer.MAX_VALUE ) + 
+                "10000100" +
+                "01111111" +
+                "11111111" +
+                "11111111" +
+                "11111111" +
+                "01111111"
+                , toAsciiString( encoded ) ) ;
+    }
+
+    public void testToEncodedBufferPrimitive()
+    {
+        Tuple t = null ;
+        ByteBuffer encoded ;
+        byte[] data ;
+        String binary ;
+        
+        data = new byte[0] ;
+        t = new Tuple( 0, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01000000"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[0] ;
+        t = new Tuple( 2, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01000010"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[0] ;
+        t = new Tuple( 30, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "01011110"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[0] ;
+        t = new Tuple( 31, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "00011111" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[0] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[1] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( 
+                "00000000" +
+                "00000001" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[127] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( Binary.toAsciiString( data ) +
+                "01111111" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[128] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( Binary.toAsciiString( data ) +
+                "10000000" +
+                "10000001" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[255] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( Binary.toAsciiString( data ) +
+                "11111111" +
+                "10000001" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+
+        data = new byte[256] ;
+        t = new Tuple( 128, TypeClass.APPLICATION, true, data ) ;
+        encoded = t.toEncodedBuffer() ;
+        binary = toAsciiString( encoded ) ;
+        assertEquals( Binary.toAsciiString( data ) + 
+                "00000001" +
+                "00000000" +
+                "10000010" +
+                "00000001" +
+                "10000000" +
+                "01011111"
+                , toAsciiString( encoded ) ) ;
+    }
+
+    
+    public String toAsciiString( ByteBuffer buf )
+    {
+        return Binary.toAsciiString( buf.array() ) ;
+    }
+    
+    
+    public void testSetTagBufferint()
+    {
+        ByteBuffer bites = ByteBuffer.allocate( 1 ) ;
+        Tuple t = new Tuple( 0, 0 ) ;
+        t.setTag( bites, 1 ) ;
+        String binary = toAsciiString( bites ) ;
+        assertEquals( "01100000", binary ) ;
+        
+        bites = ByteBuffer.allocate( 1 ) ;
+        t = new Tuple( 30, 0 ) ;
+        t.setTag( bites, 1 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111110", binary ) ;
+
+        bites = ByteBuffer.allocate( 1 ) ;
+        t = new Tuple( 30, 0 ) ;
+        t.isPrimitive = true ;
+        t.setTag( bites, 1 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01011110", binary ) ;
+
+        bites = ByteBuffer.allocate( 2 ) ;
+        t = new Tuple( 31, 0 ) ;
+        t.setTag( bites, 2 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00011111" + "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 2 ) ;
+        t = new Tuple( 127, 0 ) ;
+        t.setTag( bites, 2 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111111" + "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 3 ) ;
+        t = new Tuple( 128, 0 ) ;
+        t.setTag( bites, 3 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" + "10000000" + "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 3 ) ;
+        t = new Tuple( Tuple.BIT_13 - 1, 0 ) ;
+        t.setTag( bites, 3 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111111" + 
+                      "11111111" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( Tuple.BIT_13, 0 ) ;
+        t.setTag( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "10000000" +
+                      "10000000" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( Tuple.BIT_13 + 1, 0 ) ;
+        t.setTag( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "10000000" +
+                      "10000001" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( Tuple.BIT_20 - 1, 0 ) ;
+        t.setTag( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111111" + 
+                      "11111111" + 
+                      "11111111" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( Tuple.BIT_20, 0 ) ;
+        t.setTag( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "10000000" +
+                      "10000000" +
+                      "10000000" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( Tuple.BIT_20 + 1, 0 ) ;
+        t.setTag( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "10000000" +
+                      "10000000" +
+                      "10000001" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( Tuple.BIT_27 - 1, 0 ) ;
+        t.setTag( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111111" + 
+                      "11111111" + 
+                      "11111111" + 
+                      "11111111" + 
+                      "01111111", binary ) ;
+
+        bites = ByteBuffer.allocate( 6 ) ;
+        t = new Tuple( Tuple.BIT_27, 0 ) ;
+        
+        try
+        {
+            t.setTag( bites, 6 ) ;
+            fail( "should never reach this point due to thrown exception" ) ;
+        }
+        catch( IllegalArgumentException e )
+        {
+            assertNotNull( e ) ;
+        }
+    }
+
+    public void testSetTagbyteArrayint()
     {
         byte[] bites = new byte[1] ;
         Tuple t = new Tuple( 0, 0 ) ;
@@ -762,7 +1197,126 @@
         }
     }
 
-    public void testSetLength()
+    public void testSetLengthBuffer()
+    {
+        ByteBuffer bites = ByteBuffer.allocate( 1 ) ;
+        Tuple t = new Tuple( 0, 0 ) ;
+        t.setLength( bites, 1 ) ;
+        String binary = toAsciiString( bites ) ;
+        assertEquals( "00000000", binary ) ;
+
+        bites = ByteBuffer.allocate( 1 ) ;
+        t = new Tuple( 30, 15 ) ;
+        t.setLength( bites, 1 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00001111", binary ) ;
+
+        bites = ByteBuffer.allocate( 1 ) ;
+        t = new Tuple( 30, 127 ) ;
+        t.setLength( bites, 1 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "01111111", binary ) ;
+        
+        bites = ByteBuffer.allocate( 2 ) ;
+        t = new Tuple( 30, 128 ) ;
+        t.setLength( bites, 2 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "10000000" +
+                      "10000001", binary ) ;
+        
+        bites = ByteBuffer.allocate( 2 ) ;
+        t = new Tuple( 30, 255 ) ;
+        t.setLength( bites, 2 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "11111111" +
+                      "10000001", binary ) ;
+        
+        bites = ByteBuffer.allocate( 3 ) ;
+        t = new Tuple( 30, 256 ) ;
+        t.setLength( bites, 3 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "00000000" +
+                      "10000010", binary ) ;
+        
+        bites = ByteBuffer.allocate( 3 ) ;
+        t = new Tuple( 30, Tuple.BIT_15 - 1 ) ;
+        t.setLength( bites, 3 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "11111111" +
+                      "11111111" +
+                      "10000010", binary ) ;
+        
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( 30, Tuple.BIT_15 ) ;
+        t.setLength( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "00000000" +
+                      "00000000" +
+                      "10000011", binary ) ;
+        
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( 30, Tuple.BIT_15 + 1 ) ;
+        t.setLength( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "00000000" +
+                      "00000001" +
+                      "10000011", binary ) ;
+        
+        bites = ByteBuffer.allocate( 4 ) ;
+        t = new Tuple( 30, Tuple.BIT_23 - 1 ) ;
+        t.setLength( bites, 4 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "11111111" +
+                      "11111111" +
+                      "11111111" +
+                      "10000011", binary ) ;
+        
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( 30, Tuple.BIT_23 ) ;
+        t.setLength( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "00000000" +
+                      "00000000" +
+                      "00000000" +
+                      "10000100", binary ) ;
+        
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( 30, Tuple.BIT_23 + 1 ) ;
+        t.setLength( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( "00000001" +
+                      "00000000" +
+                      "00000000" +
+                      "00000001" +
+                      "10000100", binary ) ;
+        
+        bites = ByteBuffer.allocate( 5 ) ;
+        t = new Tuple( 30, Integer.MAX_VALUE ) ;
+        t.setLength( bites, 5 ) ;
+        binary = toAsciiString( bites ) ;
+        assertEquals( Binary.toAsciiString( Integer.MAX_VALUE ) +
+                      "10000100", binary ) ;
+        
+        
+        bites = ByteBuffer.allocate( 6 ) ;
+        t = new Tuple( 30, Integer.MAX_VALUE + 1 ) ;
+
+        try
+        {
+            t.setLength( bites, 6 ) ;
+            fail( "should never get here due to thrown exception" ) ;
+        }
+        catch( IllegalArgumentException e ) 
+        {
+            assertNotNull( e ) ;
+        }
+    }
+
+    public void testSetLengthbyteArrayintint()
     {
         byte[] bites = new byte[1] ;
         Tuple t = new Tuple( 0, 0 ) ;
@@ -891,9 +1445,9 @@
         t.id = 31 ;
         assertEquals( 2, t.getTagLength() ) ;
         t.id = 100 ;
-        assertEquals( 2, t.getTagLength() ) ;
+        assertEquals( 3, t.getTagLength() ) ;
         t.id = 127 ;
-        assertEquals( 2, t.getTagLength() ) ;
+        assertEquals( 3, t.getTagLength() ) ;
         t.id = 128 ;
         assertEquals( 3, t.getTagLength() ) ;
         t.id = 129 ;

Modified: incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTreeDecoderTest.java
==============================================================================
--- incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTreeDecoderTest.java	(original)
+++ incubator/directory/snickers/branches/buffer-branch/ber/src/test/org/apache/snickers/ber/TupleTreeDecoderTest.java	Thu Mar 25 15:02:31 2004
@@ -64,15 +64,15 @@
     {
         TupleTreeDecoder decoder = new TupleTreeDecoder() ;
         decoder.decode(ByteBuffer.wrap( 
-                        new Tuple( 1, ArrayUtils.EMPTY_BYTE_ARRAY ).encode())) ;
+                        new Tuple( 1, ArrayUtils.EMPTY_BYTE_ARRAY ).toEncodedArray())) ;
         decoder.decode( ByteBuffer.wrap( new Tuple( 1, 
-                                ArrayUtils.EMPTY_BYTE_ARRAY ).encode() ) ) ;
+                                ArrayUtils.EMPTY_BYTE_ARRAY ).toEncodedArray() ) ) ;
     }    
     
 
     public void testTTD4() throws Exception
     {
-        byte[] bites = new Tuple( 1, ArrayUtils.EMPTY_BYTE_ARRAY ).encode() ;
+        byte[] bites = new Tuple( 1, ArrayUtils.EMPTY_BYTE_ARRAY ).toEncodedArray() ;
         byte[] shorter = new byte[bites.length-1] ;
         System.arraycopy( bites, 0, shorter, 0, shorter.length ) ;
         

Mime
View raw message