Stateless static class which exposes methods used to help format strings. This class is internal and cannot be used directly. It is rather used by other classes declared in the SysExpand.Text.Formatting namespace to help format strings.
        /// <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>
        ///     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 #3
0
        /// <summary>
        ///     Converts this instance into user-friendly string.
        /// </summary>
        /// <returns>String which represents contents of this instance.</returns>
        public override string ToString()
        {
            var formatProvider = FormatInfoUtils.CreateSingleLinedFormatter();

            formatProvider.InstanceDataType = _dataType;
            formatProvider.InstanceName     = _name;

            return(string.Format(formatProvider, "{0}", _value));
        }
Exemple #4
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>
        ///     Appends formatted presentation of a given character to the given string builder.
        /// </summary>
        /// <param name="sb">String builder to which formatted character is appended.</param>
        /// <param name="c">Character which should be appended to the string builder.</param>
        /// <param name="quote">Indicates whether quotation marks should be placed around the character (true) or not (false).</param>
        /// <param name="stringEscaping">
        ///     Indicates whether escaping rules for strings should be applied (true) or only simple escaping
        ///     should be applied (false). String escaping includes double quotes and backslash characters escaping.
        /// </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 FormatChar(StringBuilder sb, char c, bool quote, bool stringEscaping, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            var quotationMark = (quote ? "'" : string.Empty);

            if (c == '\n')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\n{0}", quotationMark), success, ref maxLength);
            }
            else if (c == '\r')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\r{0}", quotationMark), success, ref maxLength);
            }
            else if (c == '\t')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\t{0}", quotationMark), success, ref maxLength);
            }
            else if (c < ' ')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("0x{0:X2}", (int)c), success, ref maxLength);
            }
            else if (!stringEscaping && c == '\'')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\'{0}", quotationMark), success, ref maxLength);
            }
            else if (stringEscaping && c == '\\')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\\\{0}", quotationMark), success, ref maxLength);
            }
            else if (stringEscaping && c == '"')
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{0}\\\"{0}", quotationMark), success, ref maxLength);
            }
            else
            {
                success = FormatInfoUtils.TryAppendString(this, sb, string.Format("{1}{0}{1}", c, quotationMark), 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);
        }
        /// <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;
        ///     ignored in this instance.
        /// </param>
        /// <param name="arg">An object to format.</param>
        /// <param name="formatProvider">An object that supplies format information about current instance.</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 string 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 (success)
                {
                    success = AppendInstanceTypeName(arg, sb, ref maxLength);
                }

                var dimensions = GetDimensions(arg);

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

                if (MaximumDepth > 0)
                {
                    MaximumDepth--;

                    success = success && RecursiveAppendDimension(sb, (Array)arg, new List <int>(), ref maxLength);

                    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;                 // Remove any characters appended to string builder in an unsuccessful attempt
            }

            return(success);
        }
        /// <summary>
        ///     Formats user friendly representation of the name of the given type. Override in derived classes to implement specific
        ///     friendly names for known types handled by derived classes. Make sure that overridden implementations call base class
        ///     implementation in case that they cannot resolve type name.
        /// </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.
        ///     Use this argument 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 virtual bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (type != null)
            {
                var typeName     = type.Name;
                var backQuotePos = typeName.IndexOf('`');
                if (backQuotePos >= 0)
                {
                    typeName = typeName.Substring(0, backQuotePos);
                }

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

                if (success && type.IsGenericType)
                {
                    var genericArguments = type.GetGenericArguments();

                    success = FormatInfoUtils.TryAppendString(this, sb, "<", success, ref maxLength);

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

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

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

            return(success);
        }
 /// <summary>
 ///     Converts current instance to user friendly string using simple formatter to format the string.
 /// </summary>
 /// <returns>String which represents contents of this instance.</returns>
 public override string ToString()
 {
     return(FormatInfoUtils.CreateSimpleFormatter().Format(this));
 }
 /// <summary>
 ///     Combines maximum formatted string length from this instance with given length and sets new maximum length for this instance.
 /// </summary>
 /// <param name="length">
 ///     Length with which maximum allowed length of the string created by this formatter is combined;
 ///     negative value indicates infinite allowed length.
 /// </param>
 /// <returns>
 ///     New value of the maximum allowed string length for this formatter, which equals value that will be returned by
 ///     MaximumFormattedLength property after this method returns. Note that return value is affected by IsMultiLinedFormat property
 ///     value in sense that whenever this formatter is multi-lined, this method will return value -1 regardless of actual
 ///     internal setting of maximum string length.
 /// </returns>
 public int CombineMaximumFormattedLength(int length)
 {
     _maximumFormattedLength = FormatInfoUtils.CombineMaxFormattedLengths(_maximumFormattedLength, length);
     return(MaximumFormattedLength);
 }
        /// <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 user friendly name for the given data type and appends it to string builder.
        /// </summary>
        /// <param name="type">Data type for which user friendly name is requested.</param>
        /// <param name="instance">
        ///     Instance for which friendly type name is appended.
        ///     Use this argument 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 data type name 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>
        internal override bool AppendFriendlyTypeName(Type type, object instance, StringBuilder sb, ref int maxLength)
        {
            var success        = true;
            var originalLength = sb.Length;

            if (type == typeof(SByte))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "sbyte", success, ref maxLength);
            }
            else if (type == typeof(Byte))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "byte", success, ref maxLength);
            }
            else if (type == typeof(Int16))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "short", success, ref maxLength);
            }
            else if (type == typeof(UInt16))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "ushort", success, ref maxLength);
            }
            else if (type == typeof(Int32))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "int", success, ref maxLength);
            }
            else if (type == typeof(UInt32))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "uint", success, ref maxLength);
            }
            else if (type == typeof(Int64))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "long", success, ref maxLength);
            }
            else if (type == typeof(UInt64))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "ulong", success, ref maxLength);
            }
            else if (type == typeof(float))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "float", success, ref maxLength);
            }
            else if (type == typeof(Double))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "double", success, ref maxLength);
            }
            else if (type == typeof(Decimal))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "decimal", success, ref maxLength);
            }
            else if (type == typeof(char))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "char", success, ref maxLength);
            }
            else if (type == typeof(String))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "string", success, ref maxLength);
            }
            else if (type == typeof(Boolean))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "bool", success, ref maxLength);
            }
            else if (type == typeof(DateTime))
            {
                success = FormatInfoUtils.TryAppendString(this, sb, "DateTime", success, ref maxLength);
            }
            else if (type.IsEnum)
            {
                success = FormatInfoUtils.TryAppendString(this, sb, type.Name, success, ref maxLength);
            }
            else
            {
                success = success && base.AppendFriendlyTypeName(type, instance, sb, 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);
        }
Exemple #15
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 (ShowDataType && !_showValuesOnly)
                {
                    success = success && AppendInstanceTypeName(arg, sb, ref maxLength);
                }

                if (ShowInstanceName && !string.IsNullOrEmpty(InstanceName) && !_showValuesOnly)
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, InstanceName, success, ref maxLength);
                }

                if (!_showValuesOnly)
                {
                    success = FormatInfoUtils.TryAppendSpaceIfNeeded(this, sb, success, ref maxLength);
                    success = FormatInfoUtils.TryAppendString(this, sb, FirstContainedValuePrefix, success, ref maxLength);
                }

                Type enumeratedType = null;
                var  enumerator     = GetEnumerator(arg, ref enumeratedType);

                var itemFormatter = new VerboseFormatInfo(this);

                var value        = new object[2];
                var valueFetched = new bool[2];

                valueFetched[0] = GetNextValue(enumerator, ref value[0]);
                if (valueFetched[0])
                {
                    valueFetched[1] = GetNextValue(enumerator, ref value[1]);
                }

                var itemPos = 0;

                while (valueFetched[0])
                {
                    IncIndentationLevel(valueFetched[1]);
                    itemFormatter.IncIndentationLevel(valueFetched[1]);

                    var valueName = string.Format("Item[{0}]", itemPos++);

                    itemFormatter.InstanceDataType = enumeratedType;
                    itemFormatter.InstanceName     = valueName;

                    success = success && FormatLinePrefix(sb, itemPos == 0, !valueFetched[1], false, 0, ref maxLength);
                    success = success && itemFormatter.Format(sb, null, value[0], itemFormatter, ref maxLength);

                    valueFetched[0] = valueFetched[1];
                    value[0]        = value[1];

                    valueFetched[1] = GetNextValue(enumerator, ref value[1]);

                    itemFormatter.DecIndentationLevel();
                    DecIndentationLevel();
                }

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

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

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

            return(success);
        }
Exemple #16
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 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 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>
        ///     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 #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;

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