/// <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()); }
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()); }
/// <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 }
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; }