You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2018/11/17 18:44:48 UTC

[directory-ldap-api] branch master updated: Added a second implementation of an Asn1Buffer, with linked internal buffers

This is an automated email from the ASF dual-hosted git repository.

elecharny pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-ldap-api.git


The following commit(s) were added to refs/heads/master by this push:
     new 83e85e8  Added a second implementation of an Asn1Buffer, with linked internal buffers
83e85e8 is described below

commit 83e85e8e19895cc199e448ef783159d2e31def86
Author: Emmanuel Lecharny <el...@apache.org>
AuthorDate: Sat Nov 17 19:44:47 2018 +0100

    Added a second implementation of an Asn1Buffer, with linked internal
    buffers
---
 .../directory/api/asn1/util/Asn1Buffer2.java       | 224 +++++++++++++++++++++
 .../directory/api/asn1/util/Asn1Buffer2Test.java   | 118 +++++++++++
 2 files changed, 342 insertions(+)

diff --git a/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1Buffer2.java b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1Buffer2.java
new file mode 100644
index 0000000..7146eb3
--- /dev/null
+++ b/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Asn1Buffer2.java
@@ -0,0 +1,224 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+
+package org.apache.directory.api.asn1.util;
+
+/**
+ * A buffer used to store an encoding PDU. It's auto-extended, and
+ * filled by the end.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Asn1Buffer2
+{
+    /** The buffer default size */
+    private static final int DEFAULT_SIZE = 1024;
+
+    /** The current position in the buffer */
+    private int pos = 0;
+
+    /** The current size */
+    private int size = DEFAULT_SIZE;
+
+    /** The internal buffer storage */
+    private class InternalBuffer
+    {
+        /** A buffer to store the encoded PDU */
+        private byte[] buffer = new byte[DEFAULT_SIZE];
+
+        /** The next buffer, if any */
+        private InternalBuffer next;
+    }
+
+    /** The current internal buffer */
+    private InternalBuffer currentBuffer;
+
+
+    /**
+     * Create a new instance of Asn1Buffer2
+     */
+    public Asn1Buffer2()
+    {
+        currentBuffer = new InternalBuffer();
+    }
+
+
+    /**
+     * @return The current position in the buffer
+     */
+    public int getPos()
+    {
+        return pos;
+    }
+
+
+    /**
+     * Store a byte at the current position in the buffer
+     *
+     * @param b The byte to store
+     */
+    public void put( byte b )
+    {
+        if ( pos == size )
+        {
+            // The buffer needs to be reallocated, its too small
+            extend();
+        }
+
+        currentBuffer.buffer[size - pos - 1] = b;
+        pos++;
+    }
+
+
+    /**
+     * Store some bytes at the current position in the buffer
+     *
+     * @param bytes The bytes to store
+     */
+    public void put( byte[] bytes )
+    {
+        int dataLength = bytes.length;
+
+        while ( true )
+        {
+            int room = size - pos;
+
+            if ( dataLength > room )
+            {
+                // First fulfill the current buffer
+                System.arraycopy(
+                    bytes,
+                    dataLength - room,
+                    currentBuffer,
+                    0,
+                    room );
+
+                dataLength -= room;
+                pos += room;
+
+                extend();
+            }
+            else
+            {
+                // Last bytes are copied in the current buffer
+                System.arraycopy(
+                    bytes,
+                    0,
+                    currentBuffer,
+                    room - dataLength,
+                    dataLength );
+
+                pos += dataLength;
+
+                break;
+            }
+        }
+    }
+
+
+    /**
+     * Extend the buffer
+     */
+    private void extend()
+    {
+        InternalBuffer newCurrentBuffer = new InternalBuffer();
+
+        newCurrentBuffer.next = currentBuffer;
+        currentBuffer = newCurrentBuffer;
+        size += DEFAULT_SIZE;
+    }
+
+
+    /**
+     * @return The stored encoded PDU.
+     */
+    public byte[] getBytes()
+    {
+        byte[] result = new byte[pos];
+
+        InternalBuffer bufferPtr = currentBuffer;
+        int currentPos = 0;
+        int dataPos = size - pos;
+        int dataLength = DEFAULT_SIZE - dataPos;
+
+        while ( bufferPtr.next != null )
+        {
+            System.arraycopy(
+                bufferPtr,
+                dataPos,
+                result,
+                currentPos,
+                dataLength );
+
+            currentPos += dataLength;
+            dataPos = 0;
+            dataLength = DEFAULT_SIZE;
+        }
+
+        return result;
+    }
+
+
+    /**
+     * @return The buffer size (ie the maximum number of bytes that can be
+     * added to this buffer before it gets extended).
+     */
+    public int getSize()
+    {
+        return size;
+    }
+
+
+    /**
+     * Clear the position, emptying the buffer. If it has grown, reallocate it
+     * to its initial size.
+     */
+    public void clear()
+    {
+        pos = 0;
+        size = DEFAULT_SIZE;
+
+        // Un-reference the extended buffer. They will be garbage collected.
+        while ( currentBuffer.next != null )
+        {
+            currentBuffer = currentBuffer.next;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append( "[" ).append( size ).append( ", " ).append( pos ).append( "] )" );
+
+        InternalBuffer bufferPtr = currentBuffer;
+
+        while ( bufferPtr.next != null )
+        {
+            sb.append( "\n    " ).append( Asn1StringUtils.dumpBytes( bufferPtr.buffer ) );
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/asn1/api/src/test/java/org/apache/directory/api/asn1/util/Asn1Buffer2Test.java b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/Asn1Buffer2Test.java
new file mode 100644
index 0000000..38e9baa
--- /dev/null
+++ b/asn1/api/src/test/java/org/apache/directory/api/asn1/util/Asn1Buffer2Test.java
@@ -0,0 +1,118 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you under the Apache License, Version 2.0 (the
+ *   "License"); you may not use this file except in compliance
+ *   with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing,
+ *   software distributed under the License is distributed on an
+ *   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *   KIND, either express or implied.  See the License for the
+ *   specific language governing permissions and limitations
+ *   under the License.
+ *
+ */
+package org.apache.directory.api.asn1.util;
+
+import static org.junit.Assert.assertEquals;
+
+import java.nio.ByteBuffer;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Test for the Asn1Buffer class
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Asn1Buffer2Test
+{
+    @Test
+    @Ignore
+    public void testPutSmallBytes()
+    {
+        Asn1Buffer buffer = new Asn1Buffer();
+
+        for ( int i = 0; i < 512; i++ )
+        {
+            buffer.put( new byte[] { 0x01, ( byte ) i } );
+        }
+
+        assertEquals( 1024, buffer.getPos() );
+        ByteBuffer result = buffer.getBytes();
+
+        for ( int i = 0; i < 512; i++ )
+        {
+            assertEquals( 0x01, result.get( i + 1 ) );
+            assertEquals( ( byte ) ( 511 - i ), result.get( i + i + 1 ) );
+        }
+    }
+
+
+    @Test
+    public void testPutByte()
+    {
+        Asn1Buffer buffer = new Asn1Buffer();
+
+        for ( int i = 0; i < 1024; i++ )
+        {
+            buffer.put( ( byte ) i );
+        }
+
+        assertEquals( 1024, buffer.getPos() );
+        ByteBuffer result = buffer.getBytes();
+
+        for ( int i = 0; i < 1024; i++ )
+        {
+            assertEquals( ( byte ) ( 1023 - i ), result.get( i ) );
+        }
+    }
+
+
+    @Test
+    public void testPutByteOOB()
+    {
+        Asn1Buffer buffer = new Asn1Buffer();
+
+        for ( int i = 0; i < 1025; i++ )
+        {
+            buffer.put( ( byte ) i );
+        }
+
+        assertEquals( 1025, buffer.getPos() );
+        assertEquals( 2048, buffer.getSize() );
+        ByteBuffer result = buffer.getBytes();
+
+        for ( int i = 0; i < 1025; i++ )
+        {
+            assertEquals( ( byte ) ( 1024 - i ), result.get( i ) );
+        }
+    }
+
+    @Test
+    @Ignore
+    public void testBytesPerf()
+    {
+        long t0 = System.currentTimeMillis();
+
+        for ( int j = 0; j < 1000; j++ )
+        {
+            Asn1Buffer buffer = new Asn1Buffer();
+
+            for ( int i = 0; i < 409600; i++ )
+            {
+                buffer.put( new byte[] { 0x01, ( byte ) i } );
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta: " + ( t1 - t0 ) );
+    }
+}