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