/// <summary> /// Creates new instance of verbose formatter which can be applied to format multi-lined string without any decorations. /// This format is applicable to objets of medium complexity. Indentation is performed using multiple whitespace characters. /// </summary> /// <returns> /// New instance of verbose formatter which can be used to format multi-lined strings /// in which indentation is performed using whitespace characters. /// </returns> public static VerboseFormatInfoBase CreateMultiLinedFormatter() { var vfi = new VerboseFormatInfo(); vfi.FieldDelimiter = Environment.NewLine; vfi.IsMultiLinedFormat = true; vfi.IndentationString = vfi.RightMostIndentationString = vfi.LastIndentationString = vfi.LastRightMostIndentationString = " "; vfi.MaximumFormattedLength = DefaultMaxFormattedLength; return(vfi); }
/// <summary> /// Copy constructor. Used to copy common property values from another formatter of the same type, /// which results in creating output string which is formatted in the same way. /// </summary> /// <param name="other">Instance from which contents is copied to new instance of this class.</param> public VerboseFormatInfo(VerboseFormatInfo other) : base(other) { }
/// <summary> /// Converts the value of a specified object to an equivalent string representation using /// specified format and culture-specific formatting information. /// </summary> /// <param name="sb">String builder to which formatted string should be appended.</param> /// <param name="format">A format string containing formatting specifications.</param> /// <param name="arg">An object to format.</param> /// <param name="formatProvider">An object that supplies format information about the current instance.</param> /// <param name="maxLength"> /// Maximum number of characters allowed to the formatter. Formatting should fail (and return false) /// if this number of characters is breached. Multi-lined formatters should ignore this parameter. /// Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available. /// </param> /// <returns> /// true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" /> /// within given number of allowed characters; otherwise false. /// </returns> internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength) { var success = true; var originalLength = sb.Length; if (PushCurrentObject(arg)) { if (ShowDataType && !_showValuesOnly) { success = success && AppendInstanceTypeName(arg, sb, ref maxLength); } if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName) && !_showValuesOnly) { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength); } if (!_showValuesOnly) { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength); } Type enumeratedType = null; var enumerator = GetEnumerator(arg, ref enumeratedType); var itemFormatter = new VerboseFormatInfo(this); var value = new object[2]; var valueFetched = new bool[2]; valueFetched[0] = GetNextValue(enumerator, ref value[0]); if (valueFetched[0]) { valueFetched[1] = GetNextValue(enumerator, ref value[1]); } var itemPos = 0; while (valueFetched[0]) { IncIndentationLevel(valueFetched[1]); itemFormatter.IncIndentationLevel(valueFetched[1]); var valueName = string.Format("Item[{0}]", itemPos++); itemFormatter.InstanceDataType = enumeratedType; itemFormatter.InstanceName = valueName; success = success && FormatLinePrefix(sb, itemPos == 0, !valueFetched[1], false, 0, ref maxLength); success = success && itemFormatter.Format(sb, null, value[0], itemFormatter, ref maxLength); valueFetched[0] = valueFetched[1]; value[0] = value[1]; valueFetched[1] = GetNextValue(enumerator, ref value[1]); itemFormatter.DecIndentationLevel(); DecIndentationLevel(); } if (!_showValuesOnly) { success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength); } PopCurrentObject(); } else { success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength); } if (!success) { sb.Length = originalLength; } return(success); }
/// <summary> /// Converts the value of a specified object to an equivalent string representation using /// specified format and culture-specific formatting information. /// </summary> /// <param name="sb">String builder to which formatted string should be appended.</param> /// <param name="format">A format string containing formatting specifications.</param> /// <param name="arg">An object to format.</param> /// <param name="formatProvider">An object that supplies format information about the current instance.</param> /// <param name="maxLength"> /// Maximum number of characters allowed to the formatter. Formatting should fail (and return false) /// if this number of characters is breached. Multi-lined formatters should ignore this parameter. /// Negative value indicates that formatter has unlimited space available. On output contains remaining number of characters available. /// </param> /// <returns> /// true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" /> /// within given number of allowed characters; otherwise false. /// </returns> internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength) { var success = true; var originalLength = sb.Length; if (PushCurrentObject(arg)) { if (arg == null) { success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength); } else { var keys = GetKeysCollection(arg); var keyType = GetDeclaredKeyValueType(arg, true); var valueType = GetDeclaredKeyValueType(arg, false); var sfi = new ScalarFormatInfo(this); success = success && sfi.AppendInstanceTypeName(arg, sb, ref maxLength); // Using scalar format info to append type name ensures that scalar types will be // represented with their short forms rather than CTS names which are less readable if (!string.IsNullOrEmpty(InstanceName)) { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength); } if (IsMultiLinedFormat) { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, "= ", success, ref maxLength); } else { success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength); } success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength); if (MaximumDepth > 0) { MaximumDepth--; var enumerator = keys.GetEnumerator(); var isFirstValue = true; var key = new object[2]; var keyFetched = new bool[2]; keyFetched[0] = enumerator.MoveNext(); if (keyFetched[0]) { key[0] = enumerator.Current; keyFetched[1] = enumerator.MoveNext(); if (keyFetched[1]) { key[1] = enumerator.Current; } } VerboseFormatInfoBase containedItemsFormat = new VerboseFormatInfo(this); var itemPos = 0; while (keyFetched[0]) { IncIndentationLevel(keyFetched[1]); containedItemsFormat.IncIndentationLevel(keyFetched[1]); success = success && FormatLinePrefix(sb, isFirstValue, !keyFetched[1], false, 0, ref maxLength); isFirstValue = false; success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, itemPos.ToString("0"), success, ref maxLength); itemPos++; success = FormatInfoUtils.TryAppendString(this, sb, "] = ", success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength); containedItemsFormat.IncIndentationLevel(true); IncIndentationLevel(true); success = success && FormatLinePrefix(sb, true, false, false, 0, ref maxLength); containedItemsFormat.InstanceDataType = keyType; containedItemsFormat.InstanceName = "Key"; success = success && containedItemsFormat.Format(sb, null, key[0], containedItemsFormat, ref maxLength); DecIndentationLevel(); containedItemsFormat.DecIndentationLevel(); containedItemsFormat.IncIndentationLevel(false); IncIndentationLevel(false); var value = GetValue(arg, key[0]); success = success && FormatLinePrefix(sb, false, true, false, 0, ref maxLength); containedItemsFormat.InstanceDataType = valueType; containedItemsFormat.InstanceName = "Value"; success = success && containedItemsFormat.Format(sb, null, value, containedItemsFormat, ref maxLength); DecIndentationLevel(); containedItemsFormat.DecIndentationLevel(); success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength); key[0] = key[1]; keyFetched[0] = keyFetched[1]; if (keyFetched[0]) { keyFetched[1] = enumerator.MoveNext(); if (keyFetched[1]) { key[1] = enumerator.Current; } } containedItemsFormat.DecIndentationLevel(); DecIndentationLevel(); } MaximumDepth++; } // if (MaximumDepth > 0) success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength); } PopCurrentObject(); } else { success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength); } if (!success) { sb.Length = originalLength; } return(success); }
/// <summary> /// Appends formatted string representing part of the array provided, starting from specific location within the array. /// </summary> /// <param name="sb">String builder to which formatted string will be appended.</param> /// <param name="arg">Array which should be formatted into string which is appended to <paramref name="sb" />.</param> /// <param name="indices"> /// List of index values for dimensions iterated this far. In every call, this method will continue /// from location within the array indicated by this parameter. /// </param> /// <param name="maxLength"> /// Maximum number of characters allowed to the formatter. /// Single-lined formatting will fail (and return false) if this number of characters is breached. /// Multi-lined formatters ignore this parameter. Negative value indicates /// that formatter has unlimited space available. On output contains remaining number of characters available. /// </param> /// <returns> /// true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" /> /// within given number of allowed characters; otherwise false. /// </returns> private bool RecursiveAppendDimension(StringBuilder sb, Array arg, List <int> indices, ref int maxLength) { var success = true; var originalLength = sb.Length; var dimension = arg.GetLength(indices.Count); if (dimension > 0) { for (var i = 0; i < dimension; i++) { indices.Add(i); IncIndentationLevel(i < dimension - 1); success = success && FormatLinePrefix(sb, true, i == dimension - 1, false, 0, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, "Item[", success, ref maxLength); var firstIndex = true; foreach (var index in indices) { if (!firstIndex) { success = FormatInfoUtils.TryAppendString(this, sb, ", ", success, ref maxLength); } firstIndex = false; success = FormatInfoUtils.TryAppendString(this, sb, index.ToString("0"), success, ref maxLength); } success = FormatInfoUtils.TryAppendString(this, sb, "] ", success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength); if (indices.Count < arg.Rank) { success = success && RecursiveAppendDimension(sb, arg, indices, ref maxLength); } else { var value = arg.GetValue(indices.ToArray()); var vfi = new VerboseFormatInfo(this); vfi.MaximumFormattedLength = FormatInfoUtils.CombineMaxFormattedLengths( RawMaximumFormattedLength, FormatInfoUtils.DefaultMaxFormattedLength); success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength); success = success && vfi.Format(sb, null, value, vfi, ref maxLength); } success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength); DecIndentationLevel(); indices.RemoveAt(indices.Count - 1); } } if (!success) { sb.Length = originalLength; } return(success); }
/// <summary> /// Converts the value of a specified object to an equivalent string representation using /// specified format and culture-specific formatting information. /// </summary> /// <param name="sb">String builder to which formatted string will be appended.</param> /// <param name="format">Format string containing formatting specifications.</param> /// <param name="arg">An object to format.</param> /// <param name="formatProvider">An object that supplies format information about the current instance.</param> /// <param name="maxLength"> /// Maximum number of characters allowed to the formatter. Formatting will fail (and return false) /// if this number of characters is breached. Multi-lined formatters will ignore this parameter. /// Negative value indicates that formatter has unlimited space available. /// On output contains remaining number of characters available. /// </param> /// <returns> /// true if representation of <paramref name="arg" /> has been successfully appended to <paramref name="sb" /> /// within given number of allowed characters; otherwise false. /// </returns> internal override bool Format(StringBuilder sb, string format, object arg, IFormatProvider formatProvider, ref int maxLength) { var success = true; var originalLength = sb.Length; if (PushCurrentObject(arg)) { if (ShowDataType) { success = success && AppendInstanceTypeName(arg, sb, ref maxLength); } if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName)) { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength); if (IsMultiLinedFormat) { success = FormatInfoUtils.TryAppendString(this, sb, " = ", success, ref maxLength); } else { success = FormatInfoUtils.TryAppendChar(this, sb, '=', success, ref maxLength); } } else { success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength); } if (arg == null) { success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength); } else { success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength); if (MaximumDepth > 0) { MaximumDepth--; var members = ExtractMembers(arg); var vfi = new VerboseFormatInfo(this); vfi.ShowDataType = true; vfi.ShowInstanceName = true; for (var i = 0; success && i < members.Length; i++) { IncIndentationLevel(i < members.Length - 1); vfi.IncIndentationLevel(i < members.Length - 1); success = success && FormatLinePrefix(sb, i == 0, i == members.Length - 1, false, 0, ref maxLength); vfi.InstanceDataType = members[i].DataType; vfi.InstanceName = members[i].Name; success = success && vfi.Format(sb, format, members[i].Value, vfi, ref maxLength); vfi.DecIndentationLevel(); DecIndentationLevel(); } MaximumDepth++; } success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength); } PopCurrentObject(); } else { success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength); } if (!success) { sb.Length = originalLength; } return(success); }