|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 using System; |
|
18 using System.Text; |
|
19 using System.Text.RegularExpressions; |
|
20 |
|
21 namespace SymbianUtils.Range |
|
22 { |
|
23 public class AddressRange : IComparable<AddressRange> |
|
24 { |
|
25 #region Delegates & events |
|
26 public delegate void ChangeHandler( AddressRange aAddressRange ); |
|
27 public event ChangeHandler RangeChanged; |
|
28 #endregion |
|
29 |
|
30 #region Constructors |
|
31 public AddressRange() |
|
32 { |
|
33 } |
|
34 |
|
35 public AddressRange( string aSpecifier ) |
|
36 { |
|
37 this.Parse( aSpecifier ); |
|
38 } |
|
39 |
|
40 public AddressRange( uint aMin, uint aMax ) |
|
41 { |
|
42 iMin = aMin; |
|
43 iMax = aMax; |
|
44 } |
|
45 |
|
46 public AddressRange( long aMin, long aMax ) |
|
47 : this( (uint) aMin, (uint) aMax ) |
|
48 { |
|
49 } |
|
50 |
|
51 public AddressRange( AddressRange aCopy ) |
|
52 : this( aCopy.Min, aCopy.Max ) |
|
53 { |
|
54 } |
|
55 #endregion |
|
56 |
|
57 #region API |
|
58 public void Set( uint aMin, uint aMax ) |
|
59 { |
|
60 iMax = aMax; |
|
61 iMin = aMin; |
|
62 } |
|
63 |
|
64 public bool Contains( uint aAddress ) |
|
65 { |
|
66 bool ret = ( aAddress >= iMin && aAddress <= iMax ); |
|
67 return ret; |
|
68 } |
|
69 |
|
70 public bool Contains( long aAddress ) |
|
71 { |
|
72 bool ret = Contains( (uint) aAddress ); |
|
73 return ret; |
|
74 } |
|
75 |
|
76 public bool Contains( AddressRange aRange ) |
|
77 { |
|
78 bool ret = Contains( aRange.Min ) && Contains( aRange.Max ); |
|
79 return ret; |
|
80 } |
|
81 |
|
82 public void Reset() |
|
83 { |
|
84 iMin = uint.MaxValue; |
|
85 iMax = uint.MinValue; |
|
86 // |
|
87 OnChanging(); |
|
88 } |
|
89 |
|
90 public void Update( AddressRange aRange ) |
|
91 { |
|
92 AddressRange transaction = TransactionBegin(); |
|
93 // |
|
94 UpdateMin( aRange.Min ); |
|
95 UpdateMax( aRange.Max ); |
|
96 // |
|
97 TransactionEnd( transaction ); |
|
98 } |
|
99 |
|
100 public void UpdateMin( uint aProposedMin ) |
|
101 { |
|
102 uint old = iMin; |
|
103 iMin = Math.Min( iMin, aProposedMin ); |
|
104 // |
|
105 if ( old != iMin ) |
|
106 { |
|
107 OnChanging(); |
|
108 } |
|
109 } |
|
110 |
|
111 public void UpdateMax( uint aProposedMax ) |
|
112 { |
|
113 uint old = iMax; |
|
114 iMax = Math.Max( iMax, aProposedMax ); |
|
115 // |
|
116 if ( old != iMax ) |
|
117 { |
|
118 OnChanging(); |
|
119 } |
|
120 } |
|
121 |
|
122 public void UpdateMin( long aProposedMin ) |
|
123 { |
|
124 UpdateMin( (uint) aProposedMin ); |
|
125 } |
|
126 |
|
127 public void UpdateMax( long aProposedMax ) |
|
128 { |
|
129 UpdateMax( (uint) aProposedMax ); |
|
130 } |
|
131 |
|
132 public void Parse( string aValue ) |
|
133 { |
|
134 Match m = KRegEx.Match( aValue ); |
|
135 if ( m.Success ) |
|
136 { |
|
137 string min = m.Groups[ "Min" ].Value.Replace( "0x", string.Empty ); |
|
138 string max = m.Groups[ "Max" ].Value.Replace( "0x", string.Empty ); |
|
139 |
|
140 // Also need to know if they are hex or decimal specifiers |
|
141 int baseMin = ( m.Groups[ 0 ].Value == "0x" ? 16 : 10 ); |
|
142 int baseMax = ( m.Groups[ 1 ].Value == "0x" ? 16 : 10 ); |
|
143 |
|
144 // Now convert |
|
145 uint valueMin = System.Convert.ToUInt32( min, baseMin ); |
|
146 uint valueMax = System.Convert.ToUInt32( max, baseMax ); |
|
147 |
|
148 // Make range... |
|
149 AddressRange transaction = TransactionBegin(); |
|
150 // |
|
151 UpdateMin( valueMin ); |
|
152 UpdateMin( valueMax ); |
|
153 // |
|
154 TransactionEnd( transaction ); |
|
155 } |
|
156 else |
|
157 { |
|
158 throw new ArgumentException( "Invalid range format - expected [0x]AAA - [0x]BBB" ); |
|
159 } |
|
160 } |
|
161 #endregion |
|
162 |
|
163 #region Properties |
|
164 public uint Min |
|
165 { |
|
166 get { return iMin; } |
|
167 set |
|
168 { |
|
169 if ( iMin != value ) |
|
170 { |
|
171 iMin = value; |
|
172 OnChanging(); |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 public uint Max |
|
178 { |
|
179 get { return iMax; } |
|
180 set |
|
181 { |
|
182 if ( iMax != value ) |
|
183 { |
|
184 iMax = value; |
|
185 OnChanging(); |
|
186 } |
|
187 } |
|
188 } |
|
189 |
|
190 public uint Size |
|
191 { |
|
192 get |
|
193 { |
|
194 uint ret = Max - Min + 1; |
|
195 return ret; |
|
196 } |
|
197 } |
|
198 |
|
199 public bool IsValid |
|
200 { |
|
201 get |
|
202 { |
|
203 bool goodMin = ( iMin != uint.MaxValue ); |
|
204 bool goodMax = ( iMax != uint.MinValue ); |
|
205 // |
|
206 return ( goodMin && goodMax ); |
|
207 } |
|
208 } |
|
209 #endregion |
|
210 |
|
211 #region From System.Object |
|
212 public override string ToString() |
|
213 { |
|
214 StringBuilder ret = new StringBuilder(); |
|
215 ret.AppendFormat( "{0:x8}-{1:x8}", Min, Max ); |
|
216 return ret.ToString(); |
|
217 } |
|
218 |
|
219 public override int GetHashCode() |
|
220 { |
|
221 return (int) ( Min ^ Max ); |
|
222 } |
|
223 |
|
224 public override bool Equals( object aObject ) |
|
225 { |
|
226 bool ret = false; |
|
227 // |
|
228 if ( aObject != null ) |
|
229 { |
|
230 if ( aObject is AddressRange ) |
|
231 { |
|
232 AddressRange other = (AddressRange) aObject; |
|
233 // |
|
234 int compareMin = other.Min.CompareTo( this.Min ); |
|
235 int compareMax = other.Max.CompareTo( this.Max ); |
|
236 // |
|
237 ret = ( compareMin == 0 && compareMax == 0 ); |
|
238 } |
|
239 else |
|
240 { |
|
241 ret = base.Equals( aObject ); |
|
242 } |
|
243 } |
|
244 // |
|
245 return ret; |
|
246 } |
|
247 #endregion |
|
248 |
|
249 #region Operators |
|
250 public static implicit operator AddressRange( string aSpecifier ) |
|
251 { |
|
252 AddressRange ret = new AddressRange( aSpecifier ); |
|
253 return ret; |
|
254 } |
|
255 #endregion |
|
256 |
|
257 #region Internal regular expressions |
|
258 private static readonly Regex KRegEx = new Regex( |
|
259 "(?<Min>(?((0x))0x[A-Fa-f0-9]{1,8}|[0-9]{1,8}))\\s*\\-\\s*(?<"+ |
|
260 "Max>(?((0x))0x[A-Fa-f0-9]{1,8}|[0-9]{1,8}))", |
|
261 RegexOptions.CultureInvariant |
|
262 | RegexOptions.Compiled |
|
263 ); |
|
264 #endregion |
|
265 |
|
266 #region From IComparable<AddressRange5> |
|
267 public int CompareTo( AddressRange aOther ) |
|
268 { |
|
269 int ret = 1; |
|
270 // |
|
271 if ( aOther != null ) |
|
272 { |
|
273 ret = this.Min.CompareTo( aOther.Min ); |
|
274 } |
|
275 // |
|
276 return ret; |
|
277 } |
|
278 #endregion |
|
279 |
|
280 #region Internal methods |
|
281 private void OnChanging() |
|
282 { |
|
283 if ( !InTransaction ) |
|
284 { |
|
285 OnChanged(); |
|
286 } |
|
287 } |
|
288 |
|
289 protected virtual void OnChanged() |
|
290 { |
|
291 if ( RangeChanged != null ) |
|
292 { |
|
293 RangeChanged( this ); |
|
294 } |
|
295 } |
|
296 |
|
297 private bool InTransaction |
|
298 { |
|
299 get { return iTransactionCount > 0; } |
|
300 } |
|
301 |
|
302 private AddressRange TransactionBegin() |
|
303 { |
|
304 ++iTransactionCount; |
|
305 // |
|
306 AddressRange ret = new AddressRange( this.Min, this.Min ); |
|
307 return ret; |
|
308 } |
|
309 |
|
310 private void TransactionEnd( AddressRange aTransaction ) |
|
311 { |
|
312 System.Diagnostics.Debug.Assert( iTransactionCount > 0 ); |
|
313 --iTransactionCount; |
|
314 // |
|
315 if ( aTransaction.CompareTo( this ) != 0 ) |
|
316 { |
|
317 OnChanging(); |
|
318 } |
|
319 } |
|
320 #endregion |
|
321 |
|
322 #region Data members |
|
323 private uint iMin = uint.MaxValue; |
|
324 private uint iMax = uint.MinValue; |
|
325 private int iTransactionCount = 0; |
|
326 #endregion |
|
327 } |
|
328 } |