package org.bouncycastle.asn1;

/**
 * Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs.
 */
public class ASN1EncodableVector
{
    static final ASN1Encodable[] EMPTY_ELEMENTS = new ASN1Encodable[0];

    private static final int DEFAULT_CAPACITY = 10;

    private ASN1Encodable[] elements;
    private int elementCount;
    private boolean copyOnWrite;

    public ASN1EncodableVector()
    {
        this(DEFAULT_CAPACITY);
    }

    public ASN1EncodableVector(int initialCapacity)
    {
        if (initialCapacity < 0)
        {
            throw new IllegalArgumentException("'initialCapacity' must not ne negative");
        }

        this.elements = (initialCapacity == 0) ? EMPTY_ELEMENTS : new ASN1Encodable[initialCapacity];
        this.elementCount = 0;
        this.copyOnWrite = false;
    }

    public void add(ASN1Encodable element)
    {
        if (null == element)
        {
            throw new NullPointerException("'element' cannot be null");
        }

        int capacity = elements.length;
        int minCapacity = elementCount + 1;
        if ((minCapacity > capacity) | copyOnWrite)
        {
            reallocate(minCapacity);
        }

        this.elements[elementCount] = element;
        this.elementCount = minCapacity;
    }

    public void addAll(ASN1EncodableVector other)
    {
        if (null == other)
        {
            throw new NullPointerException("'other' cannot be null");
        }

        int otherElementCount = other.size();

        int capacity = elements.length;
        int minCapacity = elementCount + otherElementCount;
        if ((minCapacity > capacity) | copyOnWrite)
        {
            reallocate(minCapacity);
        }

        for (int i = 0; i < otherElementCount; ++i)
        {
            ASN1Encodable otherElement = other.get(i);
            if (null == otherElement)
            {
                throw new NullPointerException("'other' elements cannot be null");
            }

            this.elements[elementCount + i] = otherElement;
        }

        this.elementCount = minCapacity;
    }

    /**
     * Return the object at position i in this vector.
     *
     * @param i the index of the object of interest.
     * @return the object at position i.
     */
    public ASN1Encodable get(int i)
    {
        if (i >= elementCount)
        {
            throw new ArrayIndexOutOfBoundsException(i + " >= " + elementCount);
        }

        return elements[i];
    }

    /**
     * Return the size of the vector.
     *
     * @return the object count in the vector.
     */
    public int size()
    {
        return elementCount;
    }

    ASN1Encodable[] copyElements()
    {
        if (0 == elementCount)
        {
            return EMPTY_ELEMENTS;
        }

        ASN1Encodable[] copy = new ASN1Encodable[elementCount];
        System.arraycopy(elements, 0, copy, 0, elementCount);
        return copy;
    }

    ASN1Encodable[] takeElements()
    {
        if (0 == elementCount)
        {
            return EMPTY_ELEMENTS;
        }

        if (elements.length == elementCount)
        {
            this.copyOnWrite = true;
            return elements;
        }

        ASN1Encodable[] copy = new ASN1Encodable[elementCount];
        System.arraycopy(elements, 0, copy, 0, elementCount);
        return copy;
    }

    private void reallocate(int minCapacity)
    {
        int oldCapacity = elements.length;
        int newCapacity = Math.max(oldCapacity, minCapacity + (minCapacity >> 1));

        ASN1Encodable[] copy = new ASN1Encodable[newCapacity];
        System.arraycopy(elements, 0, copy, 0, elementCount);

        this.elements = copy;
        this.copyOnWrite = false;
    }

    static ASN1Encodable[] cloneElements(ASN1Encodable[] elements)
    {
        return elements.length < 1 ? EMPTY_ELEMENTS : elements.clone();
    }
}

@@ -633,17 +633,17 @@
 ust not 
-n
+b
 e negati
@@ -1512,16 +1512,91 @@
 .size();
+%0A        if (otherElementCount %3C 1)%0A        %7B%0A            return;%0A        %7D
 %0A%0A      
@@ -1811,13 +1811,8 @@
     
-for (
 int 
@@ -1821,36 +1821,19 @@
 = 0;
- i %3C otherElementCount; ++i)
+%0A        do
 %0A   
@@ -2096,32 +2096,32 @@
 = otherElement;%0A
-
         %7D%0A%0A     
@@ -2105,32 +2105,73 @@
 ement;%0A        %7D
+%0A        while (++i %3C otherElementCount);
 %0A%0A        this.e

Improve addAll for empty-other case