dev@fi.java.net

Re: EncodingAlgo.getPrimtiveLengthFromOctetLength

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Thu, 03 Mar 2005 10:00:26 +0100

Alan Hudson wrote:
> I'm not sure how to respond to this call. I have some algos which
> cannot calculate the length just from the data length. An example is an
> integer encoder which uses n bits to write each integer. Right now I
> write out the number of bits used at the front of the stream. The call
> to getPrimtiveLengthFromOctetLength does not provide the stream to decode.
> Same issue with:
> getOctetLengthFromPrimitiveLength when encoding. Ie I don't know the
> length until after the encoding process has been run.
>
> Obviously we want to avoid running over the data twice as well.
>
> Lets take a really simple encoder. Scan the whole integer array,
> determine smallest number of bits needed to encode min/max value.
> Repeat through array to encode using #bits.
> Perhaps we can solve this by requiring the first call to be a int
> parseHeader(byte[]) , int parseHeader(InputStream). The algo could then
> read any header its dropped to get params. It returns the number of
> bytes read from the stream to later calls to decodeFromBytes could have
> the correct start location.
>
> This does make the encoders stateful and have thread issues. But I'm
> not certain how else to crack this one.

Only the built-in encoding algorithms use:

     getPrimtiveLengthFromOctetLength
     getOctetLengthFromPrimitiveLength

they are part of the contact of the BuiltInEncodingAlgorithm class,
which is implementation specific.


For application defined encoding algorithms the EncodingAlgorithm
interface is used and the serializer calls the method:

encodeToOutputStream(Object data, OutputStream s)

The OutputStream keeps the state of the length. A special buffer is used
and this is copied to the output buffer (double buffering). This
inefficiency needs to be revisited (e.g. use of two buffers one for
structure and one for content will avoid the double buffering issue).

See also the unit test for the application-defined encoding algorithm.


The use of OutputStream may also not be efficient (see attached mail for
an alternative proposal).

Paul.

-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109

attached mail follows:



Hi,

I have just committed what i think is a suitable class for encoding
algorithm data for use with the:

    EncodingAlgorithmInterface.encodeToOutputStream.

This allows for reuse of an underlying buffer:

public void encodeToOutputStream(Object data,
                AccessibleByteBufferOutputStream s) {

     do {
        byte[] b = buffer.getBuffer(1024)
        // write X bytes <= 1024 encoded from data
        buffer.commit(X);
     } while(...);

}

For the cases where it is known what the length will be we can have an
additional method:

        toCommit(int length)

which must be called before any of the other methods and the length must
equal the total sum of lengths committed after the encoding has completed.

Alan, is this of any use to you for the X3D algorithms?

Paul.



public abstract class AccessibleByteBufferOutputStream extends
OutputStream {

     /**
      * Get the byte buffer.
      *
      * <p>The application shall modify the byte
      * array within the the range (getStart(),
      * getStart() + getLength()].<p>
      *
      * @return The underlying byte array to write to
      */
     public abstract byte[] getBuffer();

     /**
      * Get the byte buffer.
      *
      * <p>The application shall modify the byte
      * array within the the range (getStart(),
      * getStart() + getLength()].<p>
      *
      * @param length The length of bytes of the byte array that need to
be modified
      * @return The byte array. Null is returned if the length
      * requested is too large.
      */
     public abstract byte[] getBuffer(int length);

     /**
      * Commit bytes to the byte buffer.
      *
      * <p>The bytes committed shall be in the range (getStart(),
getStart() + length].<p>
      *
      * <p>If the method completed without error then getStart() after
the call will be
      * equal to getStart() + length before the call, and getLength()
after the call will
      * be equal to getLength() - length before the call.<p>
      *
      * <p>The length shall be > 0 and <= getLength().<p>
      *
      * @param length The length of bytes in the byte array to commit.
      */
     public abstract void commitBytes(int length);

     /**
      * Get the start position to modify bytes in the byte buffer.
      *
      * @return The start position in the byte array.
      */
     public abstract int getStart();

     /**
      * Get the length of bytes that can be modified in the byte buffer.
      *
      * @return The length of bytes in the byte array.
      */
     public abstract int getLength();
}
-- 
| ? + ? = To question
----------------\
    Paul Sandoz
         x38109
+33-4-76188109
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe_at_fi.dev.java.net
For additional commands, e-mail: dev-help_at_fi.dev.java.net