#region Copyright & License Information /* * Copyright 2007-2018 The OpenRA Developers (see AUTHORS) * This file is part of OpenRA, which is free software. It is made * available to you under the terms of the GNU General Public License * as published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. For more * information, see COPYING. */ #endregion using System; using System.Collections; using System.Collections.Generic; using BitSetIndex = System.Numerics.BigInteger; namespace OpenRA.Primitives { static class BitSetAllocator where T : class { static readonly Cache Bits = new Cache(Allocate); static BitSetIndex nextBits = 1; static BitSetIndex Allocate(string value) { lock (Bits) { var bits = nextBits; nextBits <<= 1; return bits; } } public static BitSetIndex GetBits(string[] values) { BitSetIndex bits = 0; lock (Bits) foreach (var value in values) bits |= Bits[value]; return bits; } public static IEnumerable GetStrings(BitSetIndex bits) { var values = new List(); lock (Bits) foreach (var kvp in Bits) if ((kvp.Value & bits) != 0) values.Add(kvp.Key); return values; } public static bool BitsContainString(BitSetIndex bits, string value) { BitSetIndex valueBit; lock (Bits) if (!Bits.TryGetValue(value, out valueBit)) return false; return (bits & valueBit) != 0; } } public struct BitSet : IEnumerable, IEquatable> where T : class { readonly BitSetIndex bits; public BitSet(params string[] values) : this(BitSetAllocator.GetBits(values)) { } BitSet(BitSetIndex bits) { this.bits = bits; } public override string ToString() { return BitSetAllocator.GetStrings(bits).JoinWith(","); } public static bool operator ==(BitSet me, BitSet other) { return me.bits == other.bits; } public static bool operator !=(BitSet me, BitSet other) { return !(me == other); } public bool Equals(BitSet other) { return other == this; } public override bool Equals(object obj) { return obj is BitSet && Equals((BitSet)obj); } public override int GetHashCode() { return bits.GetHashCode(); } public bool IsEmpty { get { return bits == 0; } } public bool IsProperSubsetOf(BitSet other) { return IsSubsetOf(other) && !SetEquals(other); } public bool IsProperSupersetOf(BitSet other) { return IsSupersetOf(other) && !SetEquals(other); } public bool IsSubsetOf(BitSet other) { return (bits | other.bits) == other.bits; } public bool IsSupersetOf(BitSet other) { return (bits | other.bits) == bits; } public bool Overlaps(BitSet other) { return (bits & other.bits) != 0; } public bool SetEquals(BitSet other) { return bits == other.bits; } public bool Contains(string value) { return BitSetAllocator.BitsContainString(bits, value); } public IEnumerator GetEnumerator() { return BitSetAllocator.GetStrings(bits).GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public BitSet Except(BitSet other) { return new BitSet(bits & ~other.bits); } public BitSet Intersect(BitSet other) { return new BitSet(bits & other.bits); } public BitSet SymmetricExcept(BitSet other) { return new BitSet(bits ^ other.bits); } public BitSet Union(BitSet other) { return new BitSet(bits | other.bits); } } }