1 //
2 // EdgeMap.cs
3 //
4 // Authors:
5 // 	Alexander Chebaturkin (chebaturkin@gmail.com)
6 //
7 // Copyright (C) 2011 Alexander Chebaturkin
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 
29 using System;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.Linq;
33 using Mono.CodeContracts.Static.DataStructures;
34 
35 namespace Mono.CodeContracts.Static.ControlFlow {
36 	class EdgeMap<Tag> : IEnumerable<Edge<CFGBlock, Tag>>, IGraph<CFGBlock, Tag> {
37 		private readonly List<Edge<CFGBlock, Tag>> edges;
38 
EdgeMap(List<Edge<CFGBlock, Tag>> edges)39 		public EdgeMap (List<Edge<CFGBlock, Tag>> edges)
40 		{
41 			this.edges = edges;
42 			Resort ();
43 		}
44 
45 		public ICollection<Pair<Tag, CFGBlock>> this [CFGBlock node]
46 		{
47 			get { return new Successors (this, FindStartIndex (node)); }
48 		}
49 
50 		#region IEnumerable<Edge<CFGBlock,Tag>> Members
GetEnumerator()51 		public IEnumerator<Edge<CFGBlock, Tag>> GetEnumerator ()
52 		{
53 			return this.edges.GetEnumerator ();
54 		}
55 
IEnumerable.GetEnumerator()56 		IEnumerator IEnumerable.GetEnumerator ()
57 		{
58 			return GetEnumerator ();
59 		}
60 		#endregion
61 
62 		#region IGraph<CFGBlock,Tag> Members
63 		IEnumerable<CFGBlock> IGraph<CFGBlock, Tag>.Nodes
64 		{
65 			get { throw new InvalidOperationException(); }
66 		}
67 
Successors(CFGBlock node)68 		IEnumerable<Pair<Tag, CFGBlock>> IGraph<CFGBlock, Tag>.Successors (CFGBlock node)
69 		{
70 			return this [node];
71 		}
72 		#endregion
73 
Reverse()74 		public EdgeMap<Tag> Reverse ()
75 		{
76 			var newEdges = new List<Edge<CFGBlock, Tag>> (this.edges.Count);
77 
78 			newEdges.AddRange (this.edges.Select (edge => edge.Reversed ()));
79 
80 			return new EdgeMap<Tag> (newEdges);
81 		}
82 
CompareFirstBlockIndex(Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2)83 		private static int CompareFirstBlockIndex (Edge<CFGBlock, Tag> edge1, Edge<CFGBlock, Tag> edge2)
84 		{
85 			int cmp = edge1.From.Index - edge2.From.Index;
86 			if (cmp == 0)
87 				cmp = edge1.To.Index - edge2.To.Index;
88 
89 			return cmp;
90 		}
91 
FindStartIndex(CFGBlock from)92 		private int FindStartIndex (CFGBlock from)
93 		{
94 			//binary search
95 			int l = 0;
96 			int r = this.edges.Count;
97 			while (l < r) {
98 				int median = (l + r)/2;
99 				int medianBlockIndex = this.edges [median].From.Index;
100 
101 				if (medianBlockIndex == from.Index) {
102 					while (median > 0 && this.edges [median - 1].From.Index == medianBlockIndex)
103 						--median;
104 					return median;
105 				}
106 
107 				if (medianBlockIndex < from.Index)
108 					l = median + 1;
109 				else
110 					r = median;
111 			}
112 
113 			return this.edges.Count;
114 		}
115 
Filter(Predicate<Edge<CFGBlock, Tag>> keep)116 		public void Filter (Predicate<Edge<CFGBlock, Tag>> keep)
117 		{
118 			var notKeepEdges = new List<int> ();
119 			for (int i = 0; i < this.edges.Count; i++) {
120 				if (!keep (this.edges [i]))
121 					notKeepEdges.Add (i);
122 			}
123 
124 			if (notKeepEdges.Count == 0)
125 				return;
126 
127 			int ix = 0;
128 			foreach (int i in notKeepEdges) {
129 				this.edges.RemoveAt (i - ix);
130 				ix++;
131 			}
132 		}
133 
Resort()134 		public void Resort ()
135 		{
136 			this.edges.Sort (CompareFirstBlockIndex);
137 		}
138 
139 		#region Nested type: Successors
140 		private struct Successors : ICollection<Pair<Tag, CFGBlock>> {
141 			private readonly int start_index;
142 			private readonly EdgeMap<Tag> underlying;
143 
SuccessorsMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors144 			public Successors (EdgeMap<Tag> underlying, int startIndex)
145 			{
146 				this.underlying = underlying;
147 				this.start_index = startIndex;
148 			}
149 
150 			#region ICollection<Pair<Tag,CFGBlock>> Members
GetEnumeratorMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors151 			public IEnumerator<Pair<Tag, CFGBlock>> GetEnumerator ()
152 			{
153 				List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
154 				if (this.start_index < edges.Count) {
155 					int index = this.start_index;
156 					int blockIndex = edges [index].From.Index;
157 					do {
158 						yield return new Pair<Tag, CFGBlock> (edges [index].Tag, edges [index].To);
159 						++index;
160 					} while (index < edges.Count && edges [index].From.Index == blockIndex);
161 				}
162 			}
163 
IEnumerable.GetEnumeratorMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors164 			IEnumerator IEnumerable.GetEnumerator ()
165 			{
166 				return GetEnumerator ();
167 			}
168 
AddMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors169 			public void Add (Pair<Tag, CFGBlock> item)
170 			{
171 				throw new InvalidOperationException ();
172 			}
173 
ClearMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors174 			public void Clear ()
175 			{
176 				throw new InvalidOperationException ();
177 			}
178 
ContainsMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors179 			public bool Contains (Pair<Tag, CFGBlock> item)
180 			{
181 				throw new NotImplementedException ();
182 			}
183 
CopyToMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors184 			public void CopyTo (Pair<Tag, CFGBlock>[] array, int arrayIndex)
185 			{
186 				throw new NotImplementedException ();
187 			}
188 
RemoveMono.CodeContracts.Static.ControlFlow.EdgeMap.Successors189 			public bool Remove (Pair<Tag, CFGBlock> item)
190 			{
191 				throw new InvalidOperationException ();
192 			}
193 
194 			public int Count
195 			{
196 				get
197 				{
198 					int index = this.start_index;
199 					List<Edge<CFGBlock, Tag>> edges = this.underlying.edges;
200 					if (index >= edges.Count)
201 						return 0;
202 					int blockIndex = edges [index].From.Index;
203 
204 					int count = 0;
205 					do {
206 						++count;
207 						++index;
208 					} while (index < edges.Count && edges [index].From.Index == blockIndex);
209 
210 					return count;
211 				}
212 			}
213 
214 			public bool IsReadOnly
215 			{
216 				get { return true; }
217 			}
218 			#endregion
219 		}
220 		#endregion
221 	}
222 }
223