You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2004/03/26 06:25:43 UTC

svn commit: rev 9760 - incubator/directory/snickers/branches/chunking/ber/src/java/org/apache/snickers/ber

Author: akarasulu
Date: Thu Mar 25 21:25:43 2004
New Revision: 9760

Modified:
   incubator/directory/snickers/branches/chunking/ber/src/java/org/apache/snickers/ber/BERDecoder.java
Log:
chunking changes

Modified: incubator/directory/snickers/branches/chunking/ber/src/java/org/apache/snickers/ber/BERDecoder.java
==============================================================================
--- incubator/directory/snickers/branches/chunking/ber/src/java/org/apache/snickers/ber/BERDecoder.java	(original)
+++ incubator/directory/snickers/branches/chunking/ber/src/java/org/apache/snickers/ber/BERDecoder.java	Thu Mar 25 21:25:43 2004
@@ -31,36 +31,48 @@
 
 
 /**
- * Low level BER encoded bytes to Tag Value Length (TLV) tuple decoder.  
+ * 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.
+ * length, and value entities.  The decoder is a state machine which processes
+ * input as it is made available.
  * <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.
+ * 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.  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.
+ * 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>
  * 
- * @see Tuple for TLV tuple value size limitations
  * @author <a href="mailto:directory-dev@incubator.apache.org">
  * Apache Directory Project</a>
  * @version $Rev$
  */
 public class BERDecoder implements StatefulDecoder, DecoderCallback
 {
-    public static final BERDecoderCallback DEFAULT_CALLBACK = 
+    /** empty byte buffer to be reused */
+    private static final ByteBuffer EMPTY_BUFFER = 
+        ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
+    /** the callback used by this decoder */
+    private static final BERDecoderCallback DEFAULT_CALLBACK = 
         new BERDecoderCallbackAdapter() ;
-    public static final DecoderMonitor DEFAULT_MONITOR =
+    /** the monitor used by this decoder */
+    private static final DecoderMonitor DEFAULT_MONITOR =
         new DecoderMonitorAdapter() ;
     
     /** this decoder's callback */
@@ -75,8 +87,6 @@
     private final TagDecoder tagDecoder = new TagDecoder() ;
     /** a decoder used to decode length octets */ 
     private final LengthDecoder lengthDecoder = new LengthDecoder() ;
-    /** a place to store value data - this is reused */
-    private final ByteBuffer buffer ;
     
     /** stack of nested/constructed TLV tuples */
     private final Stack tlvStack = new Stack() ;
@@ -94,7 +104,6 @@
     {
         tagDecoder.setCallback( this ) ;
         lengthDecoder.setCallback( this ) ;
-        buffer = ByteBuffer.allocate( valueMax ) ;
     }
     
     
@@ -190,22 +199,20 @@
      */
     private void decodeValue( ByteBuffer buf ) throws DecoderException
     {
-        byte[] value = ( byte [] ) tlv.value ;
-        int offset = Length.UNDEFINED ;
         int needToRead = Length.UNDEFINED ;
 
         /*
-         * setup to start decoding the value
+         * 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 ;
-            offset = 0 ;
         }
         else
         {
             needToRead = tlv.length - tlv.valueIndex ;
-            offset = tlv.valueIndex ;
         }
         
         /*
@@ -214,10 +221,12 @@
          */
         if ( buf.remaining() >= needToRead )
         {
-            buf.get( value, offset, needToRead ) ;
+            tlv.value = ( ByteBuffer ) 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() ;
@@ -237,10 +246,12 @@
             }
             
             int remaining = buf.remaining() ;
-            buf.get( value, offset, remaining ) ;
+            tlv.value = buf.slice() ;
+            buf.position( buf.limit() ) ;
             tlv.valueIndex += remaining ;
             tlv.index +=remaining ;
             
+            cb.partialValueDecoded( tlv ) ;
             updateStack( remaining ) ;
         }
     }
@@ -283,8 +294,6 @@
             fireLengthDecoded() ;
             updateStack( length.size() ) ;
             
-            
-            
             if ( ! tlv.isPrimitive )
             {
                 if ( tlv.isIndefinate() || tlv.length > 0 )
@@ -306,13 +315,15 @@
             }
             else if ( tlv.length > 0 )
             {
-                tlv.value = new byte[tlv.length] ;
                 state = BERDecoderState.VALUE ;
             }
             else
             {
-                tlv.value = ArrayUtils.EMPTY_BYTE_ARRAY ;
                 state = BERDecoderState.VALUE ;
+                tlv.value = EMPTY_BUFFER ;
+                cb.partialValueDecoded( tlv ) ;
+                fireDecodeOccurred( tlv ) ;
+                state = BERDecoderState.TAG ;
             }
         }
         else