Beispiel #1
0
        /// <summary>
        /// Returns a C# string literal with the given value.
        /// </summary>
        /// <param name="value">The value that the resulting string literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A string literal with the given value.</returns>
        /// <remarks>
        /// Escapes non-printable characters.
        /// </remarks>
        public static string FormatLiteral(string value, ObjectDisplayOptions options)
        {
            ValidateOptions(options);

            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
            var quote     = useQuotes ? '"' : '\0';

            if (!useQuotes && !ReplaceAny(value, quote))
            {
                return(value);
            }

            var pooledBuilder = PooledStringBuilder.GetInstance();
            var builder       = pooledBuilder.Builder;

            if (useQuotes)
            {
                builder.Append(quote);
            }
            foreach (var c in value)
            {
                FormatStringChar(builder, c, quote);
            }
            if (useQuotes)
            {
                builder.Append(quote);
            }
            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #2
0
        /// <summary>
        /// Contains a list of buckets, each of which contains a number of flags, a slot ID, and a name.
        /// TODO: comment when the structure is understood.
        /// </summary>
        /// <remarks>
        /// Appears when there are dynamic locals.
        /// </remarks>
        private void WriteDynamicLocalsCustomDebugInfo(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.DynamicLocals);

            writer.WriteStartElement("dynamicLocals");

            var buckets = CDI.DecodeDynamicLocalsRecord(record.Data);

            foreach (DynamicLocalBucket bucket in buckets)
            {
                ulong flags     = bucket.Flags;
                int   flagCount = bucket.FlagCount;

                PooledStringBuilder pooled       = PooledStringBuilder.GetInstance();
                StringBuilder       flagsBuilder = pooled.Builder;
                for (int f = 0; f < flagCount; f++)
                {
                    flagsBuilder.Append((flags >> f) & 1UL);
                }

                writer.WriteStartElement("bucket");
                writer.WriteAttributeString("flagCount", flagCount.ToString());
                writer.WriteAttributeString("flags", pooled.ToStringAndFree());
                writer.WriteAttributeString("slotId", bucket.SlotId.ToString());
                writer.WriteAttributeString("localName", bucket.Name);
                writer.WriteEndElement(); //bucket
            }

            writer.WriteEndElement(); //dynamicLocals
        }
        /// <summary>
        /// Returns a C# string literal with the given value.
        /// </summary>
        /// <param name="value">The value that the resulting string literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A string literal with the given value.</returns>
        /// <remarks>
        /// Escapes non-printable characters.
        /// </remarks>
        public static string FormatLiteral(string value, ObjectDisplayOptions options)
        {
            ValidateOptions(options);

            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            var useQuotes = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
            var quote     = useQuotes ? '"' : '\0';
            PooledStringBuilder pooledBuilder = null;
            StringBuilder       builder       = null;

            if (useQuotes)
            {
                pooledBuilder = PooledStringBuilder.GetInstance();
                builder       = pooledBuilder.Builder;
                builder.Append(quote);
            }
            for (int i = 0; i < value.Length; i++)
            {
                FormatStringChar(ref pooledBuilder, value, i, value[i], quote, useLanguageSpecificEscapes: true, useUnicodeEscapes: true);
            }
            if (useQuotes)
            {
                builder.Append(quote);
            }
            return((pooledBuilder == null) ? value : pooledBuilder.ToStringAndFree());
        }
Beispiel #4
0
        /// <summary>
        /// Returns a C# string literal with the given value.
        /// </summary>
        /// <param name="value">The value that the resulting string literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A string literal with the given value.</returns>
        /// <remarks>
        /// Optionally escapes non-printable characters.
        /// </remarks>
        public static string FormatLiteral(string value, ObjectDisplayOptions options)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            const char quote = '"';

            var pooledBuilder = PooledStringBuilder.GetInstance();
            var builder       = pooledBuilder.Builder;

            var useQuotes          = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
            var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters);

            var isVerbatim = useQuotes && !escapeNonPrintable && ContainsNewLine(value);

            if (useQuotes)
            {
                if (isVerbatim)
                {
                    builder.Append('@');
                }
                builder.Append(quote);
            }

            foreach (var c in value)
            {
                string replaceWith;
                if (escapeNonPrintable && TryReplaceChar(c, out replaceWith))
                {
                    builder.Append(replaceWith);
                }
                else if (useQuotes && c == quote)
                {
                    if (isVerbatim)
                    {
                        builder.Append(quote);
                        builder.Append(quote);
                    }
                    else
                    {
                        builder.Append('\\');
                        builder.Append(quote);
                    }
                }
                else
                {
                    builder.Append(c);
                }
            }

            if (useQuotes)
            {
                builder.Append(quote);
            }

            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #5
0
        internal static string ToHexString(byte[] input)
        {
            PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
            StringBuilder       sb     = pooled.Builder;

            foreach (byte b in input)
            {
                sb.AppendFormat("{0:X2}", b);
            }
            return(pooled.ToStringAndFree());
        }
Beispiel #6
0
        /// <summary>
        /// If the custom debug info is in a format that we don't understand, then we will
        /// just print a standard record header followed by the rest of the record as a
        /// single hex string.
        /// </summary>
        private void WriteUnknownCustomDebugInfo(CustomDebugInfoRecord record)
        {
            writer.WriteStartElement("unknown");
            writer.WriteAttributeString("kind", record.Kind.ToString());
            writer.WriteAttributeString("version", record.Version.ToString());

            PooledStringBuilder pooled  = PooledStringBuilder.GetInstance();
            StringBuilder       builder = pooled.Builder;

            foreach (byte b in record.Data)
            {
                builder.AppendFormat("{0:X2}", b);
            }

            writer.WriteAttributeString("payload", pooled.ToStringAndFree());

            writer.WriteEndElement(); //unknown
        }
Beispiel #7
0
        /// <summary>
        /// Returns a C# character literal with the given value.
        /// </summary>
        /// <param name="c">The value that the resulting character literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A character literal with the given value.</returns>
        internal static string FormatLiteral(char c, ObjectDisplayOptions options)
        {
            const char quote = '\'';

            var pooledBuilder = PooledStringBuilder.GetInstance();
            var builder       = pooledBuilder.Builder;

            if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints))
            {
                builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString());
                builder.Append(" ");
            }

            var useQuotes          = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
            var escapeNonPrintable = options.IncludesOption(ObjectDisplayOptions.EscapeNonPrintableCharacters);

            if (useQuotes)
            {
                builder.Append(quote);
            }

            string replaceWith;

            if (escapeNonPrintable && TryReplaceChar(c, out replaceWith))
            {
                builder.Append(replaceWith);
            }
            else if (useQuotes && c == quote)
            {
                builder.Append('\\');
                builder.Append(quote);
            }
            else
            {
                builder.Append(c);
            }

            if (useQuotes)
            {
                builder.Append(quote);
            }

            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #8
0
        internal static string FormatString(string str, bool useQuotes)
        {
            if (!useQuotes)
            {
                return(str);
            }

            var        pooledBuilder = PooledStringBuilder.GetInstance();
            var        builder       = pooledBuilder.Builder;
            const char quote         = '"';

            builder.Append(quote);
            foreach (var c in str)
            {
                FormatStringChar(builder, c, quote);
            }
            builder.Append(quote);
            return(pooledBuilder.ToStringAndFree());
        }
        internal static string FormatString(string str, bool useQuotes)
        {
            if (!useQuotes)
            {
                return(str);
            }

            var        pooledBuilder = PooledStringBuilder.GetInstance();
            var        builder       = pooledBuilder.Builder;
            const char quote         = '"';

            builder.Append(quote);
            for (int i = 0; i < str.Length; i++)
            {
                FormatStringChar(ref pooledBuilder, str, i, str[i], quote, useLanguageSpecificEscapes: useQuotes, useUnicodeEscapes: false);
            }
            builder.Append(quote);
            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #10
0
        internal static string FormatLiteral(ulong value, ObjectDisplayOptions options, CultureInfo cultureInfo = null)
        {
            var pooledBuilder = PooledStringBuilder.GetInstance();
            var sb            = pooledBuilder.Builder;

            if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers))
            {
                sb.Append("0x");
                sb.Append(value.ToString("x16"));
            }
            else
            {
                sb.Append(value.ToString(GetFormatCulture(cultureInfo)));
            }

            if (options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix))
            {
                sb.Append("UL");
            }

            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #11
0
        internal static string FormatLiteral(uint value, ObjectDisplayOptions options)
        {
            var pooledBuilder = PooledStringBuilder.GetInstance();
            var sb            = pooledBuilder.Builder;

            if (options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers))
            {
                sb.Append("0x");
                sb.Append(value.ToString("x8"));
            }
            else
            {
                sb.Append(value.ToString(CultureInfo.InvariantCulture));
            }

            if (options.IncludesOption(ObjectDisplayOptions.IncludeTypeSuffix))
            {
                sb.Append('U');
            }

            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #12
0
        /// <summary>
        /// Returns a C# character literal with the given value.
        /// </summary>
        /// <param name="c">The value that the resulting character literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A character literal with the given value.</returns>
        internal static string FormatLiteral(char c, ObjectDisplayOptions options)
        {
            var pooledBuilder = PooledStringBuilder.GetInstance();
            var builder       = pooledBuilder.Builder;

            if (options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints))
            {
                builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString());
                builder.Append(" ");
            }
            if (options.IncludesOption(ObjectDisplayOptions.UseQuotes))
            {
                const char quote = '\'';
                builder.Append(quote);
                FormatStringChar(builder, c, quote);
                builder.Append(quote);
            }
            else
            {
                builder.Append(c);
            }
            return(pooledBuilder.ToStringAndFree());
        }
        /// <summary>
        /// Returns a C# character literal with the given value.
        /// </summary>
        /// <param name="c">The value that the resulting character literal should have.</param>
        /// <param name="options">Options used to customize formatting of an object value.</param>
        /// <returns>A character literal with the given value.</returns>
        internal static string FormatLiteral(char c, ObjectDisplayOptions options)
        {
            var useQuotes         = options.IncludesOption(ObjectDisplayOptions.UseQuotes);
            var quote             = useQuotes ? '\'' : '\0';
            var includeCodePoints = options.IncludesOption(ObjectDisplayOptions.IncludeCodePoints);
            var pooledBuilder     = PooledStringBuilder.GetInstance();
            var builder           = pooledBuilder.Builder;

            if (includeCodePoints)
            {
                builder.Append(options.IncludesOption(ObjectDisplayOptions.UseHexadecimalNumbers) ? "0x" + ((int)c).ToString("x4") : ((int)c).ToString());
                builder.Append(" ");
            }
            if (useQuotes)
            {
                builder.Append(quote);
            }
            FormatStringChar(ref pooledBuilder, str: null, index: 0, c: c, quote: quote, useLanguageSpecificEscapes: useQuotes, useUnicodeEscapes: !includeCodePoints);
            if (useQuotes)
            {
                builder.Append(quote);
            }
            return(pooledBuilder.ToStringAndFree());
        }
Beispiel #14
0
        private void WriteLocalsHelper(ISymUnmanagedScope scope, Dictionary <int, ImmutableArray <string> > slotNames, bool includeChildScopes)
        {
            foreach (ISymUnmanagedVariable l in scope.GetLocals())
            {
                writer.WriteStartElement("local");
                {
                    writer.WriteAttributeString("name", l.GetName());

                    // Each local maps to a "IL Index" or "slot" number.
                    // The index is not necessarily unique. Several locals may refer to the same slot.
                    // It just means that the same local is known under different names inside the same or different scopes.
                    // This index is what you pass to ICorDebugILFrame::GetLocalVariable() to get
                    // a specific local variable.
                    // NOTE: VB emits "fake" locals for resumable locals which are actually backed by fields.
                    //       These locals always map to the slot #0 which is just a valid number that is
                    //       not used. Only scoping information is used by EE in this case.
                    int slot = l.GetSlot();
                    writer.WriteAttributeString("il_index", CultureInvariantToString(slot));

                    bool reusingSlot = false;

                    // collect slot names so that we can verify ISymUnmanagedReader APIs
                    if (slotNames != null)
                    {
                        ImmutableArray <string> existingNames;
                        if (slotNames.TryGetValue(slot, out existingNames))
                        {
                            slotNames[slot] = existingNames.Add(l.GetName());
                            reusingSlot     = true;
                        }
                        else
                        {
                            slotNames.Add(slot, ImmutableArray.Create(l.GetName()));
                        }
                    }

                    // Provide scope range
                    writer.WriteAttributeString("il_start", AsILOffset(scope.GetStartOffset()));
                    writer.WriteAttributeString("il_end", AsILOffset(scope.GetEndOffset()));
                    writer.WriteAttributeString("attributes", l.GetAttributes().ToString());

                    if (reusingSlot)
                    {
                        writer.WriteAttributeString("reusingslot", reusingSlot.ToString(CultureInfo.InvariantCulture));
                    }
                }
                writer.WriteEndElement(); // </local>
            }

            foreach (ISymUnmanagedConstant c in scope.GetConstants())
            {
                // Note: We can retrieve constant tokens by saving it into signature blob
                // in our implementation of IMetadataImport.GetSigFromToken.
                writer.WriteStartElement("constant");
                {
                    writer.WriteAttributeString("name", c.GetName());

                    object value    = c.GetValue();
                    string typeName = value.GetType().Name;

                    // certain Unicode characters will give Xml writers fits...in order to avoid this, we'll replace
                    // problematic characters/sequences with their hexadecimal equivalents, like U+0000, etc...
                    var chars = value as string;
                    if (chars != null)
                    {
                        PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
                        var valueWithPlaceholders  = pooled.Builder;
                        foreach (var ch in chars)
                        {
                            // if we end up with more, we can add them here
                            if (0 == (int)ch)
                            {
                                valueWithPlaceholders.AppendFormat("U+{0:X4}", (int)ch);
                            }
                            else
                            {
                                valueWithPlaceholders.Append(ch);
                            }
                        }
                        if (valueWithPlaceholders.Length > chars.Length)
                        {
                            value = valueWithPlaceholders.ToString();
                        }
                        pooled.Free();
                    }

                    writer.WriteAttributeString("value", value.ToString());
                    writer.WriteAttributeString("type", typeName);
                }
                writer.WriteEndElement(); // </constant>
            }

            if (includeChildScopes)
            {
                foreach (ISymUnmanagedScope childScope in scope.GetScopes())
                {
                    WriteLocalsHelper(childScope, slotNames, includeChildScopes);
                }
            }
        }
Beispiel #15
0
        internal static string FormatString(string str, char quote, bool escapeNonPrintable)
        {
            PooledStringBuilder pooledBuilder = null;
            StringBuilder       sb            = null;
            int lastEscape = -1;

            for (int i = 0; i < str.Length; i++)
            {
                char c             = str[i];
                char replaceWith   = '\0';
                bool unicodeEscape = false;
                switch (c)
                {
                case '\\':
                    replaceWith = c;
                    break;

                case '\0':
                    replaceWith = '0';
                    break;

                case '\r':
                    replaceWith = 'r';
                    break;

                case '\n':
                    replaceWith = 'n';
                    break;

                case '\t':
                    replaceWith = 't';
                    break;

                case '\b':
                    replaceWith = 'b';
                    break;

                case '\v':
                    replaceWith = 'v';
                    break;

                default:
                    if (quote == c)
                    {
                        replaceWith = c;
                        break;
                    }

                    if (escapeNonPrintable)
                    {
                        switch (CharUnicodeInfo.GetUnicodeCategory(c))
                        {
                        case UnicodeCategory.OtherNotAssigned:
                        case UnicodeCategory.ParagraphSeparator:
                        case UnicodeCategory.Control:
                            unicodeEscape = true;
                            break;
                        }
                    }

                    break;
                }

                if (unicodeEscape || replaceWith != '\0')
                {
                    if (pooledBuilder == null)
                    {
                        pooledBuilder = PooledStringBuilder.GetInstance();
                        sb            = pooledBuilder.Builder;
                        if (quote != 0)
                        {
                            sb.Append(quote);
                        }
                    }

                    sb.Append(str, lastEscape + 1, i - (lastEscape + 1));
                    sb.Append('\\');
                    if (unicodeEscape)
                    {
                        sb.Append('u');
                        sb.Append(((int)c).ToString("x4"));
                    }
                    else
                    {
                        sb.Append(replaceWith);
                    }

                    lastEscape = i;
                }
            }

            if (sb != null)
            {
                sb.Append(str, lastEscape + 1, str.Length - (lastEscape + 1));
                if (quote != 0)
                {
                    sb.Append(quote);
                }

                return(pooledBuilder.ToStringAndFree());
            }

            switch (quote)
            {
            case '"': return(String.Concat("\"", str, "\""));

            case '\'': return(String.Concat("'", str, "'"));

            case '\0': return(str);
            }

            throw ExceptionUtilities.Unreachable;
        }
        private static void FormatStringChar(
            ref PooledStringBuilder pooledBuilder,
            string str,
            int index,
            char c,
            char quote,
            bool useLanguageSpecificEscapes,
            bool useUnicodeEscapes)
        {
            Debug.Assert(quote == '\0' || quote == '"' || quote == '\'');

            string replaceWith = null;

            if (useLanguageSpecificEscapes)
            {
                switch (c)
                {
                case '\\':
                    replaceWith = "\\\\";
                    break;

                case '"':
                    if (quote == c)
                    {
                        replaceWith = "\\\"";
                    }
                    break;

                case '\'':
                    if (quote == c)
                    {
                        replaceWith = "\\'";
                    }
                    break;

                case '\0':
                    replaceWith = "\\0";
                    break;

                case '\a':
                    replaceWith = "\\a";
                    break;

                case '\b':
                    replaceWith = "\\b";
                    break;

                case '\f':
                    replaceWith = "\\f";
                    break;

                case '\n':
                    replaceWith = "\\n";
                    break;

                case '\r':
                    replaceWith = "\\r";
                    break;

                case '\t':
                    replaceWith = "\\t";
                    break;

                case '\v':
                    replaceWith = "\\v";
                    break;
                }
            }

            bool unicodeEscape = false;

            if ((replaceWith == null) && useUnicodeEscapes)
            {
                switch (CharUnicodeInfo.GetUnicodeCategory(c))
                {
                case UnicodeCategory.Control:
                case UnicodeCategory.OtherNotAssigned:
                case UnicodeCategory.ParagraphSeparator:
                    unicodeEscape = true;
                    break;
                }
            }

            if ((replaceWith != null) || unicodeEscape)
            {
                if (pooledBuilder == null)
                {
                    pooledBuilder = PooledStringBuilder.GetInstance();
                    if (index > 0)
                    {
                        pooledBuilder.Builder.Append(str, 0, index);
                    }
                }
                var builder = pooledBuilder.Builder;
                if (replaceWith != null)
                {
                    builder.Append(replaceWith);
                }
                else
                {
                    builder.Append("\\u");
                    builder.Append(((int)c).ToString("x4"));
                }
            }
            else if (pooledBuilder != null)
            {
                var builder = pooledBuilder.Builder;
                builder.Append(c);
            }
        }