| /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. |
| * Use of this file is governed by the BSD 3-clause license that |
| * can be found in the LICENSE.txt file in the project root. |
| */ |
| using System; |
| using System.Collections.Generic; |
| using System.Linq; |
| using System.Text; |
| |
| namespace Antlr4.Runtime.Misc |
| { |
| /// <summary> |
| /// This class implements the |
| /// <see cref="IIntSet"/> |
| /// backed by a sorted array of |
| /// non-overlapping intervals. It is particularly efficient for representing |
| /// large collections of numbers, where the majority of elements appear as part |
| /// of a sequential range of numbers that are all part of the set. For example, |
| /// the set { 1, 2, 3, 4, 7, 8 } may be represented as { [1, 4], [7, 8] }. |
| /// <p> |
| /// This class is able to represent sets containing any combination of values in |
| /// the range |
| /// <see cref="int.MinValue"/> |
| /// to |
| /// <see cref="int.MaxValue"/> |
| /// (inclusive).</p> |
| /// </summary> |
| public class IntervalSet : IIntSet |
| { |
| public static readonly Antlr4.Runtime.Misc.IntervalSet CompleteCharSet = Antlr4.Runtime.Misc.IntervalSet.Of(Lexer.MinCharValue, Lexer.MaxCharValue); |
| |
| public static readonly Antlr4.Runtime.Misc.IntervalSet EmptySet = new Antlr4.Runtime.Misc.IntervalSet(); |
| |
| static IntervalSet() |
| { |
| CompleteCharSet.SetReadonly(true); |
| EmptySet.SetReadonly(true); |
| } |
| |
| /// <summary>The list of sorted, disjoint intervals.</summary> |
| /// <remarks>The list of sorted, disjoint intervals.</remarks> |
| protected internal IList<Interval> intervals; |
| |
| protected internal bool @readonly; |
| |
| public IntervalSet(IList<Interval> intervals) |
| { |
| this.intervals = intervals; |
| } |
| |
| public IntervalSet(Antlr4.Runtime.Misc.IntervalSet set) |
| : this() |
| { |
| AddAll(set); |
| } |
| |
| public IntervalSet(params int[] els) |
| { |
| if (els == null) |
| { |
| intervals = new ArrayList<Interval>(2); |
| } |
| else |
| { |
| // most sets are 1 or 2 elements |
| intervals = new ArrayList<Interval>(els.Length); |
| foreach (int e in els) |
| { |
| Add(e); |
| } |
| } |
| } |
| |
| /// <summary>Create a set with a single element, el.</summary> |
| /// <remarks>Create a set with a single element, el.</remarks> |
| [return: NotNull] |
| public static Antlr4.Runtime.Misc.IntervalSet Of(int a) |
| { |
| Antlr4.Runtime.Misc.IntervalSet s = new Antlr4.Runtime.Misc.IntervalSet(); |
| s.Add(a); |
| return s; |
| } |
| |
| /// <summary>Create a set with all ints within range [a..b] (inclusive)</summary> |
| public static Antlr4.Runtime.Misc.IntervalSet Of(int a, int b) |
| { |
| Antlr4.Runtime.Misc.IntervalSet s = new Antlr4.Runtime.Misc.IntervalSet(); |
| s.Add(a, b); |
| return s; |
| } |
| |
| public virtual void Clear() |
| { |
| if (@readonly) |
| { |
| throw new InvalidOperationException("can't alter readonly IntervalSet"); |
| } |
| intervals.Clear(); |
| } |
| |
| /// <summary>Add a single element to the set.</summary> |
| /// <remarks> |
| /// Add a single element to the set. An isolated element is stored |
| /// as a range el..el. |
| /// </remarks> |
| public virtual void Add(int el) |
| { |
| if (@readonly) |
| { |
| throw new InvalidOperationException("can't alter readonly IntervalSet"); |
| } |
| Add(el, el); |
| } |
| |
| /// <summary>Add interval; i.e., add all integers from a to b to set.</summary> |
| /// <remarks> |
| /// Add interval; i.e., add all integers from a to b to set. |
| /// If b<a, do nothing. |
| /// Keep list in sorted order (by left range value). |
| /// If overlap, combine ranges. For example, |
| /// If this is {1..5, 10..20}, adding 6..7 yields |
| /// {1..5, 6..7, 10..20}. Adding 4..8 yields {1..8, 10..20}. |
| /// </remarks> |
| public virtual void Add(int a, int b) |
| { |
| Add(Interval.Of(a, b)); |
| } |
| |
| // copy on write so we can cache a..a intervals and sets of that |
| protected internal virtual void Add(Interval addition) |
| { |
| if (@readonly) |
| { |
| throw new InvalidOperationException("can't alter readonly IntervalSet"); |
| } |
| //System.out.println("add "+addition+" to "+intervals.toString()); |
| if (addition.b < addition.a) |
| { |
| return; |
| } |
| // find position in list |
| // Use iterators as we modify list in place |
| for (int i = 0; i < intervals.Count; i++) |
| { |
| Interval r = intervals[i]; |
| if (addition.Equals(r)) |
| { |
| return; |
| } |
| if (addition.Adjacent(r) || !addition.Disjoint(r)) |
| { |
| // next to each other, make a single larger interval |
| Interval bigger = addition.Union(r); |
| intervals[i] = bigger; |
| // make sure we didn't just create an interval that |
| // should be merged with next interval in list |
| while (i < intervals.Count - 1) |
| { |
| i++; |
| Interval next = intervals[i]; |
| if (!bigger.Adjacent(next) && bigger.Disjoint(next)) |
| { |
| break; |
| } |
| // if we bump up against or overlap next, merge |
| intervals.RemoveAt(i); |
| // remove this one |
| i--; |
| // move backwards to what we just set |
| intervals[i] = bigger.Union(next); |
| // set to 3 merged ones |
| } |
| // first call to next after previous duplicates the result |
| return; |
| } |
| if (addition.StartsBeforeDisjoint(r)) |
| { |
| // insert before r |
| intervals.Insert(i, addition); |
| return; |
| } |
| } |
| // if disjoint and after r, a future iteration will handle it |
| // ok, must be after last interval (and disjoint from last interval) |
| // just add it |
| intervals.Add(addition); |
| } |
| |
| /// <summary>combine all sets in the array returned the or'd value</summary> |
| public static Antlr4.Runtime.Misc.IntervalSet Or(Antlr4.Runtime.Misc.IntervalSet[] sets) |
| { |
| Antlr4.Runtime.Misc.IntervalSet r = new Antlr4.Runtime.Misc.IntervalSet(); |
| foreach (Antlr4.Runtime.Misc.IntervalSet s in sets) |
| { |
| r.AddAll(s); |
| } |
| return r; |
| } |
| |
| public virtual Antlr4.Runtime.Misc.IntervalSet AddAll(IIntSet set) |
| { |
| if (set == null) |
| { |
| return this; |
| } |
| if (set is Antlr4.Runtime.Misc.IntervalSet) |
| { |
| Antlr4.Runtime.Misc.IntervalSet other = (Antlr4.Runtime.Misc.IntervalSet)set; |
| // walk set and add each interval |
| int n = other.intervals.Count; |
| for (int i = 0; i < n; i++) |
| { |
| Interval I = other.intervals[i]; |
| this.Add(I.a, I.b); |
| } |
| } |
| else |
| { |
| foreach (int value in set.ToList()) |
| { |
| Add(value); |
| } |
| } |
| return this; |
| } |
| |
| public virtual Antlr4.Runtime.Misc.IntervalSet Complement(int minElement, int maxElement) |
| { |
| return this.Complement(Antlr4.Runtime.Misc.IntervalSet.Of(minElement, maxElement)); |
| } |
| |
| /// <summary> |
| /// <inheritDoc/> |
| /// |
| /// </summary> |
| public virtual Antlr4.Runtime.Misc.IntervalSet Complement(IIntSet vocabulary) |
| { |
| if (vocabulary == null || vocabulary.IsNil) |
| { |
| return null; |
| } |
| // nothing in common with null set |
| Antlr4.Runtime.Misc.IntervalSet vocabularyIS; |
| if (vocabulary is Antlr4.Runtime.Misc.IntervalSet) |
| { |
| vocabularyIS = (Antlr4.Runtime.Misc.IntervalSet)vocabulary; |
| } |
| else |
| { |
| vocabularyIS = new Antlr4.Runtime.Misc.IntervalSet(); |
| vocabularyIS.AddAll(vocabulary); |
| } |
| return vocabularyIS.Subtract(this); |
| } |
| |
| public virtual Antlr4.Runtime.Misc.IntervalSet Subtract(IIntSet a) |
| { |
| if (a == null || a.IsNil) |
| { |
| return new Antlr4.Runtime.Misc.IntervalSet(this); |
| } |
| if (a is Antlr4.Runtime.Misc.IntervalSet) |
| { |
| return Subtract(this, (Antlr4.Runtime.Misc.IntervalSet)a); |
| } |
| Antlr4.Runtime.Misc.IntervalSet other = new Antlr4.Runtime.Misc.IntervalSet(); |
| other.AddAll(a); |
| return Subtract(this, other); |
| } |
| |
| /// <summary>Compute the set difference between two interval sets.</summary> |
| /// <remarks> |
| /// Compute the set difference between two interval sets. The specific |
| /// operation is |
| /// <c>left - right</c> |
| /// . If either of the input sets is |
| /// <see langword="null"/> |
| /// , it is treated as though it was an empty set. |
| /// </remarks> |
| [return: NotNull] |
| public static Antlr4.Runtime.Misc.IntervalSet Subtract(Antlr4.Runtime.Misc.IntervalSet left, Antlr4.Runtime.Misc.IntervalSet right) |
| { |
| if (left == null || left.IsNil) |
| { |
| return new Antlr4.Runtime.Misc.IntervalSet(); |
| } |
| Antlr4.Runtime.Misc.IntervalSet result = new Antlr4.Runtime.Misc.IntervalSet(left); |
| if (right == null || right.IsNil) |
| { |
| // right set has no elements; just return the copy of the current set |
| return result; |
| } |
| int resultI = 0; |
| int rightI = 0; |
| while (resultI < result.intervals.Count && rightI < right.intervals.Count) |
| { |
| Interval resultInterval = result.intervals[resultI]; |
| Interval rightInterval = right.intervals[rightI]; |
| // operation: (resultInterval - rightInterval) and update indexes |
| if (rightInterval.b < resultInterval.a) |
| { |
| rightI++; |
| continue; |
| } |
| if (rightInterval.a > resultInterval.b) |
| { |
| resultI++; |
| continue; |
| } |
| Interval? beforeCurrent = null; |
| Interval? afterCurrent = null; |
| if (rightInterval.a > resultInterval.a) |
| { |
| beforeCurrent = new Interval(resultInterval.a, rightInterval.a - 1); |
| } |
| if (rightInterval.b < resultInterval.b) |
| { |
| afterCurrent = new Interval(rightInterval.b + 1, resultInterval.b); |
| } |
| if (beforeCurrent != null) |
| { |
| if (afterCurrent != null) |
| { |
| // split the current interval into two |
| result.intervals[resultI] = beforeCurrent.Value; |
| result.intervals.Insert(resultI + 1, afterCurrent.Value); |
| resultI++; |
| rightI++; |
| continue; |
| } |
| else |
| { |
| // replace the current interval |
| result.intervals[resultI] = beforeCurrent.Value; |
| resultI++; |
| continue; |
| } |
| } |
| else |
| { |
| if (afterCurrent != null) |
| { |
| // replace the current interval |
| result.intervals[resultI] = afterCurrent.Value; |
| rightI++; |
| continue; |
| } |
| else |
| { |
| // remove the current interval (thus no need to increment resultI) |
| result.intervals.RemoveAt(resultI); |
| continue; |
| } |
| } |
| } |
| // If rightI reached right.intervals.size(), no more intervals to subtract from result. |
| // If resultI reached result.intervals.size(), we would be subtracting from an empty set. |
| // Either way, we are done. |
| return result; |
| } |
| |
| public virtual Antlr4.Runtime.Misc.IntervalSet Or(IIntSet a) |
| { |
| Antlr4.Runtime.Misc.IntervalSet o = new Antlr4.Runtime.Misc.IntervalSet(); |
| o.AddAll(this); |
| o.AddAll(a); |
| return o; |
| } |
| |
| /// <summary> |
| /// <inheritDoc/> |
| /// |
| /// </summary> |
| public virtual Antlr4.Runtime.Misc.IntervalSet And(IIntSet other) |
| { |
| if (other == null) |
| { |
| //|| !(other instanceof IntervalSet) ) { |
| return null; |
| } |
| // nothing in common with null set |
| IList<Interval> myIntervals = this.intervals; |
| IList<Interval> theirIntervals = ((Antlr4.Runtime.Misc.IntervalSet)other).intervals; |
| Antlr4.Runtime.Misc.IntervalSet intersection = null; |
| int mySize = myIntervals.Count; |
| int theirSize = theirIntervals.Count; |
| int i = 0; |
| int j = 0; |
| // iterate down both interval lists looking for nondisjoint intervals |
| while (i < mySize && j < theirSize) |
| { |
| Interval mine = myIntervals[i]; |
| Interval theirs = theirIntervals[j]; |
| //System.out.println("mine="+mine+" and theirs="+theirs); |
| if (mine.StartsBeforeDisjoint(theirs)) |
| { |
| // move this iterator looking for interval that might overlap |
| i++; |
| } |
| else |
| { |
| if (theirs.StartsBeforeDisjoint(mine)) |
| { |
| // move other iterator looking for interval that might overlap |
| j++; |
| } |
| else |
| { |
| if (mine.ProperlyContains(theirs)) |
| { |
| // overlap, add intersection, get next theirs |
| if (intersection == null) |
| { |
| intersection = new Antlr4.Runtime.Misc.IntervalSet(); |
| } |
| intersection.Add(mine.Intersection(theirs)); |
| j++; |
| } |
| else |
| { |
| if (theirs.ProperlyContains(mine)) |
| { |
| // overlap, add intersection, get next mine |
| if (intersection == null) |
| { |
| intersection = new Antlr4.Runtime.Misc.IntervalSet(); |
| } |
| intersection.Add(mine.Intersection(theirs)); |
| i++; |
| } |
| else |
| { |
| if (!mine.Disjoint(theirs)) |
| { |
| // overlap, add intersection |
| if (intersection == null) |
| { |
| intersection = new Antlr4.Runtime.Misc.IntervalSet(); |
| } |
| intersection.Add(mine.Intersection(theirs)); |
| // Move the iterator of lower range [a..b], but not |
| // the upper range as it may contain elements that will collide |
| // with the next iterator. So, if mine=[0..115] and |
| // theirs=[115..200], then intersection is 115 and move mine |
| // but not theirs as theirs may collide with the next range |
| // in thisIter. |
| // move both iterators to next ranges |
| if (mine.StartsAfterNonDisjoint(theirs)) |
| { |
| j++; |
| } |
| else |
| { |
| if (theirs.StartsAfterNonDisjoint(mine)) |
| { |
| i++; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| if (intersection == null) |
| { |
| return new Antlr4.Runtime.Misc.IntervalSet(); |
| } |
| return intersection; |
| } |
| |
| /// <summary> |
| /// <inheritDoc/> |
| /// |
| /// </summary> |
| public virtual bool Contains(int el) |
| { |
| int n = intervals.Count; |
| for (int i = 0; i < n; i++) |
| { |
| Interval I = intervals[i]; |
| int a = I.a; |
| int b = I.b; |
| if (el < a) |
| { |
| break; |
| } |
| // list is sorted and el is before this interval; not here |
| if (el >= a && el <= b) |
| { |
| return true; |
| } |
| } |
| // found in this interval |
| return false; |
| } |
| |
| /// <summary> |
| /// <inheritDoc/> |
| /// |
| /// </summary> |
| public virtual bool IsNil |
| { |
| get |
| { |
| return intervals == null || intervals.Count == 0; |
| } |
| } |
| |
| /// <summary> |
| /// <inheritDoc/> |
| /// |
| /// </summary> |
| public virtual int SingleElement |
| { |
| get |
| { |
| if (intervals != null && intervals.Count == 1) |
| { |
| Interval I = intervals[0]; |
| if (I.a == I.b) |
| { |
| return I.a; |
| } |
| } |
| return TokenConstants.InvalidType; |
| } |
| } |
| |
| /// <summary>Returns the maximum value contained in the set.</summary> |
| /// <remarks>Returns the maximum value contained in the set.</remarks> |
| /// <returns> |
| /// the maximum value contained in the set. If the set is empty, this |
| /// method returns |
| /// <see cref="TokenConstants.InvalidType"/> |
| /// . |
| /// </returns> |
| public virtual int MaxElement |
| { |
| get |
| { |
| if (IsNil) |
| { |
| return TokenConstants.InvalidType; |
| } |
| Interval last = intervals[intervals.Count - 1]; |
| return last.b; |
| } |
| } |
| |
| /// <summary>Returns the minimum value contained in the set.</summary> |
| /// <remarks>Returns the minimum value contained in the set.</remarks> |
| /// <returns> |
| /// the minimum value contained in the set. If the set is empty, this |
| /// method returns |
| /// <see cref="TokenConstants.InvalidType"/> |
| /// . |
| /// </returns> |
| public virtual int MinElement |
| { |
| get |
| { |
| if (IsNil) |
| { |
| return TokenConstants.InvalidType; |
| } |
| return intervals[0].a; |
| } |
| } |
| |
| /// <summary>Return a list of Interval objects.</summary> |
| /// <remarks>Return a list of Interval objects.</remarks> |
| public virtual IList<Interval> GetIntervals() |
| { |
| return intervals; |
| } |
| |
| public override int GetHashCode() |
| { |
| int hash = MurmurHash.Initialize(); |
| foreach (Interval I in intervals) |
| { |
| hash = MurmurHash.Update(hash, I.a); |
| hash = MurmurHash.Update(hash, I.b); |
| } |
| hash = MurmurHash.Finish(hash, intervals.Count * 2); |
| return hash; |
| } |
| |
| /// <summary> |
| /// Are two IntervalSets equal? Because all intervals are sorted |
| /// and disjoint, equals is a simple linear walk over both lists |
| /// to make sure they are the same. |
| /// </summary> |
| /// <remarks> |
| /// Are two IntervalSets equal? Because all intervals are sorted |
| /// and disjoint, equals is a simple linear walk over both lists |
| /// to make sure they are the same. Interval.equals() is used |
| /// by the List.equals() method to check the ranges. |
| /// </remarks> |
| public override bool Equals(object obj) |
| { |
| if (obj == null || !(obj is Antlr4.Runtime.Misc.IntervalSet)) |
| { |
| return false; |
| } |
| Antlr4.Runtime.Misc.IntervalSet other = (Antlr4.Runtime.Misc.IntervalSet)obj; |
| return this.intervals.SequenceEqual(other.intervals); |
| } |
| |
| public override string ToString() |
| { |
| return ToString(false); |
| } |
| |
| public virtual string ToString(bool elemAreChar) |
| { |
| StringBuilder buf = new StringBuilder(); |
| if (this.intervals == null || this.intervals.Count == 0) |
| { |
| return "{}"; |
| } |
| if (this.Count > 1) |
| { |
| buf.Append("{"); |
| } |
| |
| bool first = true; |
| foreach (Interval I in intervals) |
| { |
| if (!first) |
| buf.Append(", "); |
| |
| first = false; |
| int a = I.a; |
| int b = I.b; |
| if (a == b) |
| { |
| if (a == TokenConstants.EOF) |
| { |
| buf.Append("<EOF>"); |
| } |
| else |
| { |
| if (elemAreChar) |
| { |
| buf.Append("'").Append((char)a).Append("'"); |
| } |
| else |
| { |
| buf.Append(a); |
| } |
| } |
| } |
| else |
| { |
| if (elemAreChar) |
| { |
| buf.Append("'").Append((char)a).Append("'..'").Append((char)b).Append("'"); |
| } |
| else |
| { |
| buf.Append(a).Append("..").Append(b); |
| } |
| } |
| } |
| if (this.Count > 1) |
| { |
| buf.Append("}"); |
| } |
| return buf.ToString(); |
| } |
| |
| public virtual string ToString(IVocabulary vocabulary) |
| { |
| StringBuilder buf = new StringBuilder(); |
| if (this.intervals == null || this.intervals.Count == 0) |
| { |
| return "{}"; |
| } |
| if (this.Count > 1) |
| { |
| buf.Append("{"); |
| } |
| |
| bool first = true; |
| foreach (Interval I in intervals) |
| { |
| if (!first) |
| buf.Append(", "); |
| |
| first = false; |
| int a = I.a; |
| int b = I.b; |
| if (a == b) |
| { |
| buf.Append(ElementName(vocabulary, a)); |
| } |
| else |
| { |
| for (int i = a; i <= b; i++) |
| { |
| if (i > a) |
| { |
| buf.Append(", "); |
| } |
| buf.Append(ElementName(vocabulary, i)); |
| } |
| } |
| } |
| if (this.Count > 1) |
| { |
| buf.Append("}"); |
| } |
| return buf.ToString(); |
| } |
| |
| [return: NotNull] |
| protected internal virtual string ElementName(IVocabulary vocabulary, int a) |
| { |
| if (a == TokenConstants.EOF) |
| { |
| return "<EOF>"; |
| } |
| else |
| { |
| if (a == TokenConstants.EPSILON) |
| { |
| return "<EPSILON>"; |
| } |
| else |
| { |
| return vocabulary.GetDisplayName(a); |
| } |
| } |
| } |
| |
| public virtual int Count |
| { |
| get |
| { |
| int n = 0; |
| int numIntervals = intervals.Count; |
| if (numIntervals == 1) |
| { |
| Interval firstInterval = this.intervals[0]; |
| return firstInterval.b - firstInterval.a + 1; |
| } |
| for (int i = 0; i < numIntervals; i++) |
| { |
| Interval I = intervals[i]; |
| n += (I.b - I.a + 1); |
| } |
| return n; |
| } |
| } |
| |
| public virtual ArrayList<int> ToIntegerList() |
| { |
| ArrayList<int> values = new ArrayList<int>(Count); |
| int n = intervals.Count; |
| for (int i = 0; i < n; i++) |
| { |
| Interval I = intervals[i]; |
| int a = I.a; |
| int b = I.b; |
| for (int v = a; v <= b; v++) |
| { |
| values.Add(v); |
| } |
| } |
| return values; |
| } |
| |
| public virtual IList<int> ToList() |
| { |
| IList<int> values = new ArrayList<int>(); |
| int n = intervals.Count; |
| for (int i = 0; i < n; i++) |
| { |
| Interval I = intervals[i]; |
| int a = I.a; |
| int b = I.b; |
| for (int v = a; v <= b; v++) |
| { |
| values.Add(v); |
| } |
| } |
| return values; |
| } |
| |
| public virtual HashSet<int> ToSet() |
| { |
| HashSet<int> s = new HashSet<int>(); |
| foreach (Interval I in intervals) |
| { |
| int a = I.a; |
| int b = I.b; |
| for (int v = a; v <= b; v++) |
| { |
| s.Add(v); |
| } |
| } |
| return s; |
| } |
| |
| public virtual int[] ToArray() |
| { |
| return ToIntegerList().ToArray(); |
| } |
| |
| public virtual void Remove(int el) |
| { |
| if (@readonly) |
| { |
| throw new InvalidOperationException("can't alter readonly IntervalSet"); |
| } |
| int n = intervals.Count; |
| for (int i = 0; i < n; i++) |
| { |
| Interval I = intervals[i]; |
| int a = I.a; |
| int b = I.b; |
| if (el < a) |
| { |
| break; |
| } |
| // list is sorted and el is before this interval; not here |
| // if whole interval x..x, rm |
| if (el == a && el == b) |
| { |
| intervals.RemoveAt(i); |
| break; |
| } |
| // if on left edge x..b, adjust left |
| if (el == a) |
| { |
| intervals[i] = Interval.Of(I.a + 1, I.b); |
| break; |
| } |
| // if on right edge a..x, adjust right |
| if (el == b) |
| { |
| intervals[i] = Interval.Of(I.a, I.b - 1); |
| break; |
| } |
| // if in middle a..x..b, split interval |
| if (el > a && el < b) |
| { |
| // found in this interval |
| int oldb = I.b; |
| intervals[i] = Interval.Of(I.a, el - 1); |
| // [a..x-1] |
| Add(el + 1, oldb); |
| } |
| } |
| } |
| |
| public virtual bool IsReadOnly |
| { |
| get |
| { |
| // add [x+1..b] |
| return @readonly; |
| } |
| } |
| |
| public virtual void SetReadonly(bool @readonly) |
| { |
| if (this.@readonly && !@readonly) |
| { |
| throw new InvalidOperationException("can't alter readonly IntervalSet"); |
| } |
| this.@readonly = @readonly; |
| } |
| |
| IIntSet IIntSet.AddAll(IIntSet set) |
| { |
| return AddAll(set); |
| } |
| |
| IIntSet IIntSet.And(IIntSet a) |
| { |
| return And(a); |
| } |
| |
| IIntSet IIntSet.Complement(IIntSet elements) |
| { |
| return Complement(elements); |
| } |
| |
| IIntSet IIntSet.Or(IIntSet a) |
| { |
| return Or(a); |
| } |
| |
| IIntSet IIntSet.Subtract(IIntSet a) |
| { |
| return Subtract(a); |
| } |
| } |
| } |