Range.cs
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license.
4 //
5 // Microsoft Bot Framework: http://botframework.com
6 //
7 // Bot Builder SDK GitHub:
8 // https://github.com/Microsoft/BotBuilder
9 //
10 // Copyright (c) Microsoft Corporation
11 // All rights reserved.
12 //
13 // MIT License:
14 // Permission is hereby granted, free of charge, to any person obtaining
15 // a copy of this software and associated documentation files (the
16 // "Software"), to deal in the Software without restriction, including
17 // without limitation the rights to use, copy, modify, merge, publish,
18 // distribute, sublicense, and/or sell copies of the Software, and to
19 // permit persons to whom the Software is furnished to do so, subject to
20 // the following conditions:
21 //
22 // The above copyright notice and this permission notice shall be
23 // included in all copies or substantial portions of the Software.
24 //
25 // THE SOFTWARE IS PROVIDED ""AS IS"", WITHOUT WARRANTY OF ANY KIND,
26 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 //
33 
34 using System;
35 using System.Collections.Generic;
36 using System.Linq;
37 
38 namespace Microsoft.Bot.Builder.Internals.Fibers
39 {
40  public static partial class Range
41  {
42  public static Range<T> From<T>(T start, T after)
43  where T : IEquatable<T>, IComparable<T>
44  {
45  return new Range<T>(start, after);
46  }
47  }
48 
49  public struct Range<T> : IEquatable<Range<T>>, IComparable<Range<T>> where T : IEquatable<T>, IComparable<T>
50  {
51  public T Start { get; }
52  public T After { get; }
53 
54  public Range(T start, T after)
55  {
56  this.Start = start;
57  this.After = after;
58  }
59 
60  public override bool Equals(object other)
61  {
62  return other is Range<T> && this.Equals((Range<T>)other);
63  }
64 
65  public override int GetHashCode()
66  {
67  return this.Start.GetHashCode() ^ this.After.GetHashCode();
68  }
69 
70  public override string ToString()
71  {
72  return $"[{this.Start}, {this.After})";
73  }
74 
75  public bool Equals(Range<T> other)
76  {
77  return this.Start.Equals(other.Start) && this.After.Equals(other.After);
78  }
79 
80  public int CompareTo(Range<T> other)
81  {
82  if (this.After.CompareTo(other.Start) < 0)
83  {
84  return -1;
85  }
86  else if (other.After.CompareTo(this.Start) > 0)
87  {
88  return +1;
89  }
90  else
91  {
92  return 0;
93  }
94  }
95  }
96 
97  public static partial class Extensions
98  {
99  public static IEnumerable<int> Enumerate(this Range<int> range)
100  {
101  for (int index = range.Start; index < range.After; ++index)
102  {
103  yield return index;
104  }
105  }
106 
107  public static T Min<T>(T one, T two) where T : IComparable<T>
108  {
109  var compare = one.CompareTo(two);
110  return compare < 0 ? one : two;
111  }
112 
113  private static bool Advance<T>(IEnumerator<Range<T>> enumerator, ref T index, T after)
114  where T : IEquatable<T>, IComparable<T>
115  {
116  index = after;
117  var compare = index.CompareTo(enumerator.Current.After);
118  if (compare < 0)
119  {
120  return true;
121  }
122  else if (compare == 0)
123  {
124  bool more = enumerator.MoveNext();
125  if (more)
126  {
127  index = enumerator.Current.Start;
128  }
129  return more;
130  }
131  else
132  {
133  throw new InvalidOperationException();
134  }
135  }
136 
137  public static IEnumerable<Range<T>> SortedMerge<T>(this IEnumerable<Range<T>> oneItems, IEnumerable<Range<T>> twoItems)
138  where T : IEquatable<T>, IComparable<T>
139  {
140  using (var one = oneItems.GetEnumerator())
141  using (var two = twoItems.GetEnumerator())
142  {
143  T oneIndex = default(T);
144  T twoIndex = default(T);
145 
146  bool oneMore = one.MoveNext();
147  bool twoMore = two.MoveNext();
148 
149  if (oneMore)
150  {
151  oneIndex = one.Current.Start;
152  }
153  if (twoMore)
154  {
155  twoIndex = two.Current.Start;
156  }
157 
158  if (oneMore && twoMore)
159  {
160  while (true)
161  {
162  var compare = oneIndex.CompareTo(twoIndex);
163  if (compare < 0)
164  {
165  var after = Min(one.Current.After, twoIndex);
166  oneMore = Advance(one, ref oneIndex, after);
167  if (!oneMore)
168  {
169  break;
170  }
171  }
172  else if (compare == 0)
173  {
174  var after = Min(one.Current.After, two.Current.After);
175  yield return new Range<T>(oneIndex, after);
176  oneMore = Advance(one, ref oneIndex, after);
177  twoMore = Advance(two, ref twoIndex, after);
178  if (!(oneMore && twoMore))
179  {
180  break;
181  }
182  }
183  else if (compare > 0)
184  {
185  var after = Min(two.Current.After, oneIndex);
186  twoMore = Advance(two, ref twoIndex, after);
187  if (!twoMore)
188  {
189  break;
190  }
191  }
192  else
193  {
194  throw new InvalidOperationException();
195  }
196  }
197  }
198  }
199  }
200  }
201 }
override bool Equals(object other)
Definition: Range.cs:60
static IEnumerable< int > Enumerate(this Range< int > range)
Definition: Range.cs:99