public IAnalysisSet Clone() { var buckets = _buckets; var count = _count; if (buckets == null) { return(new AnalysisHashSet(Comparer)); } // Check whether we can reuse the same buckets or if // we need to combine values. We can't use 'seen' for // anything other than checking equality, as it does // not have the merge logic we need. var seen = new HashSet <AnalysisValue>(Comparer); foreach (var b in buckets) { if (b.Key != null && b.Key != _removed && !seen.Add(b.Key)) { // Cannot reuse the buckets return(new AnalysisHashSet(Comparer).Union(this, canMutate: true)); } } var res = new AnalysisHashSet(Comparer); var newBuckets = new Bucket[buckets.Length]; Array.Copy(buckets, newBuckets, buckets.Length); res._buckets = newBuckets; res._count = count; return(res); }
private IAnalysisSet UnionWorker(IEnumerable <AnalysisValue> items, out bool wasChanged, bool canMutate) { #endif if (!canMutate) { // Return ourselves if we aren't adding any new items using (var e = items.GetEnumerator()) { while (e.MoveNext()) { if (!Contains(e.Current)) { // Have to add an item, so clone and finish // enumerating var res = (AnalysisHashSet)Clone(); res.AddOne(e.Current); var b = res.Buckets; AddFromEnumerator(ref b, e, res.Comparer); res.Buckets = b; wasChanged = true; return(res); } } } wasChanged = false; return(this); } // Faster path if we are allowed to mutate ourselves var buckets = Buckets; AnalysisHashSet otherHc = items as AnalysisHashSet; if (otherHc != null && Comparer == otherHc.Comparer) { var otherBuckets = otherHc.Buckets; bool anyChanged = false; if (otherBuckets.Capacity != 0) { // do a fast copy from the other hash set... for (int i = 0; i < otherBuckets.Capacity; i++) { var key = otherBuckets.Buckets[i].Key; if (key != null && key != AnalysisDictionaryRemovedValue.Instance) { anyChanged |= AddOne(ref buckets, key, _comparer); } } Buckets = buckets; } wasChanged = anyChanged; return(this); } // some other set, copy it the slow way... using (var e = items.GetEnumerator()) { wasChanged = AddFromEnumerator(ref buckets, e, Comparer); } Buckets = buckets; return(this); }
public IAnalysisSet Clone() { var res = new AnalysisHashSet(Comparer); using (var e = GetEnumerator()) { res.AddFromEnumerator(e); } return(res); }
public IAnalysisSet Union(IEnumerable <AnalysisValue> items, out bool wasChanged, bool canMutate = true) { if (!canMutate) { // Return ourselves if we aren't adding any new items using (var e = items.GetEnumerator()) { while (e.MoveNext()) { if (!Contains(e.Current)) { // Have to add an item, so clone and finish // enumerating var res = (AnalysisHashSet)Clone(); res.AddOne(e.Current); res.AddFromEnumerator(e); wasChanged = true; return(res); } } } wasChanged = false; return(this); } // Faster path if we are allowed to mutate ourselves AnalysisHashSet otherHc = items as AnalysisHashSet; if (otherHc != null) { bool anyChanged = false; if (otherHc._count != 0) { // do a fast copy from the other hash set... var buckets = otherHc._buckets; for (int i = 0; i < buckets.Length; i++) { var key = buckets[i].Key; if (key != null && key != AnalysisDictionaryRemovedValue.Instance) { anyChanged |= AddOne(key); } } } wasChanged = anyChanged; return(this); } // some other set, copy it the slow way... using (var e = items.GetEnumerator()) { wasChanged = AddFromEnumerator(e); } return(this); }
public IAnalysisSet Clone() { var buckets = _buckets; var count = _count; if (buckets != null) { var newBuckets = new Bucket[buckets.Length]; Array.Copy(buckets, newBuckets, buckets.Length); buckets = newBuckets; } var res = new AnalysisHashSet(Comparer); res._buckets = buckets; res._count = count; return res; }
public IAnalysisSet Clone() { var buckets = _buckets; var count = _count; if (buckets != null) { var newBuckets = new Bucket[buckets.Length]; Array.Copy(buckets, newBuckets, buckets.Length); buckets = newBuckets; } var res = new AnalysisHashSet(Comparer); res._buckets = buckets; res._count = count; return res; }