AsReadOnlySpan -> AsSpan rename to fix build breaks
[platform/upstream/coreclr.git] / src / mscorlib / shared / System / Convert.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System;
6 using System.Globalization;
7 using System.Threading;
8 using System.Reflection;
9 using System.Runtime.CompilerServices;
10 using System.Runtime.InteropServices;
11 using System.Runtime.Versioning;
12 using System.Security;
13 using System.Diagnostics;
14
15 namespace System
16 {
17     [Flags]
18     public enum Base64FormattingOptions
19     {
20         None = 0,
21         InsertLineBreaks = 1
22     }
23
24     // Returns the type code of this object. An implementation of this method
25     // must not return TypeCode.Empty (which represents a null reference) or
26     // TypeCode.Object (which represents an object that doesn't implement the
27     // IConvertible interface). An implementation of this method should return
28     // TypeCode.DBNull if the value of this object is a database null. For
29     // example, a nullable integer type should return TypeCode.DBNull if the
30     // value of the object is the database null. Otherwise, an implementation
31     // of this method should return the TypeCode that best describes the
32     // internal representation of the object.
33     // The Value class provides conversion and querying methods for values. The
34     // Value class contains static members only, and it is not possible to create
35     // instances of the class.
36     //
37     // The statically typed conversion methods provided by the Value class are all
38     // of the form:
39     //
40     //    public static XXX ToXXX(YYY value)
41     //
42     // where XXX is the target type and YYY is the source type. The matrix below
43     // shows the set of supported conversions. The set of conversions is symmetric
44     // such that for every ToXXX(YYY) there is also a ToYYY(XXX).
45     //
46     // From:  To: Bol Chr SBy Byt I16 U16 I32 U32 I64 U64 Sgl Dbl Dec Dat Str
47     // ----------------------------------------------------------------------
48     // Boolean     x       x   x   x   x   x   x   x   x   x   x   x       x
49     // Char            x   x   x   x   x   x   x   x   x                   x
50     // SByte       x   x   x   x   x   x   x   x   x   x   x   x   x       x
51     // Byte        x   x   x   x   x   x   x   x   x   x   x   x   x       x
52     // Int16       x   x   x   x   x   x   x   x   x   x   x   x   x       x
53     // UInt16      x   x   x   x   x   x   x   x   x   x   x   x   x       x
54     // Int32       x   x   x   x   x   x   x   x   x   x   x   x   x       x
55     // UInt32      x   x   x   x   x   x   x   x   x   x   x   x   x       x
56     // Int64       x   x   x   x   x   x   x   x   x   x   x   x   x       x
57     // UInt64      x   x   x   x   x   x   x   x   x   x   x   x   x       x
58     // Single      x       x   x   x   x   x   x   x   x   x   x   x       x
59     // Double      x       x   x   x   x   x   x   x   x   x   x   x       x
60     // Decimal     x       x   x   x   x   x   x   x   x   x   x   x       x
61     // DateTime                                                        x   x
62     // String      x   x   x   x   x   x   x   x   x   x   x   x   x   x   x
63     // ----------------------------------------------------------------------
64     //
65     // For dynamic conversions, the Value class provides a set of methods of the
66     // form:
67     //
68     //    public static XXX ToXXX(object value)
69     //
70     // where XXX is the target type (Boolean, Char, SByte, Byte, Int16, UInt16,
71     // Int32, UInt32, Int64, UInt64, Single, Double, Decimal, DateTime,
72     // or String). The implementations of these methods all take the form:
73     //
74     //    public static XXX toXXX(object value) {
75     //        return value == null? XXX.Default: ((IConvertible)value).ToXXX();
76     //    }
77     //
78     // The code first checks if the given value is a null reference (which is the
79     // same as Value.Empty), in which case it returns the default value for type
80     // XXX. Otherwise, a cast to IConvertible is performed, and the appropriate ToXXX()
81     // method is invoked on the object. An InvalidCastException is thrown if the
82     // cast to IConvertible fails, and that exception is simply allowed to propagate out
83     // of the conversion method.
84
85     // Constant representing the database null value. This value is used in
86     // database applications to indicate the absence of a known value. Note
87     // that Value.DBNull is NOT the same as a null object reference, which is
88     // represented by Value.Empty.
89     //
90     // The Equals() method of DBNull always returns false, even when the
91     // argument is itself DBNull.
92     //
93     // When passed Value.DBNull, the Value.GetTypeCode() method returns
94     // TypeCode.DBNull.
95     //
96     // When passed Value.DBNull, the Value.ToXXX() methods all throw an
97     // InvalidCastException.
98
99     public static class Convert
100     {
101         //A typeof operation is fairly expensive (does a system call), so we'll cache these here
102         //statically.  These are exactly lined up with the TypeCode, eg. ConvertType[TypeCode.Int16]
103         //will give you the type of an Int16.
104         internal static readonly Type[] ConvertTypes = {
105             typeof(System.Empty),
106             typeof(Object),
107             typeof(System.DBNull),
108             typeof(Boolean),
109             typeof(Char),
110             typeof(SByte),
111             typeof(Byte),
112             typeof(Int16),
113             typeof(UInt16),
114             typeof(Int32),
115             typeof(UInt32),
116             typeof(Int64),
117             typeof(UInt64),
118             typeof(Single),
119             typeof(Double),
120             typeof(Decimal),
121             typeof(DateTime),
122             typeof(Object), //TypeCode is discontinuous so we need a placeholder.
123             typeof(String)
124         };
125
126         // Need to special case Enum because typecode will be underlying type, e.g. Int32
127         private static readonly Type EnumType = typeof(Enum);
128
129         internal static readonly char[] base64Table = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
130                                                        'P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d',
131                                                        'e','f','g','h','i','j','k','l','m','n','o','p','q','r','s',
132                                                        't','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
133                                                        '8','9','+','/','=' };
134
135         private const Int32 base64LineBreakPosition = 76;
136
137 #if DEBUG
138         private static bool TriggerAsserts = DoAsserts();
139         private static bool DoAsserts()
140         {
141             Debug.Assert(ConvertTypes != null, "[Convert.cctor]ConvertTypes!=null");
142             Debug.Assert(ConvertTypes.Length == ((int)TypeCode.String + 1), "[Convert.cctor]ConvertTypes.Length == ((int)TypeCode.String + 1)");
143             Debug.Assert(ConvertTypes[(int)TypeCode.Empty] == typeof(System.Empty),
144                             "[Convert.cctor]ConvertTypes[(int)TypeCode.Empty]==typeof(System.Empty)");
145             Debug.Assert(ConvertTypes[(int)TypeCode.String] == typeof(String),
146                             "[Convert.cctor]ConvertTypes[(int)TypeCode.String]==typeof(System.String)");
147             Debug.Assert(ConvertTypes[(int)TypeCode.Int32] == typeof(int),
148                             "[Convert.cctor]ConvertTypes[(int)TypeCode.Int32]==typeof(int)");
149             return true;
150         }
151 #endif
152
153         public static readonly Object DBNull = System.DBNull.Value;
154
155         // Returns the type code for the given object. If the argument is null,
156         // the result is TypeCode.Empty. If the argument is not a value (i.e. if
157         // the object does not implement IConvertible), the result is TypeCode.Object.
158         // Otherwise, the result is the type code of the object, as determined by
159         // the object's implementation of IConvertible.
160         public static TypeCode GetTypeCode(object value)
161         {
162             if (value == null) return TypeCode.Empty;
163             IConvertible temp = value as IConvertible;
164             if (temp != null)
165             {
166                 return temp.GetTypeCode();
167             }
168             return TypeCode.Object;
169         }
170
171         // Returns true if the given object is a database null. This operation
172         // corresponds to "value.GetTypeCode() == TypeCode.DBNull".
173         public static bool IsDBNull(object value)
174         {
175             if (value == System.DBNull.Value) return true;
176             IConvertible convertible = value as IConvertible;
177             return convertible != null ? convertible.GetTypeCode() == TypeCode.DBNull : false;
178         }
179
180         // Converts the given object to the given type. In general, this method is
181         // equivalent to calling the Value.ToXXX(value) method for the given
182         // typeCode and boxing the result.
183         //
184         // The method first checks if the given object implements IConvertible. If not,
185         // the only permitted conversion is from a null to TypeCode.Empty, the
186         // result of which is null.
187         //
188         // If the object does implement IConvertible, a check is made to see if the
189         // object already has the given type code, in which case the object is
190         // simply returned. Otherwise, the appropriate ToXXX() is invoked on the
191         // object's implementation of IConvertible.
192         public static Object ChangeType(Object value, TypeCode typeCode)
193         {
194             return ChangeType(value, typeCode, CultureInfo.CurrentCulture);
195         }
196
197         public static Object ChangeType(Object value, TypeCode typeCode, IFormatProvider provider)
198         {
199             if (value == null && (typeCode == TypeCode.Empty || typeCode == TypeCode.String || typeCode == TypeCode.Object))
200             {
201                 return null;
202             }
203
204             IConvertible v = value as IConvertible;
205             if (v == null)
206             {
207                 throw new InvalidCastException(SR.InvalidCast_IConvertible);
208             }
209
210             // This line is invalid for things like Enums that return a TypeCode
211             // of Int32, but the object can't actually be cast to an Int32.
212             //            if (v.GetTypeCode() == typeCode) return value;
213             switch (typeCode)
214             {
215                 case TypeCode.Boolean:
216                     return v.ToBoolean(provider);
217                 case TypeCode.Char:
218                     return v.ToChar(provider);
219                 case TypeCode.SByte:
220                     return v.ToSByte(provider);
221                 case TypeCode.Byte:
222                     return v.ToByte(provider);
223                 case TypeCode.Int16:
224                     return v.ToInt16(provider);
225                 case TypeCode.UInt16:
226                     return v.ToUInt16(provider);
227                 case TypeCode.Int32:
228                     return v.ToInt32(provider);
229                 case TypeCode.UInt32:
230                     return v.ToUInt32(provider);
231                 case TypeCode.Int64:
232                     return v.ToInt64(provider);
233                 case TypeCode.UInt64:
234                     return v.ToUInt64(provider);
235                 case TypeCode.Single:
236                     return v.ToSingle(provider);
237                 case TypeCode.Double:
238                     return v.ToDouble(provider);
239                 case TypeCode.Decimal:
240                     return v.ToDecimal(provider);
241                 case TypeCode.DateTime:
242                     return v.ToDateTime(provider);
243                 case TypeCode.String:
244                     return v.ToString(provider);
245                 case TypeCode.Object:
246                     return value;
247                 case TypeCode.DBNull:
248                     throw new InvalidCastException(SR.InvalidCast_DBNull);
249                 case TypeCode.Empty:
250                     throw new InvalidCastException(SR.InvalidCast_Empty);
251                 default:
252                     throw new ArgumentException(SR.Arg_UnknownTypeCode);
253             }
254         }
255
256         internal static Object DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
257         {
258             Debug.Assert(value != null, "[Convert.DefaultToType]value!=null");
259             if (targetType == null)
260             {
261                 throw new ArgumentNullException(nameof(targetType));
262             }
263
264             if (ReferenceEquals(value.GetType(), targetType))
265             {
266                 return value;
267             }
268
269             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Boolean]))
270                 return value.ToBoolean(provider);
271             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Char]))
272                 return value.ToChar(provider);
273             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.SByte]))
274                 return value.ToSByte(provider);
275             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Byte]))
276                 return value.ToByte(provider);
277             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Int16]))
278                 return value.ToInt16(provider);
279             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.UInt16]))
280                 return value.ToUInt16(provider);
281             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Int32]))
282                 return value.ToInt32(provider);
283             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.UInt32]))
284                 return value.ToUInt32(provider);
285             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Int64]))
286                 return value.ToInt64(provider);
287             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.UInt64]))
288                 return value.ToUInt64(provider);
289             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Single]))
290                 return value.ToSingle(provider);
291             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Double]))
292                 return value.ToDouble(provider);
293             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Decimal]))
294                 return value.ToDecimal(provider);
295             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.DateTime]))
296                 return value.ToDateTime(provider);
297             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.String]))
298                 return value.ToString(provider);
299             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Object]))
300                 return (Object)value;
301             //  Need to special case Enum because typecode will be underlying type, e.g. Int32
302             if (ReferenceEquals(targetType, EnumType))
303                 return (Enum)value;
304             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.DBNull]))
305                 throw new InvalidCastException(SR.InvalidCast_DBNull);
306             if (ReferenceEquals(targetType, ConvertTypes[(int)TypeCode.Empty]))
307                 throw new InvalidCastException(SR.InvalidCast_Empty);
308
309             throw new InvalidCastException(string.Format(SR.InvalidCast_FromTo, value.GetType().FullName, targetType.FullName));
310         }
311
312         public static Object ChangeType(Object value, Type conversionType)
313         {
314             return ChangeType(value, conversionType, CultureInfo.CurrentCulture);
315         }
316
317         public static Object ChangeType(Object value, Type conversionType, IFormatProvider provider)
318         {
319             if (ReferenceEquals(conversionType, null))
320             {
321                 throw new ArgumentNullException(nameof(conversionType));
322             }
323
324             if (value == null)
325             {
326                 if (conversionType.IsValueType)
327                 {
328                     throw new InvalidCastException(SR.InvalidCast_CannotCastNullToValueType);
329                 }
330                 return null;
331             }
332
333             IConvertible ic = value as IConvertible;
334             if (ic == null)
335             {
336                 if (value.GetType() == conversionType)
337                 {
338                     return value;
339                 }
340                 throw new InvalidCastException(SR.InvalidCast_IConvertible);
341             }
342
343             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Boolean]))
344                 return ic.ToBoolean(provider);
345             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Char]))
346                 return ic.ToChar(provider);
347             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.SByte]))
348                 return ic.ToSByte(provider);
349             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Byte]))
350                 return ic.ToByte(provider);
351             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Int16]))
352                 return ic.ToInt16(provider);
353             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.UInt16]))
354                 return ic.ToUInt16(provider);
355             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Int32]))
356                 return ic.ToInt32(provider);
357             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.UInt32]))
358                 return ic.ToUInt32(provider);
359             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Int64]))
360                 return ic.ToInt64(provider);
361             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.UInt64]))
362                 return ic.ToUInt64(provider);
363             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Single]))
364                 return ic.ToSingle(provider);
365             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Double]))
366                 return ic.ToDouble(provider);
367             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Decimal]))
368                 return ic.ToDecimal(provider);
369             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.DateTime]))
370                 return ic.ToDateTime(provider);
371             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.String]))
372                 return ic.ToString(provider);
373             if (ReferenceEquals(conversionType, ConvertTypes[(int)TypeCode.Object]))
374                 return (Object)value;
375
376             return ic.ToType(conversionType, provider);
377         }
378
379         [MethodImpl(MethodImplOptions.NoInlining)]
380         private static void ThrowCharOverflowException() { throw new OverflowException(SR.Overflow_Char); }
381
382         [MethodImpl(MethodImplOptions.NoInlining)]
383         private static void ThrowByteOverflowException() { throw new OverflowException(SR.Overflow_Byte); }
384
385         [MethodImpl(MethodImplOptions.NoInlining)]
386         private static void ThrowSByteOverflowException() { throw new OverflowException(SR.Overflow_SByte); }
387
388         [MethodImpl(MethodImplOptions.NoInlining)]
389         private static void ThrowInt16OverflowException() { throw new OverflowException(SR.Overflow_Int16); }
390
391         [MethodImpl(MethodImplOptions.NoInlining)]
392         private static void ThrowUInt16OverflowException() { throw new OverflowException(SR.Overflow_UInt16); }
393
394         [MethodImpl(MethodImplOptions.NoInlining)]
395         private static void ThrowInt32OverflowException() { throw new OverflowException(SR.Overflow_Int32); }
396
397         [MethodImpl(MethodImplOptions.NoInlining)]
398         private static void ThrowUInt32OverflowException() { throw new OverflowException(SR.Overflow_UInt32); }
399
400         [MethodImpl(MethodImplOptions.NoInlining)]
401         private static void ThrowInt64OverflowException() { throw new OverflowException(SR.Overflow_Int64); }
402
403         [MethodImpl(MethodImplOptions.NoInlining)]
404         private static void ThrowUInt64OverflowException() { throw new OverflowException(SR.Overflow_UInt64); }
405
406         // Conversions to Boolean
407         public static bool ToBoolean(Object value)
408         {
409             return value == null ? false : ((IConvertible)value).ToBoolean(null);
410         }
411
412         public static bool ToBoolean(Object value, IFormatProvider provider)
413         {
414             return value == null ? false : ((IConvertible)value).ToBoolean(provider);
415         }
416
417
418         public static bool ToBoolean(bool value)
419         {
420             return value;
421         }
422
423         [CLSCompliant(false)]
424         public static bool ToBoolean(sbyte value)
425         {
426             return value != 0;
427         }
428
429         // To be consistent with IConvertible in the base data types else we get different semantics
430         // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
431         public static bool ToBoolean(char value)
432         {
433             return ((IConvertible)value).ToBoolean(null);
434         }
435
436         public static bool ToBoolean(byte value)
437         {
438             return value != 0;
439         }
440
441
442         public static bool ToBoolean(short value)
443         {
444             return value != 0;
445         }
446
447         [CLSCompliant(false)]
448         public static bool ToBoolean(ushort value)
449         {
450             return value != 0;
451         }
452
453         public static bool ToBoolean(int value)
454         {
455             return value != 0;
456         }
457
458         [CLSCompliant(false)]
459         public static bool ToBoolean(uint value)
460         {
461             return value != 0;
462         }
463
464         public static bool ToBoolean(long value)
465         {
466             return value != 0;
467         }
468
469         [CLSCompliant(false)]
470         public static bool ToBoolean(ulong value)
471         {
472             return value != 0;
473         }
474
475         public static bool ToBoolean(String value)
476         {
477             if (value == null)
478                 return false;
479             return Boolean.Parse(value);
480         }
481
482         public static bool ToBoolean(String value, IFormatProvider provider)
483         {
484             if (value == null)
485                 return false;
486             return Boolean.Parse(value);
487         }
488
489         public static bool ToBoolean(float value)
490         {
491             return value != 0;
492         }
493
494         public static bool ToBoolean(double value)
495         {
496             return value != 0;
497         }
498
499         public static bool ToBoolean(decimal value)
500         {
501             return value != 0;
502         }
503
504         public static bool ToBoolean(DateTime value)
505         {
506             return ((IConvertible)value).ToBoolean(null);
507         }
508
509         // Disallowed conversions to Boolean
510         // public static bool ToBoolean(TimeSpan value)
511
512         // Conversions to Char
513
514
515         public static char ToChar(object value)
516         {
517             return value == null ? (char)0 : ((IConvertible)value).ToChar(null);
518         }
519
520         public static char ToChar(object value, IFormatProvider provider)
521         {
522             return value == null ? (char)0 : ((IConvertible)value).ToChar(provider);
523         }
524
525         public static char ToChar(bool value)
526         {
527             return ((IConvertible)value).ToChar(null);
528         }
529
530         public static char ToChar(char value)
531         {
532             return value;
533         }
534
535         [CLSCompliant(false)]
536         public static char ToChar(sbyte value)
537         {
538             if (value < 0) ThrowCharOverflowException();
539             return (char)value;
540         }
541
542         public static char ToChar(byte value)
543         {
544             return (char)value;
545         }
546
547         public static char ToChar(short value)
548         {
549             if (value < 0) ThrowCharOverflowException();
550             return (char)value;
551         }
552
553         [CLSCompliant(false)]
554         public static char ToChar(ushort value)
555         {
556             return (char)value;
557         }
558
559         public static char ToChar(int value)
560         {
561             if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
562             return (char)value;
563         }
564
565         [CLSCompliant(false)]
566         public static char ToChar(uint value)
567         {
568             if (value > Char.MaxValue) ThrowCharOverflowException();
569             return (char)value;
570         }
571
572         public static char ToChar(long value)
573         {
574             if (value < 0 || value > Char.MaxValue) ThrowCharOverflowException();
575             return (char)value;
576         }
577
578         [CLSCompliant(false)]
579         public static char ToChar(ulong value)
580         {
581             if (value > Char.MaxValue) ThrowCharOverflowException();
582             return (char)value;
583         }
584
585         //
586         // @VariantSwitch
587         // Remove FormatExceptions;
588         //
589         public static char ToChar(String value)
590         {
591             return ToChar(value, null);
592         }
593
594         public static char ToChar(String value, IFormatProvider provider)
595         {
596             if (value == null)
597                 throw new ArgumentNullException(nameof(value));
598
599             if (value.Length != 1)
600                 throw new FormatException(SR.Format_NeedSingleChar);
601
602             return value[0];
603         }
604
605         // To be consistent with IConvertible in the base data types else we get different semantics
606         // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
607         public static char ToChar(float value)
608         {
609             return ((IConvertible)value).ToChar(null);
610         }
611
612         // To be consistent with IConvertible in the base data types else we get different semantics
613         // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
614         public static char ToChar(double value)
615         {
616             return ((IConvertible)value).ToChar(null);
617         }
618
619         // To be consistent with IConvertible in the base data types else we get different semantics
620         // with widening operations. Without this operator this widen succeeds,with this API the widening throws.
621         public static char ToChar(decimal value)
622         {
623             return ((IConvertible)value).ToChar(null);
624         }
625
626         public static char ToChar(DateTime value)
627         {
628             return ((IConvertible)value).ToChar(null);
629         }
630
631
632         // Disallowed conversions to Char
633         // public static char ToChar(TimeSpan value)
634
635         // Conversions to SByte
636
637         [CLSCompliant(false)]
638         public static sbyte ToSByte(object value)
639         {
640             return value == null ? (sbyte)0 : ((IConvertible)value).ToSByte(null);
641         }
642
643         [CLSCompliant(false)]
644         public static sbyte ToSByte(object value, IFormatProvider provider)
645         {
646             return value == null ? (sbyte)0 : ((IConvertible)value).ToSByte(provider);
647         }
648
649         [CLSCompliant(false)]
650         public static sbyte ToSByte(bool value)
651         {
652             return value ? (sbyte)Boolean.True : (sbyte)Boolean.False;
653         }
654
655         [CLSCompliant(false)]
656         public static sbyte ToSByte(sbyte value)
657         {
658             return value;
659         }
660
661         [CLSCompliant(false)]
662         public static sbyte ToSByte(char value)
663         {
664             if (value > SByte.MaxValue) ThrowSByteOverflowException();
665             return (sbyte)value;
666         }
667
668         [CLSCompliant(false)]
669         public static sbyte ToSByte(byte value)
670         {
671             if (value > SByte.MaxValue) ThrowSByteOverflowException();
672             return (sbyte)value;
673         }
674
675         [CLSCompliant(false)]
676         public static sbyte ToSByte(short value)
677         {
678             if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
679             return (sbyte)value;
680         }
681
682         [CLSCompliant(false)]
683         public static sbyte ToSByte(ushort value)
684         {
685             if (value > SByte.MaxValue) ThrowSByteOverflowException();
686             return (sbyte)value;
687         }
688
689         [CLSCompliant(false)]
690         public static sbyte ToSByte(int value)
691         {
692             if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
693             return (sbyte)value;
694         }
695
696         [CLSCompliant(false)]
697         public static sbyte ToSByte(uint value)
698         {
699             if (value > SByte.MaxValue) ThrowSByteOverflowException();
700             return (sbyte)value;
701         }
702
703         [CLSCompliant(false)]
704         public static sbyte ToSByte(long value)
705         {
706             if (value < SByte.MinValue || value > SByte.MaxValue) ThrowSByteOverflowException();
707             return (sbyte)value;
708         }
709
710         [CLSCompliant(false)]
711         public static sbyte ToSByte(ulong value)
712         {
713             if (value > (ulong)SByte.MaxValue) ThrowSByteOverflowException();
714             return (sbyte)value;
715         }
716
717         [CLSCompliant(false)]
718         public static sbyte ToSByte(float value)
719         {
720             return ToSByte((double)value);
721         }
722
723         [CLSCompliant(false)]
724         public static sbyte ToSByte(double value)
725         {
726             return ToSByte(ToInt32(value));
727         }
728
729         [CLSCompliant(false)]
730         public static sbyte ToSByte(decimal value)
731         {
732             return Decimal.ToSByte(Decimal.Round(value, 0));
733         }
734
735         [CLSCompliant(false)]
736         public static sbyte ToSByte(String value)
737         {
738             if (value == null)
739                 return 0;
740             return SByte.Parse(value, CultureInfo.CurrentCulture);
741         }
742
743         [CLSCompliant(false)]
744         public static sbyte ToSByte(String value, IFormatProvider provider)
745         {
746             return SByte.Parse(value, NumberStyles.Integer, provider);
747         }
748
749         [CLSCompliant(false)]
750         public static sbyte ToSByte(DateTime value)
751         {
752             return ((IConvertible)value).ToSByte(null);
753         }
754
755         // Disallowed conversions to SByte
756         // public static sbyte ToSByte(TimeSpan value)
757
758         // Conversions to Byte
759
760         public static byte ToByte(object value)
761         {
762             return value == null ? (byte)0 : ((IConvertible)value).ToByte(null);
763         }
764
765         public static byte ToByte(object value, IFormatProvider provider)
766         {
767             return value == null ? (byte)0 : ((IConvertible)value).ToByte(provider);
768         }
769
770         public static byte ToByte(bool value)
771         {
772             return value ? (byte)Boolean.True : (byte)Boolean.False;
773         }
774
775         public static byte ToByte(byte value)
776         {
777             return value;
778         }
779
780         public static byte ToByte(char value)
781         {
782             if (value > Byte.MaxValue) ThrowByteOverflowException();
783             return (byte)value;
784         }
785
786         [CLSCompliant(false)]
787         public static byte ToByte(sbyte value)
788         {
789             if (value < Byte.MinValue) ThrowByteOverflowException();
790             return (byte)value;
791         }
792
793         public static byte ToByte(short value)
794         {
795             if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
796             return (byte)value;
797         }
798
799         [CLSCompliant(false)]
800         public static byte ToByte(ushort value)
801         {
802             if (value > Byte.MaxValue) ThrowByteOverflowException();
803             return (byte)value;
804         }
805
806         public static byte ToByte(int value)
807         {
808             if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
809             return (byte)value;
810         }
811
812         [CLSCompliant(false)]
813         public static byte ToByte(uint value)
814         {
815             if (value > Byte.MaxValue) ThrowByteOverflowException();
816             return (byte)value;
817         }
818
819         public static byte ToByte(long value)
820         {
821             if (value < Byte.MinValue || value > Byte.MaxValue) ThrowByteOverflowException();
822             return (byte)value;
823         }
824
825         [CLSCompliant(false)]
826         public static byte ToByte(ulong value)
827         {
828             if (value > Byte.MaxValue) ThrowByteOverflowException();
829             return (byte)value;
830         }
831
832         public static byte ToByte(float value)
833         {
834             return ToByte((double)value);
835         }
836
837         public static byte ToByte(double value)
838         {
839             return ToByte(ToInt32(value));
840         }
841
842         public static byte ToByte(decimal value)
843         {
844             return Decimal.ToByte(Decimal.Round(value, 0));
845         }
846
847         public static byte ToByte(String value)
848         {
849             if (value == null)
850                 return 0;
851             return Byte.Parse(value, CultureInfo.CurrentCulture);
852         }
853
854         public static byte ToByte(String value, IFormatProvider provider)
855         {
856             if (value == null)
857                 return 0;
858             return Byte.Parse(value, NumberStyles.Integer, provider);
859         }
860
861         public static byte ToByte(DateTime value)
862         {
863             return ((IConvertible)value).ToByte(null);
864         }
865
866
867         // Disallowed conversions to Byte
868         // public static byte ToByte(TimeSpan value)
869
870         // Conversions to Int16
871
872         public static short ToInt16(object value)
873         {
874             return value == null ? (short)0 : ((IConvertible)value).ToInt16(null);
875         }
876
877         public static short ToInt16(object value, IFormatProvider provider)
878         {
879             return value == null ? (short)0 : ((IConvertible)value).ToInt16(provider);
880         }
881
882         public static short ToInt16(bool value)
883         {
884             return value ? (short)Boolean.True : (short)Boolean.False;
885         }
886
887         public static short ToInt16(char value)
888         {
889             if (value > Int16.MaxValue) ThrowInt16OverflowException();
890             return (short)value;
891         }
892
893         [CLSCompliant(false)]
894         public static short ToInt16(sbyte value)
895         {
896             return value;
897         }
898
899         public static short ToInt16(byte value)
900         {
901             return value;
902         }
903
904         [CLSCompliant(false)]
905         public static short ToInt16(ushort value)
906         {
907             if (value > Int16.MaxValue) ThrowInt16OverflowException();
908             return (short)value;
909         }
910
911         public static short ToInt16(int value)
912         {
913             if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
914             return (short)value;
915         }
916
917         [CLSCompliant(false)]
918         public static short ToInt16(uint value)
919         {
920             if (value > Int16.MaxValue) ThrowInt16OverflowException();
921             return (short)value;
922         }
923
924         public static short ToInt16(short value)
925         {
926             return value;
927         }
928
929         public static short ToInt16(long value)
930         {
931             if (value < Int16.MinValue || value > Int16.MaxValue) ThrowInt16OverflowException();
932             return (short)value;
933         }
934
935         [CLSCompliant(false)]
936         public static short ToInt16(ulong value)
937         {
938             if (value > (ulong)Int16.MaxValue) ThrowInt16OverflowException();
939             return (short)value;
940         }
941
942         public static short ToInt16(float value)
943         {
944             return ToInt16((double)value);
945         }
946
947         public static short ToInt16(double value)
948         {
949             return ToInt16(ToInt32(value));
950         }
951
952         public static short ToInt16(decimal value)
953         {
954             return Decimal.ToInt16(Decimal.Round(value, 0));
955         }
956
957         public static short ToInt16(String value)
958         {
959             if (value == null)
960                 return 0;
961             return Int16.Parse(value, CultureInfo.CurrentCulture);
962         }
963
964         public static short ToInt16(String value, IFormatProvider provider)
965         {
966             if (value == null)
967                 return 0;
968             return Int16.Parse(value, NumberStyles.Integer, provider);
969         }
970
971         public static short ToInt16(DateTime value)
972         {
973             return ((IConvertible)value).ToInt16(null);
974         }
975
976
977         // Disallowed conversions to Int16
978         // public static short ToInt16(TimeSpan value)
979
980         // Conversions to UInt16
981
982         [CLSCompliant(false)]
983         public static ushort ToUInt16(object value)
984         {
985             return value == null ? (ushort)0 : ((IConvertible)value).ToUInt16(null);
986         }
987
988         [CLSCompliant(false)]
989         public static ushort ToUInt16(object value, IFormatProvider provider)
990         {
991             return value == null ? (ushort)0 : ((IConvertible)value).ToUInt16(provider);
992         }
993
994
995         [CLSCompliant(false)]
996         public static ushort ToUInt16(bool value)
997         {
998             return value ? (ushort)Boolean.True : (ushort)Boolean.False;
999         }
1000
1001         [CLSCompliant(false)]
1002         public static ushort ToUInt16(char value)
1003         {
1004             return value;
1005         }
1006
1007         [CLSCompliant(false)]
1008         public static ushort ToUInt16(sbyte value)
1009         {
1010             if (value < 0) ThrowUInt16OverflowException();
1011             return (ushort)value;
1012         }
1013
1014         [CLSCompliant(false)]
1015         public static ushort ToUInt16(byte value)
1016         {
1017             return value;
1018         }
1019
1020         [CLSCompliant(false)]
1021         public static ushort ToUInt16(short value)
1022         {
1023             if (value < 0) ThrowUInt16OverflowException();
1024             return (ushort)value;
1025         }
1026
1027         [CLSCompliant(false)]
1028         public static ushort ToUInt16(int value)
1029         {
1030             if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
1031             return (ushort)value;
1032         }
1033
1034         [CLSCompliant(false)]
1035         public static ushort ToUInt16(ushort value)
1036         {
1037             return value;
1038         }
1039
1040         [CLSCompliant(false)]
1041         public static ushort ToUInt16(uint value)
1042         {
1043             if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
1044             return (ushort)value;
1045         }
1046
1047
1048         [CLSCompliant(false)]
1049         public static ushort ToUInt16(long value)
1050         {
1051             if (value < 0 || value > UInt16.MaxValue) ThrowUInt16OverflowException();
1052             return (ushort)value;
1053         }
1054
1055         [CLSCompliant(false)]
1056         public static ushort ToUInt16(ulong value)
1057         {
1058             if (value > UInt16.MaxValue) ThrowUInt16OverflowException();
1059             return (ushort)value;
1060         }
1061
1062         [CLSCompliant(false)]
1063         public static ushort ToUInt16(float value)
1064         {
1065             return ToUInt16((double)value);
1066         }
1067
1068         [CLSCompliant(false)]
1069         public static ushort ToUInt16(double value)
1070         {
1071             return ToUInt16(ToInt32(value));
1072         }
1073
1074         [CLSCompliant(false)]
1075         public static ushort ToUInt16(decimal value)
1076         {
1077             return Decimal.ToUInt16(Decimal.Round(value, 0));
1078         }
1079
1080         [CLSCompliant(false)]
1081         public static ushort ToUInt16(String value)
1082         {
1083             if (value == null)
1084                 return 0;
1085             return UInt16.Parse(value, CultureInfo.CurrentCulture);
1086         }
1087
1088         [CLSCompliant(false)]
1089         public static ushort ToUInt16(String value, IFormatProvider provider)
1090         {
1091             if (value == null)
1092                 return 0;
1093             return UInt16.Parse(value, NumberStyles.Integer, provider);
1094         }
1095
1096         [CLSCompliant(false)]
1097         public static ushort ToUInt16(DateTime value)
1098         {
1099             return ((IConvertible)value).ToUInt16(null);
1100         }
1101
1102         // Disallowed conversions to UInt16
1103         // public static ushort ToUInt16(TimeSpan value)
1104
1105         // Conversions to Int32
1106
1107         public static int ToInt32(object value)
1108         {
1109             return value == null ? 0 : ((IConvertible)value).ToInt32(null);
1110         }
1111
1112         public static int ToInt32(object value, IFormatProvider provider)
1113         {
1114             return value == null ? 0 : ((IConvertible)value).ToInt32(provider);
1115         }
1116
1117
1118         public static int ToInt32(bool value)
1119         {
1120             return value ? Boolean.True : Boolean.False;
1121         }
1122
1123         public static int ToInt32(char value)
1124         {
1125             return value;
1126         }
1127
1128         [CLSCompliant(false)]
1129         public static int ToInt32(sbyte value)
1130         {
1131             return value;
1132         }
1133
1134         public static int ToInt32(byte value)
1135         {
1136             return value;
1137         }
1138
1139         public static int ToInt32(short value)
1140         {
1141             return value;
1142         }
1143
1144         [CLSCompliant(false)]
1145         public static int ToInt32(ushort value)
1146         {
1147             return value;
1148         }
1149
1150         [CLSCompliant(false)]
1151         public static int ToInt32(uint value)
1152         {
1153             if (value > Int32.MaxValue) ThrowInt32OverflowException();
1154             return (int)value;
1155         }
1156
1157         public static int ToInt32(int value)
1158         {
1159             return value;
1160         }
1161
1162         public static int ToInt32(long value)
1163         {
1164             if (value < Int32.MinValue || value > Int32.MaxValue) ThrowInt32OverflowException();
1165             return (int)value;
1166         }
1167
1168         [CLSCompliant(false)]
1169         public static int ToInt32(ulong value)
1170         {
1171             if (value > Int32.MaxValue) ThrowInt32OverflowException();
1172             return (int)value;
1173         }
1174
1175         public static int ToInt32(float value)
1176         {
1177             return ToInt32((double)value);
1178         }
1179
1180         public static int ToInt32(double value)
1181         {
1182             if (value >= 0)
1183             {
1184                 if (value < 2147483647.5)
1185                 {
1186                     int result = (int)value;
1187                     double dif = value - result;
1188                     if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++;
1189                     return result;
1190                 }
1191             }
1192             else
1193             {
1194                 if (value >= -2147483648.5)
1195                 {
1196                     int result = (int)value;
1197                     double dif = value - result;
1198                     if (dif < -0.5 || dif == -0.5 && (result & 1) != 0) result--;
1199                     return result;
1200                 }
1201             }
1202             throw new OverflowException(SR.Overflow_Int32);
1203         }
1204
1205         public static int ToInt32(decimal value)
1206         {
1207             return Decimal.ToInt32(Decimal.Round(value, 0));
1208         }
1209
1210         public static int ToInt32(String value)
1211         {
1212             if (value == null)
1213                 return 0;
1214             return Int32.Parse(value, CultureInfo.CurrentCulture);
1215         }
1216
1217         public static int ToInt32(String value, IFormatProvider provider)
1218         {
1219             if (value == null)
1220                 return 0;
1221             return Int32.Parse(value, NumberStyles.Integer, provider);
1222         }
1223
1224         public static int ToInt32(DateTime value)
1225         {
1226             return ((IConvertible)value).ToInt32(null);
1227         }
1228
1229
1230         // Disallowed conversions to Int32
1231         // public static int ToInt32(TimeSpan value)
1232
1233         // Conversions to UInt32
1234
1235         [CLSCompliant(false)]
1236         public static uint ToUInt32(object value)
1237         {
1238             return value == null ? 0 : ((IConvertible)value).ToUInt32(null);
1239         }
1240
1241         [CLSCompliant(false)]
1242         public static uint ToUInt32(object value, IFormatProvider provider)
1243         {
1244             return value == null ? 0 : ((IConvertible)value).ToUInt32(provider);
1245         }
1246
1247
1248         [CLSCompliant(false)]
1249         public static uint ToUInt32(bool value)
1250         {
1251             return value ? (uint)Boolean.True : (uint)Boolean.False;
1252         }
1253
1254         [CLSCompliant(false)]
1255         public static uint ToUInt32(char value)
1256         {
1257             return value;
1258         }
1259
1260         [CLSCompliant(false)]
1261         public static uint ToUInt32(sbyte value)
1262         {
1263             if (value < 0) ThrowUInt32OverflowException();
1264             return (uint)value;
1265         }
1266
1267         [CLSCompliant(false)]
1268         public static uint ToUInt32(byte value)
1269         {
1270             return value;
1271         }
1272
1273         [CLSCompliant(false)]
1274         public static uint ToUInt32(short value)
1275         {
1276             if (value < 0) ThrowUInt32OverflowException();
1277             return (uint)value;
1278         }
1279
1280         [CLSCompliant(false)]
1281         public static uint ToUInt32(ushort value)
1282         {
1283             return value;
1284         }
1285
1286         [CLSCompliant(false)]
1287         public static uint ToUInt32(int value)
1288         {
1289             if (value < 0) ThrowUInt32OverflowException();
1290             return (uint)value;
1291         }
1292
1293         [CLSCompliant(false)]
1294         public static uint ToUInt32(uint value)
1295         {
1296             return value;
1297         }
1298
1299         [CLSCompliant(false)]
1300         public static uint ToUInt32(long value)
1301         {
1302             if (value < 0 || value > UInt32.MaxValue) ThrowUInt32OverflowException();
1303             return (uint)value;
1304         }
1305
1306         [CLSCompliant(false)]
1307         public static uint ToUInt32(ulong value)
1308         {
1309             if (value > UInt32.MaxValue) ThrowUInt32OverflowException();
1310             return (uint)value;
1311         }
1312
1313         [CLSCompliant(false)]
1314         public static uint ToUInt32(float value)
1315         {
1316             return ToUInt32((double)value);
1317         }
1318
1319         [CLSCompliant(false)]
1320         public static uint ToUInt32(double value)
1321         {
1322             if (value >= -0.5 && value < 4294967295.5)
1323             {
1324                 uint result = (uint)value;
1325                 double dif = value - result;
1326                 if (dif > 0.5 || dif == 0.5 && (result & 1) != 0) result++;
1327                 return result;
1328             }
1329             throw new OverflowException(SR.Overflow_UInt32);
1330         }
1331
1332         [CLSCompliant(false)]
1333         public static uint ToUInt32(decimal value)
1334         {
1335             return Decimal.ToUInt32(Decimal.Round(value, 0));
1336         }
1337
1338         [CLSCompliant(false)]
1339         public static uint ToUInt32(String value)
1340         {
1341             if (value == null)
1342                 return 0;
1343             return UInt32.Parse(value, CultureInfo.CurrentCulture);
1344         }
1345
1346         [CLSCompliant(false)]
1347         public static uint ToUInt32(String value, IFormatProvider provider)
1348         {
1349             if (value == null)
1350                 return 0;
1351             return UInt32.Parse(value, NumberStyles.Integer, provider);
1352         }
1353
1354         [CLSCompliant(false)]
1355         public static uint ToUInt32(DateTime value)
1356         {
1357             return ((IConvertible)value).ToUInt32(null);
1358         }
1359
1360         // Disallowed conversions to UInt32
1361         // public static uint ToUInt32(TimeSpan value)
1362
1363         // Conversions to Int64
1364
1365         public static long ToInt64(object value)
1366         {
1367             return value == null ? 0 : ((IConvertible)value).ToInt64(null);
1368         }
1369
1370         public static long ToInt64(object value, IFormatProvider provider)
1371         {
1372             return value == null ? 0 : ((IConvertible)value).ToInt64(provider);
1373         }
1374
1375
1376         public static long ToInt64(bool value)
1377         {
1378             return value ? Boolean.True : Boolean.False;
1379         }
1380
1381         public static long ToInt64(char value)
1382         {
1383             return value;
1384         }
1385
1386         [CLSCompliant(false)]
1387         public static long ToInt64(sbyte value)
1388         {
1389             return value;
1390         }
1391
1392         public static long ToInt64(byte value)
1393         {
1394             return value;
1395         }
1396
1397         public static long ToInt64(short value)
1398         {
1399             return value;
1400         }
1401
1402         [CLSCompliant(false)]
1403         public static long ToInt64(ushort value)
1404         {
1405             return value;
1406         }
1407
1408         public static long ToInt64(int value)
1409         {
1410             return value;
1411         }
1412
1413         [CLSCompliant(false)]
1414         public static long ToInt64(uint value)
1415         {
1416             return value;
1417         }
1418
1419         [CLSCompliant(false)]
1420         public static long ToInt64(ulong value)
1421         {
1422             if (value > Int64.MaxValue) ThrowInt64OverflowException();
1423             return (long)value;
1424         }
1425
1426         public static long ToInt64(long value)
1427         {
1428             return value;
1429         }
1430
1431
1432         public static long ToInt64(float value)
1433         {
1434             return ToInt64((double)value);
1435         }
1436
1437         public static long ToInt64(double value)
1438         {
1439             return checked((long)Math.Round(value));
1440         }
1441
1442         public static long ToInt64(decimal value)
1443         {
1444             return Decimal.ToInt64(Decimal.Round(value, 0));
1445         }
1446
1447         public static long ToInt64(string value)
1448         {
1449             if (value == null)
1450                 return 0;
1451             return Int64.Parse(value, CultureInfo.CurrentCulture);
1452         }
1453
1454         public static long ToInt64(String value, IFormatProvider provider)
1455         {
1456             if (value == null)
1457                 return 0;
1458             return Int64.Parse(value, NumberStyles.Integer, provider);
1459         }
1460
1461         public static long ToInt64(DateTime value)
1462         {
1463             return ((IConvertible)value).ToInt64(null);
1464         }
1465
1466         // Disallowed conversions to Int64
1467         // public static long ToInt64(TimeSpan value)
1468
1469         // Conversions to UInt64
1470
1471         [CLSCompliant(false)]
1472         public static ulong ToUInt64(object value)
1473         {
1474             return value == null ? 0 : ((IConvertible)value).ToUInt64(null);
1475         }
1476
1477         [CLSCompliant(false)]
1478         public static ulong ToUInt64(object value, IFormatProvider provider)
1479         {
1480             return value == null ? 0 : ((IConvertible)value).ToUInt64(provider);
1481         }
1482
1483         [CLSCompliant(false)]
1484         public static ulong ToUInt64(bool value)
1485         {
1486             return value ? (ulong)Boolean.True : (ulong)Boolean.False;
1487         }
1488
1489         [CLSCompliant(false)]
1490         public static ulong ToUInt64(char value)
1491         {
1492             return value;
1493         }
1494
1495
1496         [CLSCompliant(false)]
1497         public static ulong ToUInt64(sbyte value)
1498         {
1499             if (value < 0) ThrowUInt64OverflowException();
1500             return (ulong)value;
1501         }
1502
1503         [CLSCompliant(false)]
1504         public static ulong ToUInt64(byte value)
1505         {
1506             return value;
1507         }
1508
1509         [CLSCompliant(false)]
1510         public static ulong ToUInt64(short value)
1511         {
1512             if (value < 0) ThrowUInt64OverflowException();
1513             return (ulong)value;
1514         }
1515
1516         [CLSCompliant(false)]
1517         public static ulong ToUInt64(ushort value)
1518         {
1519             return value;
1520         }
1521
1522         [CLSCompliant(false)]
1523         public static ulong ToUInt64(int value)
1524         {
1525             if (value < 0) ThrowUInt64OverflowException();
1526             return (ulong)value;
1527         }
1528
1529         [CLSCompliant(false)]
1530         public static ulong ToUInt64(uint value)
1531         {
1532             return value;
1533         }
1534
1535         [CLSCompliant(false)]
1536         public static ulong ToUInt64(long value)
1537         {
1538             if (value < 0) ThrowUInt64OverflowException();
1539             return (ulong)value;
1540         }
1541
1542         [CLSCompliant(false)]
1543         public static ulong ToUInt64(UInt64 value)
1544         {
1545             return value;
1546         }
1547
1548         [CLSCompliant(false)]
1549         public static ulong ToUInt64(float value)
1550         {
1551             return ToUInt64((double)value);
1552         }
1553
1554         [CLSCompliant(false)]
1555         public static ulong ToUInt64(double value)
1556         {
1557             return checked((ulong)Math.Round(value));
1558         }
1559
1560         [CLSCompliant(false)]
1561         public static ulong ToUInt64(decimal value)
1562         {
1563             return Decimal.ToUInt64(Decimal.Round(value, 0));
1564         }
1565
1566         [CLSCompliant(false)]
1567         public static ulong ToUInt64(String value)
1568         {
1569             if (value == null)
1570                 return 0;
1571             return UInt64.Parse(value, CultureInfo.CurrentCulture);
1572         }
1573
1574         [CLSCompliant(false)]
1575         public static ulong ToUInt64(String value, IFormatProvider provider)
1576         {
1577             if (value == null)
1578                 return 0;
1579             return UInt64.Parse(value, NumberStyles.Integer, provider);
1580         }
1581
1582         [CLSCompliant(false)]
1583         public static ulong ToUInt64(DateTime value)
1584         {
1585             return ((IConvertible)value).ToUInt64(null);
1586         }
1587
1588         // Disallowed conversions to UInt64
1589         // public static ulong ToUInt64(TimeSpan value)
1590
1591         // Conversions to Single
1592
1593         public static float ToSingle(object value)
1594         {
1595             return value == null ? 0 : ((IConvertible)value).ToSingle(null);
1596         }
1597
1598         public static float ToSingle(object value, IFormatProvider provider)
1599         {
1600             return value == null ? 0 : ((IConvertible)value).ToSingle(provider);
1601         }
1602
1603         [CLSCompliant(false)]
1604         public static float ToSingle(sbyte value)
1605         {
1606             return value;
1607         }
1608
1609         public static float ToSingle(byte value)
1610         {
1611             return value;
1612         }
1613
1614         public static float ToSingle(char value)
1615         {
1616             return ((IConvertible)value).ToSingle(null);
1617         }
1618
1619         public static float ToSingle(short value)
1620         {
1621             return value;
1622         }
1623
1624         [CLSCompliant(false)]
1625         public static float ToSingle(ushort value)
1626         {
1627             return value;
1628         }
1629
1630         public static float ToSingle(int value)
1631         {
1632             return value;
1633         }
1634
1635         [CLSCompliant(false)]
1636         public static float ToSingle(uint value)
1637         {
1638             return value;
1639         }
1640
1641         public static float ToSingle(long value)
1642         {
1643             return value;
1644         }
1645
1646         [CLSCompliant(false)]
1647         public static float ToSingle(ulong value)
1648         {
1649             return value;
1650         }
1651
1652         public static float ToSingle(float value)
1653         {
1654             return value;
1655         }
1656
1657         public static float ToSingle(double value)
1658         {
1659             return (float)value;
1660         }
1661
1662         public static float ToSingle(decimal value)
1663         {
1664             return (float)value;
1665         }
1666
1667         public static float ToSingle(String value)
1668         {
1669             if (value == null)
1670                 return 0;
1671             return Single.Parse(value, CultureInfo.CurrentCulture);
1672         }
1673
1674         public static float ToSingle(String value, IFormatProvider provider)
1675         {
1676             if (value == null)
1677                 return 0;
1678             return Single.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
1679         }
1680
1681
1682         public static float ToSingle(bool value)
1683         {
1684             return value ? Boolean.True : Boolean.False;
1685         }
1686
1687         public static float ToSingle(DateTime value)
1688         {
1689             return ((IConvertible)value).ToSingle(null);
1690         }
1691
1692         // Disallowed conversions to Single
1693         // public static float ToSingle(TimeSpan value)
1694
1695         // Conversions to Double
1696
1697         public static double ToDouble(object value)
1698         {
1699             return value == null ? 0 : ((IConvertible)value).ToDouble(null);
1700         }
1701
1702         public static double ToDouble(object value, IFormatProvider provider)
1703         {
1704             return value == null ? 0 : ((IConvertible)value).ToDouble(provider);
1705         }
1706
1707
1708         [CLSCompliant(false)]
1709         public static double ToDouble(sbyte value)
1710         {
1711             return value;
1712         }
1713
1714         public static double ToDouble(byte value)
1715         {
1716             return value;
1717         }
1718
1719         public static double ToDouble(short value)
1720         {
1721             return value;
1722         }
1723
1724         public static double ToDouble(char value)
1725         {
1726             return ((IConvertible)value).ToDouble(null);
1727         }
1728
1729         [CLSCompliant(false)]
1730         public static double ToDouble(ushort value)
1731         {
1732             return value;
1733         }
1734
1735         public static double ToDouble(int value)
1736         {
1737             return value;
1738         }
1739
1740         [CLSCompliant(false)]
1741         public static double ToDouble(uint value)
1742         {
1743             return value;
1744         }
1745
1746         public static double ToDouble(long value)
1747         {
1748             return value;
1749         }
1750
1751         [CLSCompliant(false)]
1752         public static double ToDouble(ulong value)
1753         {
1754             return value;
1755         }
1756
1757         public static double ToDouble(float value)
1758         {
1759             return value;
1760         }
1761
1762         public static double ToDouble(double value)
1763         {
1764             return value;
1765         }
1766
1767         public static double ToDouble(decimal value)
1768         {
1769             return (double)value;
1770         }
1771
1772         public static double ToDouble(String value)
1773         {
1774             if (value == null)
1775                 return 0;
1776             return Double.Parse(value, CultureInfo.CurrentCulture);
1777         }
1778
1779         public static double ToDouble(String value, IFormatProvider provider)
1780         {
1781             if (value == null)
1782                 return 0;
1783             return Double.Parse(value, NumberStyles.Float | NumberStyles.AllowThousands, provider);
1784         }
1785
1786         public static double ToDouble(bool value)
1787         {
1788             return value ? Boolean.True : Boolean.False;
1789         }
1790
1791         public static double ToDouble(DateTime value)
1792         {
1793             return ((IConvertible)value).ToDouble(null);
1794         }
1795
1796         // Disallowed conversions to Double
1797         // public static double ToDouble(TimeSpan value)
1798
1799         // Conversions to Decimal
1800
1801         public static decimal ToDecimal(object value)
1802         {
1803             return value == null ? 0 : ((IConvertible)value).ToDecimal(null);
1804         }
1805
1806         public static decimal ToDecimal(object value, IFormatProvider provider)
1807         {
1808             return value == null ? 0 : ((IConvertible)value).ToDecimal(provider);
1809         }
1810
1811         [CLSCompliant(false)]
1812         public static decimal ToDecimal(sbyte value)
1813         {
1814             return value;
1815         }
1816
1817         public static decimal ToDecimal(byte value)
1818         {
1819             return value;
1820         }
1821
1822         public static decimal ToDecimal(char value)
1823         {
1824             return ((IConvertible)value).ToDecimal(null);
1825         }
1826
1827         public static decimal ToDecimal(short value)
1828         {
1829             return value;
1830         }
1831
1832         [CLSCompliant(false)]
1833         public static decimal ToDecimal(ushort value)
1834         {
1835             return value;
1836         }
1837
1838         public static decimal ToDecimal(int value)
1839         {
1840             return value;
1841         }
1842
1843         [CLSCompliant(false)]
1844         public static decimal ToDecimal(uint value)
1845         {
1846             return value;
1847         }
1848
1849         public static decimal ToDecimal(long value)
1850         {
1851             return value;
1852         }
1853
1854         [CLSCompliant(false)]
1855         public static decimal ToDecimal(ulong value)
1856         {
1857             return value;
1858         }
1859
1860         public static decimal ToDecimal(float value)
1861         {
1862             return (decimal)value;
1863         }
1864
1865         public static decimal ToDecimal(double value)
1866         {
1867             return (decimal)value;
1868         }
1869
1870         public static decimal ToDecimal(String value)
1871         {
1872             if (value == null)
1873                 return 0m;
1874             return Decimal.Parse(value, CultureInfo.CurrentCulture);
1875         }
1876
1877         public static Decimal ToDecimal(String value, IFormatProvider provider)
1878         {
1879             if (value == null)
1880                 return 0m;
1881             return Decimal.Parse(value, NumberStyles.Number, provider);
1882         }
1883
1884         public static decimal ToDecimal(decimal value)
1885         {
1886             return value;
1887         }
1888
1889         public static decimal ToDecimal(bool value)
1890         {
1891             return value ? Boolean.True : Boolean.False;
1892         }
1893
1894         public static decimal ToDecimal(DateTime value)
1895         {
1896             return ((IConvertible)value).ToDecimal(null);
1897         }
1898
1899         // Disallowed conversions to Decimal
1900         // public static decimal ToDecimal(TimeSpan value)
1901
1902         // Conversions to DateTime
1903
1904         public static DateTime ToDateTime(DateTime value)
1905         {
1906             return value;
1907         }
1908
1909         public static DateTime ToDateTime(object value)
1910         {
1911             return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(null);
1912         }
1913
1914         public static DateTime ToDateTime(object value, IFormatProvider provider)
1915         {
1916             return value == null ? DateTime.MinValue : ((IConvertible)value).ToDateTime(provider);
1917         }
1918
1919         public static DateTime ToDateTime(String value)
1920         {
1921             if (value == null)
1922                 return new DateTime(0);
1923             return DateTime.Parse(value, CultureInfo.CurrentCulture);
1924         }
1925
1926         public static DateTime ToDateTime(String value, IFormatProvider provider)
1927         {
1928             if (value == null)
1929                 return new DateTime(0);
1930             return DateTime.Parse(value, provider);
1931         }
1932
1933         [CLSCompliant(false)]
1934         public static DateTime ToDateTime(sbyte value)
1935         {
1936             return ((IConvertible)value).ToDateTime(null);
1937         }
1938
1939         public static DateTime ToDateTime(byte value)
1940         {
1941             return ((IConvertible)value).ToDateTime(null);
1942         }
1943
1944         public static DateTime ToDateTime(short value)
1945         {
1946             return ((IConvertible)value).ToDateTime(null);
1947         }
1948
1949         [CLSCompliant(false)]
1950         public static DateTime ToDateTime(ushort value)
1951         {
1952             return ((IConvertible)value).ToDateTime(null);
1953         }
1954
1955         public static DateTime ToDateTime(int value)
1956         {
1957             return ((IConvertible)value).ToDateTime(null);
1958         }
1959
1960         [CLSCompliant(false)]
1961         public static DateTime ToDateTime(uint value)
1962         {
1963             return ((IConvertible)value).ToDateTime(null);
1964         }
1965
1966         public static DateTime ToDateTime(long value)
1967         {
1968             return ((IConvertible)value).ToDateTime(null);
1969         }
1970
1971         [CLSCompliant(false)]
1972         public static DateTime ToDateTime(ulong value)
1973         {
1974             return ((IConvertible)value).ToDateTime(null);
1975         }
1976
1977         public static DateTime ToDateTime(bool value)
1978         {
1979             return ((IConvertible)value).ToDateTime(null);
1980         }
1981
1982         public static DateTime ToDateTime(char value)
1983         {
1984             return ((IConvertible)value).ToDateTime(null);
1985         }
1986
1987         public static DateTime ToDateTime(float value)
1988         {
1989             return ((IConvertible)value).ToDateTime(null);
1990         }
1991
1992         public static DateTime ToDateTime(double value)
1993         {
1994             return ((IConvertible)value).ToDateTime(null);
1995         }
1996
1997         public static DateTime ToDateTime(decimal value)
1998         {
1999             return ((IConvertible)value).ToDateTime(null);
2000         }
2001
2002         // Disallowed conversions to DateTime
2003         // public static DateTime ToDateTime(TimeSpan value)
2004
2005         // Conversions to String
2006
2007         public static string ToString(Object value)
2008         {
2009             return ToString(value, null);
2010         }
2011
2012         public static string ToString(Object value, IFormatProvider provider)
2013         {
2014             IConvertible ic = value as IConvertible;
2015             if (ic != null)
2016                 return ic.ToString(provider);
2017             IFormattable formattable = value as IFormattable;
2018             if (formattable != null)
2019                 return formattable.ToString(null, provider);
2020             return value == null ? String.Empty : value.ToString();
2021         }
2022
2023         public static string ToString(bool value)
2024         {
2025             return value.ToString();
2026         }
2027
2028         public static string ToString(bool value, IFormatProvider provider)
2029         {
2030             return value.ToString();
2031         }
2032
2033         public static string ToString(char value)
2034         {
2035             return Char.ToString(value);
2036         }
2037
2038         public static string ToString(char value, IFormatProvider provider)
2039         {
2040             return value.ToString();
2041         }
2042
2043         [CLSCompliant(false)]
2044         public static string ToString(sbyte value)
2045         {
2046             return value.ToString(CultureInfo.CurrentCulture);
2047         }
2048
2049         [CLSCompliant(false)]
2050         public static string ToString(sbyte value, IFormatProvider provider)
2051         {
2052             return value.ToString(provider);
2053         }
2054
2055         public static string ToString(byte value)
2056         {
2057             return value.ToString(CultureInfo.CurrentCulture);
2058         }
2059
2060         public static string ToString(byte value, IFormatProvider provider)
2061         {
2062             return value.ToString(provider);
2063         }
2064
2065         public static string ToString(short value)
2066         {
2067             return value.ToString(CultureInfo.CurrentCulture);
2068         }
2069
2070         public static string ToString(short value, IFormatProvider provider)
2071         {
2072             return value.ToString(provider);
2073         }
2074
2075         [CLSCompliant(false)]
2076         public static string ToString(ushort value)
2077         {
2078             return value.ToString(CultureInfo.CurrentCulture);
2079         }
2080
2081         [CLSCompliant(false)]
2082         public static string ToString(ushort value, IFormatProvider provider)
2083         {
2084             return value.ToString(provider);
2085         }
2086
2087         public static string ToString(int value)
2088         {
2089             return value.ToString(CultureInfo.CurrentCulture);
2090         }
2091
2092         public static string ToString(int value, IFormatProvider provider)
2093         {
2094             return value.ToString(provider);
2095         }
2096
2097         [CLSCompliant(false)]
2098         public static string ToString(uint value)
2099         {
2100             return value.ToString(CultureInfo.CurrentCulture);
2101         }
2102
2103         [CLSCompliant(false)]
2104         public static string ToString(uint value, IFormatProvider provider)
2105         {
2106             return value.ToString(provider);
2107         }
2108
2109         public static string ToString(long value)
2110         {
2111             return value.ToString(CultureInfo.CurrentCulture);
2112         }
2113
2114         public static string ToString(long value, IFormatProvider provider)
2115         {
2116             return value.ToString(provider);
2117         }
2118
2119         [CLSCompliant(false)]
2120         public static string ToString(ulong value)
2121         {
2122             return value.ToString(CultureInfo.CurrentCulture);
2123         }
2124
2125         [CLSCompliant(false)]
2126         public static string ToString(ulong value, IFormatProvider provider)
2127         {
2128             return value.ToString(provider);
2129         }
2130
2131         public static string ToString(float value)
2132         {
2133             return value.ToString(CultureInfo.CurrentCulture);
2134         }
2135
2136         public static string ToString(float value, IFormatProvider provider)
2137         {
2138             return value.ToString(provider);
2139         }
2140
2141         public static string ToString(double value)
2142         {
2143             return value.ToString(CultureInfo.CurrentCulture);
2144         }
2145
2146         public static string ToString(double value, IFormatProvider provider)
2147         {
2148             return value.ToString(provider);
2149         }
2150
2151         public static string ToString(decimal value)
2152         {
2153             return value.ToString(CultureInfo.CurrentCulture);
2154         }
2155
2156         public static string ToString(Decimal value, IFormatProvider provider)
2157         {
2158             return value.ToString(provider);
2159         }
2160
2161         public static string ToString(DateTime value)
2162         {
2163             return value.ToString();
2164         }
2165
2166         public static string ToString(DateTime value, IFormatProvider provider)
2167         {
2168             return value.ToString(provider);
2169         }
2170
2171         public static String ToString(String value)
2172         {
2173             return value;
2174         }
2175
2176         public static String ToString(String value, IFormatProvider provider)
2177         {
2178             return value; // avoid the null check
2179         }
2180
2181
2182         //
2183         // Conversions which understand Base XXX numbers.
2184         //
2185         // Parses value in base base.  base can only
2186         // be 2, 8, 10, or 16.  If base is 16, the number may be preceded
2187         // by 0x; any other leading or trailing characters cause an error.
2188         //
2189         public static byte ToByte(String value, int fromBase)
2190         {
2191             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2192             {
2193                 throw new ArgumentException(SR.Arg_InvalidBase);
2194             }
2195
2196             if (value == null)
2197             {
2198                 return 0;
2199             }
2200
2201             int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
2202             if (r < Byte.MinValue || r > Byte.MaxValue)
2203                 ThrowByteOverflowException();
2204             return (byte)r;
2205         }
2206
2207         // Parses value in base fromBase.  fromBase can only
2208         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2209         // by 0x; any other leading or trailing characters cause an error.
2210         //
2211         [CLSCompliant(false)]
2212         public static sbyte ToSByte(String value, int fromBase)
2213         {
2214             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2215             {
2216                 throw new ArgumentException(SR.Arg_InvalidBase);
2217             }
2218
2219             if (value == null)
2220             {
2221                 return 0;
2222             }
2223
2224             int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI1);
2225             if (fromBase != 10 && r <= Byte.MaxValue)
2226                 return (sbyte)r;
2227
2228             if (r < SByte.MinValue || r > SByte.MaxValue)
2229                 ThrowSByteOverflowException();
2230             return (sbyte)r;
2231         }
2232
2233         // Parses value in base fromBase.  fromBase can only
2234         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2235         // by 0x; any other leading or trailing characters cause an error.
2236         //
2237         public static short ToInt16(String value, int fromBase)
2238         {
2239             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2240             {
2241                 throw new ArgumentException(SR.Arg_InvalidBase);
2242             }
2243
2244             if (value == null)
2245             {
2246                 return 0;
2247             }
2248
2249             int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsI2);
2250             if (fromBase != 10 && r <= UInt16.MaxValue)
2251                 return (short)r;
2252
2253             if (r < Int16.MinValue || r > Int16.MaxValue)
2254                 ThrowInt16OverflowException();
2255             return (short)r;
2256         }
2257
2258         // Parses value in base fromBase.  fromBase can only
2259         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2260         // by 0x; any other leading or trailing characters cause an error.
2261         //
2262         [CLSCompliant(false)]
2263         public static ushort ToUInt16(String value, int fromBase)
2264         {
2265             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2266             {
2267                 throw new ArgumentException(SR.Arg_InvalidBase);
2268             }
2269
2270             if (value == null)
2271             {
2272                 return 0;
2273             }
2274
2275             int r = ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight | ParseNumbers.TreatAsUnsigned);
2276             if (r < UInt16.MinValue || r > UInt16.MaxValue)
2277                 ThrowUInt16OverflowException();
2278             return (ushort)r;
2279         }
2280
2281         // Parses value in base fromBase.  fromBase can only
2282         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2283         // by 0x; any other leading or trailing characters cause an error.
2284         //
2285         public static int ToInt32(String value, int fromBase)
2286         {
2287             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2288             {
2289                 throw new ArgumentException(SR.Arg_InvalidBase);
2290             }
2291             return value != null ?
2292                 ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.IsTight) :
2293                 0;
2294         }
2295
2296         // Parses value in base fromBase.  fromBase can only
2297         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2298         // by 0x; any other leading or trailing characters cause an error.
2299         //
2300         [CLSCompliant(false)]
2301         public static uint ToUInt32(String value, int fromBase)
2302         {
2303             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2304             {
2305                 throw new ArgumentException(SR.Arg_InvalidBase);
2306             }
2307             return value != null ?
2308                 (uint)ParseNumbers.StringToInt(value.AsSpan(), fromBase, ParseNumbers.TreatAsUnsigned | ParseNumbers.IsTight) :
2309                 0;
2310         }
2311
2312         // Parses value in base fromBase.  fromBase can only
2313         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2314         // by 0x; any other leading or trailing characters cause an error.
2315         //
2316         public static long ToInt64(String value, int fromBase)
2317         {
2318             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2319             {
2320                 throw new ArgumentException(SR.Arg_InvalidBase);
2321             }
2322             return value != null ?
2323                 ParseNumbers.StringToLong(value.AsSpan(), fromBase, ParseNumbers.IsTight) :
2324                 0;
2325         }
2326
2327         // Parses value in base fromBase.  fromBase can only
2328         // be 2, 8, 10, or 16.  If fromBase is 16, the number may be preceded
2329         // by 0x; any other leading or trailing characters cause an error.
2330         //
2331         [CLSCompliant(false)]
2332         public static ulong ToUInt64(String value, int fromBase)
2333         {
2334             if (fromBase != 2 && fromBase != 8 && fromBase != 10 && fromBase != 16)
2335             {
2336                 throw new ArgumentException(SR.Arg_InvalidBase);
2337             }
2338             return value != null ?
2339                 (ulong)ParseNumbers.StringToLong(value.AsSpan(), fromBase, ParseNumbers.TreatAsUnsigned | ParseNumbers.IsTight) :
2340                 0;
2341         }
2342
2343         // Convert the byte value to a string in base fromBase
2344         public static String ToString(byte value, int toBase)
2345         {
2346             if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
2347             {
2348                 throw new ArgumentException(SR.Arg_InvalidBase);
2349             }
2350             return ParseNumbers.IntToString((int)value, toBase, -1, ' ', ParseNumbers.PrintAsI1);
2351         }
2352
2353         // Convert the Int16 value to a string in base fromBase
2354         public static String ToString(short value, int toBase)
2355         {
2356             if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
2357             {
2358                 throw new ArgumentException(SR.Arg_InvalidBase);
2359             }
2360             return ParseNumbers.IntToString((int)value, toBase, -1, ' ', ParseNumbers.PrintAsI2);
2361         }
2362
2363         // Convert the Int32 value to a string in base toBase
2364         public static String ToString(int value, int toBase)
2365         {
2366             if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
2367             {
2368                 throw new ArgumentException(SR.Arg_InvalidBase);
2369             }
2370             return ParseNumbers.IntToString(value, toBase, -1, ' ', 0);
2371         }
2372
2373         // Convert the Int64 value to a string in base toBase
2374         public static String ToString(long value, int toBase)
2375         {
2376             if (toBase != 2 && toBase != 8 && toBase != 10 && toBase != 16)
2377             {
2378                 throw new ArgumentException(SR.Arg_InvalidBase);
2379             }
2380             return ParseNumbers.LongToString(value, toBase, -1, ' ', 0);
2381         }
2382
2383         public static String ToBase64String(byte[] inArray)
2384         {
2385             if (inArray == null)
2386             {
2387                 throw new ArgumentNullException(nameof(inArray));
2388             }
2389             return ToBase64String(new ReadOnlySpan<byte>(inArray), Base64FormattingOptions.None);
2390         }
2391
2392         public static String ToBase64String(byte[] inArray, Base64FormattingOptions options)
2393         {
2394             if (inArray == null)
2395             {
2396                 throw new ArgumentNullException(nameof(inArray));
2397             }
2398             return ToBase64String(new ReadOnlySpan<byte>(inArray), options);
2399         }
2400
2401         public static String ToBase64String(byte[] inArray, int offset, int length)
2402         {
2403             return ToBase64String(inArray, offset, length, Base64FormattingOptions.None);
2404         }
2405
2406         public static String ToBase64String(byte[] inArray, int offset, int length, Base64FormattingOptions options)
2407         {
2408             if (inArray == null)
2409                 throw new ArgumentNullException(nameof(inArray));
2410             if (length < 0)
2411                 throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
2412             if (offset < 0)
2413                 throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_GenericPositive);
2414             if (offset > (inArray.Length - length))
2415                 throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_OffsetLength);
2416
2417             return ToBase64String(new ReadOnlySpan<byte>(inArray, offset, length), options);
2418         }
2419
2420         public static string ToBase64String(ReadOnlySpan<byte> bytes, Base64FormattingOptions options = Base64FormattingOptions.None)
2421         {
2422             if (options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks)
2423             {
2424                 throw new ArgumentException(string.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
2425             }
2426
2427             if (bytes.Length == 0)
2428             {
2429                 return string.Empty;
2430             }
2431
2432             bool insertLineBreaks = (options == Base64FormattingOptions.InsertLineBreaks);
2433             string result = string.FastAllocateString(ToBase64_CalculateAndValidateOutputLength(bytes.Length, insertLineBreaks));
2434
2435             unsafe
2436             {
2437                 fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
2438                 fixed (char* charsPtr = result)
2439                 {
2440                     int charsWritten = ConvertToBase64Array(charsPtr, bytesPtr, 0, bytes.Length, insertLineBreaks);
2441                     Debug.Assert(result.Length == charsWritten, $"Expected {result.Length} == {charsWritten}");
2442                 }
2443             }
2444
2445             return result;
2446         }
2447
2448         public static int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut)
2449         {
2450             return ToBase64CharArray(inArray, offsetIn, length, outArray, offsetOut, Base64FormattingOptions.None);
2451         }
2452
2453         public static unsafe int ToBase64CharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, Base64FormattingOptions options)
2454         {
2455             //Do data verfication
2456             if (inArray == null)
2457                 throw new ArgumentNullException(nameof(inArray));
2458             if (outArray == null)
2459                 throw new ArgumentNullException(nameof(outArray));
2460             if (length < 0)
2461                 throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
2462             if (offsetIn < 0)
2463                 throw new ArgumentOutOfRangeException(nameof(offsetIn), SR.ArgumentOutOfRange_GenericPositive);
2464             if (offsetOut < 0)
2465                 throw new ArgumentOutOfRangeException(nameof(offsetOut), SR.ArgumentOutOfRange_GenericPositive);
2466
2467             if (options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks)
2468             {
2469                 throw new ArgumentException(string.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
2470             }
2471
2472
2473             int retVal;
2474
2475             int inArrayLength;
2476             int outArrayLength;
2477             int numElementsToCopy;
2478
2479             inArrayLength = inArray.Length;
2480
2481             if (offsetIn > (int)(inArrayLength - length))
2482                 throw new ArgumentOutOfRangeException(nameof(offsetIn), SR.ArgumentOutOfRange_OffsetLength);
2483
2484             if (inArrayLength == 0)
2485                 return 0;
2486
2487             bool insertLineBreaks = (options == Base64FormattingOptions.InsertLineBreaks);
2488             //This is the maximally required length that must be available in the char array
2489             outArrayLength = outArray.Length;
2490
2491             // Length of the char buffer required
2492             numElementsToCopy = ToBase64_CalculateAndValidateOutputLength(length, insertLineBreaks);
2493
2494             if (offsetOut > (int)(outArrayLength - numElementsToCopy))
2495                 throw new ArgumentOutOfRangeException(nameof(offsetOut), SR.ArgumentOutOfRange_OffsetOut);
2496
2497             fixed (char* outChars = &outArray[offsetOut])
2498             {
2499                 fixed (byte* inData = &inArray[0])
2500                 {
2501                     retVal = ConvertToBase64Array(outChars, inData, offsetIn, length, insertLineBreaks);
2502                 }
2503             }
2504
2505             return retVal;
2506         }
2507
2508         public static unsafe bool TryToBase64Chars(ReadOnlySpan<byte> bytes, Span<char> chars, out int charsWritten, Base64FormattingOptions options = Base64FormattingOptions.None)
2509         {
2510             if (options < Base64FormattingOptions.None || options > Base64FormattingOptions.InsertLineBreaks)
2511             {
2512                 throw new ArgumentException(string.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
2513             }
2514
2515             if (bytes.Length == 0)
2516             {
2517                 charsWritten = 0;
2518                 return true;
2519             }
2520
2521             bool insertLineBreaks = (options == Base64FormattingOptions.InsertLineBreaks);
2522
2523             int charLengthRequired = ToBase64_CalculateAndValidateOutputLength(bytes.Length, insertLineBreaks);
2524             if (charLengthRequired > chars.Length)
2525             {
2526                 charsWritten = 0;
2527                 return false;
2528             }
2529
2530             fixed (char* outChars = &MemoryMarshal.GetReference(chars))
2531             fixed (byte* inData = &MemoryMarshal.GetReference(bytes))
2532             {
2533                 charsWritten = ConvertToBase64Array(outChars, inData, 0, bytes.Length, insertLineBreaks);
2534                 return true;
2535             }
2536         }
2537
2538         private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int offset, int length, bool insertLineBreaks)
2539         {
2540             int lengthmod3 = length % 3;
2541             int calcLength = offset + (length - lengthmod3);
2542             int j = 0;
2543             int charcount = 0;
2544             //Convert three bytes at a time to base64 notation.  This will consume 4 chars.
2545             int i;
2546
2547             // get a pointer to the base64Table to avoid unnecessary range checking
2548             fixed (char* base64 = &base64Table[0])
2549             {
2550                 for (i = offset; i < calcLength; i += 3)
2551                 {
2552                     if (insertLineBreaks)
2553                     {
2554                         if (charcount == base64LineBreakPosition)
2555                         {
2556                             outChars[j++] = '\r';
2557                             outChars[j++] = '\n';
2558                             charcount = 0;
2559                         }
2560                         charcount += 4;
2561                     }
2562                     outChars[j] = base64[(inData[i] & 0xfc) >> 2];
2563                     outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
2564                     outChars[j + 2] = base64[((inData[i + 1] & 0x0f) << 2) | ((inData[i + 2] & 0xc0) >> 6)];
2565                     outChars[j + 3] = base64[(inData[i + 2] & 0x3f)];
2566                     j += 4;
2567                 }
2568
2569                 //Where we left off before
2570                 i = calcLength;
2571
2572                 if (insertLineBreaks && (lengthmod3 != 0) && (charcount == base64LineBreakPosition))
2573                 {
2574                     outChars[j++] = '\r';
2575                     outChars[j++] = '\n';
2576                 }
2577
2578                 switch (lengthmod3)
2579                 {
2580                     case 2: //One character padding needed
2581                         outChars[j] = base64[(inData[i] & 0xfc) >> 2];
2582                         outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
2583                         outChars[j + 2] = base64[(inData[i + 1] & 0x0f) << 2];
2584                         outChars[j + 3] = base64[64]; //Pad
2585                         j += 4;
2586                         break;
2587                     case 1: // Two character padding needed
2588                         outChars[j] = base64[(inData[i] & 0xfc) >> 2];
2589                         outChars[j + 1] = base64[(inData[i] & 0x03) << 4];
2590                         outChars[j + 2] = base64[64]; //Pad
2591                         outChars[j + 3] = base64[64]; //Pad
2592                         j += 4;
2593                         break;
2594                 }
2595             }
2596
2597             return j;
2598         }
2599
2600         private static int ToBase64_CalculateAndValidateOutputLength(int inputLength, bool insertLineBreaks)
2601         {
2602             long outlen = ((long)inputLength) / 3 * 4;          // the base length - we want integer division here. 
2603             outlen += ((inputLength % 3) != 0) ? 4 : 0;         // at most 4 more chars for the remainder
2604
2605             if (outlen == 0)
2606                 return 0;
2607
2608             if (insertLineBreaks)
2609             {
2610                 long newLines = outlen / base64LineBreakPosition;
2611                 if ((outlen % base64LineBreakPosition) == 0)
2612                 {
2613                     --newLines;
2614                 }
2615                 outlen += newLines * 2;              // the number of line break chars we'll add, "\r\n"
2616             }
2617
2618             // If we overflow an int then we cannot allocate enough
2619             // memory to output the value so throw
2620             if (outlen > int.MaxValue)
2621                 throw new OutOfMemoryException();
2622
2623             return (int)outlen;
2624         }
2625
2626
2627         /// <summary>
2628         /// Converts the specified string, which encodes binary data as Base64 digits, to the equivalent byte array.
2629         /// </summary>
2630         /// <param name="s">The string to convert</param>
2631         /// <returns>The array of bytes represented by the specified Base64 string.</returns>
2632         public static Byte[] FromBase64String(String s)
2633         {
2634             // "s" is an unfortunate parameter name, but we need to keep it for backward compat.
2635
2636             if (s == null)
2637                 throw new ArgumentNullException(nameof(s));
2638
2639
2640             unsafe
2641             {
2642                 fixed (Char* sPtr = s)
2643                 {
2644                     return FromBase64CharPtr(sPtr, s.Length);
2645                 }
2646             }
2647         }
2648
2649         public static bool TryFromBase64String(string s, Span<byte> bytes, out int bytesWritten)
2650         {
2651             if (s == null)
2652             {
2653                 throw new ArgumentNullException(nameof(s));
2654             }
2655
2656             return TryFromBase64Chars(s.AsSpan(), bytes, out bytesWritten);
2657         }
2658
2659         public static unsafe bool TryFromBase64Chars(ReadOnlySpan<char> chars, Span<byte> bytes, out int bytesWritten)
2660         {
2661             if (chars.Length == 0)
2662             {
2663                 bytesWritten = 0;
2664                 return true;
2665             }
2666
2667             // We need to get rid of any trailing white spaces.
2668             // Otherwise we would be rejecting input such as "abc= ":
2669             while (chars.Length > 0)
2670             {
2671                 char lastChar = chars[chars.Length - 1];
2672                 if (lastChar != ' ' && lastChar != '\n' && lastChar != '\r' && lastChar != '\t')
2673                 {
2674                     break;
2675                 }
2676                 chars = chars.Slice(0, chars.Length - 1);
2677             }
2678
2679             fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
2680             {
2681                 int resultLength = FromBase64_ComputeResultLength(charsPtr, chars.Length);
2682                 Debug.Assert(resultLength >= 0);
2683                 if (resultLength > bytes.Length)
2684                 {
2685                     bytesWritten = 0;
2686                     return false;
2687                 }
2688
2689                 fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
2690                 {
2691                     bytesWritten = FromBase64_Decode(charsPtr, chars.Length, bytesPtr, bytes.Length);
2692                     return true;
2693                 }
2694             }
2695         }
2696
2697         /// <summary>
2698         /// Converts the specified range of a Char array, which encodes binary data as Base64 digits, to the equivalent byte array.     
2699         /// </summary>
2700         /// <param name="inArray">Chars representing Base64 encoding characters</param>
2701         /// <param name="offset">A position within the input array.</param>
2702         /// <param name="length">Number of element to convert.</param>
2703         /// <returns>The array of bytes represented by the specified Base64 encoding characters.</returns>
2704         public static Byte[] FromBase64CharArray(Char[] inArray, Int32 offset, Int32 length)
2705         {
2706             if (inArray == null)
2707                 throw new ArgumentNullException(nameof(inArray));
2708
2709             if (length < 0)
2710                 throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
2711
2712             if (offset < 0)
2713                 throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_GenericPositive);
2714
2715             if (offset > inArray.Length - length)
2716                 throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_OffsetLength);
2717
2718
2719             if (inArray.Length == 0)
2720             {
2721                 return Array.Empty<byte>();
2722             }
2723
2724             unsafe
2725             {
2726                 fixed (Char* inArrayPtr = &inArray[0])
2727                 {
2728                     return FromBase64CharPtr(inArrayPtr + offset, length);
2729                 }
2730             }
2731         }
2732
2733
2734
2735         /// <summary>
2736         /// Convert Base64 encoding characters to bytes:
2737         ///  - Compute result length exactly by actually walking the input;
2738         ///  - Allocate new result array based on computation;
2739         ///  - Decode input into the new array;
2740         /// </summary>
2741         /// <param name="inputPtr">Pointer to the first input char</param>
2742         /// <param name="inputLength">Number of input chars</param>
2743         /// <returns></returns>
2744         private static unsafe Byte[] FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
2745         {
2746             // The validity of parameters much be checked by callers, thus we are Critical here.
2747
2748             Debug.Assert(0 <= inputLength);
2749
2750             // We need to get rid of any trailing white spaces.
2751             // Otherwise we would be rejecting input such as "abc= ":
2752             while (inputLength > 0)
2753             {
2754                 Int32 lastChar = inputPtr[inputLength - 1];
2755                 if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
2756                     break;
2757                 inputLength--;
2758             }
2759
2760             // Compute the output length:
2761             Int32 resultLength = FromBase64_ComputeResultLength(inputPtr, inputLength);
2762
2763             Debug.Assert(0 <= resultLength);
2764
2765             // resultLength can be zero. We will still enter FromBase64_Decode and process the input.
2766             // It may either simply write no bytes (e.g. input = " ") or throw (e.g. input = "ab").
2767
2768             // Create result byte blob:
2769             Byte[] decodedBytes = new Byte[resultLength];
2770
2771             // Convert Base64 chars into bytes:
2772             Int32 actualResultLength;
2773             fixed (Byte* decodedBytesPtr = decodedBytes)
2774                 actualResultLength = FromBase64_Decode(inputPtr, inputLength, decodedBytesPtr, resultLength);
2775
2776             // Note that actualResultLength can differ from resultLength if the caller is modifying the array
2777             // as it is being converted. Silently ignore the failure.
2778             // Consider throwing exception in an non in-place release.
2779
2780             // We are done:
2781             return decodedBytes;
2782         }
2783
2784
2785         /// <summary>
2786         /// Decode characters representing a Base64 encoding into bytes:
2787         /// Walk the input. Every time 4 chars are read, convert them to the 3 corresponding output bytes.
2788         /// This method is a bit lengthy on purpose. We are trying to avoid jumps to helpers in the loop
2789         /// to aid performance.
2790         /// </summary>
2791         /// <param name="inputPtr">Pointer to first input char</param>
2792         /// <param name="inputLength">Number of input chars</param>
2793         /// <param name="destPtr">Pointer to location for the first result byte</param>
2794         /// <param name="destLength">Max length of the preallocated result buffer</param>
2795         /// <returns>If the result buffer was not large enough to write all result bytes, return -1;
2796         /// Otherwise return the number of result bytes actually produced.</returns>
2797         private static unsafe Int32 FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
2798         {
2799             // You may find this method weird to look at. It's written for performance, not aesthetics.
2800             // You will find unrolled loops label jumps and bit manipulations.
2801
2802             const UInt32 intA = (UInt32)'A';
2803             const UInt32 inta = (UInt32)'a';
2804             const UInt32 int0 = (UInt32)'0';
2805             const UInt32 intEq = (UInt32)'=';
2806             const UInt32 intPlus = (UInt32)'+';
2807             const UInt32 intSlash = (UInt32)'/';
2808             const UInt32 intSpace = (UInt32)' ';
2809             const UInt32 intTab = (UInt32)'\t';
2810             const UInt32 intNLn = (UInt32)'\n';
2811             const UInt32 intCRt = (UInt32)'\r';
2812             const UInt32 intAtoZ = (UInt32)('Z' - 'A');  // = ('z' - 'a')
2813             const UInt32 int0to9 = (UInt32)('9' - '0');
2814
2815             Char* inputPtr = startInputPtr;
2816             Byte* destPtr = startDestPtr;
2817
2818             // Pointers to the end of input and output:
2819             Char* endInputPtr = inputPtr + inputLength;
2820             Byte* endDestPtr = destPtr + destLength;
2821
2822             // Current char code/value:
2823             UInt32 currCode;
2824
2825             // This 4-byte integer will contain the 4 codes of the current 4-char group.
2826             // Eeach char codes for 6 bits = 24 bits.
2827             // The remaining byte will be FF, we use it as a marker when 4 chars have been processed.            
2828             UInt32 currBlockCodes = 0x000000FFu;
2829
2830             unchecked
2831             {
2832                 while (true)
2833                 {
2834                     // break when done:
2835                     if (inputPtr >= endInputPtr)
2836                         goto _AllInputConsumed;
2837
2838                     // Get current char:
2839                     currCode = (UInt32)(*inputPtr);
2840                     inputPtr++;
2841
2842                     // Determine current char code:
2843
2844                     if (currCode - intA <= intAtoZ)
2845                         currCode -= intA;
2846
2847                     else if (currCode - inta <= intAtoZ)
2848                         currCode -= (inta - 26u);
2849
2850                     else if (currCode - int0 <= int0to9)
2851                         currCode -= (int0 - 52u);
2852
2853                     else
2854                     {
2855                         // Use the slower switch for less common cases:
2856                         switch (currCode)
2857                         {
2858                             // Significant chars:
2859                             case intPlus:
2860                                 currCode = 62u;
2861                                 break;
2862
2863                             case intSlash:
2864                                 currCode = 63u;
2865                                 break;
2866
2867                             // Legal no-value chars (we ignore these):
2868                             case intCRt:
2869                             case intNLn:
2870                             case intSpace:
2871                             case intTab:
2872                                 continue;
2873
2874                             // The equality char is only legal at the end of the input.
2875                             // Jump after the loop to make it easier for the JIT register predictor to do a good job for the loop itself:
2876                             case intEq:
2877                                 goto _EqualityCharEncountered;
2878
2879                             // Other chars are illegal:
2880                             default:
2881                                 throw new FormatException(SR.Format_BadBase64Char);
2882                         }
2883                     }
2884
2885                     // Ok, we got the code. Save it:
2886                     currBlockCodes = (currBlockCodes << 6) | currCode;
2887
2888                     // Last bit in currBlockCodes will be on after in shifted right 4 times:
2889                     if ((currBlockCodes & 0x80000000u) != 0u)
2890                     {
2891                         if ((Int32)(endDestPtr - destPtr) < 3)
2892                             return -1;
2893
2894                         *(destPtr) = (Byte)(currBlockCodes >> 16);
2895                         *(destPtr + 1) = (Byte)(currBlockCodes >> 8);
2896                         *(destPtr + 2) = (Byte)(currBlockCodes);
2897                         destPtr += 3;
2898
2899                         currBlockCodes = 0x000000FFu;
2900                     }
2901                 }
2902             }  // unchecked while
2903
2904         // 'd be nice to have an assert that we never get here, but CS0162: Unreachable code detected.
2905         // Debug.Fail("We only leave the above loop by jumping; should never get here.");
2906
2907         // We jump here out of the loop if we hit an '=':
2908         _EqualityCharEncountered:
2909
2910             Debug.Assert(currCode == intEq);
2911
2912             // Recall that inputPtr is now one position past where '=' was read.
2913             // '=' can only be at the last input pos:
2914             if (inputPtr == endInputPtr)
2915             {
2916                 // Code is zero for trailing '=':
2917                 currBlockCodes <<= 6;
2918
2919                 // The '=' did not complete a 4-group. The input must be bad:
2920                 if ((currBlockCodes & 0x80000000u) == 0u)
2921                     throw new FormatException(SR.Format_BadBase64CharArrayLength);
2922
2923                 if ((int)(endDestPtr - destPtr) < 2)  // Autch! We underestimated the output length!
2924                     return -1;
2925
2926                 // We are good, store bytes form this past group. We had a single "=", so we take two bytes:
2927                 *(destPtr++) = (Byte)(currBlockCodes >> 16);
2928                 *(destPtr++) = (Byte)(currBlockCodes >> 8);
2929
2930                 currBlockCodes = 0x000000FFu;
2931             }
2932             else
2933             { // '=' can also be at the pre-last position iff the last is also a '=' excluding the white spaces:
2934                 // We need to get rid of any intermediate white spaces.
2935                 // Otherwise we would be rejecting input such as "abc= =":
2936                 while (inputPtr < (endInputPtr - 1))
2937                 {
2938                     Int32 lastChar = *(inputPtr);
2939                     if (lastChar != (Int32)' ' && lastChar != (Int32)'\n' && lastChar != (Int32)'\r' && lastChar != (Int32)'\t')
2940                         break;
2941                     inputPtr++;
2942                 }
2943
2944                 if (inputPtr == (endInputPtr - 1) && *(inputPtr) == '=')
2945                 {
2946                     // Code is zero for each of the two '=':
2947                     currBlockCodes <<= 12;
2948
2949                     // The '=' did not complete a 4-group. The input must be bad:
2950                     if ((currBlockCodes & 0x80000000u) == 0u)
2951                         throw new FormatException(SR.Format_BadBase64CharArrayLength);
2952
2953                     if ((Int32)(endDestPtr - destPtr) < 1)  // Autch! We underestimated the output length!
2954                         return -1;
2955
2956                     // We are good, store bytes form this past group. We had a "==", so we take only one byte:
2957                     *(destPtr++) = (Byte)(currBlockCodes >> 16);
2958
2959                     currBlockCodes = 0x000000FFu;
2960                 }
2961                 else  // '=' is not ok at places other than the end:
2962                     throw new FormatException(SR.Format_BadBase64Char);
2963             }
2964
2965         // We get here either from above or by jumping out of the loop:
2966         _AllInputConsumed:
2967
2968             // The last block of chars has less than 4 items
2969             if (currBlockCodes != 0x000000FFu)
2970                 throw new FormatException(SR.Format_BadBase64CharArrayLength);
2971
2972             // Return how many bytes were actually recovered:
2973             return (Int32)(destPtr - startDestPtr);
2974         } // Int32 FromBase64_Decode(...)
2975
2976
2977         /// <summary>
2978         /// Compute the number of bytes encoded in the specified Base 64 char array:
2979         /// Walk the entire input counting white spaces and padding chars, then compute result length
2980         /// based on 3 bytes per 4 chars.
2981         /// </summary>
2982         private static unsafe Int32 FromBase64_ComputeResultLength(Char* inputPtr, Int32 inputLength)
2983         {
2984             const UInt32 intEq = (UInt32)'=';
2985             const UInt32 intSpace = (UInt32)' ';
2986
2987             Debug.Assert(0 <= inputLength);
2988
2989             Char* inputEndPtr = inputPtr + inputLength;
2990             Int32 usefulInputLength = inputLength;
2991             Int32 padding = 0;
2992
2993             while (inputPtr < inputEndPtr)
2994             {
2995                 UInt32 c = (UInt32)(*inputPtr);
2996                 inputPtr++;
2997
2998                 // We want to be as fast as possible and filter out spaces with as few comparisons as possible.
2999                 // We end up accepting a number of illegal chars as legal white-space chars.
3000                 // This is ok: as soon as we hit them during actual decode we will recognise them as illegal and throw.
3001                 if (c <= intSpace)
3002                     usefulInputLength--;
3003
3004                 else if (c == intEq)
3005                 {
3006                     usefulInputLength--;
3007                     padding++;
3008                 }
3009             }
3010
3011             Debug.Assert(0 <= usefulInputLength);
3012
3013             // For legal input, we can assume that 0 <= padding < 3. But it may be more for illegal input.
3014             // We will notice it at decode when we see a '=' at the wrong place.
3015             Debug.Assert(0 <= padding);
3016
3017             // Perf: reuse the variable that stored the number of '=' to store the number of bytes encoded by the
3018             // last group that contains the '=':
3019             if (padding != 0)
3020             {
3021                 if (padding == 1)
3022                     padding = 2;
3023                 else if (padding == 2)
3024                     padding = 1;
3025                 else
3026                     throw new FormatException(SR.Format_BadBase64Char);
3027             }
3028
3029             // Done:
3030             return (usefulInputLength / 4) * 3 + padding;
3031         }
3032     }  // class Convert
3033 }  // namespace
3034