2 Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
\r
3 Permission is hereby granted, free of charge, to any person obtaining a copy
\r
4 of this software and associated documentation files (the "Software"), to deal
\r
5 in the Software without restriction, including without limitation the rights
\r
6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
7 copies of the Software, and to permit persons to whom the Software is
\r
8 furnished to do so, subject to the following conditions:
\r
10 The above copyright notice and this permission notice shall be included in
\r
11 all copies or substantial portions of the Software.
\r
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
16 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
17 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
18 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
22 // C5 example: ViewPatterns 2005-07-22
\r
25 // csc /r:C5.dll ViewPatterns.cs
\r
29 using SCG = System.Collections.Generic;
\r
31 namespace ViewPatterns {
\r
33 public static void Main(String[] args) {
\r
34 IList<char> lst = new ArrayList<char>();
\r
35 lst.AddAll<char>(new char[] { 'a', 'b', 'c', 'd' });
\r
36 IList<char> v1 = lst.View(1, 1);
\r
37 Console.WriteLine("v1 = {0}", v1);
\r
38 InsertBeforeFirst(v1, '<', 'b');
\r
39 InsertAfterFirst(v1, '>', 'b');
\r
40 Console.WriteLine("v1 = {0}", v1);
\r
42 if (SequencePredecessor(v1, 'b', out x))
\r
43 Console.WriteLine("Predecessor of b is " + x);
\r
44 if (SequenceSuccessor(v1, 'b', out x))
\r
45 Console.WriteLine("Successor of b is " + x);
\r
46 if (!SequencePredecessor(v1, 'c', out x))
\r
47 Console.WriteLine("c has no predecessor");
\r
48 if (!SequenceSuccessor(v1, 'a', out x))
\r
49 Console.WriteLine("a has no successor");
\r
50 IList<char> lst2 = new ArrayList<char>();
\r
51 lst2.AddAll<char>(new char[] { 'a', 'b', 'c', 'A', 'a', 'd', 'a' });
\r
52 foreach (int i in IndexesOf(lst2, 'a'))
\r
53 Console.Write("{0} ", i);
\r
54 Console.WriteLine();
\r
55 foreach (int i in ReverseIndexesOf(lst2, 'a'))
\r
56 Console.Write("{0} ", i);
\r
57 Console.WriteLine();
\r
58 Console.WriteLine(lst2);
\r
59 IList<char> view = lst2.View(2,0);
\r
60 InsertAtView(lst2, view, 'y');
\r
61 Console.WriteLine(lst2);
\r
62 InsertIntoView(view, 'x');
\r
63 Console.WriteLine(lst2);
\r
66 // --- Patterns for zero-item views -----------------------------
\r
68 // Number of items before zero-item view
\r
70 public static int ItemsBefore<T>(IList<T> view) {
\r
74 // Number of items after zero-item view
\r
76 public static int ItemsAfter<T>(IList<T> view) {
\r
77 return view.Underlying.Count - view.Offset;
\r
80 // Move (zero-item) view one item to the left
\r
82 public static void MoveLeft<T>(IList<T> view) {
\r
88 // Move (zero-item) view one item to the right
\r
90 public static void MoveRight<T>(IList<T> view) {
\r
96 // Test whether (zero-item) view is at beginning of list
\r
98 public static bool AtBeginning<T>(IList<T> view) {
\r
99 return view.Offset == 0;
\r
102 // Test whether (zero-item) view is at end of list
\r
104 public static bool AtEnd<T>(IList<T> view) {
\r
105 return view.Offset == view.Underlying.Count;
\r
108 // Insert x into zero-item view and into underlying list
\r
110 public static void InsertIntoView<T>(IList<T> view, T x) {
\r
114 // Insert x into list at zero-item view
\r
116 public static void InsertAtView<T>(IList<T> list, IList<T> view, T x) {
\r
117 list.Insert(view, x);
\r
120 // Delete the item before zero-item view
\r
122 public static void DeleteBefore<T>(IList<T> view) {
\r
123 view.Slide(-1,1).RemoveFirst();
\r
126 // Delete the item after zero-item view
\r
128 public static void DeleteAfter<T>(IList<T> view) {
\r
129 view.Slide(0,1).RemoveFirst();
\r
132 // Get the zero-item view at left endpoint. Succeeds on all lists
\r
133 // and valid views.
\r
135 public static IList<T> LeftEndView<T>(IList<T> list) {
\r
136 return list.View(0,0);
\r
139 // Get the zero-item view at right endpoint. Succeeds on all
\r
140 // lists and valid views.
\r
142 public static IList<T> RightEndView<T>(IList<T> list) {
\r
143 return list.View(list.Count,0);
\r
147 // --- Patterns for one-item views ------------------------------
\r
149 // Find the sequence predecessor x of y; or throw exception
\r
151 public static T SequencePredecessor<T>(IList<T> list, T y) {
\r
152 return list.ViewOf(y).Slide(-1)[0];
\r
155 // Find the sequence predecessor x of y; or return false
\r
157 public static bool SequencePredecessor<T>(IList<T> list, T y, out T x) {
\r
158 IList<T> view = list.ViewOf(y);
\r
159 bool ok = view != null && view.TrySlide(-1);
\r
160 x = ok ? view[0] : default(T);
\r
164 // Find the sequence successor x of y; or throw exception
\r
166 public static T SequenceSuccessor<T>(IList<T> list, T y) {
\r
167 return list.ViewOf(y).Slide(+1)[0];
\r
170 // Find the sequence successor x of y; or return false
\r
172 public static bool SequenceSuccessor<T>(IList<T> list, T y, out T x) {
\r
173 IList<T> view = list.ViewOf(y);
\r
174 bool ok = view != null && view.TrySlide(+1);
\r
175 x = ok ? view[0] : default(T);
\r
179 // Insert x into list after first occurrence of y (or throw
\r
180 // NullReferenceException).
\r
182 public static void InsertAfterFirst<T>(IList<T> list, T x, T y) {
\r
183 list.Insert(list.ViewOf(y), x);
\r
186 // Insert x into list before first occurrence of y (or throw
\r
187 // NullReferenceException)
\r
189 public static void InsertBeforeFirst<T>(IList<T> list, T x, T y) {
\r
190 list.Insert(list.ViewOf(y).Slide(0, 0), x);
\r
193 // Insert x into list after last occurrence of y (or throw
\r
194 // NullReferenceException).
\r
196 public static void InsertAfterLast<T>(IList<T> list, T x, T y) {
\r
197 list.Insert(list.LastViewOf(y), x);
\r
200 // Insert x into list before last occurrence of y (or throw
\r
201 // NullReferenceException)
\r
203 public static void InsertBeforeLast<T>(IList<T> list, T x, T y) {
\r
204 list.Insert(list.LastViewOf(y).Slide(0, 0), x);
\r
207 // Same meaning as InsertBeforeFirst on a proper list, but not on
\r
210 public static void InsertBeforeFirstAlt<T>(IList<T> list, T x, T y) {
\r
211 list.ViewOf(y).InsertFirst(x);
\r
214 // Delete the sequence predecessor of first y; or throw exception
\r
216 public static T RemovePredecessorOfFirst<T>(IList<T> list, T y) {
\r
217 return list.ViewOf(y).Slide(-1).Remove();
\r
220 // Delete the sequence successor of first y; or throw exception
\r
222 public static T RemoveSuccessorOfFirst<T>(IList<T> list, T y) {
\r
223 return list.ViewOf(y).Slide(+1).Remove();
\r
226 // --- Other view patterns --------------------------------------
\r
228 // Replace the first occurrence of each x from xs by y in list:
\r
230 public static void ReplaceXsByY<T>(HashedLinkedList<T> list, T[] xs, T y) {
\r
231 foreach (T x in xs) {
\r
232 using (IList<T> view = list.ViewOf(x)) {
\r
233 if (view != null) {
\r
241 // Get index in underlying list of view's left end
\r
243 public static int LeftEndIndex<T>(IList<T> view) {
\r
244 return view.Offset;
\r
247 // Get index in underlying list of view's right end
\r
249 public static int RightEndIndex<T>(IList<T> view) {
\r
250 return view.Offset + view.Count;
\r
253 // Test whether views overlap
\r
255 public static bool Overlap<T>(IList<T> u, IList<T> w) {
\r
256 if (u.Underlying == null || u.Underlying != w.Underlying)
\r
257 throw new ArgumentException("views must have same underlying list");
\r
259 return u.Offset < w.Offset+w.Count && w.Offset < u.Offset+u.Count;
\r
262 // Find the length of the overlap between two views
\r
264 public static int OverlapLength<T>(IList<T> u, IList<T> w) {
\r
266 return Math.Min(u.Offset+u.Count, w.Offset+w.Count)
\r
267 - Math.Max(u.Offset, w.Offset);
\r
269 return -1; // No overlap
\r
272 // Test whether view u contains view v
\r
274 public static bool ContainsView<T>(IList<T> u, IList<T> w) {
\r
275 if (u.Underlying == null || u.Underlying != w.Underlying)
\r
276 throw new ArgumentException("views must have same underlying list");
\r
279 return u.Offset <= w.Offset && w.Offset+w.Count <= u.Offset+u.Count;
\r
281 return u.Offset < w.Offset && w.Offset < u.Offset+u.Count;
\r
284 // Test whether views u and v have (or are) the same underlying list
\r
286 public static bool SameUnderlying<T>(IList<T> u, IList<T> w) {
\r
287 return (u.Underlying ?? u) == (w.Underlying ?? w);
\r
290 // Find the index of the first item that satisfies p
\r
292 public static int FindFirstIndex<T>(IList<T> list, Fun<T,bool> p) {
\r
293 using (IList<T> view = list.View(0, 0)) {
\r
294 while (view.TrySlide(0, 1)) {
\r
295 if (p(view.First))
\r
296 return view.Offset;
\r
303 // Find the index of the last item that satisfies p
\r
305 public static int FindLastIndex<T>(IList<T> list, Fun<T,bool> p) {
\r
306 using (IList<T> view = list.View(list.Count, 0)) {
\r
307 while (view.TrySlide(-1, 1)) {
\r
308 if (p(view.First))
\r
309 return view.Offset;
\r
315 // Yield indexes of all items equal to x, in list order:
\r
317 public static SCG.IEnumerable<int> IndexesOf<T>(IList<T> list, T x) {
\r
318 IList<T> tail = list.View(0, list.Count);
\r
319 tail = tail.ViewOf(x);
\r
320 while (tail != null) {
\r
321 yield return tail.Offset;
\r
322 tail = tail.Slide(+1,0).Span(list);
\r
323 tail = tail.ViewOf(x);
\r
327 // Yield indexes of items equal to x, in reverse list order.
\r
329 public static SCG.IEnumerable<int> ReverseIndexesOf<T>(IList<T> list, T x) {
\r
330 IList<T> head = list.View(0, list.Count);
\r
331 head = head.LastViewOf(x);
\r
332 while (head != null) {
\r
333 yield return head.Offset;
\r
334 head = list.Span(head.Slide(0,0));
\r
335 head = head.LastViewOf(x);
\r