예제 #1
0
 public void Test2()
 {
     using var builder = new StringBuilderSlim();
     builder.Add("abcd"); Assert.Equal("abcd", builder.ToString());
     builder.Add("efgh"); Assert.Equal("abcdefgh", builder.ToString());
     builder.Add("ijkl"); Assert.Equal("abcdefghijkl", builder.ToString());
     builder.Add("mnop"); Assert.Equal("abcdefghijklmnop", builder.ToString());
     builder.Add("qrst"); Assert.Equal("abcdefghijklmnopqrst", builder.ToString());
     builder.Add("uvwx"); Assert.Equal("abcdefghijklmnopqrstuvwx", builder.ToString());
 }
예제 #2
0
        /// <summary>
        /// Converts the logged trace record int this instance to its equivalent string representation
        /// using the specified culture-specific format information.
        /// </summary>
        /// <param name="format"></param>
        /// <param name="formatProvider"></param>
        /// <returns></returns>
        /// <remarks>
        /// <para>For this method, following style format is available:</para>
        /// <para><c>%[&lt;alignment&gt;]&lt;content-key&gt;[(&lt;format-string&gt;)]</c></para>
        /// <para>Each content-key is case insensitive.</para>
        /// <para>Ampersand (U+0026) is escape sequence and the next one character is export as it is.</para>
        /// <para>This format is equivalent to <c>{&lt;content-key&gt;[,&lt;alignment&gt;][:&lt;format-string&gt;]}</c> under .Net format string.</para>
        /// <para>Following content keys are available'</para>
        /// <list type="bullet">
        ///     <item>
        ///         <term>K</term>
        ///         <description>[<see cref="String"/>] Operator key.</description>
        ///     </item>
        ///     <item>
        ///         <term>S</term>
        ///         <description>[<see cref="Int64"/>] Subscription index.</description>
        ///     </item>
        ///     <item>
        ///         <term>I</term>
        ///         <description>[<see cref="Int64"/>] Value index.</description>
        ///     </item>
        ///     <item>
        ///         <term>P</term>
        ///         <description>[<see cref="Int32"/>] Managed thread ID.</description>
        ///     </item>
        ///     <item>
        ///         <term>T</term>
        ///         <description>[<see cref="TimeSpan"/>] Total duration.</description>
        ///     </item>
        ///     <item>
        ///         <term>L</term>
        ///         <description>[<see cref="TimeSpan"/>] Lap duration.</description>
        ///     </item>
        ///     <item>
        ///         <term>V</term>
        ///         <description>[<typeparamref name="T"/>] Value</description>
        ///     </item>
        /// </list>
        /// </remarks>
        /// <example>
        /// <para>Followings are examples of format and its result.</para>
        /// <list type="bullet">
        ///     <item>
        ///         <term><c>%K-%04S(X)-%04I(X)</c></term>
        ///         <description><c>sometrace-0002-00C1</c></description>
        ///     </item>
        ///     <item>
        ///         <term><c>&%%T(d\Dhh\:mm\:ss\.fff)&%</c></term>
        ///         <description><c>%0D00:00:05.500%</c></description>
        ///     </item>
        ///     <item>
        ///         <term><c>%L(s\.fff)/%T(s\.fff)</c></term>
        ///         <description><c>0.342/5.586</c></description>
        ///     </item>
        /// </list>
        /// </example>
        public string ToString(string format, IFormatProvider formatProvider)
        {
            const int raw = 0;
            const int beginReplacement = 1;
            const int elementSpecified = 2;
            const int formatting       = 3;

            formatProvider ??= CultureInfo.CurrentCulture;
            if (string.IsNullOrEmpty(format))
            {
                return(string.Format(
                           formatProvider,
                           "Observable trace {0}-{1}-{2}: thread={3}, total duration={4}, lap duration={5}, value={6}",
                           OperatorKey, SubscriptionIndex, ValueIndex,
                           ManagedThreadId, TotalDuration, LapDuration, Value));
            }

            var result     = new StringBuilder();
            var escaped    = false;
            var state      = raw;
            var elemKey    = default(char);
            var alignment  = default(string);
            var elemFmtStr = default(string);
            var builder    = new StringBuilderSlim();

            void popCurrentFormat()
            {
                if (elemKey == '\0')
                {
                    return;
                }

                var fmt = "{0";

                if (!string.IsNullOrEmpty(alignment))
                {
                    fmt += "," + alignment;
                }
                if (!string.IsNullOrEmpty(elemFmtStr))
                {
                    fmt += ":" + elemFmtStr;
                }
                fmt += "}";
                var retval = char.ToUpper(elemKey) switch
                {
                    'K' => string.Format(formatProvider, fmt, OperatorKey),
                    'S' => string.Format(formatProvider, fmt, SubscriptionIndex),
                    'I' => string.Format(formatProvider, fmt, ValueIndex),
                    'P' => string.Format(formatProvider, fmt, ManagedThreadId),
                    'T' => string.Format(formatProvider, fmt, TotalDuration),
                    'L' => string.Format(formatProvider, fmt, LapDuration),
                    'V' => string.Format(formatProvider, fmt, Value),
                    _ => throw new InvalidOperationException(),
                };

                elemKey    = default;
                alignment  = default;
                elemFmtStr = default;
                result.Append(retval);
            }

            foreach (var c in format)
            {
                if (escaped)
                {
                    builder.Add(c);
                    escaped = false;
                    continue;
                }
                switch (state)
                {
                case raw:
                    switch (c)
                    {
                    case EscapePrefix:
                        escaped = true;
                        continue;

                    case '%':
                        result.Append(builder.ToString());
                        builder.Clear();
                        state = beginReplacement;
                        continue;

                    default:
                        builder.Add(c);
                        continue;
                    }

                case beginReplacement:
                    switch (c)
                    {
                    case '0':
                    case '1':
                    case '2':
                    case '3':
                    case '4':
                    case '5':
                    case '6':
                    case '7':
                    case '8':
                    case '9':
                        builder.Add(c);
                        continue;

                    case '-':
                        if (builder.Length == 0)
                        {
                            goto case '0';
                        }
                        else
                        {
                            goto default;
                        }

                    case 'K':
                    case 'S':
                    case 'I':
                    case 'P':
                    case 'T':
                    case 'L':
                    case 'V':
                    case 'k':
                    case 's':
                    case 'i':
                    case 'p':
                    case 't':
                    case 'l':
                    case 'v':
                        alignment = builder.ToString();
                        builder.Clear();
                        elemKey = c;
                        state   = elementSpecified;
                        continue;

                    default:
                        throw new FormatException();
                    }

                case elementSpecified:
                    switch (c)
                    {
                    case EscapePrefix:
                        popCurrentFormat();
                        escaped = true;
                        state   = raw;
                        continue;

                    case '(':
                        state = formatting;
                        continue;

                    default:
                        state = raw;
                        popCurrentFormat();
                        builder.Add(c);
                        continue;
                    }

                case formatting:
                    switch (c)
                    {
                    case EscapePrefix:
                        escaped = true;
                        continue;

                    case ')':
                        elemFmtStr = builder.ToString();
                        builder.Clear();
                        state = raw;
                        popCurrentFormat();
                        continue;

                    default:
                        builder.Add(c);
                        continue;
                    }

                default:
                    throw new InvalidOperationException();
                }
            }
            switch (state)
            {
            case raw:
                result.Append(builder.ToString());
                builder.Clear();
                break;

            case elementSpecified:
                popCurrentFormat();
                break;

            case beginReplacement:
            case formatting:
            default:
                throw new FormatException();
            }
            return(result.ToString());
        }
예제 #3
0
 public void Test3()
 {
     using var builder = new StringBuilderSlim();
     for (var i = 0; i < 256; ++i)
     {
         builder.Clear();
         builder.Add("abcdefghijklmnopqrstuvwxyz"); Assert.Equal("abcdefghijklmnopqrstuvwxyz", builder.ToString());
     }
 }
예제 #4
0
 public void Test1()
 {
     using var builder = new StringBuilderSlim();
     Assert.Equal("", builder.ToString());
     builder.Add('a'); Assert.Equal("a", builder.ToString());
     builder.Add('b'); Assert.Equal("ab", builder.ToString());
     builder.Add('c'); Assert.Equal("abc", builder.ToString());
     builder.Add('d'); Assert.Equal("abcd", builder.ToString());
     builder.Add('e'); Assert.Equal("abcde", builder.ToString());
     builder.Add('f'); Assert.Equal("abcdef", builder.ToString());
     builder.Add('g'); Assert.Equal("abcdefg", builder.ToString());
     builder.Add('h'); Assert.Equal("abcdefgh", builder.ToString());
     builder.Add('i'); Assert.Equal("abcdefghi", builder.ToString());
     builder.Add('j'); Assert.Equal("abcdefghij", builder.ToString());
     builder.Add('k'); Assert.Equal("abcdefghijk", builder.ToString());
     builder.Add('l'); Assert.Equal("abcdefghijkl", builder.ToString());
     builder.Add('m'); Assert.Equal("abcdefghijklm", builder.ToString());
     builder.Add('n'); Assert.Equal("abcdefghijklmn", builder.ToString());
     builder.Add('o'); Assert.Equal("abcdefghijklmno", builder.ToString());
     builder.Add('p'); Assert.Equal("abcdefghijklmnop", builder.ToString());
     builder.Add('q'); Assert.Equal("abcdefghijklmnopq", builder.ToString());
     builder.Add('r'); Assert.Equal("abcdefghijklmnopqr", builder.ToString());
     builder.Add('s'); Assert.Equal("abcdefghijklmnopqrs", builder.ToString());
     builder.Add('t'); Assert.Equal("abcdefghijklmnopqrst", builder.ToString());
     builder.Add('u'); Assert.Equal("abcdefghijklmnopqrstu", builder.ToString());
     builder.Add('v'); Assert.Equal("abcdefghijklmnopqrstuv", builder.ToString());
     builder.Add('w'); Assert.Equal("abcdefghijklmnopqrstuvw", builder.ToString());
     builder.Add('x'); Assert.Equal("abcdefghijklmnopqrstuvwx", builder.ToString());
     builder.Add('y'); Assert.Equal("abcdefghijklmnopqrstuvwxy", builder.ToString());
     builder.Add('z'); Assert.Equal("abcdefghijklmnopqrstuvwxyz", builder.ToString());
 }