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 ) );
+ }
+}