2005-05-13 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / Microsoft.VisualBasic / Microsoft.VisualBasic.CompilerServices / StringType.cs
1 //
2 // StringType.cs
3 //
4 // Author:
5 //   Chris J Breisch (cjbreisch@altavista.net) 
6 //   Francesco Delfino (pluto@tipic.com)
7 //       Dennis Hayes (dennish@raytek.com)
8 //
9 // (C) 2002 Chris J Breisch
10 //     2002 Tipic, Inc. (http://www.tipic.com)
11 //
12  /*
13   * Copyright (c) 2002-2003 Mainsoft Corporation.
14   * Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15   *
16   * Permission is hereby granted, free of charge, to any person obtaining a
17   * copy of this software and associated documentation files (the "Software"),
18   * to deal in the Software without restriction, including without limitation
19   * the rights to use, copy, modify, merge, publish, distribute, sublicense,
20   * and/or sell copies of the Software, and to permit persons to whom the
21   * Software is furnished to do so, subject to the following conditions:
22   * 
23   * The above copyright notice and this permission notice shall be included in
24   * all copies or substantial portions of the Software.
25   * 
26   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
31   * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32   * DEALINGS IN THE SOFTWARE.
33   */
34
35 using System;
36 using System.Globalization;
37 using System.Text;
38 using System.ComponentModel;
39
40 namespace Microsoft.VisualBasic.CompilerServices {
41         [StandardModule, EditorBrowsableAttribute(EditorBrowsableState.Never)] 
42         sealed public class StringType {
43                 private StringType () {}
44
45                 /**
46                  * This method is called when a seconf asterisk appears in the pattern.
47                  * @param pattern the relevant part of the original user pattern
48                  * @param source the relevanr part of the original user source string
49                  * @param count number of characters that where skipped due to the first 
50                  * asterisk. 
51                  * @param compareOption the comparision method Binary or Text
52                  * @return int number of characters that should be skipped due to all the 
53                  * asterisk that where found.
54                  */
55                 private static int multipleAsteriskSkip(
56                         string pattern,
57                         string source,
58                         int count,
59                         CompareMethod compareOption) {
60                         string subString;
61                         bool isLike;
62                         int length = (source == null) ? 0 : source.Length;
63                         while (count < length) {
64                                 subString = source.Substring(length - count);
65                                 try {
66                                         isLike = StrLike(subString, pattern, compareOption);
67                                 }
68                                 catch /*(Exception exp)*/ {
69                                         isLike = false;
70                                 }
71                                 if (!isLike)
72                                         count = count + 1;
73                                 else 
74                                         break;
75                         }
76                         return count;
77                 }
78     
79                 /**
80                  * This method determines the number of characters that can be skipped due to
81                  * the asterisk.
82                  * @param pattern the relevant part of the original user pattern
83                  * @param source the relevanr part of the original user source string
84                  * @param compareOption the comparision method Binary or Text
85                  * @return int number of characters that should be skipped due to all the 
86                  * asterisk that where found.
87                  */
88     
89                 private static int asteriskSkip(
90                         string pattern,
91                         string source,
92                         CompareMethod compareOption) {
93
94                         int sourceLength = source.Length;
95                         int numberOfSkipedChars = 0;
96                         int patternLen;
97                         int patternIndex = 0;
98                         bool exactMatch = false;
99                         string sub;
100                         char currentPatternChar;
101
102                         //java patternLen = Strings.Len(pattern); /elsewhere patteren.toString is used, why not here?
103                         patternLen = pattern.Length;
104                         while (patternIndex < patternLen) {
105              
106                                 currentPatternChar = pattern[patternIndex];
107                                 if (currentPatternChar == '*') {
108                                         //if in the original pattern the where two asterisks together the
109                                         //second is ignored 
110                                         if (numberOfSkipedChars > 0) {
111                                                 if (exactMatch) {
112                                                         numberOfSkipedChars =
113                                                                 multipleAsteriskSkip(
114                                                                 pattern,
115                                                                 source,
116                                                                 numberOfSkipedChars,
117                                                                 compareOption);
118                                                         return sourceLength - numberOfSkipedChars;
119                                                 }
120                                                 sub = pattern.Substring(0, patternIndex);
121                                                 numberOfSkipedChars =
122                                                         Strings.InStrRev(
123                                                         source,
124                                                         sub,
125                                                         source.Length,
126                                                         compareOption);
127                                                 return numberOfSkipedChars;
128                                         }
129                                 }
130                                 else if (currentPatternChar == '[') {
131                                         sub = pattern.Substring(patternIndex);
132                                         int skipCharInPattern = sub.IndexOf(']');
133                                         if (skipCharInPattern < 0)
134                                                 break;
135                                         if (skipCharInPattern != patternIndex + 1) {
136                                                 numberOfSkipedChars ++;
137                                         }
138                                         patternIndex += skipCharInPattern+1;    
139                                 }
140                                 else if (currentPatternChar == ']' || currentPatternChar == '?' || 
141                                         currentPatternChar == '#' || currentPatternChar == '!' ||
142                                         currentPatternChar == '-') {
143                                         numberOfSkipedChars++;
144                                         patternIndex ++;
145                                         exactMatch = true;
146                                 }
147                                 else {
148                                         numberOfSkipedChars++;
149                                         patternIndex++;         
150                                 }
151                         }
152                         //this value is returned if there are not more '*' in the pattern
153                         return sourceLength - numberOfSkipedChars;
154                 }
155
156                 public static string FromBoolean (bool Value) { 
157                         return Convert.ToString(Value);
158                 }
159
160                 public static string FromByte(byte Value) {
161                         return Convert.ToString(Value);
162                 }
163
164                 public static string FromChar(char Value) {
165                         return Convert.ToString(Value);
166                 }
167
168                 private static string FromCharAndCount(char Value, int count) {
169                         //return StringStaticWrapper.Ctor(Value,count);
170                         return Value.ToString().Substring(0,count);
171                 }
172
173                 private static string FromCharArray(char[] Value) {
174                         return new string(Value);
175                 }
176
177                 private static string FromCharArraySubset(
178                         char[] Value,
179                         int startIndex,
180                         int length) {
181                         return new string(Value, startIndex, length);
182                 }
183
184                 public static string FromDate(DateTime Value) {
185                         //TODO: which is right, Mono or Mainsoft
186                         //implmented in mono by
187                         //return Convert.ToString(Value);
188                 
189                         //implmented in java
190                         long lTime;
191                         TimeSpan ts;
192
193                         ts = Value.TimeOfDay;
194                         lTime = ts.Ticks;
195                         //if only the part of the hours ,minute ... is relevant (not day, month,
196                         // year) the format is "T"        
197                         if (lTime == Value.Ticks ||
198                                 (Value.Year == 1899
199                                 && Value.Month == 12
200                                 && Value.Day == 30))
201                                 return Value.ToString("T", null);
202                         // only the part of day,month and year is relevant , the format is "d".    
203                         if (lTime == 0)   
204                                 return Value.ToString("d", null);
205                         return Value.ToString("G", null);
206                 }
207
208                 public static string FromDecimal(Decimal Value) {
209                         return FromDecimal(Value, null);
210                 }
211
212                 public static string FromDecimal(Decimal Value, NumberFormatInfo NumberFormat) {
213                         return Convert.ToString(Value, NumberFormat);
214                         //java code return Value.ToString("G", numberFormat);
215                 }
216
217                 public static string FromDouble(double Value) {
218                         return Convert.ToString(Value);
219                         //java return FromDouble(Value, null);
220                 }
221
222                 public static string FromDouble(double Value, NumberFormatInfo NumberFormat) {
223                         return Convert.ToString(Value,NumberFormat);
224                         //return new ClrDouble(Value).ToString("G");
225                 }
226
227                 public static string FromInteger(int Value) {
228                         return Value.ToString();
229                 }
230
231                 public static string FromLong(long Value) {
232                         return Value.ToString();
233                         //return Convert.ToString(Value);
234                 }
235
236                 public static string FromShort(short Value) {
237                         return Value.ToString();
238                 }
239
240                 public static string FromSingle(float Value) {
241                         return Convert.ToString(Value);
242                         //return FromSingle(Value, null);
243                 }
244
245                 public static string FromSingle(float Value, NumberFormatInfo NumberFormat) {
246                         return Convert.ToString(Value,NumberFormat);
247                         //return new ClrSingle(Value).ToString(NumberFormat);
248                 }
249
250                 public static string FromObject(object Value) {
251                         if (Value == null)
252                                 return null;
253
254                         if (Value is string)
255                                 return (string) Value;
256
257                         if (
258                                 (Value is char[])
259                                 && ((Array)Value).Rank == 1)
260                                 return new string(CharArrayType.FromObject(Value));
261             
262                         return Convert.ToString(Value);   
263
264                 }
265
266
267                 /**
268                  * This method replace in the reference strDesRef parameter the characters 
269                  * from position  startPosition. the number of characters that are been replaced
270                  * is the minimum between maxInsertLength and the length of sInsert.
271                  * @param strDesRef the destination string reference. 
272                  * @param startPosition the index from which the change should be done.      
273                  * @param maxInsertLength the maximum number of characters that should be change.
274                  * @param sInsert the string from which the character should be taken
275                  */
276
277                 public static void MidStmtStr(ref string strDesRef, int startPosition, int maxInsertLength, string sInsert) 
278                 {
279                         int destLen = 0;
280                         int insertLen = 0;
281                         string dest = strDesRef;
282                 
283                         if (dest != null)
284                                 destLen = dest.Length;
285                         if (sInsert != null)
286                                 insertLen = sInsert.Length;
287                         else
288                                 return;    
289
290                         //change to java location in array.
291                         startPosition = startPosition - 1;
292                         if (startPosition < 0 || startPosition >= destLen) {
293                                 throw new ArgumentException("Invalid Argument Value", "Start");
294                                 //throw new IllegalArgumentException(//java
295                                 //      Utils.GetResourceString("Argument_InvalidValue1", "Start"));
296                         }
297                         if (maxInsertLength < 0) {
298                                 throw new ArgumentException("Invalid Argument Value", "Length");
299                                 //throw new IllegalArgumentException(//java
300                                 //      Utils.GetResourceString("Argument_InvalidValue1", "Length"));
301                         }
302                         if (insertLen > maxInsertLength)
303                                 insertLen = maxInsertLength;
304                         if (insertLen > destLen - startPosition)
305                                 insertLen = destLen - startPosition;
306                         if (insertLen == 0)
307                                 return;
308                         //TODO: are the next two lines equvlent to the 8 that follow?
309                         dest = dest.Remove(startPosition,insertLen);
310                         dest = dest.Insert(startPosition,sInsert.Substring(0,insertLen));
311                         //Java version
312                         //sb = new StringBuilder(dest);
313                         //if (sInsert.Length == insertLen)
314                         //      sb.Replace(startPosition ,startPosition + insertLen, sInsert);
315                         //else
316                         //      sb.Replace(
317                         //              startPosition,
318                         //              startPosition + insertLen,
319                         //              sInsert.Substring(0, insertLen));
320
321
322                         //strDesRef.setValue(sb.ToString());//java
323                         strDesRef = dest;//sb.ToString();
324                 }
325
326                 public static int StrCmp(string sLeft, string sRight, bool TextCompare) {
327                         if (sLeft == null)
328                                 sLeft = "";
329                         if (sRight == null)
330                                 sRight = "";
331
332                         if (TextCompare)
333                                 return string.Compare(sLeft, sRight, TextCompare);
334                         //return StringStaticWrapper.Compare(sLeft, sRight, TextCompare);
335                         return sLeft.CompareTo(sRight);
336                         // return StringStaticWrapper.CompareOrdinal(sLeft, sRight);
337                 }
338
339                 internal static string ToHalfwidthNumbers(string s) {
340                         return s;
341                 }
342
343                 private static bool compareBinary(
344                         bool seenNot,
345                         bool match,
346                         char patternChar,
347                         char sourceChar) {
348                         // if (seenNot ^ notMatch ) == true then a previous pattern character
349                         // matched the current source character . the current comparision is not
350                         // required
351                         if (seenNot ^ match )
352                                 return match;   
353                         else if (seenNot && match)
354                                 return patternChar != sourceChar;
355                         else 
356                                 return patternChar == sourceChar;
357                 }
358
359                 private static bool compare(        
360                         bool seenNot,
361                         bool match,
362                         char patternChar,
363                         char sourceChar) {
364                         // if (seenNot ^ notMatch ) == true then a previous pattern character
365                         // matched the current source character . the current comparision is not
366                         // required
367                         //if (seenNot ^ match )
368                         if (seenNot || match )
369                                 return match;         
370                         else if (seenNot && match)
371                                 return string.Compare(FromChar(patternChar), FromChar(sourceChar)) != 0;
372                         //return StringStaticWrapper.Compare(FromChar(patternChar), FromChar(sourceChar)) != 0;
373                         //else 
374                                 return string.Compare(FromChar(patternChar), FromChar(sourceChar)) == 0;
375 //                              return StringStaticWrapper.Compare(FromChar(patternChar), FromChar(sourceChar)) != 0;
376 //                      return StringStaticWrapper.Compare(FromChar(patternChar), FromChar(sourceChar)) != 0;
377 //                      else 
378 //                              return StringStaticWrapper.Compare(FromChar(patternChar), FromChar(sourceChar)) == 0;
379                 }
380
381                 /**
382                  * check if a specified string is an hex or oct representation of
383                  * an integer number
384                  * @param Value The string Value
385                  * @param res a long array (minimum size 1).
386                  * @return true if <code>Value<\code> can be parse into integer Value.
387                  * the result of parsing is located in the <code>res[0]<\code>.
388                  */
389                 internal static bool IsHexOrOctValue(string Value, long[] res) {
390                         try {
391                                 // if the string starts with '&h' or '&H' it represents an Hex number
392                                 if (Value.StartsWith("&H") || Value.StartsWith("&h"))
393                                         res[0] = Convert.ToInt64(Value.Substring(2), 16);
394                                         // if the string starts with '&o' or '&O' it represents an Oct number
395                                 else if (Value.StartsWith("&O") || Value.StartsWith("&o"))
396                                         res[0] = Convert.ToInt64(Value.Substring(2), 8);
397                                 else
398                                         return false;
399                         }
400                         catch /*(Java catches NumberFormatException, presumable passing all other excptions back up to the caller
401                                    * //TODO: we should narrow the ececptions that we catch here)*/ 
402                         {
403                         //catch (NumberFormatException e) {
404                                 return false;
405                         }
406                         return true;
407                 }
408     
409                 /**
410                  * This method matches a pattern between brackets and the relevant character.
411                  * The pattern matching is for binary comparision   
412                  * @param pattern the part of the pattern that is between the brackets without
413                  * the brackets 
414                  * @param sourceChar the relevant character in the source string
415                  * @return bool true if the character matches the pattern and false otherwise.
416                  */
417                 private static bool inBracketBinary(string pattern, char sourceChar) {
418                         char currentPatternChar = (char)0;
419                         char currentCharInRange = (char)0;
420                         char previousCharInRange = (char)0;
421                         char previousChar = (char)0;
422                         int patternIndex = 0;
423                         bool isMatch = false;
424                         bool isNotSignAppears = false;
425                         bool specialChar = false;
426                         bool isRangeSignAppears = false;
427                         int patternLength = (pattern == null)? 0 : pattern.Length;
428                         if (pattern.Length == 1) {
429                                 // Single Character
430                                 return (sourceChar == pattern[0]);
431                         }       
432
433                         previousCharInRange = pattern [0];
434                         while (patternIndex < patternLength) {
435                                 currentPatternChar = pattern[patternIndex];
436
437                                 if (currentPatternChar == '-') {
438                                         bool seenRangeSign = isRangeSignAppears;
439                                         if (previousCharInRange != (char)0)
440                                                 isRangeSignAppears = true;
441                                         if (seenRangeSign) {
442                                                 // The previous char was '-'
443                                                 // handle patterns like '--'
444                                                 if (patternIndex > 2 && pattern [patternIndex - 2] == '!') {
445                                                         // pattern is like !-- ....
446                                                         // so the first '-' (and not '!') is the lower bound of a range
447                                                         // the current pattern char '-' is the range char
448                                                         previousCharInRange = previousChar;
449                                                 } else if (patternIndex > 1) {
450                                                         // pattern like -- ...
451                                                         // the second '-' is the upper bound of a range
452                                                         specialChar = true;
453                                                         if (previousCharInRange > currentPatternChar)
454                                                                 throw new Exception ("Bad pattern string");
455                                                         if (sourceChar >= previousCharInRange && sourceChar <= currentPatternChar)
456                                                                 return (true ^ isNotSignAppears);
457                                                         else 
458                                                                 isMatch = false;
459                                                         previousCharInRange = (char) 0;
460                                                         isRangeSignAppears = false;
461                                                 } else 
462                                                         previousCharInRange = previousChar;
463                                         }
464
465                                         if (previousChar == '!' && !specialChar) {
466                                                 // Handle cases like !- ..
467                                                 // in this case '-' is a not treated as a range character
468                                                 specialChar = true;
469                                                 isRangeSignAppears = false;
470                                         }
471                                         
472                                         if (!isRangeSignAppears) {
473                                                 if (sourceChar == currentPatternChar)
474                                                         isMatch = true;
475                                                 else 
476                                                         isMatch = false;
477
478                                                 if (isMatch)
479                                                         return (isMatch ^ isNotSignAppears);
480                                         }
481                                 } else if (currentPatternChar == '!') {
482                                         if (!isNotSignAppears) {
483                                                 isNotSignAppears = true;
484                                         } else {
485                                                 specialChar = true;
486                                                 if (sourceChar == currentPatternChar)
487                                                         isMatch = true;
488                                                 else 
489                                                         isMatch = false;
490                                                 if (!isNotSignAppears && isMatch)
491                                                         return true;
492                                         }
493                                 } else {
494                                         if (isRangeSignAppears) {
495                                                 isRangeSignAppears = false;
496                                                 if (!(currentPatternChar == '*' ||
497                                                       currentPatternChar == '#' ||
498                                                       currentPatternChar == '?' ||
499                                                       currentPatternChar == '[')) {
500                                                         specialChar = true;
501                                                 }
502
503                                                 currentCharInRange = currentPatternChar;
504                                                 if (previousCharInRange > currentCharInRange)
505                                                         throw new Exception ("Bad pattern string");
506         
507                                                 if (sourceChar >= previousCharInRange && sourceChar <= currentCharInRange)
508                                                         isMatch = true;
509                                                 else 
510                                                         isMatch = false;
511
512                                                 if (isMatch)
513                                                         return (isMatch ^ isNotSignAppears);
514                                                 previousCharInRange = (char) 0;
515                                         } else {
516                                                 if (currentPatternChar == '*' ||
517                                                     currentPatternChar == '#' ||
518                                                     currentPatternChar == '?' ||
519                                                     currentPatternChar == '[') {
520                                                         specialChar = true;
521                                                 }
522                                                 previousCharInRange = currentPatternChar;
523                                                 if (sourceChar == currentPatternChar)
524                                                         isMatch = true;
525                                                 else 
526                                                         isMatch = false;
527                                                 if (isMatch)
528                                                         return (isMatch ^ isNotSignAppears);
529                                         }
530
531                                 }
532                                 previousChar = currentPatternChar;
533                                 patternIndex++;
534                         }
535
536
537                         if (isNotSignAppears ^ isMatch) 
538                                 return true;
539
540                         return false;
541                 }
542     
543                 /**
544                  * this method checks if the soutce string matches the pattern according to 
545                  * binary comparision.
546                  * @param source the source string 
547                  * @param pattern the pattern string
548                  * @return bool True if the source match the pattern and false otherwise.
549                  */
550
551                 public static bool StrLikeBinary(string source, string pattern) {
552
553                         bool startRangeSignAppears = false;
554                         bool isMatch = false;
555                         char currentPatternChar = (char)0;
556                         int patternLength = (char)0;
557                         int patternIndex = (char)0;
558                         char currentSourceChar = (char)0;
559                         //bool isRangeSignAppears = false;
560                         //bool specialChar = false;
561                         bool isNotSignAppears = false;
562                         int numberOfSkipedChars = 0;
563                         int sourceLength = 0;
564                         int sourceIndex = 0;
565          
566
567                         patternLength = (pattern == null)? 0 : pattern.Length;
568                         sourceLength = (source == null)? 0 : source.Length ;
569
570                         if (sourceIndex < sourceLength)
571                                 currentSourceChar = source[sourceIndex];
572
573                         while (patternIndex < patternLength) {
574                                 currentPatternChar = pattern[patternIndex];
575                                 if (currentPatternChar == '*') {
576                                         numberOfSkipedChars =
577                                                 asteriskSkip(
578                                                 pattern.Substring(patternIndex + 1),
579                                                 source.Substring(sourceIndex),
580                                                 CompareMethod.Binary);
581                                         if (numberOfSkipedChars < 0) {
582                                                 break;
583                                         }
584                                         if (numberOfSkipedChars > 0) {
585                                                 sourceIndex += numberOfSkipedChars;
586                                                 if (sourceIndex < sourceLength)
587                                                         currentSourceChar = source[sourceIndex];        
588                                                 else 
589                                                         currentSourceChar = (char) 0;
590                                         }
591                                 }
592                                 else if (currentPatternChar == '?') {
593                                         sourceIndex++;
594                                         if (sourceIndex < sourceLength)
595                                                 currentSourceChar = source[sourceIndex];
596                                         else 
597                                                 currentSourceChar = (char) 0;
598                                 }
599                                 else if (currentPatternChar == '#') {
600                                         if (!(char.IsDigit(currentSourceChar)))
601                                                 break;
602                                         sourceIndex++;
603                                         if (sourceIndex < sourceLength)
604                                                 currentSourceChar = source[sourceIndex];
605                                         else 
606                                                 currentSourceChar = (char) 0;
607                                 }          
608                                 else if (currentPatternChar == '-') {
609                                         isMatch =
610                                                 compareBinary(
611                                                 isNotSignAppears,
612                                                 isMatch,
613                                                 currentPatternChar,
614                                                 currentSourceChar);
615                                         sourceIndex++;
616                                         if (sourceIndex < sourceLength)
617                                                 currentSourceChar = source[sourceIndex];
618                                         else 
619                                                 currentSourceChar = (char) 0;
620                                         //isRangeSignAppears = true;
621                                 }
622                                 else if (currentPatternChar == '!') {
623                                         //specialChar = true;
624                                         isMatch =
625                                                 compareBinary(
626                                                 isNotSignAppears,
627                                                 isMatch,
628                                                 currentPatternChar,
629                                                 currentSourceChar);
630                                         sourceIndex++;
631                                         if (sourceIndex < sourceLength)
632                                                 currentSourceChar = source[sourceIndex];
633                                         else 
634                                                 currentSourceChar = (char) 0;
635                                 }
636                                 else if (currentPatternChar == '[') {
637                                         string sub = pattern.Substring(patternIndex);
638                                         int indexOfEndBracket = sub.IndexOf(']');
639                                         startRangeSignAppears = true;
640                                         if (indexOfEndBracket == -1)
641                                                 break;
642                                         sub = sub.Substring(1, indexOfEndBracket - 1);
643                                         startRangeSignAppears = false;
644                                         bool isOk = false;
645                                         // Ignore empty patterns like '[]'
646                                         if (!sub.Equals (String.Empty)) {
647                                                 isOk = inBracketBinary(sub, currentSourceChar);
648                                                 if (!isOk)                                 
649                                                         break;                
650                                                 sourceIndex++;
651                                         }
652                                         if (sourceIndex < sourceLength)
653                                                 currentSourceChar = source[sourceIndex];
654                                         else 
655                                                 currentSourceChar = (char) 0;
656                                         patternIndex += (sub.Length + 2);
657                                         continue;
658                                 }
659                                 else if (currentPatternChar == ']') {
660                                         //string sub = pattern.Substring(patternIndex);
661                                         isMatch =
662                                                 compareBinary(
663                                                 isNotSignAppears,
664                                                 isMatch,
665                                                 currentPatternChar,
666                                                 currentSourceChar);
667                                         if (!(isMatch))
668                                                 break;
669                                         sourceIndex++;
670                                         if (sourceIndex < sourceLength)
671                                                 currentSourceChar = source[sourceIndex];
672                                         isMatch = false;
673                                         //specialChar = false;
674                                         isNotSignAppears = false;
675                                         //isRangeSignAppears = false;
676                                 }
677                                 else if (currentPatternChar == currentSourceChar || isNotSignAppears) {
678                                         //specialChar = true;
679                                         isNotSignAppears = false;
680                                         sourceIndex++;
681                                         if (sourceIndex < sourceLength)
682                                                 currentSourceChar = source[sourceIndex];
683                                         else if (sourceIndex > sourceLength)
684                                                 return false;
685                                         else 
686                                                 currentSourceChar = (char) 0;
687                                 }
688                                 else
689                                         break;
690
691                                 patternIndex++;
692                         }
693                         if (startRangeSignAppears) {
694                                 if (sourceLength == 0)
695                                         return false;
696                                 throw new ArgumentException(Utils.GetResourceString("Argument_InvalidValue1", "Pattern"));
697                         }
698                         if (patternIndex != patternLength || sourceIndex != sourceLength)
699                                 return false;
700                         return true;
701                 }
702
703                 public static bool StrLike(
704                         string source,
705                         string pattern,
706                         CompareMethod compareOption) {
707                         if(compareOption == CompareMethod.Text)
708                                 return StrLikeText(source, pattern);
709                         else
710                                 return StrLikeBinary(source, pattern);
711                 }
712
713 //              /**
714 //               * this method checks if the soutce string matches the pattern according to
715 //               * the comparision method.
716 //               * @param source the source string 
717 //               * @param pattern the pattern string
718 //               * @param compareOption this param determines if the comparision is binary
719 //               * or text
720 //               * @return bool True if the source match the pattern and false otherwise.
721 //               */
722 //
723 //              public static bool StrLike(
724 //                      string source,
725 //                      string pattern,
726 //                      int compareOption) {
727 //                      if (compareOption == 0)
728 //                              
729 //                      
730 //              }
731     
732
733                 /**
734                  * this method checks if the soutce string matches the pattern according to 
735                  * binary comparision.
736                  * @param source the source string 
737                  * @param pattern the pattern string
738                  * @return bool True if the source match the pattern and false otherwise.
739                  */
740
741                 public static bool StrLikeText(string source, string pattern) {
742                         //char currentCharInRange = (char)0;
743                         bool startRangeSignAppears = false;
744                         bool isMatch = false;
745                         char currentPatternChar = (char)0;
746                         int patternLength = 0;
747                         int patternIndex = 0;
748                         char currentSourceChar = (char)0;
749                         //bool isRangeSignAppears = false;
750                         //bool specialChar = false;
751                         bool isNotSignAppears = false;
752                         int numberOfSkipedChars = 0;
753                         int sourceLength = 0;
754                         int sourceIndex = 0;
755                         //char previousCharInRange = (char)0;
756
757                         patternLength = (pattern == null)? 0 : pattern.Length;
758                         sourceLength = (source == null)? 0 : source.Length ;
759
760                         if (sourceIndex < sourceLength)
761                                 currentSourceChar = source[sourceIndex];
762
763                         while (patternIndex < patternLength) {
764                                 currentPatternChar = pattern[patternIndex];
765                                 if (currentPatternChar == '*') {
766                                         numberOfSkipedChars =
767                                                 asteriskSkip(
768                                                 pattern.Substring(patternIndex + 1),
769                                                 source.Substring(sourceIndex),
770                                                 CompareMethod.Text);
771                                         if (numberOfSkipedChars < 0) {
772                                                 break;
773                                         }
774                                         if (numberOfSkipedChars > 0) {
775                                                 sourceIndex += numberOfSkipedChars;
776                                                 if (sourceIndex < sourceLength)
777                                                         currentSourceChar = source[sourceIndex];
778                                                 else 
779                                                         currentSourceChar = (char) 0;
780                                         }
781                                 }
782                                 else if (currentPatternChar == '?') {
783                                         sourceIndex++;
784                                         if (sourceIndex < sourceLength)
785                                                 currentSourceChar = source[sourceIndex];
786                                         else 
787                                                 currentSourceChar = (char) 0;
788                                 }
789                                 else if (currentPatternChar == '#') {
790                                         if (!(char.IsDigit(currentSourceChar)))
791                                                 break;
792                                         sourceIndex++;
793                                         if (sourceIndex < sourceLength)
794                                                 currentSourceChar = source[sourceIndex];
795                                         else
796                                                 currentSourceChar = (char) 0;
797                                 }
798                                 else if (currentPatternChar == '-') {
799                                         isMatch =
800                                                 compare(
801                                                 isNotSignAppears,
802                                                 isMatch,
803                                                 currentPatternChar,
804                                                 currentSourceChar);
805                                         sourceIndex++;
806                                         if (sourceIndex < sourceLength)
807                                                 currentSourceChar = source[sourceIndex];
808                                         else
809                                                 currentSourceChar = (char) 0;
810                                         //isRangeSignAppears = true;
811                                 }
812                                 else if (currentPatternChar == '!') {
813                                         //specialChar = true;
814                                         isMatch =
815                                                 compare(
816                                                 isNotSignAppears,
817                                                 isMatch,
818                                                 currentPatternChar,
819                                                 currentSourceChar);
820                                         sourceIndex++;
821                                         if (sourceIndex < sourceLength)
822                                                 currentSourceChar = source[sourceIndex];
823                                         else
824                                                 currentSourceChar = (char) 0;
825                                 }
826                                 else if (currentPatternChar == '[') {
827                                         string sub = pattern.Substring(patternIndex);
828                                         int indexOfEndBracket = sub.IndexOf(']');
829                                         startRangeSignAppears = true;
830                                         if (indexOfEndBracket == -1)
831                                                 break;
832                                         sub = sub.Substring(1, indexOfEndBracket);
833                                         startRangeSignAppears = false;
834                                         bool isOk = false;
835                                         // Ignore empty patterns like []
836                                         if (!sub.Equals (String.Empty)) {
837                                                 isOk = inBracketBinary(sub, currentSourceChar);
838                                                 if (!isOk)
839                                                         break;
840                                                 sourceIndex++;
841                                         }
842                                         if (sourceIndex < sourceLength)
843                                                 currentSourceChar = source[sourceIndex];
844                                         else
845                                                 currentSourceChar = (char) 0;
846                                         patternIndex += (sub.Length + 2);
847                                         continue;
848                                 }
849                                 else if (currentPatternChar == ']') {
850                                         isMatch =
851                                                 compare(
852                                                 isNotSignAppears,
853                                                 isMatch,
854                                                 currentPatternChar,
855                                                 currentSourceChar);
856                                         //specialChar = true;
857                                         if (!(isMatch))
858                                                 break;
859                                         sourceIndex++;
860                                         if (sourceIndex < sourceLength)
861                                                 currentSourceChar = source[sourceIndex];
862                                         isMatch = false;
863                                         //specialChar = false;
864                                         isNotSignAppears = false;
865                                         //isRangeSignAppears = false;
866                                 }
867                                 else if (currentPatternChar == currentSourceChar || isNotSignAppears) {
868                                 
869                                         isNotSignAppears = false;
870                                         sourceIndex++;
871                                         if (sourceIndex < sourceLength)
872                                                 currentSourceChar = source[sourceIndex];
873                                         else if (sourceIndex > sourceLength)
874                                                 return false;
875                                         else
876                                                 currentSourceChar = (char) 0;
877                                 }
878                                 else
879                                         break;
880                                 patternIndex++;
881                         }
882                         if (startRangeSignAppears) {
883                                 if (sourceLength == 0)
884                                         return false;
885                                 throw new ArgumentException(Utils.GetResourceString("Argument_InvalidValue1", "Pattern"));
886                         }
887                         if (patternIndex != patternLength || sourceIndex != sourceLength)
888                                 return false;
889                         return true;
890                 }
891     
892                 /**
893                  * This method matches a pattern between brackets and the relevant character.
894                  * The pattern matching is for text comparision   
895                  * @param pattern the part of the pattern that is between the brackets without
896                  * the brackets 
897                  * @param sourceChar the relevant character in the source string
898                  * @return bool true if the character matches the pattern and false otherwise.
899                  */
900     
901                 private static bool inBracketText(string pattern, char sourceChar) {
902                         char currentPatternChar = (char)0;
903                         char currentCharInRange = (char)0;
904                         char previousCharInRange = (char)0;
905                         int patternIndex = 0;
906                         bool isMatch = false;
907                         bool isNotSignAppears = false;
908                         bool specialChar = false;
909                         bool isRangeSignAppears = false;
910                         int patternLength = (pattern == null)? 0 : pattern.Length;
911                         while (patternIndex < patternLength) {
912                                 currentPatternChar = pattern[patternIndex];
913                                 if (currentPatternChar == '*') {
914                                         isMatch =
915                                                 compare(                            
916                                                 isNotSignAppears,
917                                                 isMatch,
918                                                 currentPatternChar,
919                                                 sourceChar);
920                                         specialChar = true;
921                                 }
922                                 else if (currentPatternChar == '?') {
923                                         if (isRangeSignAppears) {
924                                                 isRangeSignAppears = false;
925                                                 currentCharInRange = currentPatternChar;
926                                                 if (previousCharInRange > currentCharInRange)
927                                                         throw new Exception("Bad patteren string");
928                                                         //throw (
929                                                         //      Exception) ExceptionUtils.VbMakeException(
930                                                         //      vbErrors.BadPatStr);
931                                                 //when the previous char in the range matches the char in
932                                                 // the source
933                                                 if (!(isNotSignAppears ^ isMatch)){
934                                                         if (!(string.Compare(
935                                                                 FromChar(previousCharInRange),
936                                                                 FromChar(sourceChar),
937                                                                 true)
938                                                                 >= 0
939                                                                 || string.Compare(
940                                                                 FromChar(currentCharInRange),
941                                                                 FromChar(sourceChar),
942                                                                 true)
943                                                                 < 0))
944                                                                 isMatch = true;
945                                                         if (isNotSignAppears)
946                                                                 isMatch = (isMatch == false);
947                                                 }
948                                         }
949                                                 // the first place in the range '[?'
950                                         else {
951                                                 previousCharInRange = currentPatternChar;
952                                                 specialChar = true;
953                                                 isMatch =
954                                                         compare(
955                                                         isNotSignAppears,
956                                                         isMatch,
957                                                         currentPatternChar,
958                                                         sourceChar);
959                                         }
960                                 }
961                                 else if (currentPatternChar == '#') {
962                                         // the pattern is '[previousCharInRange-#
963                                         if (isRangeSignAppears) {
964                                                 isRangeSignAppears = false;
965                                                 currentCharInRange = currentPatternChar;
966                                                 if (previousCharInRange > currentCharInRange)
967                                                         throw new Exception("Bad pattern string");
968                                                         //throw (Exception)ExceptionUtils.VbMakeException(vbErrors.BadPatStr);
969                                                 if (!(isNotSignAppears || isMatch)){
970                                                         if (!(string.Compare(
971                                                                 FromChar(previousCharInRange),
972                                                                 FromChar(sourceChar),
973                                                                 true)
974                                                                 >= 0
975                                                                 || string.Compare(
976                                                                 FromChar(currentCharInRange),
977                                                                 FromChar(sourceChar),
978                                                                 true)
979                                                                 < 0))
980                                                                 isMatch = true;
981                                                         if (isNotSignAppears)
982                                                                 isMatch = isMatch == false;
983                                                 }
984                                         }
985                                                 // the first place in the range '[#'
986                                         else {
987                                                 previousCharInRange = currentPatternChar;
988                                                 specialChar = true;
989                                                 isMatch =
990                                                         compare(
991                                                         isNotSignAppears,
992                                                         isMatch,
993                                                         currentPatternChar,
994                                                         sourceChar);
995                                         }
996                                 }
997                                 else if (currentPatternChar == '-') {
998                                         //this pattern is not valid example is '[9--'
999                                         if (isRangeSignAppears && specialChar)
1000                                                 throw new ArgumentException(Utils.GetResourceString("Argument_InvalidValue1", "Pattern"));
1001                                         if (!(specialChar) && !(isRangeSignAppears)) {
1002                                                 isMatch =
1003                                                         compare(isNotSignAppears, isMatch, currentPatternChar, sourceChar);
1004                                         }
1005                                         isRangeSignAppears = true;
1006                                 }
1007                                 else if (currentPatternChar == '!') {
1008                                         //this is the first symbol is the range
1009                                         if (!(isNotSignAppears)) {
1010                                                 isNotSignAppears = true;
1011                                                 isMatch = true;
1012                                         }
1013                                                 //this is the second '!' in the range '[!! ' or appears
1014                                                 //as a symbol in the pattern
1015                                         else {
1016                                                 specialChar = true;
1017                                                 isMatch =
1018                                                         compare(isNotSignAppears, isMatch, currentPatternChar, sourceChar);
1019                                         }
1020                                 }
1021                                 else if (currentPatternChar == '[') {
1022                                         if (isRangeSignAppears) {
1023                                                 isRangeSignAppears = false;
1024                                                 currentCharInRange = currentPatternChar;
1025                                                 if (previousCharInRange > currentCharInRange)
1026                                                         throw new Exception("Bad patteren string");
1027                                                         //throw (
1028                                                         //      Exception) ExceptionUtils.VbMakeException(
1029                                                         //      vbErrors.BadPatStr);
1030                                                 //when the previous char in the range matches the char in
1031                                                 // the source 
1032                                                 if (!(isNotSignAppears || isMatch)){
1033                                                         if (!(string.Compare(
1034                                                                 FromChar(previousCharInRange),
1035                                                                 FromChar(sourceChar),
1036                                                                 true)
1037                                                                 >= 0
1038                                                                 || string.Compare(
1039                                                                 FromChar(currentCharInRange),
1040                                                                 FromChar(sourceChar),
1041                                                                 true)
1042                                                                 < 0))
1043                                                                 isMatch = true;
1044                                                         if (isNotSignAppears)
1045                                                                 isMatch = (isMatch == false);
1046                                                 }
1047                                         }
1048                                                 // the first sign in the range of chars
1049                                         else {
1050                                                 previousCharInRange = currentPatternChar;
1051                                                 specialChar = true;
1052                                                 isMatch = compare(isNotSignAppears,isMatch,
1053                                                         currentPatternChar,sourceChar);
1054                                         }
1055                                 }
1056                                 else if (currentPatternChar == ']') {
1057                                         isMatch =
1058                                                 compare(
1059                                                 isNotSignAppears,
1060                                                 isMatch,
1061                                                 currentPatternChar,
1062                                                 sourceChar);
1063                                         if (!(isMatch))
1064                                                 break;
1065                                 }
1066                                         //this pattern char appears in range of chars.
1067                                 else {
1068                                         specialChar = true;
1069                                         if (isRangeSignAppears) {
1070                                                 isRangeSignAppears = false;
1071                                                 currentCharInRange = currentPatternChar;
1072                                                 if (previousCharInRange > currentCharInRange)
1073                                                         throw new Exception("Bad patteren string");
1074                                                         //throw (Exception)ExceptionUtils.VbMakeException(vbErrors.BadPatStr);
1075                                                 if (!(isNotSignAppears ^ isMatch)){
1076                                                         if (sourceChar <= previousCharInRange || sourceChar > currentCharInRange)
1077                                                                 isMatch = true;
1078                                                         else
1079                                                                 isMatch = false;    
1080                                                         if (isNotSignAppears)
1081                                                                 isMatch = !isMatch;
1082                                                 }
1083                                         }
1084                                         else {
1085                                                 previousCharInRange = currentPatternChar;
1086                                                 isMatch =
1087                                                         compare(isNotSignAppears, isMatch, currentPatternChar, sourceChar);
1088                                         }
1089                                 }
1090                                 patternIndex++;
1091
1092                         }
1093                         if (isNotSignAppears || isMatch) return true;
1094                         if (isRangeSignAppears && !isMatch)
1095                                 return false;
1096                         else if (isNotSignAppears) {
1097                                 if ('!' != sourceChar)
1098                                         return false;
1099                         }
1100                         return true;
1101                 }    
1102     
1103         }
1104 }