diff --git a/Core/AssemblyReport.md b/Core/AssemblyReport.md index 78233b0e..19dd5e7b 100644 --- a/Core/AssemblyReport.md +++ b/Core/AssemblyReport.md @@ -2,6 +2,9 @@ ### Classes Class | Description ---- | ---- +BitHelper | Static methods to help with bit manipulation. +ByteSizeFormatter | A custom formatter for byte sizes (things like files, network bandwidth, etc.) that will automatically determine the best abbreviation. +ComConnectionPoint | Helper class to create an advised COM sink. When this class is constructed, the source is queried for an `IConnectionPointContainer` reference. ComReleaser | A safe variable to hold an instance of a COM class that automatically calls `Marshal.ReleaseComObject(System.Object)` on disposal. CorrespondingTypeAttribute | Attribute for enum values that provides information about corresponding types and related actions. Useful for Get/Set methods that use an enumeration value to determine the type to get or set. CoTaskMemoryMethods | Unmanaged memory methods for COM. @@ -9,6 +12,8 @@ EnumerableEqualityComparer | Checks the linear equality of two enumerated lis EnumExtensions | Extensions for enumerated types. EventedList | A generic list that provides event for changes to the list. This is an alternative to ObservableCollection that provides distinct events for each action (add, insert, remove, changed). FileTimeExtensions | Extensions for `FILETIME`. +Formatter | Base class for expandable formatters. +FormatterComposer | Extension method to combine formatter instances. GenericSafeHandle | A `SafeHandle` that takes a delegate in the constructor that closes the supplied handle. HGlobalMemoryMethods | Unmanaged memory methods for HGlobal. InteropExtensions | Extension methods for System.Runtime.InteropServices. diff --git a/Core/BkwdComp/HashSet.NET2.cs b/Core/BkwdComp/HashSet.NET2.cs new file mode 100644 index 00000000..335adfea --- /dev/null +++ b/Core/BkwdComp/HashSet.NET2.cs @@ -0,0 +1,521 @@ +#if NET20 +using System.Linq; +using System.Runtime.Serialization; + +namespace System.Collections.Generic +{ + /// Provides the base interface for the abstraction of sets. + public interface ISet : ICollection + { + /// Adds an element to the current set and returns a value to indicate if the element was successfully added. + /// The element to add to the set. + /// true if the element is added to the set; false if the element is already in the set. + new bool Add(T item); + + /// Removes all elements in the specified collection from the current set. + /// The collection of items to remove from the set. + void ExceptWith(IEnumerable other); + + /// Modifies the current set so that it contains only elements that are also in a specified collection. + /// The collection to compare to the current set. + void IntersectWith(IEnumerable other); + + /// Determines whether the current set is a proper (strict) subset of a specified collection. + /// The collection to compare to the current set. + /// true if the current set is a proper subset of ; otherwise, false. + bool IsProperSubsetOf(IEnumerable other); + + /// Determines whether the current set is a proper (strict) superset of a specified collection. + /// The collection to compare to the current set. + /// true if the current set is a proper superset of ; otherwise, false. + bool IsProperSupersetOf(IEnumerable other); + + /// Determines whether a set is a subset of a specified collection. + /// The collection to compare to the current set. + /// true if the current set is a subset of ; otherwise, false. + bool IsSubsetOf(IEnumerable other); + + /// Determines whether the current set is a superset of a specified collection. + /// The collection to compare to the current set. + /// true if the current set is a superset of ; otherwise, false. + bool IsSupersetOf(IEnumerable other); + + /// Determines whether the current set overlaps with the specified collection. + /// The collection to compare to the current set. + /// true if the current set and share at least one common element; otherwise, false. + bool Overlaps(IEnumerable other); + + /// Determines whether the current set and the specified collection contain the same elements. + /// The collection to compare to the current set. + /// true if the current set is equal to ; otherwise, false. + bool SetEquals(IEnumerable other); + + /// + /// Modifies the current set so that it contains only elements that are present either in the current set or in the specified + /// collection, but not both. + /// + /// The collection to compare to the current set. + void SymmetricExceptWith(IEnumerable other); + + /// + /// Modifies the current set so that it contains all elements that are present in the current set, in the specified collection, or in both. + /// + /// The collection to compare to the current set. + void UnionWith(IEnumerable other); + } + + /// + /// Represents a set of values. This is less efficient than the native implementation in .NET versions after 2.0, but functionally equivalent. + /// + /// The type of elements in the hash set. + public class HashSet : ISet, IReadOnlyCollection, ISerializable, IDeserializationCallback + { + private readonly Dictionary dict; + + /// + /// Initializes a new instance of the class that is empty and uses the default equality comparer for the set type. + /// + public HashSet() : this((IEqualityComparer)null) + { + } + + /// + /// Initializes a new instance of the class that uses the default equality comparer for the set type, + /// contains elements copied from the specified collection, and has sufficient capacity to accommodate the number of elements copied.. + /// + /// The collection whose elements are copied to the new set. + public HashSet(IEnumerable collection) : this(collection, null) + { + } + + /// + /// Initializes a new instance of the class that is empty and uses the specified equality comparer for the + /// set type.. + /// + /// + /// The implementation to use when comparing values in the set, or null to use the default + /// implementation for the set type. + /// + public HashSet(IEqualityComparer comparer) + { + dict = new Dictionary(comparer); + } + + /// + /// Initializes a new instance of the class that uses the specified equality comparer for the set type, + /// contains elements copied from the specified collection, and has sufficient capacity to accommodate the number of elements copied.. + /// + /// The collection whose elements are copied to the new set. + /// + /// The implementation to use when comparing values in the set, or null to use the default + /// implementation for the set type. + /// + public HashSet(IEnumerable collection, IEqualityComparer comparer) + { + dict = new Dictionary(comparer); + foreach (T elem in collection) + { + Add(elem); + } + } + + /* ***** Unnecessary since implemented in .NET 4.7.2 + /// + /// Initializes a new instance of the class that is empty, but has reserved space for capacity items and + /// uses the default equality comparer for the set type.. + /// + /// The initial size of the + public HashSet(int capacity) : this(capacity, null) + { + } + + /// + /// Initializes a new instance of the class that uses the specified equality comparer for the set type, and + /// has sufficient capacity to accommodate capacity elements.. + /// + /// The initial size of the + /// + /// The implementation to use when comparing values in the set, or null to use the default + /// implementation for the set type. + /// + public HashSet(int capacity, IEqualityComparer comparer) + { + dict = new Dictionary(capacity, comparer); + } + */ + + /// Gets the object that is used to determine equality for the values in the set. + public IEqualityComparer Comparer => dict.Comparer; + + /// + public int Count => dict.Count; + + /// + bool ICollection.IsReadOnly { get; } = false; + + /// + public bool Add(T item) + { + if (null == item) + { + throw new ArgumentNullException(nameof(item)); + } + + if (Contains(item)) + { + return false; + } + + dict[item] = null; + return true; + } + + /// + public void Clear() + { + dict.Clear(); + } + + /// + public bool Contains(T item) + { + return item != null && dict.ContainsKey(item); + } + + /// + public void CopyTo(T[] array, int arrayIndex) + { + if (array == null) + { + throw new ArgumentNullException(nameof(array)); + } + + if (arrayIndex < 0 || arrayIndex >= array.Length || arrayIndex >= Count) + { + throw new ArgumentOutOfRangeException(nameof(arrayIndex)); + } + + dict.Keys.CopyTo(array, arrayIndex); + } + + /// + public void ExceptWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0) + { + return; + } + + if (other == this) + { + Clear(); + return; + } + foreach (T elem in other) + { + dict.Remove(elem); + } + } + + /// + public IEnumerator GetEnumerator() + { + return dict.Keys.GetEnumerator(); + } + + /// + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + { + throw new ArgumentNullException(nameof(info)); + } + + dict.GetObjectData(info, context); + } + + /// + public void IntersectWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (other is ICollection c && c.Count == 0) + { + Clear(); + return; + } + + var l = this.ToList(); + foreach (var elem in l) + { + if (!other.Contains(elem)) + { + Remove(elem); + } + } + } + + /// + public bool IsProperSubsetOf(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0 && other is ICollection c) + { + return c.Count > 0; + } + + CheckUniqueAndUnfoundElements(other, out int unique, out int unfound, false); + return unique == Count && unfound > 0; + } + + /// + public bool IsProperSupersetOf(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0) + { + return false; + } + + if (other is ICollection c && c.Count == 0) + { + return true; + } + + CheckUniqueAndUnfoundElements(other, out int unique, out int unfound, true); + return unique < Count && unfound == 0; + } + + /// + public bool IsSubsetOf(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0) + { + return true; + } + + CheckUniqueAndUnfoundElements(other, out int unique, out int unfound, false); + return unique == Count && unfound >= 0; + } + + /// + public bool IsSupersetOf(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (other is ICollection c && c.Count == 0) + { + return true; + } + + foreach (T elem in other) + { + if (!Contains(elem)) + { + return false; + } + } + + return true; + } + + /// + public virtual void OnDeserialization(object sender) + { + dict.OnDeserialization(sender); + } + + /// + public bool Overlaps(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0) + { + return false; + } + + foreach (T elem in other) + { + if (Contains(elem)) + { + return true; + } + } + + return false; + } + + /// + public bool Remove(T item) + { + return item != null && dict.Remove(item); + } + + /// + public bool SetEquals(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (other is ICollection c && c.Count != Count) + { + return false; + } + + CheckUniqueAndUnfoundElements(other, out int unique, out int unfound, true); + return unique == Count && unfound == 0; + } + + /// + public void SymmetricExceptWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (Count == 0) + { + UnionWith(other); + return; + } + if (other == this) + { + Clear(); + return; + } + + HashSet oh = new HashSet(other, Comparer); + List dup = this.ToList(); + ExceptWith(oh); + oh.ExceptWith(dup); + UnionWith(oh); + } + + /// Searches the set for a given value and returns the equal value it finds, if any. + /// The value to search for. + /// + /// The value from the set that the search found, or the default value of T when the search yielded no match. + /// + /// A value indicating whether the search was successful. + /// + /// This can be useful when you want to reuse a previously stored reference instead of a newly constructed one (so that more sharing + /// of references can occur) or to look up a value that has more complete data than the value you currently have, although their + /// comparer functions indicate they are equal. + /// + public bool TryGetValue(T equalValue, out T actualValue) + { + foreach (T k in dict.Keys) + { + if (!Comparer.Equals(k, equalValue)) + { + continue; + } + + actualValue = k; + return true; + } + actualValue = default(T); + return false; + } + + /// + public void UnionWith(IEnumerable other) + { + if (other == null) + { + throw new ArgumentNullException(nameof(other)); + } + + if (this == other) + { + return; + } + + foreach (T elem in other) + { + Add(elem); + } + } + + /// + void ICollection.Add(T item) + { + Add(item); + } + + /// + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + private void CheckUniqueAndUnfoundElements(IEnumerable other, out int unique, out int unfound, bool returnIfUnfound) + { + if (Count == 0) + { + unique = 0; + unfound = other.Any() ? 1 : 0; + return; + } + + unfound = 0; + unique = 0; + List l = this.ToList(); + BitArray bits = new BitArray(l.Count); + foreach (T o in other) + { + int index = l.IndexOf(o); + if (index >= 0) + { + if (bits[index]) + { + continue; + } + // item hasn't been seen yet + bits[index] = true; + unique++; + } + else + { + unfound++; + if (returnIfUnfound) + { + break; + } + } + } + } + } +} +#endif \ No newline at end of file diff --git a/Core/BkwdComp/System.Collections.Generic.PreNet45.cs b/Core/BkwdComp/System.Collections.Generic.PreNet45.cs index 7daa9aa2..aa63d6cf 100644 --- a/Core/BkwdComp/System.Collections.Generic.PreNet45.cs +++ b/Core/BkwdComp/System.Collections.Generic.PreNet45.cs @@ -1,4 +1,4 @@ -#if (NET20 || NET35 || NET40) +#if NET20 || NET35 || NET40 namespace System.Collections.Generic { /// Represents a strongly-typed, read-only collection of elements. @@ -22,6 +22,7 @@ namespace System.Collections.Generic /// if the read-only dictionary contains an element that has the specified key; otherwise, . /// bool ContainsKey(TKey key); + /// Gets the value that is associated with the specified key. /// The key to locate. /// @@ -33,13 +34,16 @@ namespace System.Collections.Generic /// element that has the specified key; otherwise, . /// bool TryGetValue(TKey key, out TValue value); + /// Gets the element that has the specified key in the read-only dictionary. /// The key to locate. /// The element that has the specified key in the read-only dictionary. TValue this[TKey key] { get; } + /// Gets an enumerable collection that contains the keys in the read-only dictionary. /// An enumerable collection that contains the keys in the read-only dictionary. IEnumerable Keys { get; } + /// Gets an enumerable collection that contains the values in the read-only dictionary. /// An enumerable collection that contains the values in the read-only dictionary. IEnumerable Values { get; } diff --git a/Core/Vanara.Core.csproj b/Core/Vanara.Core.csproj index 1d197e8d..592be8b6 100644 --- a/Core/Vanara.Core.csproj +++ b/Core/Vanara.Core.csproj @@ -30,7 +30,7 @@ Currently implements: Classes -ComReleaser<T>, CorrespondingTypeAttribute, CoTaskMemoryMethods, EnumerableEqualityComparer<T>, EnumExtensions, EventedList<T>, FileTimeExtensions, GenericSafeHandle, HGlobalMemoryMethods, InteropExtensions, IOExtensions, ListChangedEventArgs<T>, MarshalingStream, PinnedObject, ReflectionExtensions, SafeAllocatedMemoryHandle, SafeByteArray, SafeCoTaskMemHandle, SafeCoTaskMemString, SafeHGlobalHandle, SafeMemoryHandle<T>, SafeMemoryHandleExt<T>, SparseArray<T>, StringHelper +BitHelper, ByteSizeFormatter, ComConnectionPoint, ComReleaser<T>, CorrespondingTypeAttribute, CoTaskMemoryMethods, EnumerableEqualityComparer<T>, EnumExtensions, EventedList<T>, FileTimeExtensions, Formatter, FormatterComposer, GenericSafeHandle, HGlobalMemoryMethods, InteropExtensions, IOExtensions, ListChangedEventArgs<T>, MarshalingStream, PinnedObject, ReflectionExtensions, SafeAllocatedMemoryHandle, SafeByteArray, SafeCoTaskMemHandle, SafeCoTaskMemString, SafeHGlobalHandle, SafeMemoryHandle<T>, SafeMemoryHandleExt<T>, SparseArray<T>, StringHelper Structures EnumFlagIndexer<T>, StrPtrAnsi, StrPtrAuto, StrPtrUni