File: System\Xml\XmlConverter.cs
Project: ndp\cdf\src\WCF\Serialization\System.Runtime.Serialization.csproj (System.Runtime.Serialization)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
// PERF, Microsoft, Microsoft: Make LookupNamespace do something smarter when lots of names
// PERF, Microsoft, Microsoft: Make Attribute lookup smarter when lots of attributes
// PERF: Microsoft, Microsoft: Compare safe/unsafe versions
 
namespace System.Xml
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.Runtime;
    using System.Runtime.Serialization;
    using System.Security;
    using System.Text;
 
    static class XmlConverter
    {
        public const int MaxDateTimeChars = 64;
        public const int MaxInt32Chars = 16;
        public const int MaxInt64Chars = 32;
        public const int MaxBoolChars = 5;
        public const int MaxFloatChars = 16;
        public const int MaxDoubleChars = 32;
        public const int MaxDecimalChars = 40;
        public const int MaxUInt64Chars = 32;
        public const int MaxPrimitiveChars = MaxDateTimeChars;
 
        static char[] whiteSpaceChars = new char[] { ' ', '\t', '\n', '\r' };
        static UTF8Encoding utf8Encoding;
        static UnicodeEncoding unicodeEncoding;
        static Base64Encoding base64Encoding;
 
        static public Base64Encoding Base64Encoding
        {
            get
            {
                if (base64Encoding == null)
                    base64Encoding = new Base64Encoding();
                return base64Encoding;
            }
        }
 
        static UTF8Encoding UTF8Encoding
        {
            get
            {
                if (utf8Encoding == null)
                    utf8Encoding = new UTF8Encoding(false, true);
                return utf8Encoding;
            }
        }
 
        static UnicodeEncoding UnicodeEncoding
        {
            get
            {
                if (unicodeEncoding == null)
                    unicodeEncoding = new UnicodeEncoding(false, false, true);
                return unicodeEncoding;
            }
        }
 
        static public bool ToBoolean(string value)
        {
            try
            {
                return XmlConvert.ToBoolean(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Boolean", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Boolean", exception));
            }
        }
 
        static public bool ToBoolean(byte[] buffer, int offset, int count)
        {
            if (count == 1)
            {
                byte ch = buffer[offset];
                if (ch == (byte)'1')
                    return true;
                else if (ch == (byte)'0')
                    return false;
            }
            return ToBoolean(ToString(buffer, offset, count));
        }
 
        static public int ToInt32(string value)
        {
            try
            {
                return XmlConvert.ToInt32(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
            }
        }
 
        static public int ToInt32(byte[] buffer, int offset, int count)
        {
            int value;
            if (TryParseInt32(buffer, offset, count, out value))
                return value;
            return ToInt32(ToString(buffer, offset, count));
        }
 
        static public Int64 ToInt64(string value)
        {
            try
            {
                return XmlConvert.ToInt64(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
            }
        }
 
        static public Int64 ToInt64(byte[] buffer, int offset, int count)
        {
            long value;
            if (TryParseInt64(buffer, offset, count, out value))
                return value;
            return ToInt64(ToString(buffer, offset, count));
        }
 
        static public float ToSingle(string value)
        {
            try
            {
                return XmlConvert.ToSingle(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "float", exception));
            }
        }
 
        static public float ToSingle(byte[] buffer, int offset, int count)
        {
            float value;
            if (TryParseSingle(buffer, offset, count, out value))
                return value;
            return ToSingle(ToString(buffer, offset, count));
        }
 
        static public double ToDouble(string value)
        {
            try
            {
                return XmlConvert.ToDouble(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "double", exception));
            }
        }
 
        static public double ToDouble(byte[] buffer, int offset, int count)
        {
            double value;
            if (TryParseDouble(buffer, offset, count, out value))
                return value;
            return ToDouble(ToString(buffer, offset, count));
        }
 
        static public decimal ToDecimal(string value)
        {
            try
            {
                return XmlConvert.ToDecimal(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
            }
        }
 
        static public decimal ToDecimal(byte[] buffer, int offset, int count)
        {
            return ToDecimal(ToString(buffer, offset, count));
        }
 
        static public DateTime ToDateTime(Int64 value)
        {
            try
            {
                return DateTime.FromBinary(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(ToString(value), "DateTime", exception));
            }
        }
 
        static public DateTime ToDateTime(string value)
        {
            try
            {
                return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "DateTime", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "DateTime", exception));
            }
        }
 
        static public DateTime ToDateTime(byte[] buffer, int offset, int count)
        {
            DateTime value;
            if (TryParseDateTime(buffer, offset, count, out value))
                return value;
            return ToDateTime(ToString(buffer, offset, count));
        }
 
        static public UniqueId ToUniqueId(string value)
        {
            try
            {
                return new UniqueId(Trim(value));
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UniqueId", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UniqueId", exception));
            }
        }
 
        static public UniqueId ToUniqueId(byte[] buffer, int offset, int count)
        {
            return ToUniqueId(ToString(buffer, offset, count));
        }
 
        static public TimeSpan ToTimeSpan(string value)
        {
            try
            {
                return XmlConvert.ToTimeSpan(value);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "TimeSpan", exception));
            }
        }
 
        static public TimeSpan ToTimeSpan(byte[] buffer, int offset, int count)
        {
            return ToTimeSpan(ToString(buffer, offset, count));
        }
 
        [SuppressMessage("Reliability", "Reliability113", Justification = "Catching expected exceptions inline instead of calling Fx.CreateGuid to minimize code change")]
        static public Guid ToGuid(string value)
        {
            try
            {
                return Guid.Parse(Trim(value));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Guid", exception));
            }
        }
 
        static public Guid ToGuid(byte[] buffer, int offset, int count)
        {
            return ToGuid(ToString(buffer, offset, count));
        }
 
        static public UInt64 ToUInt64(string value)
        {
            try
            {
                return ulong.Parse(value, NumberFormatInfo.InvariantInfo);
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
            }
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
            }
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "UInt64", exception));
            }
        }
 
        static public UInt64 ToUInt64(byte[] buffer, int offset, int count)
        {
            return ToUInt64(ToString(buffer, offset, count));
        }
 
        static public string ToString(byte[] buffer, int offset, int count)
        {
            try
            {
                return UTF8Encoding.GetString(buffer, offset, count);
            }
            catch (DecoderFallbackException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
            }
        }
 
        static public string ToStringUnicode(byte[] buffer, int offset, int count)
        {
            try
            {
                return UnicodeEncoding.GetString(buffer, offset, count);
            }
            catch (DecoderFallbackException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
            }
        }
 
 
        static public byte[] ToBytes(string value)
        {
            try
            {
                return UTF8Encoding.GetBytes(value);
            }
            catch (DecoderFallbackException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(value, exception));
            }
        }
 
        static public int ToChars(byte[] buffer, int offset, int count, char[] chars, int charOffset)
        {
            try
            {
                return UTF8Encoding.GetChars(buffer, offset, count, chars, charOffset);
            }
            catch (DecoderFallbackException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateEncodingException(buffer, offset, count, exception));
            }
        }
 
        static public string ToString(bool value) { return value ? "true" : "false"; }
        static public string ToString(int value) { return XmlConvert.ToString(value); }
        static public string ToString(Int64 value) { return XmlConvert.ToString(value); }
        static public string ToString(float value) { return XmlConvert.ToString(value); }
        static public string ToString(double value) { return XmlConvert.ToString(value); }
        static public string ToString(decimal value) { return XmlConvert.ToString(value); }
        static public string ToString(TimeSpan value) { return XmlConvert.ToString(value); }
        static public string ToString(UniqueId value) { return value.ToString(); }
        static public string ToString(Guid value) { return value.ToString(); }
        static public string ToString(UInt64 value) { return value.ToString(NumberFormatInfo.InvariantInfo); }
 
        static public string ToString(DateTime value)
        {
            byte[] dateChars = new byte[MaxDateTimeChars];
            int count = ToChars(value, dateChars, 0);
            return ToString(dateChars, 0, count);
        }
 
        static string ToString(object value)
        {
            if (value is int)
                return ToString((int)value);
            else if (value is Int64)
                return ToString((Int64)value);
            else if (value is float)
                return ToString((float)value);
            else if (value is double)
                return ToString((double)value);
            else if (value is decimal)
                return ToString((decimal)value);
            else if (value is TimeSpan)
                return ToString((TimeSpan)value);
            else if (value is UniqueId)
                return ToString((UniqueId)value);
            else if (value is Guid)
                return ToString((Guid)value);
            else if (value is UInt64)
                return ToString((UInt64)value);
            else if (value is DateTime)
                return ToString((DateTime)value);
            else if (value is bool)
                return ToString((bool)value);
            else
                return value.ToString();
        }
 
        static public string ToString(object[] objects)
        {
            if (objects.Length == 0)
                return string.Empty;
            string value = ToString(objects[0]);
            if (objects.Length > 1)
            {
                StringBuilder sb = new StringBuilder(value);
                for (int i = 1; i < objects.Length; i++)
                {
                    sb.Append(' ');
                    sb.Append(ToString(objects[i]));
                }
                value = sb.ToString();
            }
            return value;
        }
 
        static public void ToQualifiedName(string qname, out string prefix, out string localName)
        {
            int index = qname.IndexOf(':');
            if (index < 0)
            {
                prefix = string.Empty;
                localName = Trim(qname);
            }
            else
            {
                if (index == qname.Length - 1)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.XmlInvalidQualifiedName, qname)));
                prefix = Trim(qname.Substring(0, index));
                localName = Trim(qname.Substring(index + 1));
            }
        }
 
        static bool TryParseInt32(byte[] chars, int offset, int count, out int result)
        {
            result = 0;
            if (count == 0)
                return false;
            int value = 0;
            int offsetMax = offset + count;
            if (chars[offset] == '-')
            {
                if (count == 1)
                    return false;
                for (int i = offset + 1; i < offsetMax; i++)
                {
                    int digit = (chars[i] - '0');
                    if ((uint)digit > 9)
                        return false;
                    if (value < int.MinValue / 10)
                        return false;
                    value *= 10;
                    if (value < int.MinValue + digit)
                        return false;
                    value -= digit;
                }
            }
            else
            {
                for (int i = offset; i < offsetMax; i++)
                {
                    int digit = (chars[i] - '0');
                    if ((uint)digit > 9)
                        return false;
                    if (value > int.MaxValue / 10)
                        return false;
                    value *= 10;
                    if (value > int.MaxValue - digit)
                        return false;
                    value += digit;
                }
            }
            result = value;
            return true;
        }
 
        static bool TryParseInt64(byte[] chars, int offset, int count, out long result)
        {
            result = 0;
            if (count < 11)
            {
                int value;
                if (!TryParseInt32(chars, offset, count, out value))
                    return false;
                result = value;
                return true;
            }
            else
            {
                long value = 0;
                int offsetMax = offset + count;
                if (chars[offset] == '-')
                {
                    if (count == 1)
                        return false;
                    for (int i = offset + 1; i < offsetMax; i++)
                    {
                        int digit = (chars[i] - '0');
                        if ((uint)digit > 9)
                            return false;
                        if (value < long.MinValue / 10)
                            return false;
                        value *= 10;
                        if (value < long.MinValue + digit)
                            return false;
                        value -= digit;
                    }
                }
                else
                {
                    for (int i = offset; i < offsetMax; i++)
                    {
                        int digit = (chars[i] - '0');
                        if ((uint)digit > 9)
                            return false;
                        if (value > long.MaxValue / 10)
                            return false;
                        value *= 10;
                        if (value > long.MaxValue - digit)
                            return false;
                        value += digit;
                    }
                }
                result = value;
                return true;
            }
        }
 
        static bool TryParseSingle(byte[] chars, int offset, int count, out float result)
        {
            result = 0;
            int offsetMax = offset + count;
            bool negative = false;
            if (offset < offsetMax && chars[offset] == '-')
            {
                negative = true;
                offset++;
                count--;
            }
            if (count < 1 || count > 10)
                return false;
            int value = 0;
            int ch;
            while (offset < offsetMax)
            {
                ch = (chars[offset] - '0');
                if (ch == ('.' - '0'))
                {
                    offset++;
                    int pow10 = 1;
                    while (offset < offsetMax)
                    {
                        ch = chars[offset] - '0';
                        if (((uint)ch) >= 10)
                            return false;
                        pow10 *= 10;
                        value = value * 10 + ch;
                        offset++;
                    }
                    // More than 8 characters (7 sig figs and a decimal) and int -> float conversion is lossy, so use double
                    if (count > 8)
                    {
                        result = (float)((double)value / (double)pow10);
                    }
                    else
                    {
                        result = (float)value / (float)pow10;
                    }
                    if (negative)
                        result = -result;
                    return true;
                }
                else if (((uint)ch) >= 10)
                    return false;
                value = value * 10 + ch;
                offset++;
            }
            // Ten digits w/out a decimal point might've overflowed the int
            if (count == 10)
                return false;
            if (negative)
                result = -value;
            else
                result = value;
            return true;
        }
 
        static bool TryParseDouble(byte[] chars, int offset, int count, out double result)
        {
            result = 0;
            int offsetMax = offset + count;
            bool negative = false;
            if (offset < offsetMax && chars[offset] == '-')
            {
                negative = true;
                offset++;
                count--;
            }
            if (count < 1 || count > 10)
                return false;
            int value = 0;
            int ch;
            while (offset < offsetMax)
            {
                ch = (chars[offset] - '0');
                if (ch == ('.' - '0'))
                {
                    offset++;
                    int pow10 = 1;
                    while (offset < offsetMax)
                    {
                        ch = chars[offset] - '0';
                        if (((uint)ch) >= 10)
                            return false;
                        pow10 *= 10;
                        value = value * 10 + ch;
                        offset++;
                    }
                    if (negative)
                        result = -(double)value / pow10;
                    else
                        result = (double)value / pow10;
                    return true;
                }
                else if (((uint)ch) >= 10)
                    return false;
                value = value * 10 + ch;
                offset++;
            }
            // Ten digits w/out a decimal point might've overflowed the int
            if (count == 10)
                return false;
            if (negative)
                result = -value;
            else
                result = value;
            return true;
        }
 
        static int ToInt32D2(byte[] chars, int offset)
        {
            byte ch1 = (byte)(chars[offset + 0] - '0');
            byte ch2 = (byte)(chars[offset + 1] - '0');
            if (ch1 > 9 || ch2 > 9)
                return -1;
            return 10 * ch1 + ch2;
        }
 
        static int ToInt32D4(byte[] chars, int offset, int count)
        {
            return ToInt32D7(chars, offset, count);
        }
 
        static int ToInt32D7(byte[] chars, int offset, int count)
        {
            int value = 0;
            for (int i = 0; i < count; i++)
            {
                byte ch = (byte)(chars[offset + i] - '0');
                if (ch > 9)
                    return -1;
                value = value * 10 + ch;
            }
            return value;
        }
 
        static bool TryParseDateTime(byte[] chars, int offset, int count, out DateTime result)
        {
            int offsetMax = offset + count;
            result = DateTime.MaxValue;
 
            if (count < 19)
                return false;
 
            //            1         2         3
            //  012345678901234567890123456789012
            // "yyyy-MM-ddTHH:mm:ss"
            // "yyyy-MM-ddTHH:mm:ss.fffffff"
            // "yyyy-MM-ddTHH:mm:ss.fffffffZ"
            // "yyyy-MM-ddTHH:mm:ss.fffffff+xx:yy"
            // "yyyy-MM-ddTHH:mm:ss.fffffff-xx:yy"
            if (chars[offset + 4] != '-' || chars[offset + 7] != '-' || chars[offset + 10] != 'T' ||
                chars[offset + 13] != ':' || chars[offset + 16] != ':')
                return false;
 
            int year = ToInt32D4(chars, offset + 0, 4);
            int month = ToInt32D2(chars, offset + 5);
            int day = ToInt32D2(chars, offset + 8);
            int hour = ToInt32D2(chars, offset + 11);
            int minute = ToInt32D2(chars, offset + 14);
            int second = ToInt32D2(chars, offset + 17);
 
            if ((year | month | day | hour | minute | second) < 0)
                return false;
 
            DateTimeKind kind = DateTimeKind.Unspecified;
            offset += 19;
 
            int ticks = 0;
            if (offset < offsetMax && chars[offset] == '.')
            {
                offset++;
                int digitOffset = offset;
                while (offset < offsetMax)
                {
                    byte ch = chars[offset];
                    if (ch < '0' || ch > '9')
                        break;
                    offset++;
                }
                int digitCount = offset - digitOffset;
                if (digitCount < 1 || digitCount > 7)
                    return false;
                ticks = ToInt32D7(chars, digitOffset, digitCount);
                if (ticks < 0)
                    return false;
                for (int i = digitCount; i < 7; ++i)
                    ticks *= 10;
            }
 
            bool isLocal = false;
            int hourDelta = 0;
            int minuteDelta = 0;
            if (offset < offsetMax)
            {
                byte ch = chars[offset];
                if (ch == 'Z')
                {
                    offset++;
                    kind = DateTimeKind.Utc;
                }
                else if (ch == '+' || ch == '-')
                {
                    offset++;
                    if (offset + 5 > offsetMax || chars[offset + 2] != ':')
                        return false;
                    kind = DateTimeKind.Utc;
                    isLocal = true;
                    hourDelta = ToInt32D2(chars, offset);
                    minuteDelta = ToInt32D2(chars, offset + 3);
                    if ((hourDelta | minuteDelta) < 0)
                        return false;
                    if (ch == '+')
                    {
                        hourDelta = -hourDelta;
                        minuteDelta = -minuteDelta;
                    }
                    offset += 5;
                }
            }
            if (offset < offsetMax)
                return false;
 
            DateTime value;
            try
            {
                value = new DateTime(year, month, day, hour, minute, second, kind);
            }
            catch (ArgumentException)
            {
                return false;
            }
 
            if (ticks > 0)
            {
                value = value.AddTicks(ticks);
            }
            if (isLocal)
            {
                try
                {
                    TimeSpan ts = new TimeSpan(hourDelta, minuteDelta, 0);
                    if (hourDelta >= 0 && (value < DateTime.MaxValue - ts) ||
                        hourDelta < 0 && (value > DateTime.MinValue - ts))
                    {
                        value = value.Add(ts).ToLocalTime();
                    }
                    else
                    {
                        value = value.ToLocalTime().Add(ts);
                    }
                }
                catch (ArgumentOutOfRangeException) // Overflow
                {
                    return false;
                }
            }
 
            result = value;
            return true;
        }
 
        static public int ToChars(bool value, byte[] buffer, int offset)
        {
            if (value)
            {
                buffer[offset + 0] = (byte)'t';
                buffer[offset + 1] = (byte)'r';
                buffer[offset + 2] = (byte)'u';
                buffer[offset + 3] = (byte)'e';
                return 4;
            }
            else
            {
                buffer[offset + 0] = (byte)'f';
                buffer[offset + 1] = (byte)'a';
                buffer[offset + 2] = (byte)'l';
                buffer[offset + 3] = (byte)'s';
                buffer[offset + 4] = (byte)'e';
                return 5;
            }
        }
 
        // Works left from offset
        static public int ToCharsR(int value, byte[] chars, int offset)
        {
            int count = 0;
            if (value >= 0)
            {
                while (value >= 10)
                {
                    int valueDiv10 = value / 10;
                    count++;
                    chars[--offset] = (byte)('0' + (value - valueDiv10 * 10));
                    value = valueDiv10;
                }
                chars[--offset] = (byte)('0' + value);
                count++;
            }
            else
            {
                while (value <= -10)
                {
                    int valueDiv10 = value / 10;
                    count++;
                    chars[--offset] = (byte)('0' - (value - valueDiv10 * 10));
                    value = valueDiv10;
                }
                chars[--offset] = (byte)('0' - value);
                chars[--offset] = (byte)'-';
                count += 2;
            }
            return count;
        }
 
        static public int ToChars(int value, byte[] chars, int offset)
        {
            int count = ToCharsR(value, chars, offset + MaxInt32Chars);
            Buffer.BlockCopy(chars, offset + MaxInt32Chars - count, chars, offset, count);
            return count;
        }
 
        static public int ToCharsR(long value, byte[] chars, int offset)
        {
            int count = 0;
            if (value >= 0)
            {
                while (value > int.MaxValue)
                {
                    long valueDiv10 = value / 10;
                    count++;
                    chars[--offset] = (byte)('0' + (int)(value - valueDiv10 * 10));
                    value = valueDiv10;
                }
            }
            else
            {
                while (value < int.MinValue)
                {
                    long valueDiv10 = value / 10;
                    count++;
                    chars[--offset] = (byte)('0' - (int)(value - valueDiv10 * 10));
                    value = valueDiv10;
                }
            }
            Fx.Assert(value >= int.MinValue && value <= int.MaxValue, "");
            return count + ToCharsR((int)value, chars, offset);
        }
 
        static public int ToChars(long value, byte[] chars, int offset)
        {
            int count = ToCharsR(value, chars, offset + MaxInt64Chars);
            Buffer.BlockCopy(chars, offset + MaxInt64Chars - count, chars, offset, count);
            return count;
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical]
        static unsafe bool IsNegativeZero(float value)
        {
            // Simple equals function will report that -0 is equal to +0, so compare bits instead
            float negativeZero = -0e0F;
            return (*(Int32*)&value == *(Int32*)&negativeZero);
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical]
        static unsafe bool IsNegativeZero(double value)
        {
            // Simple equals function will report that -0 is equal to +0, so compare bits instead
            double negativeZero = -0e0;
            return (*(Int64*)&value == *(Int64*)&negativeZero);
        }
 
        static int ToInfinity(bool isNegative, byte[] buffer, int offset)
        {
            if (isNegative)
            {
                buffer[offset + 0] = (byte)'-';
                buffer[offset + 1] = (byte)'I';
                buffer[offset + 2] = (byte)'N';
                buffer[offset + 3] = (byte)'F';
                return 4;
            }
            else
            {
                buffer[offset + 0] = (byte)'I';
                buffer[offset + 1] = (byte)'N';
                buffer[offset + 2] = (byte)'F';
                return 3;
            }
        }
 
        static int ToZero(bool isNegative, byte[] buffer, int offset)
        {
            if (isNegative)
            {
                buffer[offset + 0] = (byte)'-';
                buffer[offset + 1] = (byte)'0';
                return 2;
            }
            else
            {
                buffer[offset] = (byte)'0';
                return 1;
            }
        }
 
        static public int ToChars(double value, byte[] buffer, int offset)
        {
            if (double.IsInfinity(value))
                return ToInfinity(double.IsNegativeInfinity(value), buffer, offset);
            if (value == 0.0)
                return ToZero(IsNegativeZero(value), buffer, offset);
            return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
        }
 
        static public int ToChars(float value, byte[] buffer, int offset)
        {
            if (float.IsInfinity(value))
                return ToInfinity(float.IsNegativeInfinity(value), buffer, offset);
            if (value == 0.0)
                return ToZero(IsNegativeZero(value), buffer, offset);
            return ToAsciiChars(value.ToString("R", NumberFormatInfo.InvariantInfo), buffer, offset);
        }
 
        static public int ToChars(decimal value, byte[] buffer, int offset)
        {
            return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
        }
 
        static public int ToChars(UInt64 value, byte[] buffer, int offset)
        {
            return ToAsciiChars(value.ToString(null, NumberFormatInfo.InvariantInfo), buffer, offset);
        }
 
        static int ToAsciiChars(string s, byte[] buffer, int offset)
        {
            for (int i = 0; i < s.Length; i++)
            {
                Fx.Assert(s[i] < 128, "");
                buffer[offset++] = (byte)s[i];
            }
            return s.Length;
        }
 
        static int ToCharsD2(int value, byte[] chars, int offset)
        {
            Fx.Assert(value >= 0 && value < 100, "");
            if (value < 10)
            {
                chars[offset + 0] = (byte)'0';
                chars[offset + 1] = (byte)('0' + value);
            }
            else
            {
                int valueDiv10 = value / 10;
                chars[offset + 0] = (byte)('0' + valueDiv10);
                chars[offset + 1] = (byte)('0' + value - valueDiv10 * 10);
            }
            return 2;
        }
 
        static int ToCharsD4(int value, byte[] chars, int offset)
        {
            Fx.Assert(value >= 0 && value < 10000, "");
            ToCharsD2(value / 100, chars, offset + 0);
            ToCharsD2(value % 100, chars, offset + 2);
            return 4;
        }
 
        static int ToCharsD7(int value, byte[] chars, int offset)
        {
            Fx.Assert(value >= 0 && value < 10000000, "");
            int zeroCount = 7 - ToCharsR(value, chars, offset + 7);
            for (int i = 0; i < zeroCount; i++)
                chars[offset + i] = (byte)'0';
            int count = 7;
            while (count > 0 && chars[offset + count - 1] == '0')
                count--;
            return count;
        }
 
        static public int ToChars(DateTime value, byte[] chars, int offset)
        {
            const long TicksPerMillisecond = 10000;
            const long TicksPerSecond = TicksPerMillisecond * 1000;
            int offsetMin = offset;
            // "yyyy-MM-ddTHH:mm:ss.fffffff";
            offset += ToCharsD4(value.Year, chars, offset);
            chars[offset++] = (byte)'-';
            offset += ToCharsD2(value.Month, chars, offset);
            chars[offset++] = (byte)'-';
            offset += ToCharsD2(value.Day, chars, offset);
            chars[offset++] = (byte)'T';
            offset += ToCharsD2(value.Hour, chars, offset);
            chars[offset++] = (byte)':';
            offset += ToCharsD2(value.Minute, chars, offset);
            chars[offset++] = (byte)':';
            offset += ToCharsD2(value.Second, chars, offset);
            int ms = (int)(value.Ticks % TicksPerSecond);
            if (ms != 0)
            {
                chars[offset++] = (byte)'.';
                offset += ToCharsD7(ms, chars, offset);
            }
            switch (value.Kind)
            {
                case DateTimeKind.Unspecified:
                    break;
                case DateTimeKind.Local:
                    // +"zzzzzz";
                    TimeSpan ts = TimeZoneInfo.Local.GetUtcOffset(value);
                    if (ts.Ticks < 0)
                        chars[offset++] = (byte)'-';
                    else
                        chars[offset++] = (byte)'+';
                    offset += ToCharsD2(Math.Abs(ts.Hours), chars, offset);
                    chars[offset++] = (byte)':';
                    offset += ToCharsD2(Math.Abs(ts.Minutes), chars, offset);
                    break;
                case DateTimeKind.Utc:
                    // +"Z"
                    chars[offset++] = (byte)'Z';
                    break;
                default:
                    throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException());
            }
            return offset - offsetMin;
        }
 
        static public bool IsWhitespace(string s)
        {
            for (int i = 0; i < s.Length; i++)
            {
                if (!IsWhitespace(s[i]))
                    return false;
            }
            return true;
        }
 
        static public bool IsWhitespace(char ch)
        {
            return (ch <= ' ' && (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n'));
        }
 
        static public string StripWhitespace(string s)
        {
            int count = s.Length;
            for (int i = 0; i < s.Length; i++)
            {
                if (IsWhitespace(s[i]))
                {
                    count--;
                }
            }
            if (count == s.Length)
                return s;
            char[] chars = new char[count];
            count = 0;
            for (int i = 0; i < s.Length; i++)
            {
                char ch = s[i];
                if (!IsWhitespace(ch))
                {
                    chars[count++] = ch;
                }
            }
            return new string(chars);
        }
 
        static string Trim(string s)
        {
            int i;
            for (i = 0; i < s.Length && IsWhitespace(s[i]); i++);
 
            int j;
            for (j = s.Length; j > 0 && IsWhitespace(s[j - 1]); j--);
 
            if (i == 0 && j == s.Length)
                return s;
            else if (j == 0)
                return string.Empty;
            else
                return s.Substring(i, j - i);
        }
    }
}