Fixed API: added missing attribute System.Serializable
[mono.git] / mcs / class / Microsoft.VisualBasic / Microsoft.VisualBasic / Strings.cs
1 //
2 // Strings.cs
3 //
4 // Authors:
5 //   Martin Adoue (martin@cwanet.com)
6 //   Chris J Breisch (cjbreisch@altavista.net)
7 //   Francesco Delfino (pluto@tipic.com)
8 //   Daniel Campos (danielcampos@netcourrier.com)
9 //   Rafael Teixeira (rafaelteixeirabr@hotmail.com)
10 //   Jochen Wezel (jwezel@compumaster.de)
11 //   Dennis Hayes (dennish@raytek.com)
12 //
13 // (C) 2002 Ximian Inc.
14 //     2002 Tipic, Inc. (http://www.tipic.com)
15 //     2003 CompuMaster GmbH (http://www.compumaster.de)
16 //     2004 Novell
17 //
18
19 //
20 // Copyright (c) 2002-2003 Mainsoft Corporation.
21 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
22 //
23 // Permission is hereby granted, free of charge, to any person obtaining
24 // a copy of this software and associated documentation files (the
25 // "Software"), to deal in the Software without restriction, including
26 // without limitation the rights to use, copy, modify, merge, publish,
27 // distribute, sublicense, and/or sell copies of the Software, and to
28 // permit persons to whom the Software is furnished to do so, subject to
29 // the following conditions:
30 // 
31 // The above copyright notice and this permission notice shall be
32 // included in all copies or substantial portions of the Software.
33 // 
34 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
35 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
36 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
37 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
38 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
39 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
40 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 //
42
43 using System;
44 using System.Text;
45 using System.ComponentModel;
46
47 using System.Runtime.InteropServices;
48 using Microsoft.VisualBasic.CompilerServices;
49
50 namespace Microsoft.VisualBasic
51 {
52         /// <summary>
53         /// The Strings module contains procedures used to perform string operations. 
54         /// </summary>
55
56         [StandardModule] 
57         [StructLayout(LayoutKind.Auto)] 
58         public class Strings
59         {
60                 private Strings()
61                 {
62                         //Do nothing. Nobody should be creating this.
63                 }
64
65                 
66                 /// <summary>
67                 /// Returns an Integer value representing the character code corresponding to a character.
68                 /// </summary>
69                 /// <param name="String">Required. Any valid Char or String expression. If String is a String expression, only the first character of the string is used for input. If String is Nothing or contains no characters, an ArgumentException error occurs.</param>
70                 public static int Asc(char String) 
71                 {
72                         //FIXME: Check the docs, it says something about Locales, DBCS, etc.
73
74                         //2003-12-29 JW
75                         //TODO: for some ideas/further documentation (currently not much), see the Strings test unit
76                         //              1. Byte count (switching of CurrentCulture isn't relevant but current machine's setting)
77                         //              2. Little or big endian
78                         //Tipp: use a western OS and at least a japanese Windows to do the testings!
79                         //
80
81                         return (int)String;
82                 }
83
84
85                 /// <summary>
86                 /// Returns an Integer value representing the character code corresponding to a character.
87                 /// </summary>
88                 /// <param name="String">Required. Any valid Char or String expression. If String is a String expression, only the first character of the string is used for input. If String is Nothing or contains no characters, an ArgumentException error occurs.</param>
89                 public static int Asc(string String)
90                 {
91                         if ((String == null) || (String.Length < 1))
92                                 throw new ArgumentException("Length of argument 'String' must be at least one.", "String");
93
94                         return Asc(String[0]);
95                 }
96
97
98                 /// <summary>
99                 /// Returns an Integer value representing the character code corresponding to a character.
100                 /// </summary>
101                 /// <param name="String">Required. Any valid Char or String expression. If String is a String expression, only the first character of the string is used for input. If String is Nothing or contains no characters, an ArgumentException error occurs.</param>
102                 public static int AscW(char String) 
103                 {
104                         /*
105                          * AscW returns the Unicode code point for the input character. 
106                          * This can be 0 through 65535. The returned value is independent 
107                          * of the culture and code page settings for the current thread.
108                          */
109                                 return (int) String;
110                 }
111                 
112                 /// <summary>
113                 /// Returns an Integer value representing the character code corresponding to a character.
114                 /// </summary>
115                 /// <param name="String">Required. Any valid Char or String expression. If String is a String expression, only the first character of the string is used for input. If String is Nothing or contains no characters, an ArgumentException error occurs.</param>
116                 public static int AscW(string String) 
117                 {
118                         /*
119                          * AscW returns the Unicode code point for the input character. 
120                          * This can be 0 through 65535. The returned value is independent 
121                          * of the culture and code page settings for the current thread.
122                          */
123                         if ((String == null) || (String.Length == 0))
124                                 throw new ArgumentException("Length of argument 'String' must be at least one.", "String");
125
126                         return AscW(String[0]);
127                 }
128
129                 /// <summary>
130                 /// Returns the character associated with the specified character code.
131                 /// </summary>
132                 /// <param name="CharCode">Required. An Integer expression representing the code point, or character code, for the character. If CharCode is outside the range -32768 through 65535, an ArgumentException error occurs.</param>
133                 public static char Chr(int CharCode) 
134                 {
135
136                         // According to docs (ms-help://MS.VSCC/MS.MSDNVS/vblr7/html/vafctchr.htm)
137                         // Chr and ChrW should throw ArgumentException if ((CharCode < -32768) || (CharCode > 65535))
138                         // Instead, VB.net throws an OverflowException. I'm following the implementation
139                         // instead of the docs. 
140
141                         if ((CharCode < -32768) || (CharCode > 65535))
142                                 throw new OverflowException("Value was either too large or too small for a character.");
143
144                         //FIXME: Check the docs, it says something about Locales, DBCS, etc.
145                         return System.Convert.ToChar(CharCode);
146                 }
147
148                 /// <summary>
149                 /// Returns the character associated with the specified character code.
150                 /// </summary>
151                 /// <param name="CharCode">Required. An Integer expression representing the code point, or character code, for the character. If CharCode is outside the range -32768 through 65535, an ArgumentException error occurs.</param>
152                 public static char ChrW(int CharCode ) 
153                 {
154                         /*
155                          * According to docs ()
156                          * Chr and ChrW should throw ArgumentException if ((CharCode < -32768) || (CharCode > 65535))
157                          * Instead, VB.net throws an OverflowException. I'm following the implementation
158                          * instead of the docs
159                          */
160                         if ((CharCode < -32768) || (CharCode > 65535))
161                                 throw new OverflowException("Value was either too large or too small for a character.");
162
163                         /*
164                          * ChrW takes CharCode as a Unicode code point. The range is independent of the 
165                          * culture and code page settings for the current thread. Values from -32768 through 
166                          * -1 are treated the same as values in the range +32768 through +65535.
167                          */
168                         if (CharCode < 0)
169                                 CharCode += 0x10000;
170
171                         return System.Convert.ToChar(CharCode);
172                 }
173
174                 /// <summary>
175                 /// Returns a zero-based array containing a subset of a String array based on specified filter criteria.
176                 /// </summary>
177                 /// <param name="Source">Required. One-dimensional array of strings to be searched.</param>
178                 /// <param name="Match">Required. String to search for.</param>
179                 /// <param name="Include">Optional. Boolean value indicating whether to return substrings that include or exclude Match. If Include is True, the Filter function returns the subset of the array that contains Match as a substring. If Include is False, the Filter function returns the subset of the array that does not contain Match as a substring.</param>
180                 /// <param name="Compare">Optional. Numeric value indicating the kind of string comparison to use. See Settings for values.</param>
181                 public static string[] Filter(object[] Source, 
182                         string Match, 
183                         [Optional]
184                         [DefaultValue(true)] 
185                         bool Include,
186                         [OptionCompare] [Optional]
187                         [DefaultValue(CompareMethod.Binary)] 
188                         CompareMethod Compare)
189                 {
190                         if (Source == null)
191                                 throw new ArgumentException("Argument 'Source' can not be null.", "Source");
192                         if (Source.Rank > 1)
193                                 throw new ArgumentException("Argument 'Source' can have only one dimension.", "Source");
194
195                         string[] strings;
196                         strings = new string[Source.Length];
197
198                         Source.CopyTo(strings, 0);
199                         return Filter(strings, Match, Include, Compare);
200
201                 }
202
203                 /// <summary>
204                 /// Returns a zero-based array containing a subset of a String array based on specified filter criteria.
205                 /// </summary>
206                 /// <param name="Source">Required. One-dimensional array of strings to be searched.</param>
207                 /// <param name="Match">Required. String to search for.</param>
208                 /// <param name="Include">Optional. Boolean value indicating whether to return substrings that include or exclude Match. If Include is True, the Filter function returns the subset of the array that contains Match as a substring. If Include is False, the Filter function returns the subset of the array that does not contain Match as a substring.</param>
209                 /// <param name="Compare">Optional. Numeric value indicating the kind of string comparison to use. See Settings for values.</param>
210                 public static string[] Filter(string[] Source, 
211                         string Match, 
212                         [Optional]
213                         [DefaultValue(true)] 
214                         bool Include,
215                         [Optional]
216                         [DefaultValue(CompareMethod.Binary)] 
217                         CompareMethod Compare)
218                 {
219                         if (Source == null)
220                                 throw new ArgumentException("Argument 'Source' can not be null.", "Source");
221                         if (Source.Rank > 1)
222                                 throw new ArgumentException("Argument 'Source' can have only one dimension.", "Source");
223
224                         /*
225                          * Well, I don't like it either. But I figured that two iterations
226                          * on the array would be better than many aloocations. Besides, this
227                          * way I can isolate the special cases.
228                          * I'd love to hear from a different approach.
229                          */
230
231                         int count = Source.Length;
232                         bool[] matches = new bool[count];
233                         int matchesCount = 0;
234
235                         for (int i = 0; i < count; i++)
236                         {
237                                 if (InStr(1, Source[i], Match, Compare) != 0)
238                                 {
239                                         //found one more
240                                         matches[i] = true;
241                                         matchesCount ++;
242                                 }
243                                 else
244                                 {
245                                         matches[i] = false;
246                                 }
247                         }
248
249                         if (matchesCount == 0)
250                         {
251                                 if (Include)
252                                         return new string[0];
253                                 else
254                                         return Source;
255                         }
256                         else
257                         {
258                                 if (matchesCount == count)
259                                 {
260                                         if (Include)
261                                                 return Source;
262                                         else
263                                                 return new string[0];
264                                 }
265                                 else
266                                 {
267                                         string[] ret;
268                                         int j = 0;
269                                         if (Include)
270                                                 ret = new string [matchesCount];
271                                         else
272                                                 ret = new string [count - matchesCount];
273
274                                         for (int i=0; i < count; i++)
275                                         {
276                                                 if ((matches[i] && Include) || !(matches[i] || Include))
277                                                 {
278                                                         ret[j] = Source[i];
279                                                         j++;
280                                                 }
281                                         }
282                                         return ret;
283                                 }
284                         }
285                 }
286
287                 /// <summary>
288                 /// Returns a string formatted according to instructions contained in a format String expression.
289                 /// </summary>
290                 /// <param name="Expression">Required. Any valid expression.</param>
291                 /// <param name="Style">Optional. A valid named or user-defined format String expression. </param>
292                 public static string Format(object expression, [Optional][DefaultValue("")]string style)
293                 {
294                         string returnstr=null;
295                         string expstring=expression.GetType().ToString();;
296                         switch(expstring)
297                         {
298                                 case "System.Char":
299                                         if ( style!="")
300                                                 throw new System.ArgumentException("'expression' argument has a not valid value");
301                                         returnstr=Convert.ToChar(expression).ToString();
302                                         break;
303                                 case "System.String":
304                                         if (style == "")
305                                                 returnstr=expression.ToString();
306                                         else
307                                         {
308                                                 switch ( style.ToLower ())
309                                                 {
310                                                         case "yes/no":
311                                                         case "on/off":
312                                                                 switch (expression.ToString().ToLower())
313                                                                 {
314                                                                         case "true":
315                                                                         case "On":
316                                                                                 if (style.ToLower ()=="yes/no")
317                                                                                         returnstr="Yes";
318                                                                                 else
319                                                                                         returnstr="On";
320                                                                                 break;
321                                                                         case "false":
322                                                                         case "off":
323                                                                                 if (style.ToLower ()=="yes/no")
324                                                                                         returnstr="No";
325                                                                                 else
326                                                                                         returnstr="Off";
327                                                                                 break;
328                                                                         default:
329                                                                                 throw new System.ArgumentException();
330
331                                                                 }
332                                                                 break;
333                                                         default:
334                                                                 returnstr=style.ToString();
335                                                                 break;
336                                                 }
337                                         }
338                                         break;
339                                 case "System.Boolean":
340                                         if ( style=="")
341                                         {
342                                                 if ( Convert.ToBoolean(expression)==true)
343                                                         returnstr="True"; 
344                                                 else
345                                                         returnstr="False";
346                                         }
347                                         else
348                                                 returnstr=style;
349                                         break;
350                                 case "System.DateTime":
351                                         switch (style.ToLower ()){
352                                                 case "general date":
353                                                         style = "G"; break;
354                                                 case "long date":
355                                                         style = "D"; break;
356                                                 case "medium date":
357                                                         style = "D"; break;
358                                                 case "short date":
359                                                         style = "d"; break;
360                                                 case "long time":
361                                                         style = "T"; break;
362                                                 case "medium time":
363                                                         style = "T"; break;
364                                                 case "short time":
365                                                         style = "t"; break;
366                                         }
367                                         returnstr=Convert.ToDateTime(expression).ToString(style) ;
368                                         break;
369                                 case "System.Decimal":  case "System.Byte":     case "System.SByte":
370                                 case "System.Int16":    case "System.Int32":    case "System.Int64":
371                                 case "System.Double":   case "System.Single":   case "System.UInt16":
372                                 case "System.UInt32":   case "System.UInt64":
373                                         switch (style.ToLower ())
374                                         {
375                                                 case "yes/no": case "true":     case "false": case "on/off":
376                                                         style=style.ToLower();
377                                                         double dblbuffer=Convert.ToDouble(expression);
378                                                         if (dblbuffer == 0)
379                                                         {
380                                                                 switch (style)
381                                                                 {
382                                                                         case "on/off":
383                                                                                 returnstr= "Off";break; 
384                                                                         case "yes/no":
385                                                                                 returnstr= "No";break; 
386                                                                         case "true/false":
387                                                                                 returnstr= "False";break;
388                                                                 }
389                                                         }
390                                                         else
391                                                         {
392                                                                 switch (style)
393                                                                 {
394                                                                         case "on/off":
395                                                                                 returnstr="On";break;
396                                                                         case "yes/no":
397                                                                                 returnstr="Yes";break;
398                                                                         case "true/false":
399                                                                                 returnstr="True";break;
400                                                                 }
401                                                         }
402                                                         break;
403                                                 default:
404                                                         returnstr=Convert.ToDouble(expression).ToString (style);
405                                                         break;
406                                         }
407                                         break;
408                         }
409                         if (returnstr==null)
410                                 throw new System.ArgumentException();
411                         return returnstr;
412                 }
413
414                 /// <summary>
415                 /// Returns an expression formatted as a currency value using the currency symbol defined in the system control panel.
416                 /// </summary>
417                 /// <param name="Expression">Required. Expression to be formatted.</param>
418                 /// <param name="NumDigitsAfterDecimal">Optional. Numeric value indicating how many places are displayed to the right of the decimal. Default value is \961, which indicates that the computer's regional settings are used.</param>
419                 /// <param name="IncludeLeadingDigit">Optional. Tristate enumeration that indicates whether or not a leading zero is displayed for fractional values. See Settings for values.</param>
420                 /// <param name="UseParensForNegativeNumbers">Optional. Tristate enumeration that indicates whether or not to place negative values within parentheses. See Settings for values.</param>
421                 /// <param name="GroupDigits">Optional. Tristate enumeration that indicates whether or not numbers are grouped using the group delimiter specified in the computer's regional settings. See Settings for values.</param>
422                 public static string FormatCurrency(object Expression, 
423                         [Optional]
424                         [DefaultValue(-1)] 
425                         int NumDigitsAfterDecimal, 
426                         [Optional]
427                         [DefaultValue(TriState.UseDefault)] 
428                         TriState IncludeLeadingDigit, 
429                         [Optional]
430                         [DefaultValue(TriState.UseDefault)] 
431                         TriState UseParensForNegativeNumbers, 
432                         [Optional]
433                         [DefaultValue(TriState.UseDefault)] 
434                         TriState GroupDigits)
435                 {
436                         if (NumDigitsAfterDecimal > 99 || NumDigitsAfterDecimal < -1 )\r
437                                 throw new ArgumentException(\r
438                                         VBUtils.GetResourceString("Argument_Range0to99_1",\r
439                                                 "NumDigitsAfterDecimal" ));       \r
440 \r
441                         if (Expression == null)\r
442                                 return "";\r
443 \r
444                         if (!(Expression is IFormattable))\r
445                                 throw new InvalidCastException(\r
446                                         VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
447
448                         String formatStr = "00";
449
450                         if (GroupDigits == TriState.True)
451                                 formatStr = formatStr + ",00";
452
453                         if (NumDigitsAfterDecimal > -1) {
454                                 string decStr = ".";
455                                 for (int count=1; count<=NumDigitsAfterDecimal; count ++)
456                                         decStr = decStr + "0";
457                         
458                                 formatStr = formatStr + decStr;
459                         }
460
461                         if (UseParensForNegativeNumbers == TriState.True) {
462                                 String temp = formatStr;
463                                 formatStr = formatStr + ";(" ;
464                                 formatStr = formatStr + temp;
465                                 formatStr = formatStr + ")";
466                         }
467
468                         //Console.WriteLine("formatStr : " + formatStr);        
469
470                         string returnstr=null;
471                         string expstring= Expression.GetType().ToString();
472                         switch(expstring) {
473                                 case "System.Decimal":  case "System.Byte":     case "System.SByte":
474                                 case "System.Int16":    case "System.Int32":    case "System.Int64":
475                                 case "System.Double":   case "System.Single":   case "System.UInt16":
476                                 case "System.UInt32":   case "System.UInt64":
477                                         returnstr = Convert.ToDouble(Expression).ToString (formatStr);
478                                         break;
479                                 default:
480                                         throw new InvalidCastException(
481                                                 VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
482                         }
483                         String curSumbol = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol;
484                         returnstr = curSumbol + returnstr;
485                         
486                         return returnstr;
487                 }
488
489                 /// <summary>
490                 /// Returns an expression formatted as a date or time.
491                 /// </summary>
492                 /// <param name="Expression">Required. Date expression to be formatted. </param>
493                 /// <param name="NamedFormat">Optional. Numeric value that indicates the date or time format used. If omitted, GeneralDate is used.</param>
494                 public static string FormatDateTime(DateTime Expression, 
495                         [Optional]
496                         [DefaultValue(DateFormat.GeneralDate)] 
497                         DateFormat NamedFormat)
498                 {
499                         switch(NamedFormat) {
500                                 case DateFormat.GeneralDate:
501                                         return Expression.ToString("G");
502                                 case DateFormat.LongDate:  
503                                         return Expression.ToString("D");
504                                 case DateFormat.ShortDate:
505                                         return Expression.ToString("d");
506                                 case DateFormat.LongTime:
507                                         return Expression.ToString("T");
508                                 case DateFormat.ShortTime:
509                                         return Expression.ToString("t");
510                                 default:
511                                         throw new ArgumentException("Argument 'NamedFormat' must be a member of DateFormat", "NamedFormat");
512                         }
513                 }
514
515                 /// <summary>
516                 /// Returns an expression formatted as a number.
517                 /// </summary>
518                 /// <param name="Expression">Required. Expression to be formatted.</param>
519                 /// <param name="NumDigitsAfterDecimal">Optional. Numeric value indicating how many places are displayed to the right of the decimal. Default value is \961, which indicates that the computer's regional settings are used.</param>
520                 /// <param name="IncludeLeadingDigit">Optional. Tristate enumeration that indicates whether or not a leading zero is displayed for fractional values. See Settings for values.</param>
521                 /// <param name="UseParensForNegativeNumbers">Optional. Tristate enumeration that indicates whether or not to place negative values within parentheses. See Settings for values.</param>
522                 /// <param name="GroupDigits">Optional. Tristate enumeration that indicates whether or not numbers are grouped using the group delimiter specified in the computer's regional settings. See Settings for values.</param>
523                 public static string FormatNumber(object Expression, 
524                         [Optional]
525                         [DefaultValue(-1)] 
526                         int NumDigitsAfterDecimal, 
527                         [Optional]
528                         [DefaultValue(TriState.UseDefault)] 
529                         TriState IncludeLeadingDigit, 
530                         [Optional]
531                         [DefaultValue(TriState.UseDefault)] 
532                         TriState UseParensForNegativeNumbers, 
533                         [Optional]
534                         [DefaultValue(TriState.UseDefault)] 
535                         TriState GroupDigits)
536                 {
537                         if (NumDigitsAfterDecimal > 99 || NumDigitsAfterDecimal < -1 )\r
538                                 throw new ArgumentException(\r
539                                         VBUtils.GetResourceString("Argument_Range0to99_1",\r
540                                         "NumDigitsAfterDecimal" ));       \r
541 \r
542                         if (Expression == null)\r
543                                 return "";\r
544 \r
545                         if (!(Expression is IFormattable))\r
546                                 throw new InvalidCastException(\r
547                                         VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
548
549                         String formatStr = "00";
550
551                         if (GroupDigits == TriState.True)
552                                 formatStr = formatStr + ",00";
553
554                         if (NumDigitsAfterDecimal > -1) {
555                                 string decStr = ".";
556                                 for (int count=1; count<=NumDigitsAfterDecimal; count ++)
557                                         decStr = decStr + "0";
558                         
559                                 formatStr = formatStr + decStr;
560                         }
561
562                         if (UseParensForNegativeNumbers == TriState.True) {
563                                 String temp = formatStr;
564                                 formatStr = formatStr + ";(" ;
565                                 formatStr = formatStr + temp;
566                                 formatStr = formatStr + ")";
567                         }
568
569                         //Console.WriteLine("formatStr : " + formatStr);        
570
571                         string returnstr=null;
572                         string expstring= Expression.GetType().ToString();
573                         switch(expstring) {
574                                 case "System.Decimal":  case "System.Byte":     case "System.SByte":
575                                 case "System.Int16":    case "System.Int32":    case "System.Int64":
576                                 case "System.Double":   case "System.Single":   case "System.UInt16":
577                                 case "System.UInt32":   case "System.UInt64":
578                                         returnstr = Convert.ToDouble(Expression).ToString (formatStr);
579                                         break;
580                                 default:
581                                         throw new InvalidCastException(\r
582                                                 VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
583                         }
584                         
585                         return returnstr;
586                 }
587
588                 /// <summary>
589                 /// Returns an expression formatted as a percentage (that is, multiplied by 100) with a trailing % character.
590                 /// </summary>
591                 /// <param name="Expression">Required. Expression to be formatted.</param>
592                 /// <param name="NumDigitsAfterDecimal">Optional. Numeric value indicating how many places are displayed to the right of the decimal. Default value is \961, which indicates that the computer's regional settings are used.</param>
593                 /// <param name="IncludeLeadingDigit">Optional. Tristate enumeration that indicates whether or not a leading zero is displayed for fractional values. See Settings for values.</param>
594                 /// <param name="UseParensForNegativeNumbers">Optional. Tristate enumeration that indicates whether or not to place negative values within parentheses. See Settings for values.</param>
595                 /// <param name="GroupDigits">Optional. Tristate enumeration that indicates whether or not numbers are grouped using the group delimiter specified in the computer's regional settings. See Settings for values.</param>
596                 public static string FormatPercent(object Expression, 
597                         [Optional]
598                         [DefaultValue(-1)] 
599                         int NumDigitsAfterDecimal, 
600                         [Optional]
601                         [DefaultValue(TriState.UseDefault)] 
602                         TriState IncludeLeadingDigit, 
603                         [Optional]
604                         [DefaultValue(TriState.UseDefault)] 
605                         TriState UseParensForNegativeNumbers, 
606                         [Optional]
607                         [DefaultValue(TriState.UseDefault)] 
608                         TriState GroupDigits)
609                 {
610                         if (NumDigitsAfterDecimal > 99 || NumDigitsAfterDecimal < -1 )\r
611                                 throw new ArgumentException(\r
612                                         VBUtils.GetResourceString("Argument_Range0to99_1",\r
613                                         "NumDigitsAfterDecimal" ));       \r
614 \r
615                         if (Expression == null)\r
616                                 return "";\r
617 \r
618                         if (!(Expression is IFormattable))\r
619                                 throw new InvalidCastException(\r
620                                         VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
621
622                         String formatStr = "00";
623
624                         if (GroupDigits == TriState.True)
625                                 formatStr = formatStr + ",00";
626
627                         if (NumDigitsAfterDecimal > -1) {
628                                 string decStr = ".";
629                                 for (int count=1; count<=NumDigitsAfterDecimal; count ++)
630                                         decStr = decStr + "0";
631                         
632                                 formatStr = formatStr + decStr;
633                         }
634
635                         if (UseParensForNegativeNumbers == TriState.True) {
636                                 String temp = formatStr;
637                                 formatStr = formatStr + ";(" ;
638                                 formatStr = formatStr + temp;
639                                 formatStr = formatStr + ")";
640                         }
641
642                         formatStr = formatStr + "%";
643
644                         string returnstr=null;
645                         string expstring= Expression.GetType().ToString();
646                         switch(expstring) {
647                                 case "System.Decimal":  case "System.Byte":     case "System.SByte":
648                                 case "System.Int16":    case "System.Int32":    case "System.Int64":
649                                 case "System.Double":   case "System.Single":   case "System.UInt16":
650                                 case "System.UInt32":   case "System.UInt64":
651                                         returnstr = Convert.ToDouble(Expression).ToString (formatStr);
652                                         break;
653                                 default:
654                                         throw new InvalidCastException(\r
655                                                 VBUtils.GetResourceString("InvalidCast_FromStringTo",Expression.ToString(),"Double"));
656                         }
657                         
658                         return returnstr;
659                 }
660
661                 /// <summary>
662                 /// Returns a Char value representing the character from the specified index in the supplied string.
663                 /// </summary>
664                 /// <param name="Str">Required. Any valid String expression.</param>
665                 /// <param name="Index">Required. Integer expression. The (1-based) index of the character in Str to be returned.</param>
666                 public static char GetChar(string Str, 
667                         int Index)
668                 {
669
670                         if ((Str == null) || (Str.Length == 0))
671                                 throw new ArgumentException("Length of argument 'Str' must be greater than zero.", "Sre");
672                         if (Index < 1) 
673                                 throw new ArgumentException("Argument 'Index' must be greater than or equal to 1.", "Index");
674                         if (Index > Str.Length)
675                                 throw new ArgumentException("Argument 'Index' must be less than or equal to the length of argument 'String'.", "Index");
676
677                         return Str.ToCharArray(Index -1, 1)[0];
678                 }
679
680                 /// <summary>
681                 /// Returns an integer specifying the start position of the first occurrence of one string within another.
682                 /// </summary>
683                 /// <param name="Start">Required. Numeric expression that sets the starting position for each search. If omitted, search begins at the first character position. The start index is 1 based.</param>
684                 /// <param name="String1">Required. String expression being searched.</param>
685                 /// <param name="String2">Required. String expression sought.</param>
686                 /// <param name="Compare">Optional. Specifies the type of string comparison. If Compare is omitted, the Option Compare setting determines the type of comparison. Specify a valid LCID (LocaleID) to use locale-specific rules in the comparison. </param>
687                 public static int InStr(string String1, 
688                         string String2, 
689                         [OptionCompare]
690                         [Optional]
691                         [DefaultValue(CompareMethod.Binary)] 
692                         CompareMethod Compare)
693                 {
694                         return InStr(1, String1, String2, Compare);
695                 }
696                 
697                 /// <summary>
698                 /// Returns an integer specifying the start position of the first occurrence of one string within another.
699                 /// </summary>
700                 /// <param name="Start">Required. Numeric expression that sets the starting position for each search. If omitted, search begins at the first character position. The start index is 1 based.</param>
701                 /// <param name="String1">Required. String expression being searched.</param>
702                 /// <param name="String2">Required. String expression sought.</param>
703                 /// <param name="Compare">Optional. Specifies the type of string comparison. If Compare is omitted, the Option Compare setting determines the type of comparison. Specify a valid LCID (LocaleID) to use locale-specific rules in the comparison. </param>
704                 public static int InStr(int Start, 
705                         string String1, 
706                         string String2, 
707                         [OptionCompare]
708                         [Optional]
709                         [DefaultValue(CompareMethod.Binary)] 
710                         CompareMethod Compare)
711                 {
712                         if (Start < 1)
713                                 throw new ArgumentException("Argument 'Start' must be non-negative.", "Start");
714                         
715                         int leng = 0;
716                         if (String1 != null) {
717                                 leng = String1.Length;
718                         }
719                         if (Start > leng || leng == 0){
720                                 return 0;
721                         }
722                         if (String2 == null || String2.Length == 0) {
723                                 return Start;
724                         }
725
726                         switch (Compare) {
727                                 case CompareMethod.Text:
728                                         return System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(
729                                                 String1.ToLower(System.Globalization.CultureInfo.CurrentCulture), 
730                                                 String2.ToLower(System.Globalization.CultureInfo.CurrentCulture)
731                                                 , Start - 1) + 1;
732                                 case CompareMethod.Binary:
733                                         return (String1.IndexOf(String2, Start - 1)) + 1;
734                                 default:
735                                         throw new System.ArgumentException("Argument 'Compare' must be CompareMethod.Binary or CompareMethod.Text.", "Compare");
736                         }
737                 }
738
739                 /// <summary>
740                 /// Returns the position of the first occurrence of one string within another, starting from the right side of the string.
741                 /// </summary>
742                 /// <param name="StringCheck">Required. String expression being searched.</param>
743                 /// <param name="StringMatch">Required. String expression being searched for.</param>
744                 /// <param name="Start">Optional. Numeric expression that sets the one-based starting position for each search, starting from the left side of the string. If Start is omitted, \961 is used, which means that the search begins at the last character position. Search then proceeds from right to left.</param>
745                 /// <param name="Compare">Optional. Numeric value indicating the kind of comparison to use when evaluating substrings. If omitted, a binary comparison is performed. See Settings for values.</param>
746                 public static int InStrRev(string StringCheck, 
747                         string StringMatch, 
748                         [Optional]
749                         [DefaultValue(-1)] 
750                         int Start,
751                         [OptionCompare]  
752                         [Optional]
753                         [DefaultValue(CompareMethod.Binary)] 
754                         CompareMethod Compare)
755                 {
756                         if ((Start == 0) || (Start < -1))
757                                 throw new ArgumentException("Argument 'StringCheck' must be greater than 0 or equal to -1", "StringCheck");
758
759                         if (StringCheck == null)\r
760                                 return 0;\r
761 \r
762                         if (Start == -1)\r
763                                 Start = StringCheck.Length;\r
764 \r
765                         if (Start > StringCheck.Length || StringCheck.Length == 0)\r
766                                 return 0;\r
767 \r
768                         if (StringMatch == null || StringMatch.Length == 0)
769                                 return Start;
770
771                         int retindex = -1;
772                         int index = -1;
773                         while (index == 0){
774                 switch (Compare)
775                                 {
776                                         case CompareMethod.Text:
777                                                 index = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(
778                                                         StringCheck.ToLower(System.Globalization.CultureInfo.CurrentCulture), 
779                                                         StringMatch.ToLower(System.Globalization.CultureInfo.CurrentCulture), 
780                                                         Start - 1) + 1;
781                                                 break;
782                                         case CompareMethod.Binary:
783                                                 index = StringCheck.IndexOf(StringMatch, Start - 1) + 1;
784                                                 break;
785                                         default:
786                                                 throw new System.ArgumentException("Argument 'Compare' must be CompareMethod.Binary or CompareMethod.Text.", "Compare");
787                                 }
788                                 if (index == 0){
789                                         if (retindex == -1)
790                                                 return index;
791                                         else
792                                                 return retindex;
793                                 }
794                                 else {
795                                         retindex = index;
796                                         Start = index;
797                                 }
798                         }
799                         return retindex;
800                 }
801
802                 /// <summary>
803                 /// Returns a string created by joining a number of substrings contained in an array.
804                 /// </summary>
805                 /// <param name="SourceArray">Required. One-dimensional array containing substrings to be joined.</param>
806                 /// <param name="Delimiter">Optional. String used to separate the substrings in the returned string. If omitted, the space character (" ") is used. If Delimiter is a zero-length string (""), all items in the list are concatenated with no delimiters.</param>
807                 public static string Join(string[] SourceArray, 
808                         [Optional]
809                         [DefaultValue(" ")] 
810                         string Delimiter)
811                 {
812                         if (SourceArray == null)
813                                 throw new ArgumentException("Argument 'SourceArray' can not be null.", "SourceArray");
814                         if (SourceArray.Rank > 1)
815                                 throw new ArgumentException("Argument 'SourceArray' can have only one dimension.", "SourceArray");
816
817                         return string.Join(Delimiter, SourceArray);
818                 }
819                 /// <summary>
820                 /// Returns a string created by joining a number of substrings contained in an array.
821                 /// </summary>
822                 /// <param name="SourceArray">Required. One-dimensional array containing substrings to be joined.</param>
823                 /// <param name="Delimiter">Optional. String used to separate the substrings in the returned string. If omitted, the space character (" ") is used. If Delimiter is a zero-length string (""), all items in the list are concatenated with no delimiters.</param>
824                 public static string Join(object[] SourceArray, 
825                         [Optional]
826                         [DefaultValue(" ")] 
827                         string Delimiter)
828                 {
829
830                         if (SourceArray == null)
831                                 throw new ArgumentException("Argument 'SourceArray' can not be null.", "SourceArray");
832                         if (SourceArray.Rank > 1)
833                                 throw new ArgumentException("Argument 'SourceArray' can have only one dimension.", "SourceArray");
834
835                         string[] dest;
836                         dest = new string[SourceArray.Length];
837
838                         SourceArray.CopyTo(dest, 0);
839                         return string.Join(Delimiter, dest);
840                 }
841
842                 /// <summary>
843                 /// Returns a string or character converted to lowercase.
844                 /// </summary>
845                 /// <param name="Value">Required. Any valid String or Char expression.</param>
846                 public static char LCase(char Value) 
847                 {
848                         return char.ToLower(Value);
849                 }
850
851                 /// <summary>
852                 /// Returns a string or character converted to lowercase.
853                 /// </summary>
854                 /// <param name="Value">Required. Any valid String or Char expression.</param>
855                 public static string LCase(string Value) 
856                 {
857                         if ((Value == null) || (Value.Length == 0)) 
858                                 return Value; // comparing nunit test results say this is an exception to the return String.Empty rule
859
860                         return Value.ToLower();
861                 }
862
863                 
864                 /// <summary>
865                 /// Returns a string containing a specified number of characters from the left side of a string.
866                 /// </summary>
867                 /// <param name="Str">Required. String expression from which the leftmost characters are returned.</param>
868                 /// <param name="Length">Required. Integer expression. Numeric expression indicating how many characters to return. 
869                 ///     If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in Str, 
870                 ///     the entire string is returned.</param>
871                 public static string Left(string Str, int Length) 
872                 {
873                         if (Length < 0)
874                                 throw new ArgumentException("Argument 'Length' must be non-negative.", "Length");
875                         if ((Str == null) || (Str.Length == 0) || Length == 0)
876                                 return String.Empty; // VB.net does this.
877                         if (Length < Str.Length)
878                                 return Str.Substring(0, Length);
879                         return Str;
880                 }
881
882                 /// <summary>
883                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
884                 /// </summary>
885                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
886                 public static int Len(bool Expression) 
887                 {
888                         return 2; //sizeof(bool)
889                 }
890
891                 /// <summary>
892                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
893                 /// </summary>
894                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
895                 public static int Len(byte Expression) 
896                 {
897                         return 1; //sizeof(byte)
898                 }
899                 
900                 /// <summary>
901                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
902                 /// </summary>
903                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
904                 public static int Len(char Expression) 
905                 {
906                         return 2; //sizeof(char)
907                 }
908                 
909                 /// <summary>
910                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
911                 /// </summary>
912                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
913                 public static int Len(double Expression) 
914                 {
915                         return 8; //sizeof(double)
916                 }
917                 
918                 /// <summary>
919                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
920                 /// </summary>
921                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
922                 public static int Len(int Expression) 
923                 {
924                         return 4; //sizeof(int)
925                 }
926                 
927                 /// <summary>
928                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
929                 /// </summary>
930                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
931                 public static int Len(long Expression) 
932                 {
933                         return 8; //sizeof(long)
934                 }
935
936                 /// <summary>
937                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
938                 /// </summary>
939                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
940                 public static int Len(object expression) 
941                 {
942                     IConvertible convertible = null;\r
943 \r
944                         if (expression == null)\r
945                                 return 0;\r
946 \r
947                         if (expression is String)\r
948                                 return ((String)expression).Length;\r
949 \r
950                         if (expression is char[])\r
951                                 return ((char[])expression).Length;\r
952 \r
953                         if (expression is IConvertible)\r
954                                 convertible = (IConvertible)expression;\r
955                         \r
956                         if (convertible != null) {\r
957                                 switch (convertible.GetTypeCode()) {\r
958                                         case TypeCode.String :\r
959                                                 return expression.ToString().Length;\r
960                                         case TypeCode.Int16 :\r
961                                                 return 2;\r
962                                         case TypeCode.Byte :\r
963                                                 return 1;\r
964                                         case TypeCode.Int32 :\r
965                                                 return 4;\r
966                                         case TypeCode.Int64 :\r
967                                                 return 8;\r
968                                         case TypeCode.Single :\r
969                                                 return 4;\r
970                                         case TypeCode.Double :\r
971                                                 return 8;\r
972                                         case TypeCode.Boolean :\r
973                                                 return 2;\r
974                                         case TypeCode.Decimal :\r
975                                                 return 16;\r
976                                         case TypeCode.Char :\r
977                                                 return 2;\r
978                                         case TypeCode.DateTime :\r
979                                                 return 8;\r
980                                 }\r
981 \r
982                         }\r
983                         if (expression is ValueType)\r
984                                 return System.Runtime.InteropServices.Marshal.SizeOf(expression);\r
985 \r
986                         throw new InvalidCastException(VBUtils.GetResourceString(13));
987                 }
988                 
989                 /// <summary>
990                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
991                 /// </summary>
992                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
993                 public static int Len(short Expression) 
994                 {
995                         return 2; //sizeof(short)
996                 }
997                 
998                 /// <summary>
999                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
1000                 /// </summary>
1001                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
1002                 public static int Len(Single Expression) 
1003                 {
1004                         return 4; //sizeof(Single)
1005                 }
1006                 
1007                 /// <summary>
1008                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
1009                 /// </summary>
1010                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
1011                 //public static int Len(string Expression) 
1012                 //{
1013                 //      return Expression.Length; //length of the string
1014                 //}
1015                 public static int Len(string Expression) {\r
1016                         if (Expression == null)return 0;\r
1017                         return Expression.Length;\r
1018                 }\r
1019
1020                 /// <summary>
1021                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
1022                 /// </summary>
1023                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
1024                 public static int Len(DateTime Expression) 
1025                 {
1026                         return 8; //sizeof(DateTime)
1027                 }
1028                 
1029                 /// <summary>
1030                 /// Returns an integer containing either the number of characters in a string or the number of bytes required to store a variable.
1031                 /// </summary>
1032                 /// <param name="Expression">Any valid String expression or variable name. If Expression is of type Object, the Len function returns the size as it will be written to the file.</param>
1033                 public static int Len(decimal Expression) 
1034                 {
1035                         return 8; //sizeof(decimal)
1036                 }
1037
1038                 /// <summary>
1039                 /// Returns a left-aligned string containing the specified string adjusted to the specified length.
1040                 /// </summary>
1041                 /// <param name="Source">Required. String expression. Name of string variable.</param>
1042                 /// <param name="Length">Required. Integer expression. Length of returned string.</param>
1043                 public static string LSet(string Source, 
1044                         int Length) 
1045                 {
1046                         if (Length < 0)
1047                                 throw new ArgumentOutOfRangeException("Length", "Length must be must be non-negative.");
1048
1049                         if (Source == null)
1050                                 Source = String.Empty;
1051
1052                         if (Length > Source.Length)
1053                                 return Source.PadRight(Length);
1054
1055                         return Source.Substring(0, Length);
1056                 }
1057
1058                 /// <summary>
1059                 /// Returns a string containing a copy of a specified string with no leading spaces.
1060                 /// </summary>
1061                 /// <param name="Str">Required. Any valid String expression.</param>
1062                 public static string LTrim(string Str) 
1063                 {
1064                         if ((Str == null) || (Str.Length == 0))
1065                                 return String.Empty; // VB.net does this.
1066
1067                         return Str.TrimStart(null);
1068                 }
1069
1070                 /// <summary>
1071                 /// Returns a string containing a copy of a specified string with no trailing spaces.
1072                 /// </summary>
1073                 /// <param name="Str">Required. Any valid String expression.</param>
1074                 public static string RTrim(string Str) 
1075                 {
1076                         if ((Str == null) || (Str.Length == 0))
1077                                 return String.Empty; // VB.net does this.
1078
1079                         return Str.TrimEnd(null);
1080                 }
1081         
1082                 /// <summary>
1083                 /// Returns a string containing a copy of a specified string with no leading or trailing spaces.
1084                 /// </summary>
1085                 /// <param name="Str">Required. Any valid String expression.</param>
1086                 public static string Trim(string Str) 
1087                 {
1088                         if ((Str == null) || (Str.Length == 0))
1089                                 return String.Empty; // VB.net does this.
1090                         
1091                         return Str.Trim();
1092                 }
1093
1094                 /// <summary>
1095                 /// Returns a string containing a specified number of characters from a string.
1096                 /// </summary>
1097                 /// <param name="Str">Required. String expression from which characters are returned.</param>
1098                 /// <param name="Start">Required. Integer expression. Character position in Str at which the part to be taken starts. If Start is greater than the number of characters in Str, the Mid function returns a zero-length string (""). Start is one based.</param>
1099                 /// <param name="Length">Required Integer expression. Number of characters to return. If there are fewer than Length characters in the text (including the character at position Start), all characters from the start position to the end of the string are returned.</param>
1100                 public static string Mid(string Str, 
1101                         int Start, 
1102                         int Length)
1103                 {
1104
1105                         if (Length < 0)
1106                                 throw new System.ArgumentException("Argument 'Length' must be greater or equal to zero.", "Length");
1107                         if (Start <= 0)
1108                                 throw new System.ArgumentException("Argument 'Start' must be greater than zero.", "Start");
1109                         if ((Str == null) || (Str.Length == 0))
1110                                 return String.Empty; // VB.net does this.
1111
1112                         if ((Length == 0) || (Start > Str.Length))
1113                                 return String.Empty;
1114
1115                         if (Length > (Str.Length - Start))
1116                                 Length = (Str.Length - Start) + 1;
1117
1118                         return Str.Substring(Start - 1, Length);
1119
1120                 }
1121
1122                 /// <summary>
1123                 /// Returns a string containing all characters from a string beyond an start point.
1124                 /// </summary>
1125                 /// <param name="Str">Required. String expression from which characters are returned.</param>
1126                 /// <param name="Start">Required. Integer expression. Character position in Str at which the part to be taken starts. If Start is greater than the number of characters in Str, the Mid function returns a zero-length string (""). Start is one based.</param>
1127                 public static string Mid (string Str, int Start) 
1128                 {
1129                         if (Start <= 0)
1130                                 throw new System.ArgumentException("Argument 'Start' must be greater than zero.", "Start");
1131
1132                         if ((Str == null) || (Str.Length == 0))
1133                                 return String.Empty; // VB.net does this.
1134
1135                         if (Start > Str.Length)
1136                                 return String.Empty;
1137
1138                         return Str.Substring(Start - 1);
1139                 }
1140
1141                 /// <summary>
1142                 /// Returns a string in which a specified substring has been replaced with another substring a specified number of times.
1143                 /// </summary>
1144                 /// <param name="Expression">Required. String expression containing substring to replace.</param>
1145                 /// <param name="Find">Required. Substring being searched for.</param>
1146                 /// <param name="Replacement">Required. Replacement substring.</param>
1147                 /// <param name="Start">Optional. Position within Expression where substring search is to begin. If omitted, 1 is assumed.</param>
1148                 /// <param name="Count">Optional. Number of substring substitutions to perform. If omitted, the default value is \961, which means make all possible substitutions.</param>
1149                 /// <param name="Compare">Optional. Numeric value indicating the kind of comparison to use when evaluating substrings. See Settings for values.</param>
1150                 public static string Replace(string Expression, 
1151                         string Find, 
1152                         string Replacement, 
1153                         [Optional]
1154                         [DefaultValue(1)] 
1155                         int Start,
1156                         [Optional]
1157                         [DefaultValue(-1)] 
1158                         int Count,
1159                         [OptionCompare] 
1160                         [Optional]
1161                         [DefaultValue(CompareMethod.Binary)] 
1162                         CompareMethod Compare)
1163                 {
1164
1165                         if (Count < -1)
1166                                 throw new ArgumentException("Argument 'Count' must be greater than or equal to -1.", "Count");
1167                         if (Start <= 0)
1168                                 throw new ArgumentException("Argument 'Start' must be greater than zero.", "Start");
1169
1170                         if ((Expression == null) || (Expression.Length == 0))
1171                                 return String.Empty; // VB.net does this.
1172                         if ((Find == null) || (Find.Length == 0))
1173                                 return Expression; // VB.net does this.
1174                         if (Replacement == null)
1175                                 Replacement = String.Empty; // VB.net does this.
1176
1177                         return Expression.Replace(Find, Replacement);
1178                 }
1179  
1180                 /// <summary>
1181                 /// Returns a string containing a specified number of characters from the right side of a string.
1182                 /// </summary>
1183                 /// <param name="Str">Required. String expression from which the rightmost characters are returned.</param>
1184                 /// <param name="Length">Required. Integer. Numeric expression indicating how many characters to return. If 0, a zero-length string ("") is returned. If greater than or equal to the number of characters in Str, the entire string is returned.</param>
1185                 public static string Right(string Str, 
1186                         int Length) 
1187                 {
1188                         if (Length < 0)
1189                                 throw new ArgumentException("Argument 'Length' must be greater or equal to zero.", "Length");
1190
1191                         // Fixing Bug #49660 - Start
1192                         if ((Str == null) || (Str.Length == 0))
1193                                 return String.Empty; // VB.net does this.
1194
1195                         if (Length >= Str.Length)
1196                                 return Str;
1197                         // Fixing Bug #49660 - End
1198
1199                         return Str.Substring (Str.Length - Length);
1200                 }
1201
1202                 /// <summary>
1203                 /// Returns a right-aligned string containing the specified string adjusted to the specified length.
1204                 /// </summary>
1205                 /// <param name="Source">Required. String expression. Name of string variable.</param>
1206                 /// <param name="Length">Required. Integer expression. Length of returned string.</param>
1207                 public static string RSet(string Source, int Length) 
1208                 {
1209                 
1210                         if (Source == null)
1211                                 Source = String.Empty;
1212                         if (Length < 0)
1213                                 throw new ArgumentOutOfRangeException("Length", "Length must be non-negative.");
1214                         if (Length > Source.Length)
1215                                 return Source.PadLeft(Length);
1216                         return Source.Substring(0, Length);
1217                 }
1218
1219                 /// <summary>
1220                 /// Returns a string consisting of the specified number of spaces.
1221                 /// </summary>
1222                 /// <param name="Number">Required. Integer expression. The number of spaces you want in the string.</param>
1223                 public static string Space(int Number) 
1224                 {
1225                         if (Number < 0)
1226                                 throw new ArgumentException("Argument 'Number' must be greater or equal to zero.", "Number");
1227
1228                         return new string((char) ' ', Number);
1229                 }
1230
1231                 /// <summary>
1232                 /// Returns a zero-based, one-dimensional array containing a specified number of substrings.
1233                 /// </summary>
1234                 /// <param name="Expression">Required. String expression containing substrings and delimiters. If Expression is a zero-length string (""), the Split function returns an array with no elements and no data.</param>
1235                 /// <param name="Delimiter">Optional. Single character used to identify substring limits. If Delimiter is omitted, the space character (" ") is assumed to be the delimiter. If Delimiter is a zero-length string, a single-element array containing the entire Expression string is returned.</param>
1236                 /// <param name="Limit">Optional. Number of substrings to be returned; the default, \961, indicates that all substrings are returned.</param>
1237                 /// <param name="Compare">Optional. Numeric value indicating the comparison to use when evaluating substrings. See Settings for values.</param>
1238                 public static string[] Split(string Expression, 
1239                         [Optional]
1240                         [DefaultValue(" ")] 
1241                         string Delimiter,
1242                         [Optional]
1243                         [DefaultValue(-1)] 
1244                         int Limit,
1245                         [OptionCompare] 
1246                         [Optional]
1247                         [DefaultValue(CompareMethod.Binary)] 
1248                         CompareMethod Compare)
1249                 {
1250
1251                         
1252                         if (Expression == null)
1253                                 return new string[1];
1254
1255                         if ((Delimiter == null) || (Delimiter.Length == 0))
1256                         {
1257                                 string [] ret = new string[1];
1258                                 ret[0] = Expression;
1259                                 return ret;
1260                         }
1261                         if (Limit == 0)
1262                                 Limit = 1; 
1263
1264                         if (Limit < -1)
1265                                 throw new OverflowException("Arithmetic operation resulted in an overflow.");
1266                         switch (Compare)
1267                         {
1268                                 case CompareMethod.Binary:
1269                                         return Expression.Split(Delimiter.ToCharArray(0, 1), Limit);
1270                                 case CompareMethod.Text:
1271                                         return Expression.Split(Delimiter.ToCharArray(0, 1), Limit);
1272                                 default:
1273                                         throw new System.ArgumentException("Argument 'Compare' must be CompareMethod.Binary or CompareMethod.Text.", "Compare");
1274                         }
1275                 }
1276
1277                 /// <summary>
1278                 /// Returns -1, 0, or 1, based on the result of a string comparison. 
1279                 /// </summary>
1280                 /// <param name="String1">Required. Any valid String expression.</param>
1281                 /// <param name="String2">Required. Any valid String expression.</param>
1282                 /// <param name="Compare">Optional. Specifies the type of string comparison. If compare is omitted, the Option Compare setting determines the type of comparison.</param>
1283                 public static int StrComp(string String1, 
1284                         string String2,
1285                         [OptionCompare] 
1286                         [Optional]
1287                         [DefaultValue(CompareMethod.Binary)] 
1288                         CompareMethod Compare)
1289                 {
1290                         if (String1 == null)
1291                                 String1 = string.Empty;
1292                         if (String2 == null)
1293                                 String2 = string.Empty;
1294
1295                         switch (Compare)
1296                         {
1297                                 case CompareMethod.Binary:
1298                                         return string.Compare(String2, String1, false);
1299                                 case CompareMethod.Text:
1300                     return System.Globalization.CultureInfo.CurrentCulture.CompareInfo.Compare(
1301                                                 String1.ToLower(System.Globalization.CultureInfo.CurrentCulture), 
1302                                                 String2.ToLower(System.Globalization.CultureInfo.CurrentCulture));
1303                                 default:
1304                                         throw new System.ArgumentException("Argument 'Compare' must be CompareMethod.Binary or CompareMethod.Text", "Compare");
1305                         }
1306                 }
1307
1308                 /// <summary>
1309                 /// Returns a string converted as specified.
1310                 /// </summary>
1311                 /// <param name="Str">Required. String expression to be converted.</param>
1312                 /// <param name="Conversion">Required. VbStrConv member. The enumeration value specifying the type of conversion to perform. </param>
1313                 /// <param name="LocaleID">Optional. The LocaleID value, if different from the system LocaleID value. (The system LocaleID value is the default.)</param>
1314                 public static string StrConv (string str, 
1315                         VbStrConv Conversion, 
1316                         [Optional]
1317                         [DefaultValue(0)]
1318                         int LocaleID)
1319                 {
1320                         if (str == null)\r
1321                                 throw new ArgumentNullException("str");\r
1322                         \r
1323                         if (Conversion == VbStrConv.None){\r
1324                                 return str;\r
1325                         }\r
1326                         else if (Conversion == VbStrConv.UpperCase)     {\r
1327                                 return str.ToUpper();\r
1328                         }\r
1329                         else if (Conversion == VbStrConv.LowerCase)     {\r
1330                                 return str.ToLower();\r
1331                         }\r
1332                         else if (Conversion == VbStrConv.ProperCase){\r
1333                                 String[] arr = str.Split(null);\r
1334                                 String tmp = "" ;\r
1335                                 for (int i =0 ; i < (arr.Length - 1) ; i++)     {\r
1336                                         arr[i] =  arr[i].ToLower();\r
1337                                         tmp +=  arr[i].Substring(0,1).ToUpper() + arr[i].Substring(1) + " ";\r
1338                                 }\r
1339                                 arr[arr.Length - 1] =  arr[arr.Length - 1].ToLower();\r
1340                                 tmp +=  arr[arr.Length - 1].Substring(0,1).ToUpper() + arr[arr.Length - 1].Substring(1);\r
1341 \r
1342                                 return tmp;\r
1343                         }         \r
1344                         else if (Conversion == VbStrConv.SimplifiedChinese || \r
1345                                 Conversion == VbStrConv.TraditionalChinese ) \r
1346                                 return str;\r
1347                         else\r
1348                                 throw new ArgumentException("Unsuported conversion in StrConv");        
1349                 }
1350
1351                 /// <summary>
1352                 /// Returns a string or object consisting of the specified character repeated the specified number of times.
1353                 /// </summary>
1354                 /// <param name="Number">Required. Integer expression. The length to the string to be returned.</param>
1355                 /// <param name="Character">Required. Any valid Char, String, or Object expression. Only the first character of the expression will be used. If Character is of type Object, it must contain either a Char or a String value.</param>
1356                 public static string StrDup(int Number, 
1357                         char Character)
1358                 {
1359                         if (Number < 0)
1360                                 throw new ArgumentException("Argument 'Number' must be non-negative.", "Number");
1361
1362                         return new string(Character, Number);
1363                 }
1364                 /// <summary>
1365                 /// Returns a string or object consisting of the specified character repeated the specified number of times.
1366                 /// </summary>
1367                 /// <param name="Number">Required. Integer expression. The length to the string to be returned.</param>
1368                 /// <param name="Character">Required. Any valid Char, String, or Object expression. Only the first character of the expression will be used. If Character is of type Object, it must contain either a Char or a String value.</param>
1369                 public static string StrDup(int Number, 
1370                         string Character)
1371                 {
1372                         if (Number < 0)
1373                                 throw new ArgumentException("Argument 'Number' must be greater or equal to zero.", "Number");
1374                         if ((Character == null) || (Character.Length == 0))
1375                                 throw new ArgumentNullException("Character", "Length of argument 'Character' must be greater than zero.");
1376
1377                         return new string(Character[0], Number);
1378                 }
1379
1380                 /// <summary>
1381                 /// Returns a string or object consisting of the specified character repeated the specified number of times.
1382                 /// </summary>
1383                 /// <param name="Number">Required. Integer expression. The length to the string to be returned.</param>
1384                 /// <param name="Character">Required. Any valid Char, String, or Object expression. Only the first character of the expression will be used. If Character is of type Object, it must contain either a Char or a String value.</param>
1385                 public static object StrDup(int Number, 
1386                         object Character)
1387                 {
1388                         if (Number < 0)
1389                                 throw new ArgumentException("Argument 'Number' must be non-negative.", "Number");
1390                         
1391                         if (Character is string)
1392                         {
1393                                 string sCharacter = (string) Character;
1394                                 if ((sCharacter == null) || (sCharacter.Length == 0))
1395                                         throw new ArgumentNullException("Character", "Length of argument 'Character' must be greater than zero.");
1396
1397                                 return StrDup(Number, sCharacter);
1398                         }
1399                         else
1400                         {
1401                                 if (Character is char)
1402                                 {
1403                                         return StrDup(Number, (char) Character);
1404                                 }
1405                                 else
1406                                 {
1407                                         // "If Character is of type Object, it must contain either a Char or a String value."
1408                                         throw new ArgumentException("Argument 'Character' is not a valid value.", "Character");
1409                                 }
1410                         }
1411                 }
1412
1413                 /// <summary>
1414                 /// Returns a string in which the character order of a specified string is reversed.
1415                 /// </summary>
1416                 /// <param name="Expression">Required. String expression whose characters are to be reversed. If Expression is a zero-length string (""), a zero-length string is returned.</param>
1417                 public static string StrReverse(string Expression)
1418                 {
1419                         // Patched by Daniel Campos (danielcampos@myway.com)
1420                         // Simplified by Rafael Teixeira (2003-12-02)
1421                         if (Expression == null || Expression.Length < 1)
1422                                 return String.Empty;
1423                         else {
1424                                 int length = Expression.Length;
1425                                 char[] buf = new char[length];
1426                                 int counter = 0;
1427                                 int backwards = length - 1;
1428                                 while (counter < length)
1429                                         buf[counter++] = Expression[backwards--];
1430                                 return new string(buf);
1431                         }
1432                 }
1433
1434                 /// <summary>
1435                 /// Returns a string or character containing the specified string converted to uppercase.
1436                 /// </summary>
1437                 /// <param name="Value">Required. Any valid String or Char expression.</param>
1438                 public static char UCase(char Value) 
1439                 {
1440                         return char.ToUpper(Value);
1441                 }
1442
1443                 /// <summary>
1444                 /// Returns a string or character containing the specified string converted to uppercase.
1445                 /// </summary>
1446                 /// <param name="Value">Required. Any valid String or Char expression.</param>
1447                 public static string UCase(string Value) 
1448                 {
1449                         if ((Value == null) || (Value.Length == 0))
1450                                 return String.Empty; // VB.net does this. 
1451
1452                         return Value.ToUpper();
1453                 }
1454
1455
1456
1457         }
1458
1459 }