diff --git a/crypto/src/util/collections/CollectionUtilities.cs b/crypto/src/util/collections/CollectionUtilities.cs
index 37551e5b3..426700903 100644
--- a/crypto/src/util/collections/CollectionUtilities.cs
+++ b/crypto/src/util/collections/CollectionUtilities.cs
@@ -15,6 +15,36 @@ namespace Org.BouncyCastle.Utilities.Collections
}
}
+ public static void CollectMatches<T>(ICollection<T> matches, ISelector<T> selector, params IStore<T>[] stores)
+ {
+ CollectMatches(matches, selector, stores);
+ }
+
+ public static void CollectMatches<T>(ICollection<T> matches, ISelector<T> selector,
+ IEnumerable<IStore<T>> stores)
+ {
+ if (matches == null)
+ throw new ArgumentNullException(nameof(matches));
+ if (stores == null)
+ return;
+
+ foreach (var store in stores)
+ {
+ if (store == null)
+ continue;
+
+ foreach (T match in store.EnumerateMatches(selector))
+ {
+ matches.Add(match);
+ }
+ }
+ }
+
+ public static IStore<T> CreateStore<T>(IEnumerable<T> contents)
+ {
+ return new StoreImpl<T>(contents);
+ }
+
public static IEnumerable Proxy(IEnumerable e)
{
return new EnumerableProxy(e);
@@ -48,18 +78,18 @@ namespace Org.BouncyCastle.Utilities.Collections
return e.Current;
}
- public static string ToString(IEnumerable c)
+ public static string ToString<T>(IEnumerable<T> c)
{
- IEnumerator e = c.GetEnumerator();
+ IEnumerator<T> e = c.GetEnumerator();
if (!e.MoveNext())
return "[]";
StringBuilder sb = new StringBuilder("[");
- sb.Append(e.Current.ToString());
+ sb.Append(e.Current);
while (e.MoveNext())
{
sb.Append(", ");
- sb.Append(e.Current.ToString());
+ sb.Append(e.Current);
}
sb.Append(']');
return sb.ToString();
diff --git a/crypto/src/util/collections/ISelector.cs b/crypto/src/util/collections/ISelector.cs
new file mode 100644
index 000000000..186b922d3
--- /dev/null
+++ b/crypto/src/util/collections/ISelector.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+ /// <summary>Interface for matching objects in an <see cref="IStore{T}"/>.</summary>
+ /// <typeparam name="T">The contravariant type of selectable objects.</typeparam>
+ public interface ISelector<in T>
+ : ICloneable
+ {
+ /// <summary>Match the passed in object, returning true if it would be selected by this selector, false
+ /// otherwise.</summary>
+ /// <param name="candidate">The object to be matched.</param>
+ /// <returns><code>true</code> if the objects is matched by this selector, false otherwise.</returns>
+ bool Match(T candidate);
+ }
+}
diff --git a/crypto/src/util/collections/IStore.cs b/crypto/src/util/collections/IStore.cs
new file mode 100644
index 000000000..12c19aaf4
--- /dev/null
+++ b/crypto/src/util/collections/IStore.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+ /// <summary>A generic interface describing a simple store of objects.</summary>
+ /// <typeparam name="T">The covariant type of stored objects.</typeparam>
+ public interface IStore<out T>
+ {
+ /// <summary>Enumerate the (possibly empty) collection of objects matched by the given selector.</summary>
+ /// <param name="selector">The <see cref="ISelector{T}"/> used to select matching objects.</param>
+ /// <returns>An <see cref="IEnumerable{T}"/> of the matching objects.</returns>
+ IEnumerable<T> EnumerateMatches(ISelector<T> selector);
+ }
+}
diff --git a/crypto/src/util/collections/StoreImpl.cs b/crypto/src/util/collections/StoreImpl.cs
new file mode 100644
index 000000000..3a7135007
--- /dev/null
+++ b/crypto/src/util/collections/StoreImpl.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+
+namespace Org.BouncyCastle.Utilities.Collections
+{
+ internal sealed class StoreImpl<T>
+ : IStore<T>
+ {
+ private readonly List<T> m_contents;
+
+ internal StoreImpl(IEnumerable<T> e)
+ {
+ m_contents = new List<T>(e);
+ }
+
+ IEnumerable<T> IStore<T>.EnumerateMatches(ISelector<T> selector)
+ {
+ foreach (T candidate in m_contents)
+ {
+ if (selector == null || selector.Match(candidate))
+ yield return candidate;
+ }
+ }
+ }
+}
|