TryAppendChar() public static méthode

Tries to append character to the string builder within given amount of characters allowed. Always succeeds in multi-lined formatters.
public static TryAppendChar ( VerboseFormatInfoBase formatter, StringBuilder sb, char c, bool success, int &maxLength ) : bool
formatter VerboseFormatInfoBase Formatter which has requested character to be appended.
sb StringBuilder String builder to which string should be appended.
c char Character which should be appended.
success bool /// Indicates whether appending operations this far have been successful (true) /// or some of the previous append operations has already failed (false). If false, appending will not be attempted. ///
maxLength int /// On input contains maximum number of characters that are allowed to be appended to the string builder. /// On output indicates remaining character positions allowed before appending will fail. ///
Résultat bool
        /// <summary>
        ///     Appends formatted string to the given string builder. String will be fully escaped.
        /// </summary>
        /// <param name="sb">String builder to which string should be appended.</param>
        /// <param name="s">String which should be formatted and appended to the string builder.</param>
        /// <param name="quote">Indicates whether formatted string should be enclosed in double quotation marks (true) or not (false).</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>
        private bool FormatString(StringBuilder sb, string s, bool quote, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (quote)
            {
                success = FormatInfoUtils.TryAppendChar(this, sb, '"', success, ref maxLength);
            }

            for (var i = 0; success && i < s.Length; i++)
            {
                success = FormatChar(sb, s[i], false, true, ref maxLength);
            }

            if (quote)
            {
                success = FormatInfoUtils.TryAppendChar(this, sb, '"', success, ref maxLength);
            }

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

            return(success);
        }
Exemple #2
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);
        }
        /// <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);
        }
Exemple #4
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>
        ///     Appends all fields that should be placed before next contained value is appended to the output.
        ///     In single-lined formats that will only be the field delimiter.
        ///     In multi-lined formats that may include indentation strings.
        /// </summary>
        /// <param name="sb">
        ///     String builder which ends with a field after which strings that are used to
        ///     delimit successive fields should be appended.
        /// </param>
        /// <param name="firstValueFollows">
        ///     Indicates whether next value to be formatted is the first contained value
        ///     under the current instance (true) or other fields at the same level have already been appended to the output (false).
        /// </param>
        /// <param name="lastValueFollows">
        ///     Indicates whether next value is the last one (true) or there are more values to follow (false).
        ///     Ignored if this format provider is single-lined.
        /// </param>
        /// <param name="skipRightMostIndentationString">
        ///     Indicates whether right-most indentation string should be replaced with normal indentation string
        ///     (true) or not (false). This stands for last right most indentation string as well.
        /// </param>
        /// <param name="padLineToLength">
        ///     Indicates required length of the line in multi-lined formats. If string created by applying
        ///     all prefixes and delimiters is shorter than this value then it is right-padded with blank spaces until this length is reached.
        /// </param>
        /// <param name="maxLength">
        ///     Maximum number of characters allowed to be appended to string builder by this function.
        ///     Negative value indicates unlimited number. If this function cannot fit the content into this number of characters
        ///     then it fails and returns false. On output contains remaining number of characters available.
        /// </param>
        /// <returns>
        ///     true if function has successfully appended specified content to the string builder without breaching the allowed
        ///     number of characters specified by parameter <paramref name="maxLength" />; otherwise false.
        /// </returns>
        internal bool FormatLinePrefix(StringBuilder sb, bool firstValueFollows, bool lastValueFollows, bool skipRightMostIndentationString,
                                       int padLineToLength, ref int maxLength)
        {
            var originalLength = sb.Length;
            var success        = true;

            if (firstValueFollows && _isMultiLinedFormat)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, Environment.NewLine, success, ref maxLength);
            }
            else if (!firstValueFollows)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, _fieldDelimiter, success, ref maxLength);
            }

            if (_isMultiLinedFormat)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, _linePrefix, success, ref maxLength);

                for (var i = 0; success && i < IndentationLevel; i++)
                {
                    string indentString     = null;
                    string lastIndentString = null;

                    if (IsIndentationLevelOccupied(i + 1))
                    {
                        indentString     = IndentationString;
                        lastIndentString = LastIndentationString;
                    }
                    else
                    {
                        indentString = string.Empty;
                        for (var j = 0; j < IndentationString.Length; j++)
                        {
                            if (IndentationString[j] == '\t')
                            {
                                indentString += '\t';
                            }
                            else
                            {
                                indentString += ' ';
                            }
                        }

                        lastIndentString = string.Empty;
                        for (var j = 0; j < LastIndentationString.Length; j++)
                        {
                            if (LastIndentationString[j] == '\t')
                            {
                                lastIndentString += '\t';
                            }
                            else
                            {
                                lastIndentString += ' ';
                            }
                        }
                    }

                    var rightMostIndentString     = (skipRightMostIndentationString ? indentString : RightMostIndentationString);
                    var lastRightMostIndentString = (skipRightMostIndentationString ? lastIndentString : LastRightMostIndentationString);

                    if (lastValueFollows && i == IndentationLevel - 1)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb,
                                                                  lastRightMostIndentString ?? lastIndentString ?? rightMostIndentString ?? indentString, success, ref maxLength);
                    }
                    else if (lastValueFollows)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, lastIndentString ?? indentString, success, ref maxLength);
                    }
                    else if (i == IndentationLevel - 1)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, rightMostIndentString ?? indentString, success, ref maxLength);
                    }
                    else
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, indentString, success, ref maxLength);
                    }
                }

                if (padLineToLength > 0)
                {
                    var lineLength = GetCurrentLineLength(sb);
                    while (success && lineLength++ < padLineToLength)
                    {
                        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">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 (!string.IsNullOrEmpty(InstanceName))
                {
                    var name = string.Format("{0}{1}{2}={2}", sb.Length > originalLength ? " " : "", InstanceName, IsMultiLinedFormat ? " " : "");
                    success = FormatInfoUtils.TryAppendString(this, sb, name, success, ref maxLength);
                }
                else if (sb.Length > originalLength)
                {
                    success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
                }

                var argType = GetInstanceType(arg);

                if (arg == null)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, FormatInfoUtils.DefaultNullFormatted, success, ref maxLength);
                }
                else if (arg is char)
                {
                    success = success && FormatChar(sb, (char)arg, true, false, ref maxLength);
                }
                else if (arg is string)
                {
                    success = success && FormatString(sb, (string)arg, true, ref maxLength);
                }
                else if (arg is Boolean)
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, ((bool)arg) ? "true" : "false", success, ref maxLength);
                }
                else if (argType.IsEnum)
                {
                    var plainName = Enum.GetName(argType, arg);

                    if (plainName != null)
                    {
                        success = FormatInfoUtils.TryAppendString(this, sb, plainName, success, ref maxLength);
                    }
                    else
                    {
                        success = success && AppendEnumFlags((Enum)arg, sb, ref maxLength);                          // arg is an OR-ed combination of values
                    }
                }
                else
                {
                    success = FormatInfoUtils.TryAppendString(this, sb, arg.ToString(), success, ref maxLength);
                }

                while (success && sb.Length - originalLength < _fieldLength)
                {
                    success = FormatInfoUtils.TryAppendChar(this, sb, ' ', success, ref maxLength);
                }

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

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

            return(success);
        }
        /// <summary>
        ///     Appends names of enumeration constants that are present in the OR-ed value.
        /// </summary>
        /// <param name="value">Enumeration value which is possibly a combination of multiple OR-ed values.</param>
        /// <param name="sb">String builder to which enumeration value names should be appended.</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>
        private bool AppendEnumFlags(Enum value, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            var enumType       = value.GetType();
            var underlyingType = Enum.GetUnderlyingType(enumType);

            // The following code tries to recover flags in a flagged enum value
            // in .NET 4.0 this can be done much easier using Enum.HasFlag instance-level method, but with some unpredictable outcomes
            // e.g. if enumeration defines Left, Right and Both=Left | Right; then Both might be shown as Left | Right | Both which is avoided by this function

            var    isInt64     = false;
            var    isUint64    = false;
            Int64  int64Value  = 0;
            UInt64 uint64Value = 0;

            if (underlyingType == typeof(sbyte) || underlyingType == typeof(Int16) || underlyingType == typeof(Int32) ||
                underlyingType == typeof(Int64))
            {
                isInt64    = true;
                int64Value = ((IConvertible)value).ToInt64(null);
            }
            else if (underlyingType == typeof(byte) || underlyingType == typeof(UInt16) || underlyingType == typeof(UInt32) ||
                     underlyingType == typeof(UInt64))
            {
                isUint64    = true;
                uint64Value = ((IConvertible)value).ToUInt64(null);
            }

            Int64  constructedInt64Value  = 0;
            UInt64 constructedUint64Value = 0;

            var values = Enum.GetValues(enumType);
            var constructionComplete = false;
            var flags = new List <object>();            // Enumeration values that are incorporated in OR-ed value

            foreach (var simpleValue in values)
            {
                if (isInt64)
                {
                    var curInt64Value = ((IConvertible)simpleValue).ToInt64(null);

                    if ((int64Value & curInt64Value) == curInt64Value && (constructedInt64Value & curInt64Value) != curInt64Value)
                    {
                        // simpleValue is part of the resulting OR-ed value and is not included in currently constructed value (or is not completely included)

                        constructedInt64Value = constructedInt64Value | curInt64Value;
                        flags.Add(simpleValue);

                        if (constructedInt64Value == int64Value)
                        {
                            constructionComplete = true;
                            break;
                        }
                    }
                }
                else if (isUint64)
                {
                    var curUint64Value = ((IConvertible)simpleValue).ToUInt64(null);

                    if ((uint64Value & curUint64Value) == curUint64Value && (constructedUint64Value & curUint64Value) != curUint64Value)
                    {
                        // simpleValue is part of the resulting OR-ed value and is not included in currently constructed value (or is not completely included)

                        constructedUint64Value = constructedUint64Value | curUint64Value;
                        flags.Add(simpleValue);

                        if (constructedUint64Value == uint64Value)
                        {
                            constructionComplete = true;
                            break;
                        }
                    }
                }
            }

            if (!constructionComplete)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, value.ToString(), success, ref maxLength);
                // Append it as number or whatever Enum.ToString() makes out of this value
            }
            else
            {
                var isFirst = true;

                foreach (var simpleValue in flags)
                {
                    if (!isFirst)
                    {
                        success = FormatInfoUtils.TryAppendChar(this, sb, '+', success, ref maxLength);
                    }
                    isFirst = false;

                    success = FormatInfoUtils.TryAppendString(this, sb, Enum.GetName(enumType, simpleValue), success, ref maxLength);

                    if (!success)
                    {
                        break;
                    }
                }
            }

            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);
        }
Exemple #10
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);
        }