5 // Chris J Breisch (cjbreisch@altavista.net)
6 // Dennis Hayes (dennish@raytek.com)
8 // (C) 2002 Chris J Breisch
11 * Copyright (c) 2002-2003 Mainsoft Corporation.
12 * Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
21 * The above copyright notice and this permission notice shall be included in
22 * all copies or substantial portions of the Software.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 * DEALINGS IN THE SOFTWARE.
33 * This class allows to execute loop statement of VisualBasic .NET
37 using System
.Collections
;
38 using System
.ComponentModel
;
40 namespace Microsoft
.VisualBasic
.CompilerServices
42 [StandardModule
, EditorBrowsable(EditorBrowsableState
.Never
)]
43 sealed public class FlowControl
{
44 private FlowControl () {}
46 private sealed /*static (final)in mainsoft java code*/ class ObjectFor
{
47 public object Counter
;
51 public object StepValue
;
53 public bool PositiveStep
;
59 * This method check if the loop can continued.
60 * if the StepValue is positive it check that count is smaller than the limit.
61 * if the StepValue is negative it check that count is bigger than the limit.
65 * @return boolean True of the for next loop can continue and false otherwise.
67 public static bool ForNextCheckR4(float count
, float limit
, float StepValue
) {
68 bool positiveStep
= StepValue
> 0.0F
;
69 bool isCountSmallThenLimit
= count
<= limit
;
70 return positiveStep
? isCountSmallThenLimit
: !isCountSmallThenLimit
;
74 * This method check if the loop can continued.
75 * if the StepValue is positive it check that count is smaller than the limit.
76 * if the StepValue is negative it check that count is bigger than the limit.
80 * @return boolean True of the for next loop can continue and false otherwise.
82 public static bool ForNextCheckR8(double count
, double limit
, double StepValue
) {
83 bool positiveStep
= StepValue
> 0.0;
84 bool isCountSmallThenLimit
= count
<= limit
;
85 return positiveStep
? isCountSmallThenLimit
: !isCountSmallThenLimit
;
89 * This method check if the loop can continued.
90 * if the StepValue is positive it check that count is smaller than the limit.
91 * if the StepValue is negative it check that count is bigger than the limit.
95 * @return boolean True of the for next loop can continue and false otherwise.
97 public static bool ForNextCheckDec(Decimal count
, Decimal limit
, Decimal StepValue
) {
98 bool positiveStep
= StepValue
.CompareTo(Decimal
.Zero
) < 0;
99 bool isCountSmallThenLimit
= count
.CompareTo(limit
) >= 0;
100 return positiveStep
? isCountSmallThenLimit
: !isCountSmallThenLimit
;
104 * This method method updates the LoopFor reference and the Counter reference
105 * object according to the given params and returns if this loop can continue.
106 * @param Counter this loop counter value
107 * @param Start this loop start value
108 * @param Limit this loop limitation value
109 * @param StepValue this loop step value
110 * @param lfr the LoopFor reference object
111 * @param cr the Counter object reference
112 * @return boolean is the returned LoopFor object can continue.
114 public static bool ForLoopInitObj(
119 ref System
.Object lfr
,
120 ref System
.Object cr
) {
122 object CounterResult
= cr
;
125 throw new ArgumentException("Argument_InvalidNullValue1 " + " Start");
128 throw new ArgumentException("Argument_InvalidNullValue1 " + " Limit");
130 if (StepValue
== null) {
131 throw new ArgumentException("Argument_InvalidNullValue1 " + " Step");
133 //gets the type of all the given parameters
134 Type startType
= Start
.GetType();
135 Type limitType
= Limit
.GetType();
136 Type stepType
= StepValue
.GetType();
138 //gets the widest common type code
140 TypeCode commonTypeCode
= ObjectType
.GetWidestType(Start
, Limit
, false);
141 commonTypeCode
= ObjectType
.GetWidestType(StepValue
, commonTypeCode
);
142 if (commonTypeCode
== TypeCode
.String
) {
143 commonTypeCode
= TypeCode
.Double
;
145 if (commonTypeCode
== TypeCode
.Object
) {
147 //throw new ArgumentException(
148 // Utils.GetResourceString(
149 // "ForLoop_CommonType3",
150 // Utils.VBFriendlyName(startType),
151 // Utils.VBFriendlyName(limitType),
152 // Utils.VBFriendlyName(StepValue)));
153 throw new ArgumentException("ForLoop_CommonType3 startType limitType StepValue");
156 ObjectFor objectFor
= new ObjectFor();
157 TypeCode startTypeCode
= Type
.GetTypeCode(startType
);
158 TypeCode limitTypeCode
= Type
.GetTypeCode(limitType
);
159 TypeCode stepTypeCode
= Type
.GetTypeCode(stepType
);
160 Type enumType
= null;
162 bool isStartTypeValidEnum
= (startTypeCode
== commonTypeCode
) && (startType
.IsEnum
);
163 bool isLimitTypeValidEnum
= (limitTypeCode
== commonTypeCode
) && (limitType
.IsEnum
);
164 bool isStepTypeValidEnum
= (stepTypeCode
== commonTypeCode
) && (stepType
.IsEnum
);
166 bool isStartAndStepTypeEqual
= (startType
== stepType
);
167 bool isStartAndLimitTypeEqual
= (startType
== limitType
);
168 bool isStepAndLimitTypeEqual
= (stepType
== limitType
);
170 //the For loop has enum type in the following case
171 //1. step is enum and it's type code equal to commonTypeCode and start and
172 // limit don't meet this condition.
173 //2. step and start are enum and their type code equal to commonTypeCode and
174 // their types are equal. limit doesn't meet this condition about been enum
175 // or about been equal to commonTypeCode.
176 //3. step and limit are enum and their type code equal to commonTypeCode and
177 // their types are equal. start doesn't meet this condition about been enum
178 // or about been equal to commonTypeCode.
179 //4. step and limit and start are enum and their type code equal to commonTypeCode and
180 // their types are equal.
181 //5. start is enum and it's type code equal to commonTypeCode .step and
182 // limit don't meet this condition.
183 //6. limit is enum and it's type code equal to commonTypeCode .step and
184 // start don't meet this condition.
185 //7.start and limit are enum and their type code equal to commonTypeCode and
186 // their types are equal. step doesn't meet this condition about been enum
187 // or about been equal to commonTypeCode.
190 if (isStartTypeValidEnum
&& isLimitTypeValidEnum
&& isStepTypeValidEnum
191 && isStartAndStepTypeEqual
&& isStartAndLimitTypeEqual
)
192 enumType
= startType
;
193 else if (isStartTypeValidEnum
&& isStepTypeValidEnum
&& isStartAndStepTypeEqual
)
194 enumType
= startType
;
195 else if (isStartTypeValidEnum
&& isStepTypeValidEnum
&& isStartAndStepTypeEqual
)
196 enumType
= startType
;
197 else if (isStartTypeValidEnum
&& isLimitTypeValidEnum
&& isStartAndLimitTypeEqual
)
198 enumType
= startType
;
199 else if (isStartTypeValidEnum
&& !isLimitTypeValidEnum
&& !isStepTypeValidEnum
)
200 enumType
= startType
;
201 else if (!isStartTypeValidEnum
&& isLimitTypeValidEnum
&& !isStepTypeValidEnum
)
202 enumType
= limitType
;
203 else if (!isStartTypeValidEnum
&& !isLimitTypeValidEnum
&& isStepTypeValidEnum
)
206 objectFor
.EnumType
= enumType
;
208 //set the counter field of objectFor with Start value transleted to
209 // the widest common type code
210 objectFor
.Counter
= convertType(Start
, commonTypeCode
,"Start");
211 //set the Limit field of objectFor with Limit value transleted to
212 // the widest common type code
213 objectFor
.Limit
= convertType(Limit
, commonTypeCode
,"Limit");
214 //set the StepValue field of objectFor with StepValue value transleted to
215 // the widest common type code
216 objectFor
.StepValue
= convertType(StepValue
, commonTypeCode
,"Step");
217 //local is the value of zero in the widest common type code
219 object local
= ObjectType
.CTypeHelper(0, commonTypeCode
);
221 IComparable iComparable
= (IComparable
)objectFor
.StepValue
;
222 objectFor
.PositiveStep
= iComparable
.CompareTo(local
) >= 0;
224 // sets the loop for reference
227 //sets the counter reference
228 if (objectFor
.EnumType
!= null) {
229 cr
= Enum
.ToObject(objectFor
.EnumType
, objectFor
.Counter
);
232 cr
= objectFor
.Counter
;
234 return CheckContinueLoop(objectFor
);
237 private static object convertType(object original
, TypeCode typeCode
, string fieldName
) {
239 return ObjectType
.CTypeHelper(original
, typeCode
);
241 catch /*(Exception e)*/ {
242 throw new ArgumentException("ForLoop_ConvertToType3 " + fieldName
);
246 public static bool ForNextCheckObj(object Counter
, object LoopObj
,
247 ref System
.Object CounterResult
) {// throws java.lang.Exception
248 TypeCode generalTypeCode
= 0;
250 if (LoopObj
== null) {
251 //TODO: use resource for the correct execption.
252 throw new Exception("VB error message #92 ForNextCheckObj LoopObj cannot be null");
253 //throw ExceptionUtils.VbMakeException(92);//correct java version
255 if (Counter
== null) {
256 throw new NullReferenceException("Argument_InvalidNullValue1 " + " Counter");
258 //throw new NullReferenceException(
259 // Utils.GetResourceString(
260 // "Argument_InvalidNullValue1",
263 ObjectFor objectFor
= (ObjectFor
) LoopObj
;
265 IConvertible iConvertible_counter
= (IConvertible
)Counter
;
266 IConvertible iConvertible_step
= (IConvertible
) objectFor
.StepValue
;
268 TypeCode counterTypeCode
= iConvertible_counter
.GetTypeCode();
269 TypeCode stepTypeCode
= iConvertible_step
.GetTypeCode();
271 if (counterTypeCode
== stepTypeCode
&& counterTypeCode
!= TypeCode
.String
) {
272 generalTypeCode
= counterTypeCode
;
275 generalTypeCode
= ObjectType
.GetWidestType(counterTypeCode
, stepTypeCode
);
276 if (generalTypeCode
== TypeCode
.String
) {
277 generalTypeCode
= TypeCode
.Double
;
279 Counter
= convertType(Counter
, generalTypeCode
,"Start");
280 objectFor
.Limit
= convertType(objectFor
.Limit
, generalTypeCode
,"Limit");
281 objectFor
.StepValue
= convertType(objectFor
.StepValue
, generalTypeCode
,"Step");
283 //changes the counter field to be the sum of step and counter
284 objectFor
.Counter
= ObjectType
.AddObj(Counter
, objectFor
.StepValue
);
285 IConvertible iConvertible_objectCounter
= (IConvertible
)objectFor
.Counter
;
286 TypeCode objectCounterTypeCode
= iConvertible_objectCounter
.GetTypeCode();
288 //setting the counter in counter reference.
289 //if the for is enum type change counter to enum.
290 if (objectFor
.EnumType
!= null) {
291 CounterResult
= Enum
.ToObject(objectFor
.EnumType
, objectFor
.Counter
);
294 CounterResult
= objectFor
.Counter
;
297 //if the counter after the change didn't change it's type return true if
298 // the for object can continue loop and false otherwise.
299 //if the counter changed it's type change all for object fields to counter
300 //current type and return false.
301 if (objectCounterTypeCode
== generalTypeCode
) {
302 return CheckContinueLoop(objectFor
);
305 objectFor
.Limit
= ObjectType
.CTypeHelper(objectFor
.Limit
, objectCounterTypeCode
);
307 objectFor
.StepValue
=
308 ObjectType
.CTypeHelper(objectFor
.StepValue
, objectCounterTypeCode
);
314 * This method returns IEnumertator for a given array
315 * @param ary the given array
316 * @return IEnumerator the array's Enumerator
318 public static IEnumerator
ForEachInArr(Array ary
) {// throws java.lang.Exception
319 IEnumerator iEnumerator
= (IEnumerator
)ary
;//is ArrayStaticWrapper.GetEnumerator(ary); in java code.
320 if (iEnumerator
!= null)
322 throw ExceptionUtils
.VbMakeException(92);
326 * This method gets IEnumerator for a given object that implements IEnumerable
327 * @param obj the object that implements IEnumerable
328 * @return IEnumerator the object's IEnumerator.
330 public static IEnumerator
ForEachInObj(object obj
) {// throws java.lang.Exception
332 throw ExceptionUtils
.VbMakeException(91);
334 IEnumerable iEnumerable
= (IEnumerable
)obj
;
335 if (iEnumerable
!= null) {
336 IEnumerator iEnumerator
= iEnumerable
.GetEnumerator();
337 if (iEnumerator
!= null)
340 string s
= obj
.GetType().ToString();
341 ExceptionUtils
.ThrowException1(100, s
);
346 * This method set the next value of teh Enumerator in the reference.
347 * if there isn't next value , null is been set in the referece.
350 * @return boolean returns the value of enumerator.MoveNext().
352 public static bool ForEachNextObj(ref System
.Object obj
, IEnumerator enumerator
) {
353 if (enumerator
.MoveNext()) {
354 obj
= enumerator
.Current
;
362 * This method check if the loop can continued.
363 * if the step is positive it check that the counter is smaller than the limit.
364 * if the step is negative it check that the counter is bigger than the limit.
368 private static bool CheckContinueLoop(ObjectFor LoopFor
) {
370 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
371 IComparable iComparable
= (IComparable
)LoopFor
.Counter
;
373 if (iComparable
!= null) {
374 int i
= iComparable
.CompareTo(LoopFor
.Limit
);
375 bool isCountSmallThenLimit
= i
<=0;
376 return LoopFor
.PositiveStep
? isCountSmallThenLimit
: !isCountSmallThenLimit
;
378 throw new ArgumentException("Argument_IComparable2 loop control variable"); // + Utils.VBFriendlyName(LoopFor.Counter)));
379 //TODO: verify this and the above are the same and remove.
380 //throw new ArgumentException(Utils.GetResourceString(
381 // "Argument_IComparable2", "loop control variable",
382 // Utils.VBFriendlyName(LoopFor.Counter)));
386 * This method throws exception if the input is Valuetype
387 * @param obj the object that need to be checked
389 public static void CheckForSyncLockOnValueType(object obj
) {
391 //throw new NotImplementedException("MSVB.Compilerservices.flowcontrol needs help");
392 if (obj
!= null && obj
.GetType().IsValueType
)
393 throw new ArgumentException(Utils
.GetResourceString("SyncLockRequiresReferenceType1 "));
394 //TODO: verify this and the above are the same and remove.
395 //if (obj != null && ObjectStaticWrapper.GetType(obj).get_IsValueType())
396 // throw new ArgumentException(Utils.GetResourceString(
397 // "SyncLockRequiresReferenceType1",Utils.VBFriendlyName(obj)));