Provides formatting services for scalar data types and for strings. These types include numeric types, Boolean, characters, date time, enumerations and strings. VerboseFormatInfo delegates calls to this class when one of the listed types is formatted. This class is internal and cannot be used directly.
Inheritance: VerboseFormatInfoBase
Example #1
0
        /// <summary>
        ///     Iterates through all values in the matrix or jagged array and finds maximum length required
        ///     to show any of the values contained.
        /// </summary>
        /// <param name="array">Matrix or jagged array through which this method will iterate.</param>
        /// <returns>Number of characters sufficient to receive any formatted value contained in <paramref name="array" />.</returns>
        private int GetMaxValueLength(Array array)
        {
            var maxLength = 0;

            if (IsMultiLinedFormat)
            {
                var sfi = new ScalarFormatInfo(this);
                sfi.ShowDataType     = false;
                sfi.ShowInstanceName = false;

                if (array.Rank == 2)
                {
                    maxLength = sfi.GetMaxValueLength(array.GetEnumerator());
                }
                else
                {
                    // In jagged array we have to iterate through rows manually

                    var rowsEnumerator = array.GetEnumerator();
                    while (rowsEnumerator.MoveNext())
                    {
                        var row          = (Array)rowsEnumerator.Current;
                        var curMaxLength = sfi.GetMaxValueLength(row.GetEnumerator());
                        maxLength = Math.Max(maxLength, curMaxLength);
                    }
                }
            }

            return(maxLength);
        }
		/// <summary>
		///     Iterates through all values in the matrix or jagged array and finds maximum length required
		///     to show any of the values contained.
		/// </summary>
		/// <param name="array">Matrix or jagged array through which this method will iterate.</param>
		/// <returns>Number of characters sufficient to receive any formatted value contained in <paramref name="array" />.</returns>
		private int GetMaxValueLength(Array array)
		{
			var maxLength = 0;

			if (IsMultiLinedFormat)
			{
				var sfi = new ScalarFormatInfo(this);
				sfi.ShowDataType = false;
				sfi.ShowInstanceName = false;

				if (array.Rank == 2)
				{
					maxLength = sfi.GetMaxValueLength(array.GetEnumerator());
				}
				else
				{
					// In jagged array we have to iterate through rows manually

					var rowsEnumerator = array.GetEnumerator();
					while (rowsEnumerator.MoveNext())
					{
						var row = (Array) rowsEnumerator.Current;
						var curMaxLength = sfi.GetMaxValueLength(row.GetEnumerator());
						maxLength = Math.Max(maxLength, curMaxLength);
					}
				}
			}

			return maxLength;
		}
        /// <summary>
        ///     Formats user friendly representation of the name of the given type.
        /// </summary>
        /// <param name="type">Type for which user friendly representation of the name is required.</param>
        /// <param name="instance">
        ///     Instance for which friendly type name is appended.
        ///     This argument is used to gather additional information which might not be available from the type information.
        ///     This argument may be null if instance is not available.
        /// </param>
        /// <param name="sb">
        ///     String builder to which user friendly representation of the name of <paramref name="type" /> is appended.
        ///     If <paramref name="type" /> is null then nothing is appended to this string builder.
        /// </param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to this method to append to string builder. Negative value indicates
        ///     unlimited number of characters allowed. Method fails and returns false if it could not perform the task within given number of
        ///     characters.
        ///     On output contains remaining number of characters allowed.
        /// </param>
        /// <returns>
        ///     true if method has successfully appended friendly name of the data type within given number of characters allowed; otherwise
        ///     false.
        /// </returns>
        internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (type.IsArray && type.GetArrayRank() == 1)
            {
                // This

                var elementType = type.GetElementType();

                var sfi = new ScalarFormatInfo(this);
                success = success && sfi.AppendFriendlyTypeName(elementType, null, sb, ref maxLength);                 // This will append compact name for scalar types

                var ar        = (Array)instance;
                var dimension = string.Format("[{0}]", ar.GetLength(0));
                success = FormatInfoUtils.TryAppendString(this, sb, dimension, success, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
        /// <summary>
        ///     Iterates through values that will be formatted in order to determine whether
        ///     field length should be set to some specific value in order to align values better.
        /// </summary>
        /// <param name="sb">
        ///     String builder which can be conveniently used to format value.
        ///     This function will return the string builder into present state on output.
        /// </param>
        private void UpdateFieldLength(StringBuilder sb)
        {
            if (IsMultiLinedFormat && _fieldLength <= 0 && _maxLineLength > 0)
            {
                // Field length will be updated only in multi-lined formats and only if not already set to positive value from outside.

                var maxLength   = 0;
                var totalLength = 0;

                var enumerator = GetEnumerator();
                var sfi        = new ScalarFormatInfo(this);
                sfi.FieldLength      = 0;
                sfi.ShowDataType     = false;
                sfi.ShowInstanceName = false;

                var isFirstField = true;

                while (enumerator.MoveNext())
                {
                    var fieldLength = sfi.GetValueLength(enumerator.Current, sb);

                    maxLength    = Math.Max(maxLength, fieldLength);
                    totalLength += (!isFirstField ? 1 : 0) + fieldLength;                     // Each but the first value is prefixed with a white space of length 1
                    isFirstField = false;
                }

                if (totalLength > _maxLineLength)
                {
                    _fieldLength = maxLength;                     // Field length is set only if total contents of the array will breach the maximum allowed line length
                }
                // and consequently values should be aligned
            }
        }
Example #5
0
        /// <summary>
        ///     Formats user friendly representation of the name of the given matrix or jagged array type.
        /// </summary>
        /// <param name="type">Type for which user friendly representation of the name is required.</param>
        /// <param name="instance">
        ///     Instance for which friendly type name is appended.
        ///     This argument is used to gather additional information which might not be available from the type information.
        ///     This argument may be null if instance is not available.
        /// </param>
        /// <param name="sb">
        ///     String builder to which user friendly representation of the name of <paramref name="type" /> is appended.
        ///     If <paramref name="type" /> is null then nothing is appended to this string builder.
        /// </param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to this method to append to string builder. Negative value indicates
        ///     unlimited number of characters allowed. Method fails and returns false if it could not perform the task within given number of
        ///     characters.
        ///     On output contains remaining number of characters allowed.
        /// </param>
        /// <returns>
        ///     true if method has successfully appended friendly name of the data type within given number of characters allowed; otherwise
        ///     false.
        /// </returns>
        internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (type != null)
            {
                var elementType = GetElementType(type);
                if (elementType != null)
                {
                    var sfi = new ScalarFormatInfo();
                    success = success && sfi.AppendFriendlyTypeName(elementType, null, sb, ref maxLength);
                }
            }

            var rows     = 0;
            var lowCols  = 0;
            var highCols = 0;

            if (instance != null)
            {
                GetDimensions((Array)instance, out rows, out lowCols, out highCols);
            }

            success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);
            if (instance != null)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, rows.ToString("0"), success, ref maxLength);
            }
            success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, ref maxLength);

            success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);
            if (instance != null)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, lowCols.ToString("0"), success, ref maxLength);
                if (highCols != lowCols)
                {
                    success = FormatInfoUtils.TryAppendChar(this, sb, '-', success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, highCols.ToString("0"), success, ref maxLength);
                }
            }
            success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, ref maxLength);

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
Example #6
0
        /// <summary>
        ///     Gets value indicating whether this format provider can be applied to specified data type or not.
        ///     This format provider is applicable to matrices (arrays of rank 2) and to jagged arrays, but only
        ///     if element type is supported by ScalarFormatInfo format provider.
        /// </summary>
        /// <param name="dataType">Data type agianst which this format provider is tested.</param>
        /// <returns>true if this format provider is applicable; otherwise false.</returns>
        internal override bool IsFormatApplicable(Type dataType)
        {
            var elementType = GetElementType(dataType);

            var applicable = false;

            if (elementType != null)
            {
                // Existence of elementType proves that dataType is matrix or jagged array
                var sfi = new ScalarFormatInfo(this);
                applicable = sfi.IsFormatApplicable(elementType);
            }

            return(applicable);
        }
        /// <summary>
        ///     Formats friendly representation of the name of the given type.
        /// </summary>
        /// <param name="type">Type for which friendly representation of the name is required.</param>
        /// <param name="instance">
        ///     Instance for which friendly type name is appended.
        ///     This argument is used to gather additional information which might not be available
        ///     from the type information. This argument may be null if instance is not available.
        /// </param>
        /// <param name="sb">
        ///     String builder to which friendly name of <paramref name="type" /> is appended.
        ///     If <paramref name="type" /> is null then nothing is appended to this string builder.
        /// </param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to this method
        ///     to append to string builder. Negative value indicates unlimited number of characters allowed.
        ///     Method fails and returns false if it could not perform the task within given number
        ///     of characters. On output contains remaining number of characters allowed.
        /// </param>
        /// <returns>
        ///     true if method has successfully appended friendly name of the data type
        ///     within given number of characters allowed; otherwise false.
        /// </returns>
        internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (type != null)
            {
                type = type.GetElementType();                 // For arrays print element type rather than array type
            }

            if (success)
            {
                var sfi = new ScalarFormatInfo(this);
                success = sfi.AppendFriendlyTypeName(type, null, sb, ref maxLength);
                // Use scalar format info because it can write simple data types in a more compact way
            }

            // Now append dimensions of the array
            // If instance is null then dimensions cannot be determined and braces will remain empty, like int[].
            // Otherwise, if instance is present, dimensions will be fully shown, like int[3, 4, 2] in case of three-dimensional array.

            success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);

            if (instance != null)
            {
                var dimensions = GetDimensions(instance);
                for (var i = 0; success && i < dimensions.Length; i++)
                {
                    if (i > 0)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, ", ", success, ref maxLength);
                    }
                    success = FormatInfoUtils.TryAppendString(this, sb, dimensions[i].ToString("0"), success, ref maxLength);
                }
            }

            success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, ref maxLength);

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
        /// <summary>
        ///     Gets value indicating whether current format provider is applicable to format strings
        ///     that represent instances of given data type. This format provider is applicable if
        ///     data type is an array of values to which ScalarFormatInfo format provider is applicable.
        ///     This format provider can also be applied to last dimension of a multi-dimensional array
        ///     if specified so by the internal properties.
        /// </summary>
        /// <param name="dataType">Data type for which current format provider is tested.</param>
        /// <returns>
        ///     true if current format provider is capable to format string representing instance
        ///     of given data type; otherwise false.
        /// </returns>
        internal override bool IsFormatApplicable(Type dataType)
        {
            var applicable = false;

            if (dataType != null && dataType.IsArray)
            {
                if (_showLastDimension || dataType.GetArrayRank() == 1)
                {
                    var elementType = dataType.GetElementType();
                    var sfi         = new ScalarFormatInfo(this);

                    if (sfi.IsFormatApplicable(elementType))
                    {
                        applicable = true;
                    }
                }
            }

            return(applicable);
        }
		/// <summary>
		///     Formats user friendly representation of the name of the given matrix or jagged array type.
		/// </summary>
		/// <param name="type">Type for which user friendly representation of the name is required.</param>
		/// <param name="instance">
		///     Instance for which friendly type name is appended.
		///     This argument is used to gather additional information which might not be available from the type information.
		///     This argument may be null if instance is not available.
		/// </param>
		/// <param name="sb">
		///     String builder to which user friendly representation of the name of <paramref name="type" /> is appended.
		///     If <paramref name="type" /> is null then nothing is appended to this string builder.
		/// </param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to this method to append to string builder. Negative value indicates
		///     unlimited number of characters allowed. Method fails and returns false if it could not perform the task within given number of
		///     characters.
		///     On output contains remaining number of characters allowed.
		/// </param>
		/// <returns>
		///     true if method has successfully appended friendly name of the data type within given number of characters allowed; otherwise
		///     false.
		/// </returns>
		internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			if (type != null)
			{
				var elementType = GetElementType(type);
				if (elementType != null)
				{
					var sfi = new ScalarFormatInfo();
					success = success && sfi.AppendFriendlyTypeName(elementType, null, sb, ref maxLength);
				}
			}

			var rows = 0;
			var lowCols = 0;
			var highCols = 0;

			if (instance != null)
			{
				GetDimensions((Array) instance, out rows, out lowCols, out highCols);
			}

			success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);
			if (instance != null)
			{
				success = FormatInfoUtils.TryAppendString(this, sb, rows.ToString("0"), success, ref maxLength);
			}
			success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, ref maxLength);

			success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);
			if (instance != null)
			{
				success = FormatInfoUtils.TryAppendString(this, sb, lowCols.ToString("0"), success, ref maxLength);
				if (highCols != lowCols)
				{
					success = FormatInfoUtils.TryAppendChar(this, sb, '-', success, ref maxLength);
					success = FormatInfoUtils.TryAppendString(this, sb, highCols.ToString("0"), success, ref maxLength);
				}
			}
			success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, 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;

			var formatters = new List<VerboseFormatInfoBase>();
			var singleLinedFormat = SingleLinedFormat;

			if (arg != null || InstanceDataType != null)
			{
				var type = GetInstanceType(arg);

				var sfi = new ScalarFormatInfo(this);
				sfi.MaximumFormattedLength = maxLength;

				if (sfi.IsFormatApplicable(type))
				{
					if (IsMultiLinedFormat)
					{
						var singleLinedSfi = new ScalarFormatInfo(this);
						FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedSfi);
						singleLinedSfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
						formatters.Add(singleLinedSfi);
					}

					formatters.Add(sfi);
				}

				if (formatters.Count == 0)
				{
					var dfi = new DictionaryFormatInfo(this);
					dfi.MaximumFormattedLength = maxLength;

					if (dfi.IsFormatApplicable(type))
					{
						if (IsMultiLinedFormat)
						{
							var singleLinedDfi = new DictionaryFormatInfo(this);
							FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedDfi);
							singleLinedDfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
							formatters.Add(singleLinedDfi);
						}
						formatters.Add(dfi);
					}
				}

				if (formatters.Count == 0)
				{
					var cmfi = new CompactMatrixFormatInfo(this);
					cmfi.MaximumFormattedLength = maxLength;

					if (cmfi.IsFormatApplicable(type))
					{
						//if (IsMultiLinedFormat)   // Uncomment these lines to enable inlining compactly presented matrices; that operation is not suggested
						//{
						//    CompactMatrixFormatInfo singleLinedCmfi = new CompactMatrixFormatInfo(this);
						//    FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedCmfi);
						//    singleLinedCmfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
						//    formatters.Add(singleLinedCmfi);
						//}
						formatters.Add(cmfi);
					}
				}

				if (formatters.Count == 0)
				{
					var cafi = new CompactArrayFormatInfo(this);
					cafi.MaximumFormattedLength = maxLength;

					if (cafi.IsFormatApplicable(type))
					{
						if (IsMultiLinedFormat)
						{
							var singleLinedCafi = new CompactArrayFormatInfo(this);
							FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedCafi);
							singleLinedCafi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
							formatters.Add(singleLinedCafi);
						}
						formatters.Add(cafi);
					}
				}

				if (formatters.Count == 0)
				{
					var afi = new ArrayFormatInfo(this);
					afi.MaximumFormattedLength = maxLength;

					if (afi.IsFormatApplicable(type))
					{
						if (IsMultiLinedFormat)
						{
							var singleLinedAfi = new ArrayFormatInfo(this);
							FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedAfi);
							singleLinedAfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
							formatters.Add(singleLinedAfi);
						}
						formatters.Add(afi);
					}
				}

				if (formatters.Count == 0)
				{
					var efi = new EnumerableFormatInfo(this);
					efi.MaximumFormattedLength = maxLength;

					if (efi.IsFormatApplicable(type))
					{
						if (IsMultiLinedFormat)
						{
							var singleLinedEfi = new EnumerableFormatInfo(this);
							FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedEfi);
							singleLinedEfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
							formatters.Add(singleLinedEfi);
						}
						formatters.Add(efi);
					}
				}

				if (formatters.Count == 0)
				{
					if (IsMultiLinedFormat)
					{
						var singleLinedGfi = new GeneralFormatInfo(this);
						FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedGfi);
						singleLinedGfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
						formatters.Add(singleLinedGfi);
					}

					var gfi = new GeneralFormatInfo(this);
					gfi.MaximumFormattedLength = maxLength;

					formatters.Add(gfi);
				}
			}

			if (formatters.Count > 0)
			{
				success = success && FormatInfoUtils.BestTryFormat(sb, format, arg, formatters, ref maxLength);
			}

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}
 /// <summary>
 ///     Copy constructor which initializes new instance and copies common values from another instance of this class.
 /// </summary>
 /// <param name="other">Instance from which common values should be copied.</param>
 public ScalarFormatInfo(ScalarFormatInfo other)
     : base(other)
 {
     _fieldLength = other._fieldLength;
 }
		/// <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 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)
				{
					var instanceType = GetInstanceType(arg);
					success = success && AppendFriendlyTypeName(instanceType, arg, sb, ref maxLength);
				}

				if (sb.Length > originalLength)
				{
					success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
				}
				success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

				if (arg != null)
				{
					IncIndentationLevel(true);

					var array = (Array) arg;
					var rows = array.GetLength(0);

					var cafi = new CompactArrayFormatInfo(this);
					cafi.ShowItemsOnly = true;
					cafi.FieldLength = GetMaxValueLength(array);

					var rowNumberFormatProvider = new ScalarFormatInfo(VerboseFormatInfo.SingleLinedFormat);
					rowNumberFormatProvider.ShowDataType = false;
					rowNumberFormatProvider.ShowInstanceName = false;
					if (IsMultiLinedFormat)
					{
						rowNumberFormatProvider.FieldLength = rowNumberFormatProvider.GetValueLength(rows);
					}

					for (var i = 0; i < rows; i++)
					{
						if (i == rows - 1)
						{
							DecIndentationLevel();
							IncIndentationLevel(false); // There are no more rows in the matrix

							cafi.DecIndentationLevel();
							cafi.IncIndentationLevel(false);
						}

						success = success && FormatLinePrefix(sb, true, i == rows - 1, false, 0, ref maxLength);
						success = FormatInfoUtils.TryAppendString(this, sb, "Row ", success, ref maxLength);
						success = success && rowNumberFormatProvider.Format(sb, null, i, rowNumberFormatProvider, ref maxLength);

						success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
						success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

						// Now we should append row content, which is obtained differently in case of matrix and in case of jagged array
						if (array.Rank == 1)
						{
							// Array is jagged
							var row = (Array) array.GetValue(i);
							cafi.ShowLastDimension = false;
							success = success && cafi.Format(sb, null, row, cafi, ref maxLength);
						}
						else
						{
							// Array is a matrix
							cafi.HeadingIndices = new[] { i };
							cafi.ShowLastDimension = true;
							success = success && cafi.Format(sb, null, array, cafi, ref maxLength);
							cafi.HeadingIndices = null;
						}

						success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
					}

					DecIndentationLevel();
				}

				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;
		}
Example #14
0
        /// <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 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)
                {
                    var instanceType = GetInstanceType(arg);
                    success = success && AppendFriendlyTypeName(instanceType, arg, sb, ref maxLength);
                }

                if (sb.Length > originalLength)
                {
                    success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
                }
                success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                if (arg != null)
                {
                    IncIndentationLevel(true);

                    var array = (Array)arg;
                    var rows  = array.GetLength(0);

                    var cafi = new CompactArrayFormatInfo(this);
                    cafi.ShowItemsOnly = true;
                    cafi.FieldLength   = GetMaxValueLength(array);

                    var rowNumberFormatProvider = new ScalarFormatInfo(VerboseFormatInfo.SingleLinedFormat);
                    rowNumberFormatProvider.ShowDataType     = false;
                    rowNumberFormatProvider.ShowInstanceName = false;
                    if (IsMultiLinedFormat)
                    {
                        rowNumberFormatProvider.FieldLength = rowNumberFormatProvider.GetValueLength(rows);
                    }

                    for (var i = 0; i < rows; i++)
                    {
                        if (i == rows - 1)
                        {
                            DecIndentationLevel();
                            IncIndentationLevel(false);                             // There are no more rows in the matrix

                            cafi.DecIndentationLevel();
                            cafi.IncIndentationLevel(false);
                        }

                        success = success && FormatLinePrefix(sb, true, i == rows - 1, false, 0, ref maxLength);
                        success = FormatInfoUtils.TryAppendString(this, sb, "Row ", success, ref maxLength);
                        success = success && rowNumberFormatProvider.Format(sb, null, i, rowNumberFormatProvider, ref maxLength);

                        success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
                        success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);

                        // Now we should append row content, which is obtained differently in case of matrix and in case of jagged array
                        if (array.Rank == 1)
                        {
                            // Array is jagged
                            var row = (Array)array.GetValue(i);
                            cafi.ShowLastDimension = false;
                            success = success && cafi.Format(sb, null, row, cafi, ref maxLength);
                        }
                        else
                        {
                            // Array is a matrix
                            cafi.HeadingIndices    = new[] { i };
                            cafi.ShowLastDimension = true;
                            success             = success && cafi.Format(sb, null, array, cafi, ref maxLength);
                            cafi.HeadingIndices = null;
                        }

                        success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
                    }

                    DecIndentationLevel();
                }

                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>
		///     Gets value indicating whether this format provider can be applied to specified data type or not.
		///     This format provider is applicable to matrices (arrays of rank 2) and to jagged arrays, but only
		///     if element type is supported by ScalarFormatInfo format provider.
		/// </summary>
		/// <param name="dataType">Data type agianst which this format provider is tested.</param>
		/// <returns>true if this format provider is applicable; otherwise false.</returns>
		internal override bool IsFormatApplicable(Type dataType)
		{
			var elementType = GetElementType(dataType);

			var applicable = false;

			if (elementType != null)
			{
				// Existence of elementType proves that dataType is matrix or jagged array
				var sfi = new ScalarFormatInfo(this);
				applicable = sfi.IsFormatApplicable(elementType);
			}

			return applicable;
		}
        /// <summary>
        ///     Converts the value of a specified array 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 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.
        /// </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;

            var array = (Array)arg;
            var rank  = array.Rank;

            if (rank > 1 || PushCurrentObject(arg))
            {
                _currentInstance = array;

                var prevFieldLength = _fieldLength;
                UpdateFieldLength(sb);                 // Autonomously updates field length if that will help better format values from the array

                if (!_showItemsOnly && ShowDataType)
                {
                    success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);
                }

                var enumerator = GetEnumerator();

                var sfi = new ScalarFormatInfo(this);
                sfi.ShowDataType     = false;
                sfi.ShowInstanceName = false;
                sfi.FieldLength      = _fieldLength;

                var linePrefixLength   = GetCurrentLineLength(sb);
                var lineStartPos       = sb.Length;
                var isFirstValueInLine = true;
                var repeatLastValue    = false;

                while (success && (repeatLastValue || enumerator.MoveNext()))
                {
                    // At every position it might happen that line should be broken and formatting continued on the following line
                    var prevLineLength = sb.Length - lineStartPos;

                    string delimiter = null;
                    if (isFirstValueInLine)
                    {
                        delimiter = "";
                    }
                    else if (IsMultiLinedFormat)
                    {
                        delimiter = " ";
                    }
                    else
                    {
                        delimiter = FieldDelimiter;
                    }

                    success            = FormatInfoUtils.TryAppendString(this, sb, delimiter, success, ref maxLength);
                    success            = success && sfi.Format(sb, null, enumerator.Current, sfi, ref maxLength);
                    isFirstValueInLine = false;
                    repeatLastValue    = false;

                    if (IsMultiLinedFormat && _maxLineLength > 0 && sb.Length - lineStartPos > _maxLineLength && !isFirstValueInLine)
                    {
                        // Maximum line length has been breached in the multi-lined format
                        // As a consequence, last value should be deleted from output, new line should be started and last value formatted again

                        sb.Length = prevLineLength + lineStartPos;

                        success = success && FormatLinePrefix(sb, true, false, true, linePrefixLength, ref maxLength);

                        lineStartPos       = sb.Length;
                        repeatLastValue    = true;
                        isFirstValueInLine = true;
                    }
                }

                if (!_showItemsOnly)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, LastContainedValueSuffix, success, ref maxLength);
                }

                _fieldLength = prevFieldLength;                 // Restore field length to value before this method was called

                if (rank == 1)
                {
                    PopCurrentObject();
                }
            }
            else
            {
                success = success && FormatInfoUtils.ReportInfiniteLoop(sb, arg, InstanceName, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
		/// <summary>
		///     Copy constructor which initializes new instance and copies common values from another instance of this class.
		/// </summary>
		/// <param name="other">Instance from which common values should be copied.</param>
		public ScalarFormatInfo(ScalarFormatInfo other)
			: base(other)
		{
			_fieldLength = other._fieldLength;
		}
		/// <summary>
		///     Formats friendly representation of the name of the given type.
		/// </summary>
		/// <param name="type">Type for which friendly representation of the name is required.</param>
		/// <param name="instance">
		///     Instance for which friendly type name is appended.
		///     This argument is used to gather additional information which might not be available
		///     from the type information. This argument may be null if instance is not available.
		/// </param>
		/// <param name="sb">
		///     String builder to which friendly name of <paramref name="type" /> is appended.
		///     If <paramref name="type" /> is null then nothing is appended to this string builder.
		/// </param>
		/// <param name="maxLength">
		///     Maximum number of characters allowed to this method
		///     to append to string builder. Negative value indicates unlimited number of characters allowed.
		///     Method fails and returns false if it could not perform the task within given number
		///     of characters. On output contains remaining number of characters allowed.
		/// </param>
		/// <returns>
		///     true if method has successfully appended friendly name of the data type
		///     within given number of characters allowed; otherwise false.
		/// </returns>
		internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
		{
			var success = true;
			var originalLength = sb.Length;

			if (type != null)
			{
				type = type.GetElementType(); // For arrays print element type rather than array type
			}

			if (success)
			{
				var sfi = new ScalarFormatInfo(this);
				success = sfi.AppendFriendlyTypeName(type, null, sb, ref maxLength);
				// Use scalar format info because it can write simple data types in a more compact way
			}

			// Now append dimensions of the array
			// If instance is null then dimensions cannot be determined and braces will remain empty, like int[].
			// Otherwise, if instance is present, dimensions will be fully shown, like int[3, 4, 2] in case of three-dimensional array.

			success = FormatInfoUtils.TryAppendChar(this, sb, '[', success, ref maxLength);

			if (instance != null)
			{
				var dimensions = GetDimensions(instance);
				for (var i = 0; success && i < dimensions.Length; i++)
				{
					if (i > 0)
					{
						success = FormatInfoUtils.TryAppendString(this, sb, ", ", success, ref maxLength);
					}
					success = FormatInfoUtils.TryAppendString(this, sb, dimensions[i].ToString("0"), success, ref maxLength);
				}
			}

			success = FormatInfoUtils.TryAppendChar(this, sb, ']', success, ref maxLength);

			if (!success)
			{
				sb.Length = originalLength;
			}

			return success;
		}
Example #19
0
        /// <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;

            var formatters        = new List <VerboseFormatInfoBase>();
            var singleLinedFormat = SingleLinedFormat;

            if (arg != null || InstanceDataType != null)
            {
                var type = GetInstanceType(arg);

                var sfi = new ScalarFormatInfo(this);
                sfi.MaximumFormattedLength = maxLength;

                if (sfi.IsFormatApplicable(type))
                {
                    if (IsMultiLinedFormat)
                    {
                        var singleLinedSfi = new ScalarFormatInfo(this);
                        FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedSfi);
                        singleLinedSfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                        formatters.Add(singleLinedSfi);
                    }

                    formatters.Add(sfi);
                }

                if (formatters.Count == 0)
                {
                    var dfi = new DictionaryFormatInfo(this);
                    dfi.MaximumFormattedLength = maxLength;

                    if (dfi.IsFormatApplicable(type))
                    {
                        if (IsMultiLinedFormat)
                        {
                            var singleLinedDfi = new DictionaryFormatInfo(this);
                            FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedDfi);
                            singleLinedDfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                            formatters.Add(singleLinedDfi);
                        }
                        formatters.Add(dfi);
                    }
                }

                if (formatters.Count == 0)
                {
                    var cmfi = new CompactMatrixFormatInfo(this);
                    cmfi.MaximumFormattedLength = maxLength;

                    if (cmfi.IsFormatApplicable(type))
                    {
                        //if (IsMultiLinedFormat)   // Uncomment these lines to enable inlining compactly presented matrices; that operation is not suggested
                        //{
                        //    CompactMatrixFormatInfo singleLinedCmfi = new CompactMatrixFormatInfo(this);
                        //    FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedCmfi);
                        //    singleLinedCmfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                        //    formatters.Add(singleLinedCmfi);
                        //}
                        formatters.Add(cmfi);
                    }
                }

                if (formatters.Count == 0)
                {
                    var cafi = new CompactArrayFormatInfo(this);
                    cafi.MaximumFormattedLength = maxLength;

                    if (cafi.IsFormatApplicable(type))
                    {
                        if (IsMultiLinedFormat)
                        {
                            var singleLinedCafi = new CompactArrayFormatInfo(this);
                            FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedCafi);
                            singleLinedCafi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                            formatters.Add(singleLinedCafi);
                        }
                        formatters.Add(cafi);
                    }
                }

                if (formatters.Count == 0)
                {
                    var afi = new ArrayFormatInfo(this);
                    afi.MaximumFormattedLength = maxLength;

                    if (afi.IsFormatApplicable(type))
                    {
                        if (IsMultiLinedFormat)
                        {
                            var singleLinedAfi = new ArrayFormatInfo(this);
                            FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedAfi);
                            singleLinedAfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                            formatters.Add(singleLinedAfi);
                        }
                        formatters.Add(afi);
                    }
                }

                if (formatters.Count == 0)
                {
                    var efi = new EnumerableFormatInfo(this);
                    efi.MaximumFormattedLength = maxLength;

                    if (efi.IsFormatApplicable(type))
                    {
                        if (IsMultiLinedFormat)
                        {
                            var singleLinedEfi = new EnumerableFormatInfo(this);
                            FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedEfi);
                            singleLinedEfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                            formatters.Add(singleLinedEfi);
                        }
                        formatters.Add(efi);
                    }
                }

                if (formatters.Count == 0)
                {
                    if (IsMultiLinedFormat)
                    {
                        var singleLinedGfi = new GeneralFormatInfo(this);
                        FormatInfoUtils.CopyFormatting(singleLinedFormat, singleLinedGfi);
                        singleLinedGfi.CombineMaximumFormattedLength(FormatInfoUtils.DefaultMaxFormattedLength);
                        formatters.Add(singleLinedGfi);
                    }

                    var gfi = new GeneralFormatInfo(this);
                    gfi.MaximumFormattedLength = maxLength;

                    formatters.Add(gfi);
                }
            }

            if (formatters.Count > 0)
            {
                success = success && FormatInfoUtils.BestTryFormat(sb, format, arg, formatters, ref maxLength);
            }

            if (!success)
            {
                sb.Length = originalLength;
            }

            return(success);
        }
Example #20
0
        /// <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);
        }