diff --git a/crypto/src/asn1/Asn1EncodableVector.cs b/crypto/src/asn1/Asn1EncodableVector.cs
index 8a97e8b4f..987aa5298 100644
--- a/crypto/src/asn1/Asn1EncodableVector.cs
+++ b/crypto/src/asn1/Asn1EncodableVector.cs
@@ -1,101 +1,191 @@
using System;
using System.Collections;
-using Org.BouncyCastle.Utilities;
-
namespace Org.BouncyCastle.Asn1
{
+ /**
+ * Mutable class for building ASN.1 constructed objects such as SETs or SEQUENCEs.
+ */
public class Asn1EncodableVector
- : IEnumerable
+ : IEnumerable
{
- private IList v = Platform.CreateArrayList();
-
- public static Asn1EncodableVector FromEnumerable(
- IEnumerable e)
- {
- Asn1EncodableVector v = new Asn1EncodableVector();
- foreach (Asn1Encodable obj in e)
- {
- v.Add(obj);
- }
- return v;
- }
-
-// public Asn1EncodableVector()
-// {
-// }
-
- public Asn1EncodableVector(
- params Asn1Encodable[] v)
- {
- Add(v);
- }
-
-// public void Add(
-// Asn1Encodable obj)
-// {
-// v.Add(obj);
-// }
-
- public void Add(
- params Asn1Encodable[] objs)
- {
- foreach (Asn1Encodable obj in objs)
- {
- v.Add(obj);
- }
- }
-
- public void AddOptional(
- params Asn1Encodable[] objs)
- {
- if (objs != null)
- {
- foreach (Asn1Encodable obj in objs)
- {
- if (obj != null)
- {
- v.Add(obj);
- }
- }
- }
- }
+ internal static readonly Asn1Encodable[] EmptyElements = new Asn1Encodable[0];
+
+ private const int DefaultCapacity = 10;
+
+ private Asn1Encodable[] elements;
+ private int elementCount;
+ private bool copyOnWrite;
+
+ public static Asn1EncodableVector FromEnumerable(IEnumerable e)
+ {
+ Asn1EncodableVector v = new Asn1EncodableVector();
+ foreach (Asn1Encodable obj in e)
+ {
+ v.Add(obj);
+ }
+ return v;
+ }
+
+ public Asn1EncodableVector()
+ : this(DefaultCapacity)
+ {
+ }
+
+ public Asn1EncodableVector(int initialCapacity)
+ {
+ if (initialCapacity < 0)
+ throw new ArgumentException("must not be negative", "initialCapacity");
+
+ this.elements = (initialCapacity == 0) ? EmptyElements : new Asn1Encodable[initialCapacity];
+ this.elementCount = 0;
+ this.copyOnWrite = false;
+ }
+
+ public Asn1EncodableVector(params Asn1Encodable[] v)
+ : this()
+ {
+ Add(v);
+ }
+
+ public void Add(Asn1Encodable element)
+ {
+ if (null == element)
+ throw new ArgumentNullException("element");
+
+ int capacity = elements.Length;
+ int minCapacity = elementCount + 1;
+ if ((minCapacity > capacity) | copyOnWrite)
+ {
+ Reallocate(minCapacity);
+ }
+
+ this.elements[elementCount] = element;
+ this.elementCount = minCapacity;
+ }
+
+ public void Add(params Asn1Encodable[] objs)
+ {
+ foreach (Asn1Encodable obj in objs)
+ {
+ Add(obj);
+ }
+ }
+
+ public void AddOptional(params Asn1Encodable[] objs)
+ {
+ if (objs != null)
+ {
+ foreach (Asn1Encodable obj in objs)
+ {
+ if (obj != null)
+ {
+ Add(obj);
+ }
+ }
+ }
+ }
public void AddOptionalTagged(bool isExplicit, int tagNo, Asn1Encodable obj)
{
if (null != obj)
{
- v.Add(new DerTaggedObject(isExplicit, tagNo, obj));
+ Add(new DerTaggedObject(isExplicit, tagNo, obj));
}
}
- public Asn1Encodable this[
- int index]
- {
- get { return (Asn1Encodable) v[index]; }
- }
+ public void AddAll(Asn1EncodableVector other)
+ {
+ if (null == other)
+ throw new ArgumentNullException("other");
- [Obsolete("Use 'object[index]' syntax instead")]
- public Asn1Encodable Get(
- int index)
+ int otherElementCount = other.Count;
+ if (otherElementCount < 1)
+ return;
+
+ int capacity = elements.Length;
+ int minCapacity = elementCount + otherElementCount;
+ if ((minCapacity > capacity) | copyOnWrite)
+ {
+ Reallocate(minCapacity);
+ }
+
+ int i = 0;
+ do
+ {
+ Asn1Encodable otherElement = other[i];
+ if (null == otherElement)
+ throw new NullReferenceException("'other' elements cannot be null");
+
+ this.elements[elementCount + i] = otherElement;
+ }
+ while (++i < otherElementCount);
+
+ this.elementCount = minCapacity;
+ }
+
+ public Asn1Encodable this[int index]
{
- return this[index];
+ get
+ {
+ if (index >= elementCount)
+ throw new IndexOutOfRangeException(index + " >= " + elementCount);
+
+ return elements[index];
+ }
}
- [Obsolete("Use 'Count' property instead")]
- public int Size
- {
- get { return v.Count; }
- }
+ public int Count
+ {
+ get { return elementCount; }
+ }
- public int Count
- {
- get { return v.Count; }
- }
+ public IEnumerator GetEnumerator()
+ {
+ return CopyElements().GetEnumerator();
+ }
- public IEnumerator GetEnumerator()
- {
- return v.GetEnumerator();
- }
- }
+ internal Asn1Encodable[] CopyElements()
+ {
+ if (0 == elementCount)
+ return EmptyElements;
+
+ Asn1Encodable[] copy = new Asn1Encodable[elementCount];
+ Array.Copy(elements, 0, copy, 0, elementCount);
+ return copy;
+ }
+
+ internal Asn1Encodable[] TakeElements()
+ {
+ if (0 == elementCount)
+ return EmptyElements;
+
+ if (elements.Length == elementCount)
+ {
+ this.copyOnWrite = true;
+ return elements;
+ }
+
+ Asn1Encodable[] copy = new Asn1Encodable[elementCount];
+ Array.Copy(elements, 0, copy, 0, elementCount);
+ return copy;
+ }
+
+ private void Reallocate(int minCapacity)
+ {
+ int oldCapacity = elements.Length;
+ int newCapacity = System.Math.Max(oldCapacity, minCapacity + (minCapacity >> 1));
+
+ Asn1Encodable[] copy = new Asn1Encodable[newCapacity];
+ Array.Copy(elements, 0, copy, 0, elementCount);
+
+ this.elements = copy;
+ this.copyOnWrite = false;
+ }
+
+ internal static Asn1Encodable[] CloneElements(Asn1Encodable[] elements)
+ {
+ return elements.Length < 1 ? EmptyElements : (Asn1Encodable[])elements.Clone();
+ }
+ }
}
|