WebConvert.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DataWeb / Server / System / Data / Services / Parsing / WebConvert.cs / 1 / WebConvert.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides methods to convert URI and payload values.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Parsing
{
    using System; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Text; 
    using System.Xml;
#if ASTORIA_CLIENT 
    using System.Data.Services.Client;
#endif

    /// Use this class to convert URI and payload values. 
    internal static class WebConvert
    { 
        /// Constant table of nibble-to-hex convertion values. 
        private const string HexValues = "0123456789ABCDEF";
 
        /// Prefix to hex-encoded values.
        private const string XmlHexEncodePrefix = "0x";

#if ASTORIA_SERVER 
        /// -INF - negative infinity.
        private const string XmlNegativeInfinity = "-INF"; 
 
        /// INF - positive infinity.
        private const string XmlPositiveInfinity = "INF"; 

        /// XML whitespace characters to trim around literals.
        private static char[] XmlWhitespaceChars = new char[] { ' ', '\t', '\n', '\r' };
 
        /// Determines whether the specified character is a valid hexadecimal digit.
        /// Character to check. 
        /// true if  is a valid hex digit; false otherwise. 
        internal static bool IsCharHexDigit(char c)
        { 
            return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
        }

#endif 

        /// Converts the given byte[] into string. 
        /// byte[] that needs to be converted. 
        /// String containing hex values representing the byte[].
        internal static string ConvertByteArrayToKeyString(byte[] byteArray) 
        {
            StringBuilder hexBuilder = new StringBuilder(3 + byteArray.Length * 2);
            hexBuilder.Append("X'");
            for (int i = 0; i < byteArray.Length; i++) 
            {
                hexBuilder.Append(HexValues[byteArray[i] >> 4]); 
                hexBuilder.Append(HexValues[byteArray[i] & 0x0F]); 
            }
 
            hexBuilder.Append("'");
            return hexBuilder.ToString();
        }
 
#if ASTORIA_SERVER
 
        /// Checks whether the specified text is a correctly formatted quoted value. 
        /// Text to check.
        /// true if the text is correctly formatted, false otherwise. 
        internal static bool IsKeyValueQuoted(string text)
        {
            Debug.Assert(text != null, "text != null");
            if (text.Length < 2 || text[0] != '\'' || text[text.Length - 1] != '\'') 
            {
                return false; 
            } 
            else
            { 
                int startIndex = 1;
                while (startIndex < text.Length - 1)
                {
                    int match = text.IndexOf('\'', startIndex, text.Length - startIndex - 1); 
                    if (match == -1)
                    { 
                        break; 
                    }
                    else if (match == startIndex - 1 || text[match + 1] != '\'') 
                    {
                        return false;
                    }
                    else 
                    {
                        startIndex = match + 2; 
                    } 
                }
 
                return true;
            }
        }
 
#endif
 
        ///  
        /// Determines whether the values for the specified types should be
        /// quoted in URI keys. 
        /// 
        /// Type to check.
        /// 
        /// true if values of  require quotes; false otherwise. 
        /// 
        internal static bool IsKeyTypeQuoted(Type type) 
        { 
            Debug.Assert(type != null, "type != null");
            return 
                type == typeof(System.Xml.Linq.XElement) || type == typeof(string);
        }

        /// Converts the specified value to a serializable string for URI key. 
        /// Non-null value to convert.
        /// out parameter for value converted to a serializable string for URI key. 
        /// true/ false indicating success 
        internal static bool TryKeyPrimitiveToString(object value, out string result)
        { 
            Debug.Assert(value != null, "value != null");
            if (value.GetType() == typeof(byte[]))
            {
                result = ConvertByteArrayToKeyString((byte[])value); 
            }
#if !ASTORIA_CLIENT 
            else if (value.GetType() == typeof(System.Data.Linq.Binary)) 
            {
                return TryKeyPrimitiveToString(((System.Data.Linq.Binary)value).ToArray(), out result); 
            }
#endif
            else
            { 
                if (!TryXmlPrimitiveToString(value, out result))
                { 
                    return false; 
                }
 
                Debug.Assert(result != null, "result != null");
                if (value.GetType() == typeof(DateTime))
                {
                    result = XmlConstants.LiteralPrefixDateTime + "'" + result + "'"; 
                }
                else if (value.GetType() == typeof(decimal)) 
                { 
                    result = result + 'M';
                } 
                else if (value.GetType() == typeof(Guid))
                {
                    result = XmlConstants.LiteralPrefixGuid + "'" + result + "'";
                } 
                else if (value.GetType() == typeof(Int64))
                { 
                    result = result + 'L'; 
                }
                else if (value.GetType() == typeof(Single)) 
                {
                    result = result + 'f';
                }
                else if (IsKeyTypeQuoted(value.GetType())) 
                {
                    result = "'" + result.Replace("'", "''") + "'"; 
                } 
            }
 
            return true;
        }

#if ASTORIA_SERVER 

        /// Removes quotes from the single-quotes text. 
        /// Text to remove quotes from. 
        /// The specified  with single quotes removed.
        internal static string RemoveQuotes(string text) 
        {
            Debug.Assert(!String.IsNullOrEmpty(text), "!String.IsNullOrEmpty(text)");

            char quote = text[0]; 
            Debug.Assert(quote == '\'', "quote == '\''");
            string s = text.Substring(1, text.Length - 2); 
            int start = 0; 
            while (true)
            { 
                int i = s.IndexOf(quote, start);
                if (i < 0)
                {
                    break; 
                }
 
                s = s.Remove(i, 1); 
                start = i + 1;
            } 

            return s;
        }
 
        /// Converts a string to a byte[] value.
        /// String text to convert. 
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToByteArray(string text, out byte[] targetValue) 
        {
            Debug.Assert(text != null, "text != null");

            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixBinary, ref text) && 
                !TryRemoveLiteralPrefix("X", ref text))
            { 
                targetValue = null; 
                return false;
            } 

            if (!TryRemoveQuotes(ref text))
            {
                targetValue = null; 
                return false;
            } 
 
            if ((text.Length % 2) != 0)
            { 
                targetValue = null;
                return false;
            }
 
            byte[] result = new byte[text.Length / 2];
            int resultIndex = 0; 
            int textIndex = 0; 
            while (resultIndex < result.Length)
            { 
                char ch0 = text[textIndex];
                char ch1 = text[textIndex + 1];
                if (!IsCharHexDigit(ch0) || !IsCharHexDigit(ch1))
                { 
                    targetValue = null;
                    return false; 
                } 

                result[resultIndex] = (byte)((byte)(HexCharToNibble(ch0) << 4) + HexCharToNibble(ch1)); 
                textIndex += 2;
                resultIndex++;
            }
 
            targetValue = result;
            return true; 
        } 

        /// Converts a string to a DateTime value. 
        /// String text to convert.
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToDateTime(string text, out DateTime targetValue) 
        {
            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixDateTime, ref text)) 
            { 
                targetValue = default(DateTime);
                return false; 
            }

            if (!TryRemoveQuotes(ref text))
            { 
                targetValue = default(DateTime);
                return false; 
            } 

            try 
            {
                targetValue = XmlConvert.ToDateTime(text, XmlDateTimeSerializationMode.RoundtripKind);
                return true;
            } 
            catch (FormatException)
            { 
                targetValue = default(DateTime); 
                return false;
            } 
        }

        /// Converts a string to a decimal value.
        /// String text to convert. 
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise. 
        internal static bool TryKeyStringToDecimal(string text, out decimal targetValue) 
        {
            Debug.Assert(text != null, "text != null"); 
            bool result;
            text = text.Trim(XmlWhitespaceChars);
            if (text.Length == 0 || text[text.Length - 1] != 'M')
            { 
                targetValue = default(decimal);
                return false; 
            } 
            else
            { 
                result = decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue);
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-')
                {
                    targetValue = 0; 
                }
            } 
 
            return result;
        } 

        /// Converts a string to a double value.
        /// String text to convert.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToDouble(string text, out double targetValue) 
        { 
            Debug.Assert(text != null, "text != null");
            bool result; 
            text = text.Trim(XmlWhitespaceChars);
            if (text == XmlPositiveInfinity)
            {
                targetValue = double.PositiveInfinity; 
                result = true;
            } 
            else if (text == XmlNegativeInfinity) 
            {
                targetValue = double.NegativeInfinity; 
                result = true;
            }
            else
            { 
                result = double.TryParse(text, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue);
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-') 
                { 
                    targetValue = 0;
                } 
            }

            return result;
        } 

        /// Converts a string to a GUID value. 
        /// String text to convert. 
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise. 
        internal static bool TryKeyStringToGuid(string text, out Guid targetValue)
        {
            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixGuid, ref text))
            { 
                targetValue = default(Guid);
                return false; 
            } 

            if (!TryRemoveQuotes(ref text)) 
            {
                targetValue = default(Guid);
                return false;
            } 

            try 
            { 
                targetValue = XmlConvert.ToGuid(text);
                return true; 
            }
            catch (FormatException)
            {
                targetValue = default(Guid); 
                return false;
            } 
        } 

        /// Converts a string to an Int64 value. 
        /// String text to convert.
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToInt64(string text, out Int64 targetValue) 
        {
            Debug.Assert(text != null, "text != null"); 
            text = text.Trim(XmlWhitespaceChars); 
            if (text.Length == 0 || text[text.Length - 1] != 'L')
            { 
                targetValue = default(Int64);
                return false;
            }
            else 
            {
                return Int64.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out targetValue); 
            } 
        }
 
        /// Converts a string to a primitive value.
        /// String text to convert.
        /// Type to convert string to.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToPrimitive(string text, Type targetType, out object targetValue) 
        { 
            return TryKeyStringToPrimitive(text, targetType, true, out targetValue);
        } 

        /// Converts a string to a single value.
        /// String text to convert.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToSingle(string text, out Single targetValue) 
        { 
            Debug.Assert(text != null, "text != null");
            bool result; 
            text = text.Trim(XmlWhitespaceChars);
            if (text.Length == 0 || text[text.Length - 1] != 'f')
            {
                targetValue = default(Single); 
                result = false;
            } 
            else 
            {
                result = Single.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue); 
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-')
                {
                    targetValue = 0;
                } 
            }
 
            return result; 
        }
 
        /// Converts a string to a primitive value.
        /// String text to convert.
        /// Type to convert string to.
        /// value converted to the target type. 
        internal static object StringToPrimitive(string text, Type targetType)
        { 
            Debug.Assert(text != null, "text != null"); 
            Debug.Assert(targetType != null, "targetType != null");
 
            object targetValue = null;
            targetType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            if (typeof(String) == targetType) 
            {
                targetValue = text; 
            } 
            else if (typeof(Boolean) == targetType)
            { 
                targetValue = XmlConvert.ToBoolean(text);
            }
            else if (typeof(Byte) == targetType)
            { 
                targetValue = XmlConvert.ToByte(text);
            } 
            else if (typeof(byte[]) == targetType) 
            {
                targetValue = Convert.FromBase64String(text); 
            }
            else if (typeof(System.Data.Linq.Binary) == targetType)
            {
                targetValue = new System.Data.Linq.Binary(Convert.FromBase64String(text)); 
            }
            else if (typeof(SByte) == targetType) 
            { 
                targetValue = XmlConvert.ToSByte(text);
            } 
            else if (typeof(DateTime) == targetType)
            {
                targetValue = XmlConvert.ToDateTime(text, XmlDateTimeSerializationMode.RoundtripKind);
            } 
            else if (typeof(Decimal) == targetType)
            { 
                targetValue = XmlConvert.ToDecimal(text); 
            }
            else if (typeof(Double) == targetType) 
            {
                targetValue = XmlConvert.ToDouble(text);
            }
            else if (typeof(Guid) == targetType) 
            {
                targetValue = new Guid(text); 
            } 
            else if (typeof(Int16) == targetType)
            { 
                targetValue = XmlConvert.ToInt16(text);
            }
            else if (typeof(Int32) == targetType)
            { 
                targetValue = XmlConvert.ToInt32(text);
            } 
            else if (typeof(Int64) == targetType) 
            {
                targetValue = XmlConvert.ToInt64(text); 
            }
            else if (typeof(System.Xml.Linq.XElement) == targetType)
            {
                targetValue = System.Xml.Linq.XElement.Parse(text, System.Xml.Linq.LoadOptions.PreserveWhitespace); 
            }
            else 
            { 
                Debug.Assert(typeof(Single) == targetType, "typeof(Single) == targetType(" + targetType + ")");
                targetValue = XmlConvert.ToSingle(text); 
            }

            return targetValue;
        } 

        /// Removes quotes from the single-quotes text. 
        /// Text to remove quotes from. 
        /// Whether quotes were successfully removed.
        internal static bool TryRemoveQuotes(ref string text) 
        {
            if (text.Length < 2)
            {
                return false; 
            }
 
            char quote = text[0]; 
            if (quote != '\'' || text[text.Length - 1] != quote)
            { 
                return false;
            }

            string s = text.Substring(1, text.Length - 2); 
            int start = 0;
            while (true) 
            { 
                int i = s.IndexOf(quote, start);
                if (i < 0) 
                {
                    break;
                }
 
                s = s.Remove(i, 1);
                if (s.Length < i + 1 || s[i] != quote) 
                { 
                    return false;
                } 

                start = i + 1;
            }
 
            text = s;
            return true; 
        } 
#endif
 
        /// Converts the specified value to a serializable string for XML content.
        /// Non-null value to convert.
        /// The specified value converted to a serializable string for XML content. 
        /// boolean value indicating conversion successful conversion 
        internal static bool TryXmlPrimitiveToString(object value, out string result)
        { 
            Debug.Assert(value != null, "value != null"); 
            result = null;
 
            Type valueType = value.GetType();
            valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;

            if (typeof(String) == valueType) 
            {
                result = (string)value; 
            } 
            else if (typeof(Boolean) == valueType)
            { 
                result = XmlConvert.ToString((bool)value);
            }
            else if (typeof(Byte) == valueType)
            { 
                result = XmlConvert.ToString((byte)value);
            } 
            else if (typeof(DateTime) == valueType) 
            {
                result = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind); 
            }
            else if (typeof(Decimal) == valueType)
            {
                result = XmlConvert.ToString((decimal)value); 
            }
            else if (typeof(Double) == valueType) 
            { 
                result = XmlConvert.ToString((double)value);
            } 
            else if (typeof(Guid) == valueType)
            {
                result = value.ToString();
            } 
            else if (typeof(Int16) == valueType)
            { 
                result = XmlConvert.ToString((Int16)value); 
            }
            else if (typeof(Int32) == valueType) 
            {
                result = XmlConvert.ToString((Int32)value);
            }
            else if (typeof(Int64) == valueType) 
            {
                result = XmlConvert.ToString((Int64)value); 
            } 
            else if (typeof(SByte) == valueType)
            { 
                result = XmlConvert.ToString((SByte)value);
            }
            else if (typeof(Single) == valueType)
            { 
                result = XmlConvert.ToString((Single)value);
            } 
            else if (typeof(byte[]) == valueType) 
            {
                byte[] byteArray = (byte[])value; 
                result = Convert.ToBase64String(byteArray);
            }
            #if ASTORIA_SERVER
            else if (typeof(System.Data.Linq.Binary) == valueType) 
            {
                return TryXmlPrimitiveToString(((System.Data.Linq.Binary)value).ToArray(), out result); 
            } 
            #else
            #if !ASTORIA_LIGHT 
            else if (ClientConvert.IsBinaryValue(value))
            {
                return ClientConvert.TryKeyBinaryToString(value, out result);
            } 
            #endif
            #endif 
            else if (typeof(System.Xml.Linq.XElement) == valueType) 
            {
                result = ((System.Xml.Linq.XElement)value).ToString(System.Xml.Linq.SaveOptions.None); 
            }
            else
            {
                result = null; 
                return false;
            } 
 
            Debug.Assert(result != null, "result != null");
            return true; 
        }

        #if ASTORIA_SERVER
 
        /// Returns the 4 bits that correspond to the specified character.
        /// Character in the 0-F range to be converted. 
        /// The 4 bits that correspond to the specified character. 
        /// Thrown when 'c' is not in the '0'-'9','a'-'f' range.
        private static byte HexCharToNibble(char c) 
        {
            Debug.Assert(IsCharHexDigit(c));
            switch (c)
            { 
                case '0':
                    return 0; 
                case '1': 
                    return 1;
                case '2': 
                    return 2;
                case '3':
                    return 3;
                case '4': 
                    return 4;
                case '5': 
                    return 5; 
                case '6':
                    return 6; 
                case '7':
                    return 7;
                case '8':
                    return 8; 
                case '9':
                    return 9; 
                case 'a': 
                case 'A':
                    return 10; 
                case 'b':
                case 'B':
                    return 11;
                case 'c': 
                case 'C':
                    return 12; 
                case 'd': 
                case 'D':
                    return 13; 
                case 'e':
                case 'E':
                    return 14;
                case 'f': 
                case 'F':
                    return 15; 
                default: 
                    throw new InvalidOperationException();
            } 
        }

        /// Converts a string to a primitive value.
        /// String text to convert. 
        /// Type to convert string to.
        /// After invocation, converted value. 
        /// Whether recursion is allowed by binary-encoded values. 
        /// true if the value was converted; false otherwise.
        private static bool TryKeyStringToPrimitive(string text, Type targetType, bool allowRecursion, out object targetValue) 
        {
            Debug.Assert(text != null, "text != null");
            Debug.Assert(targetType != null, "targetType != null");
 
            byte[] byteArrayValue;
            bool binaryResult = TryKeyStringToByteArray(text, out byteArrayValue); 
            if (targetType == typeof(byte[]) || targetType == typeof(System.Data.Linq.Binary)) 
            {
                // The object cast is required because otherwise the compiler uses the implicit byte[] 
                // to Binary conversion and always returns Binary.
                targetValue =
                    (byteArrayValue != null && targetType == typeof(System.Data.Linq.Binary)) ?
                    (object)new System.Data.Linq.Binary(byteArrayValue) : (object)byteArrayValue; 
                return binaryResult;
            } 
            else if (binaryResult) 
            {
                if (allowRecursion) 
                {
                    string keyValue = Encoding.UTF8.GetString(byteArrayValue);
                    return TryKeyStringToPrimitive(keyValue, targetType, out targetValue);
                } 
                else
                { 
                    targetValue = null; 
                    return false;
                } 
            }
            // These have separate handlers for convenience - reuse them.
            else if (targetType == typeof(double))
            { 
                double doubleValue;
                bool result = TryKeyStringToDouble(text, out doubleValue); 
                targetValue = doubleValue; 
                return result;
            } 
            else if (targetType == typeof(decimal))
            {
                decimal decimalValue;
                bool result = TryKeyStringToDecimal(text, out decimalValue); 
                targetValue = decimalValue;
                return result; 
            } 
            else if (targetType == typeof(Guid))
            { 
                Guid guidValue;
                bool result = TryKeyStringToGuid(text, out guidValue);
                targetValue = guidValue;
                return result; 
            }
            else if (targetType == typeof(DateTime)) 
            { 
                DateTime dateTimeValue;
                bool result = TryKeyStringToDateTime(text, out dateTimeValue); 
                targetValue = dateTimeValue;
                return result;
            }
            else if (targetType == typeof(Int64)) 
            {
                Int64 intValue; 
                bool result = TryKeyStringToInt64(text, out intValue); 
                targetValue = intValue;
                return result; 
            }
            else if (targetType == typeof(Single))
            {
                Single singleValue; 
                bool result = TryKeyStringToSingle(text, out singleValue);
                targetValue = singleValue; 
                return result; 
            }
 
            bool quoted = WebConvert.IsKeyTypeQuoted(targetType);
            if (quoted != WebConvert.IsKeyValueQuoted(text))
            {
                targetValue = null; 
                return false;
            } 
 
            if (quoted)
            { 
                Debug.Assert(IsKeyValueQuoted(text), "IsKeyValueQuoted(text) - otherwise caller didn't check this before");
                text = RemoveQuotes(text);
            }
 
            try
            { 
                if (typeof(String) == targetType) 
                {
                    targetValue = text; 
                }
                else if (typeof(Boolean) == targetType)
                {
                    targetValue = XmlConvert.ToBoolean(text); 
                }
                else if (typeof(Byte) == targetType) 
                { 
                    targetValue = XmlConvert.ToByte(text);
                } 
                else if (typeof(SByte) == targetType)
                {
                    targetValue = XmlConvert.ToSByte(text);
                } 
                else if (typeof(Int16) == targetType)
                { 
                    targetValue = XmlConvert.ToInt16(text); 
                }
                else if (typeof(Int32) == targetType) 
                {
                    targetValue = XmlConvert.ToInt32(text);
                }
                else 
                {
                    Debug.Assert(typeof(System.Xml.Linq.XElement) == targetType, "XElement == " + targetType); 
                    targetValue = System.Xml.Linq.XElement.Parse(text, System.Xml.Linq.LoadOptions.PreserveWhitespace); 
                }
 
                return true;
            }
            catch (FormatException)
            { 
                targetValue = null;
                return false; 
            } 
        }
 
        /// 
        /// Tries to remove a literal  from the specified .
        /// 
        /// Prefix to remove; one-letter prefixes are case-sensitive, others insensitive. 
        /// Text to attempt to remove prefix from.
        /// true if the prefix was found and removed; false otherwise. 
        private static bool TryRemoveLiteralPrefix(string prefix, ref string text) 
        {
            Debug.Assert(prefix != null, "prefix != null"); 
            StringComparison sc = (prefix.Length == 1) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
            if (text.StartsWith(prefix, sc))
            {
                text = text.Remove(0, prefix.Length); 
                return true;
            } 
            else 
            {
                return false; 
            }
        }
#endif
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides methods to convert URI and payload values.
//  
// 
// @owner  [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Parsing
{
    using System; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Text; 
    using System.Xml;
#if ASTORIA_CLIENT 
    using System.Data.Services.Client;
#endif

    /// Use this class to convert URI and payload values. 
    internal static class WebConvert
    { 
        /// Constant table of nibble-to-hex convertion values. 
        private const string HexValues = "0123456789ABCDEF";
 
        /// Prefix to hex-encoded values.
        private const string XmlHexEncodePrefix = "0x";

#if ASTORIA_SERVER 
        /// -INF - negative infinity.
        private const string XmlNegativeInfinity = "-INF"; 
 
        /// INF - positive infinity.
        private const string XmlPositiveInfinity = "INF"; 

        /// XML whitespace characters to trim around literals.
        private static char[] XmlWhitespaceChars = new char[] { ' ', '\t', '\n', '\r' };
 
        /// Determines whether the specified character is a valid hexadecimal digit.
        /// Character to check. 
        /// true if  is a valid hex digit; false otherwise. 
        internal static bool IsCharHexDigit(char c)
        { 
            return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F');
        }

#endif 

        /// Converts the given byte[] into string. 
        /// byte[] that needs to be converted. 
        /// String containing hex values representing the byte[].
        internal static string ConvertByteArrayToKeyString(byte[] byteArray) 
        {
            StringBuilder hexBuilder = new StringBuilder(3 + byteArray.Length * 2);
            hexBuilder.Append("X'");
            for (int i = 0; i < byteArray.Length; i++) 
            {
                hexBuilder.Append(HexValues[byteArray[i] >> 4]); 
                hexBuilder.Append(HexValues[byteArray[i] & 0x0F]); 
            }
 
            hexBuilder.Append("'");
            return hexBuilder.ToString();
        }
 
#if ASTORIA_SERVER
 
        /// Checks whether the specified text is a correctly formatted quoted value. 
        /// Text to check.
        /// true if the text is correctly formatted, false otherwise. 
        internal static bool IsKeyValueQuoted(string text)
        {
            Debug.Assert(text != null, "text != null");
            if (text.Length < 2 || text[0] != '\'' || text[text.Length - 1] != '\'') 
            {
                return false; 
            } 
            else
            { 
                int startIndex = 1;
                while (startIndex < text.Length - 1)
                {
                    int match = text.IndexOf('\'', startIndex, text.Length - startIndex - 1); 
                    if (match == -1)
                    { 
                        break; 
                    }
                    else if (match == startIndex - 1 || text[match + 1] != '\'') 
                    {
                        return false;
                    }
                    else 
                    {
                        startIndex = match + 2; 
                    } 
                }
 
                return true;
            }
        }
 
#endif
 
        ///  
        /// Determines whether the values for the specified types should be
        /// quoted in URI keys. 
        /// 
        /// Type to check.
        /// 
        /// true if values of  require quotes; false otherwise. 
        /// 
        internal static bool IsKeyTypeQuoted(Type type) 
        { 
            Debug.Assert(type != null, "type != null");
            return 
                type == typeof(System.Xml.Linq.XElement) || type == typeof(string);
        }

        /// Converts the specified value to a serializable string for URI key. 
        /// Non-null value to convert.
        /// out parameter for value converted to a serializable string for URI key. 
        /// true/ false indicating success 
        internal static bool TryKeyPrimitiveToString(object value, out string result)
        { 
            Debug.Assert(value != null, "value != null");
            if (value.GetType() == typeof(byte[]))
            {
                result = ConvertByteArrayToKeyString((byte[])value); 
            }
#if !ASTORIA_CLIENT 
            else if (value.GetType() == typeof(System.Data.Linq.Binary)) 
            {
                return TryKeyPrimitiveToString(((System.Data.Linq.Binary)value).ToArray(), out result); 
            }
#endif
            else
            { 
                if (!TryXmlPrimitiveToString(value, out result))
                { 
                    return false; 
                }
 
                Debug.Assert(result != null, "result != null");
                if (value.GetType() == typeof(DateTime))
                {
                    result = XmlConstants.LiteralPrefixDateTime + "'" + result + "'"; 
                }
                else if (value.GetType() == typeof(decimal)) 
                { 
                    result = result + 'M';
                } 
                else if (value.GetType() == typeof(Guid))
                {
                    result = XmlConstants.LiteralPrefixGuid + "'" + result + "'";
                } 
                else if (value.GetType() == typeof(Int64))
                { 
                    result = result + 'L'; 
                }
                else if (value.GetType() == typeof(Single)) 
                {
                    result = result + 'f';
                }
                else if (IsKeyTypeQuoted(value.GetType())) 
                {
                    result = "'" + result.Replace("'", "''") + "'"; 
                } 
            }
 
            return true;
        }

#if ASTORIA_SERVER 

        /// Removes quotes from the single-quotes text. 
        /// Text to remove quotes from. 
        /// The specified  with single quotes removed.
        internal static string RemoveQuotes(string text) 
        {
            Debug.Assert(!String.IsNullOrEmpty(text), "!String.IsNullOrEmpty(text)");

            char quote = text[0]; 
            Debug.Assert(quote == '\'', "quote == '\''");
            string s = text.Substring(1, text.Length - 2); 
            int start = 0; 
            while (true)
            { 
                int i = s.IndexOf(quote, start);
                if (i < 0)
                {
                    break; 
                }
 
                s = s.Remove(i, 1); 
                start = i + 1;
            } 

            return s;
        }
 
        /// Converts a string to a byte[] value.
        /// String text to convert. 
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToByteArray(string text, out byte[] targetValue) 
        {
            Debug.Assert(text != null, "text != null");

            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixBinary, ref text) && 
                !TryRemoveLiteralPrefix("X", ref text))
            { 
                targetValue = null; 
                return false;
            } 

            if (!TryRemoveQuotes(ref text))
            {
                targetValue = null; 
                return false;
            } 
 
            if ((text.Length % 2) != 0)
            { 
                targetValue = null;
                return false;
            }
 
            byte[] result = new byte[text.Length / 2];
            int resultIndex = 0; 
            int textIndex = 0; 
            while (resultIndex < result.Length)
            { 
                char ch0 = text[textIndex];
                char ch1 = text[textIndex + 1];
                if (!IsCharHexDigit(ch0) || !IsCharHexDigit(ch1))
                { 
                    targetValue = null;
                    return false; 
                } 

                result[resultIndex] = (byte)((byte)(HexCharToNibble(ch0) << 4) + HexCharToNibble(ch1)); 
                textIndex += 2;
                resultIndex++;
            }
 
            targetValue = result;
            return true; 
        } 

        /// Converts a string to a DateTime value. 
        /// String text to convert.
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToDateTime(string text, out DateTime targetValue) 
        {
            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixDateTime, ref text)) 
            { 
                targetValue = default(DateTime);
                return false; 
            }

            if (!TryRemoveQuotes(ref text))
            { 
                targetValue = default(DateTime);
                return false; 
            } 

            try 
            {
                targetValue = XmlConvert.ToDateTime(text, XmlDateTimeSerializationMode.RoundtripKind);
                return true;
            } 
            catch (FormatException)
            { 
                targetValue = default(DateTime); 
                return false;
            } 
        }

        /// Converts a string to a decimal value.
        /// String text to convert. 
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise. 
        internal static bool TryKeyStringToDecimal(string text, out decimal targetValue) 
        {
            Debug.Assert(text != null, "text != null"); 
            bool result;
            text = text.Trim(XmlWhitespaceChars);
            if (text.Length == 0 || text[text.Length - 1] != 'M')
            { 
                targetValue = default(decimal);
                return false; 
            } 
            else
            { 
                result = decimal.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue);
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-')
                {
                    targetValue = 0; 
                }
            } 
 
            return result;
        } 

        /// Converts a string to a double value.
        /// String text to convert.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToDouble(string text, out double targetValue) 
        { 
            Debug.Assert(text != null, "text != null");
            bool result; 
            text = text.Trim(XmlWhitespaceChars);
            if (text == XmlPositiveInfinity)
            {
                targetValue = double.PositiveInfinity; 
                result = true;
            } 
            else if (text == XmlNegativeInfinity) 
            {
                targetValue = double.NegativeInfinity; 
                result = true;
            }
            else
            { 
                result = double.TryParse(text, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue);
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-') 
                { 
                    targetValue = 0;
                } 
            }

            return result;
        } 

        /// Converts a string to a GUID value. 
        /// String text to convert. 
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise. 
        internal static bool TryKeyStringToGuid(string text, out Guid targetValue)
        {
            if (!TryRemoveLiteralPrefix(XmlConstants.LiteralPrefixGuid, ref text))
            { 
                targetValue = default(Guid);
                return false; 
            } 

            if (!TryRemoveQuotes(ref text)) 
            {
                targetValue = default(Guid);
                return false;
            } 

            try 
            { 
                targetValue = XmlConvert.ToGuid(text);
                return true; 
            }
            catch (FormatException)
            {
                targetValue = default(Guid); 
                return false;
            } 
        } 

        /// Converts a string to an Int64 value. 
        /// String text to convert.
        /// After invocation, converted value.
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToInt64(string text, out Int64 targetValue) 
        {
            Debug.Assert(text != null, "text != null"); 
            text = text.Trim(XmlWhitespaceChars); 
            if (text.Length == 0 || text[text.Length - 1] != 'L')
            { 
                targetValue = default(Int64);
                return false;
            }
            else 
            {
                return Int64.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out targetValue); 
            } 
        }
 
        /// Converts a string to a primitive value.
        /// String text to convert.
        /// Type to convert string to.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToPrimitive(string text, Type targetType, out object targetValue) 
        { 
            return TryKeyStringToPrimitive(text, targetType, true, out targetValue);
        } 

        /// Converts a string to a single value.
        /// String text to convert.
        /// After invocation, converted value. 
        /// true if the value was converted; false otherwise.
        internal static bool TryKeyStringToSingle(string text, out Single targetValue) 
        { 
            Debug.Assert(text != null, "text != null");
            bool result; 
            text = text.Trim(XmlWhitespaceChars);
            if (text.Length == 0 || text[text.Length - 1] != 'f')
            {
                targetValue = default(Single); 
                result = false;
            } 
            else 
            {
                result = Single.TryParse(text.Substring(0, text.Length - 1), NumberStyles.Float, NumberFormatInfo.InvariantInfo, out targetValue); 
                if (result && targetValue == 0 && text.Length > 0 && text[0] == '-')
                {
                    targetValue = 0;
                } 
            }
 
            return result; 
        }
 
        /// Converts a string to a primitive value.
        /// String text to convert.
        /// Type to convert string to.
        /// value converted to the target type. 
        internal static object StringToPrimitive(string text, Type targetType)
        { 
            Debug.Assert(text != null, "text != null"); 
            Debug.Assert(targetType != null, "targetType != null");
 
            object targetValue = null;
            targetType = Nullable.GetUnderlyingType(targetType) ?? targetType;

            if (typeof(String) == targetType) 
            {
                targetValue = text; 
            } 
            else if (typeof(Boolean) == targetType)
            { 
                targetValue = XmlConvert.ToBoolean(text);
            }
            else if (typeof(Byte) == targetType)
            { 
                targetValue = XmlConvert.ToByte(text);
            } 
            else if (typeof(byte[]) == targetType) 
            {
                targetValue = Convert.FromBase64String(text); 
            }
            else if (typeof(System.Data.Linq.Binary) == targetType)
            {
                targetValue = new System.Data.Linq.Binary(Convert.FromBase64String(text)); 
            }
            else if (typeof(SByte) == targetType) 
            { 
                targetValue = XmlConvert.ToSByte(text);
            } 
            else if (typeof(DateTime) == targetType)
            {
                targetValue = XmlConvert.ToDateTime(text, XmlDateTimeSerializationMode.RoundtripKind);
            } 
            else if (typeof(Decimal) == targetType)
            { 
                targetValue = XmlConvert.ToDecimal(text); 
            }
            else if (typeof(Double) == targetType) 
            {
                targetValue = XmlConvert.ToDouble(text);
            }
            else if (typeof(Guid) == targetType) 
            {
                targetValue = new Guid(text); 
            } 
            else if (typeof(Int16) == targetType)
            { 
                targetValue = XmlConvert.ToInt16(text);
            }
            else if (typeof(Int32) == targetType)
            { 
                targetValue = XmlConvert.ToInt32(text);
            } 
            else if (typeof(Int64) == targetType) 
            {
                targetValue = XmlConvert.ToInt64(text); 
            }
            else if (typeof(System.Xml.Linq.XElement) == targetType)
            {
                targetValue = System.Xml.Linq.XElement.Parse(text, System.Xml.Linq.LoadOptions.PreserveWhitespace); 
            }
            else 
            { 
                Debug.Assert(typeof(Single) == targetType, "typeof(Single) == targetType(" + targetType + ")");
                targetValue = XmlConvert.ToSingle(text); 
            }

            return targetValue;
        } 

        /// Removes quotes from the single-quotes text. 
        /// Text to remove quotes from. 
        /// Whether quotes were successfully removed.
        internal static bool TryRemoveQuotes(ref string text) 
        {
            if (text.Length < 2)
            {
                return false; 
            }
 
            char quote = text[0]; 
            if (quote != '\'' || text[text.Length - 1] != quote)
            { 
                return false;
            }

            string s = text.Substring(1, text.Length - 2); 
            int start = 0;
            while (true) 
            { 
                int i = s.IndexOf(quote, start);
                if (i < 0) 
                {
                    break;
                }
 
                s = s.Remove(i, 1);
                if (s.Length < i + 1 || s[i] != quote) 
                { 
                    return false;
                } 

                start = i + 1;
            }
 
            text = s;
            return true; 
        } 
#endif
 
        /// Converts the specified value to a serializable string for XML content.
        /// Non-null value to convert.
        /// The specified value converted to a serializable string for XML content. 
        /// boolean value indicating conversion successful conversion 
        internal static bool TryXmlPrimitiveToString(object value, out string result)
        { 
            Debug.Assert(value != null, "value != null"); 
            result = null;
 
            Type valueType = value.GetType();
            valueType = Nullable.GetUnderlyingType(valueType) ?? valueType;

            if (typeof(String) == valueType) 
            {
                result = (string)value; 
            } 
            else if (typeof(Boolean) == valueType)
            { 
                result = XmlConvert.ToString((bool)value);
            }
            else if (typeof(Byte) == valueType)
            { 
                result = XmlConvert.ToString((byte)value);
            } 
            else if (typeof(DateTime) == valueType) 
            {
                result = XmlConvert.ToString((DateTime)value, XmlDateTimeSerializationMode.RoundtripKind); 
            }
            else if (typeof(Decimal) == valueType)
            {
                result = XmlConvert.ToString((decimal)value); 
            }
            else if (typeof(Double) == valueType) 
            { 
                result = XmlConvert.ToString((double)value);
            } 
            else if (typeof(Guid) == valueType)
            {
                result = value.ToString();
            } 
            else if (typeof(Int16) == valueType)
            { 
                result = XmlConvert.ToString((Int16)value); 
            }
            else if (typeof(Int32) == valueType) 
            {
                result = XmlConvert.ToString((Int32)value);
            }
            else if (typeof(Int64) == valueType) 
            {
                result = XmlConvert.ToString((Int64)value); 
            } 
            else if (typeof(SByte) == valueType)
            { 
                result = XmlConvert.ToString((SByte)value);
            }
            else if (typeof(Single) == valueType)
            { 
                result = XmlConvert.ToString((Single)value);
            } 
            else if (typeof(byte[]) == valueType) 
            {
                byte[] byteArray = (byte[])value; 
                result = Convert.ToBase64String(byteArray);
            }
            #if ASTORIA_SERVER
            else if (typeof(System.Data.Linq.Binary) == valueType) 
            {
                return TryXmlPrimitiveToString(((System.Data.Linq.Binary)value).ToArray(), out result); 
            } 
            #else
            #if !ASTORIA_LIGHT 
            else if (ClientConvert.IsBinaryValue(value))
            {
                return ClientConvert.TryKeyBinaryToString(value, out result);
            } 
            #endif
            #endif 
            else if (typeof(System.Xml.Linq.XElement) == valueType) 
            {
                result = ((System.Xml.Linq.XElement)value).ToString(System.Xml.Linq.SaveOptions.None); 
            }
            else
            {
                result = null; 
                return false;
            } 
 
            Debug.Assert(result != null, "result != null");
            return true; 
        }

        #if ASTORIA_SERVER
 
        /// Returns the 4 bits that correspond to the specified character.
        /// Character in the 0-F range to be converted. 
        /// The 4 bits that correspond to the specified character. 
        /// Thrown when 'c' is not in the '0'-'9','a'-'f' range.
        private static byte HexCharToNibble(char c) 
        {
            Debug.Assert(IsCharHexDigit(c));
            switch (c)
            { 
                case '0':
                    return 0; 
                case '1': 
                    return 1;
                case '2': 
                    return 2;
                case '3':
                    return 3;
                case '4': 
                    return 4;
                case '5': 
                    return 5; 
                case '6':
                    return 6; 
                case '7':
                    return 7;
                case '8':
                    return 8; 
                case '9':
                    return 9; 
                case 'a': 
                case 'A':
                    return 10; 
                case 'b':
                case 'B':
                    return 11;
                case 'c': 
                case 'C':
                    return 12; 
                case 'd': 
                case 'D':
                    return 13; 
                case 'e':
                case 'E':
                    return 14;
                case 'f': 
                case 'F':
                    return 15; 
                default: 
                    throw new InvalidOperationException();
            } 
        }

        /// Converts a string to a primitive value.
        /// String text to convert. 
        /// Type to convert string to.
        /// After invocation, converted value. 
        /// Whether recursion is allowed by binary-encoded values. 
        /// true if the value was converted; false otherwise.
        private static bool TryKeyStringToPrimitive(string text, Type targetType, bool allowRecursion, out object targetValue) 
        {
            Debug.Assert(text != null, "text != null");
            Debug.Assert(targetType != null, "targetType != null");
 
            byte[] byteArrayValue;
            bool binaryResult = TryKeyStringToByteArray(text, out byteArrayValue); 
            if (targetType == typeof(byte[]) || targetType == typeof(System.Data.Linq.Binary)) 
            {
                // The object cast is required because otherwise the compiler uses the implicit byte[] 
                // to Binary conversion and always returns Binary.
                targetValue =
                    (byteArrayValue != null && targetType == typeof(System.Data.Linq.Binary)) ?
                    (object)new System.Data.Linq.Binary(byteArrayValue) : (object)byteArrayValue; 
                return binaryResult;
            } 
            else if (binaryResult) 
            {
                if (allowRecursion) 
                {
                    string keyValue = Encoding.UTF8.GetString(byteArrayValue);
                    return TryKeyStringToPrimitive(keyValue, targetType, out targetValue);
                } 
                else
                { 
                    targetValue = null; 
                    return false;
                } 
            }
            // These have separate handlers for convenience - reuse them.
            else if (targetType == typeof(double))
            { 
                double doubleValue;
                bool result = TryKeyStringToDouble(text, out doubleValue); 
                targetValue = doubleValue; 
                return result;
            } 
            else if (targetType == typeof(decimal))
            {
                decimal decimalValue;
                bool result = TryKeyStringToDecimal(text, out decimalValue); 
                targetValue = decimalValue;
                return result; 
            } 
            else if (targetType == typeof(Guid))
            { 
                Guid guidValue;
                bool result = TryKeyStringToGuid(text, out guidValue);
                targetValue = guidValue;
                return result; 
            }
            else if (targetType == typeof(DateTime)) 
            { 
                DateTime dateTimeValue;
                bool result = TryKeyStringToDateTime(text, out dateTimeValue); 
                targetValue = dateTimeValue;
                return result;
            }
            else if (targetType == typeof(Int64)) 
            {
                Int64 intValue; 
                bool result = TryKeyStringToInt64(text, out intValue); 
                targetValue = intValue;
                return result; 
            }
            else if (targetType == typeof(Single))
            {
                Single singleValue; 
                bool result = TryKeyStringToSingle(text, out singleValue);
                targetValue = singleValue; 
                return result; 
            }
 
            bool quoted = WebConvert.IsKeyTypeQuoted(targetType);
            if (quoted != WebConvert.IsKeyValueQuoted(text))
            {
                targetValue = null; 
                return false;
            } 
 
            if (quoted)
            { 
                Debug.Assert(IsKeyValueQuoted(text), "IsKeyValueQuoted(text) - otherwise caller didn't check this before");
                text = RemoveQuotes(text);
            }
 
            try
            { 
                if (typeof(String) == targetType) 
                {
                    targetValue = text; 
                }
                else if (typeof(Boolean) == targetType)
                {
                    targetValue = XmlConvert.ToBoolean(text); 
                }
                else if (typeof(Byte) == targetType) 
                { 
                    targetValue = XmlConvert.ToByte(text);
                } 
                else if (typeof(SByte) == targetType)
                {
                    targetValue = XmlConvert.ToSByte(text);
                } 
                else if (typeof(Int16) == targetType)
                { 
                    targetValue = XmlConvert.ToInt16(text); 
                }
                else if (typeof(Int32) == targetType) 
                {
                    targetValue = XmlConvert.ToInt32(text);
                }
                else 
                {
                    Debug.Assert(typeof(System.Xml.Linq.XElement) == targetType, "XElement == " + targetType); 
                    targetValue = System.Xml.Linq.XElement.Parse(text, System.Xml.Linq.LoadOptions.PreserveWhitespace); 
                }
 
                return true;
            }
            catch (FormatException)
            { 
                targetValue = null;
                return false; 
            } 
        }
 
        /// 
        /// Tries to remove a literal  from the specified .
        /// 
        /// Prefix to remove; one-letter prefixes are case-sensitive, others insensitive. 
        /// Text to attempt to remove prefix from.
        /// true if the prefix was found and removed; false otherwise. 
        private static bool TryRemoveLiteralPrefix(string prefix, ref string text) 
        {
            Debug.Assert(prefix != null, "prefix != null"); 
            StringComparison sc = (prefix.Length == 1) ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
            if (text.StartsWith(prefix, sc))
            {
                text = text.Remove(0, prefix.Length); 
                return true;
            } 
            else 
            {
                return false; 
            }
        }
#endif
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK