示例#1
0
        //
        // IRI normalization for strings containing characters that are not allowed or
        // escaped characters that should be unescaped in the context of the specified Uri component.
        //
        internal static unsafe string EscapeUnescapeIri(char *pInput, int start, int end, UriComponents component)
        {
            int size = end - start;
            ValueStringBuilder dest = size <= 256
                ? new ValueStringBuilder(stackalloc char[256])
                : new ValueStringBuilder(size);

            Span <byte> maxUtf8EncodedSpan = stackalloc byte[4];

            for (int i = start; i < end; ++i)
            {
                char ch = pInput[i];
                if (ch == '%')
                {
                    if (end - i > 2)
                    {
                        ch = UriHelper.DecodeHexChars(pInput[i + 1], pInput[i + 2]);

                        // Do not unescape a reserved char
                        if (ch == Uri.c_DummyChar || ch == '%' || CheckIsReserved(ch, component) || UriHelper.IsNotSafeForUnescape(ch))
                        {
                            // keep as is
                            dest.Append(pInput[i++]);
                            dest.Append(pInput[i++]);
                            dest.Append(pInput[i]);
                            continue;
                        }
                        else if (ch <= '\x7F')
                        {
                            Debug.Assert(ch < 0xFF, "Expecting ASCII character.");
                            //ASCII
                            dest.Append(ch);
                            i += 2;
                            continue;
                        }
                        else
                        {
                            // possibly utf8 encoded sequence of unicode
                            int charactersRead = PercentEncodingHelper.UnescapePercentEncodedUTF8Sequence(
                                pInput + i,
                                end - i,
                                ref dest,
                                component == UriComponents.Query,
                                iriParsing: true);

                            Debug.Assert(charactersRead > 0);
                            i += charactersRead - 1; // -1 as i will be incremented in the loop
                        }
                    }
                    else
                    {
                        dest.Append(pInput[i]);
                    }
                }
                else if (ch > '\x7f')
                {
                    // unicode

                    bool isInIriUnicodeRange;
                    bool surrogatePair = false;

                    char ch2 = '\0';

                    if ((char.IsHighSurrogate(ch)) && (i + 1 < end))
                    {
                        ch2 = pInput[i + 1];
                        isInIriUnicodeRange = CheckIriUnicodeRange(ch, ch2, out surrogatePair, component == UriComponents.Query);
                    }
                    else
                    {
                        isInIriUnicodeRange = CheckIriUnicodeRange(ch, component == UriComponents.Query);
                    }

                    if (isInIriUnicodeRange)
                    {
                        dest.Append(ch);
                        if (surrogatePair)
                        {
                            dest.Append(ch2);
                        }
                    }
                    else
                    {
                        Rune rune;
                        if (surrogatePair)
                        {
                            rune = new Rune(ch, ch2);
                        }
                        else if (!Rune.TryCreate(ch, out rune))
                        {
                            rune = Rune.ReplacementChar;
                        }

                        int         bytesWritten = rune.EncodeToUtf8(maxUtf8EncodedSpan);
                        Span <byte> encodedBytes = maxUtf8EncodedSpan.Slice(0, bytesWritten);

                        foreach (byte b in encodedBytes)
                        {
                            UriHelper.EscapeAsciiChar(b, ref dest);
                        }
                    }

                    if (surrogatePair)
                    {
                        i++;
                    }
                }
                else
                {
                    // just copy the character
                    dest.Append(pInput[i]);
                }
            }

            return(dest.ToString());
        }
示例#2
0
        /// <summary>
        /// Replaces all occurrences of the regex in the string with the
        /// replacement evaluator.
        ///
        /// Note that the special case of no matches is handled on its own:
        /// with no matches, the input string is returned unchanged.
        /// The right-to-left case is split out because StringBuilder
        /// doesn't handle right-to-left string building directly very well.
        /// </summary>
        private static string Replace(MatchEvaluator evaluator, Regex regex, string input, int count, int startat)
        {
            if (evaluator == null)
            {
                throw new ArgumentNullException(nameof(evaluator));
            }
            if (count < -1)
            {
                throw new ArgumentOutOfRangeException(nameof(count), SR.CountTooSmall);
            }
            if (startat < 0 || startat > input.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(startat), SR.BeginIndexNotNegative);
            }

            if (count == 0)
            {
                return(input);
            }

            Match match = regex.Match(input, startat);

            if (!match.Success)
            {
                return(input);
            }
            else
            {
                Span <char> charInitSpan = stackalloc char[ReplaceBufferSize];
                var         vsb          = new ValueStringBuilder(charInitSpan);

                if (!regex.RightToLeft)
                {
                    int prevat = 0;

                    do
                    {
                        if (match.Index != prevat)
                        {
                            vsb.Append(input.AsSpan(prevat, match.Index - prevat));
                        }

                        prevat = match.Index + match.Length;
                        vsb.Append(evaluator(match) ?? "");

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();
                    } while (match.Success);

                    if (prevat < input.Length)
                    {
                        vsb.Append(input.AsSpan(prevat, input.Length - prevat));
                    }
                }
                else
                {
                    // In right to left mode append all the inputs in reversed order to avoid an extra dynamic data structure
                    // and to be able to work with Spans. A final reverse of the transformed reversed input string generates
                    // the desired output. Similar to Tower of Hanoi.

                    int prevat = input.Length;

                    do
                    {
                        if (match.Index + match.Length != prevat)
                        {
                            vsb.AppendReversed(input.AsSpan(match.Index + match.Length, prevat - match.Index - match.Length));
                        }

                        prevat = match.Index;
                        vsb.AppendReversed(evaluator(match));

                        if (--count == 0)
                        {
                            break;
                        }

                        match = match.NextMatch();
                    } while (match.Success);

                    if (prevat > 0)
                    {
                        vsb.AppendReversed(input.AsSpan(0, prevat));
                    }

                    vsb.Reverse();
                }

                return(vsb.ToString());
            }
        }
示例#3
0
        /// <summary>
        /// Try to remove relative segments from the given path (without combining with a root).
        /// </summary>
        /// <param name="rootLength">The length of the root of the given path</param>
        internal static string RemoveRelativeSegments(string path, int rootLength)
        {
            Debug.Assert(rootLength > 0);
            bool flippedSeparator = false;

            int skip = rootLength;

            // We treat "\.." , "\." and "\\" as a relative segment. We want to collapse the first separator past the root presuming
            // the root actually ends in a separator. Otherwise the first segment for RemoveRelativeSegments
            // in cases like "\\?\C:\.\" and "\\?\C:\..\", the first segment after the root will be ".\" and "..\" which is not considered as a relative segment and hence not be removed.
            if (PathInternal.IsDirectorySeparator(path[skip - 1]))
            {
                skip--;
            }

            Span <char>        initialBuffer = stackalloc char[260 /* PathInternal.MaxShortPath */];
            ValueStringBuilder sb            = new ValueStringBuilder(initialBuffer);

            // Remove "//", "/./", and "/../" from the path by copying each character to the output,
            // except the ones we're removing, such that the builder contains the normalized path
            // at the end.
            if (skip > 0)
            {
                sb.Append(path.AsSpan(0, skip));
            }

            for (int i = skip; i < path.Length; i++)
            {
                char c = path[i];

                if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length)
                {
                    // Skip this character if it's a directory separator and if the next character is, too,
                    // e.g. "parent//child" => "parent/child"
                    if (PathInternal.IsDirectorySeparator(path[i + 1]))
                    {
                        continue;
                    }

                    // Skip this character and the next if it's referring to the current directory,
                    // e.g. "parent/./child" => "parent/child"
                    if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) &&
                        path[i + 1] == '.')
                    {
                        i++;
                        continue;
                    }

                    // Skip this character and the next two if it's referring to the parent directory,
                    // e.g. "parent/child/../grandchild" => "parent/grandchild"
                    if (i + 2 < path.Length &&
                        (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) &&
                        path[i + 1] == '.' && path[i + 2] == '.')
                    {
                        // Unwind back to the last slash (and if there isn't one, clear out everything).
                        int s;
                        for (s = sb.Length - 1; s >= skip; s--)
                        {
                            if (PathInternal.IsDirectorySeparator(sb[s]))
                            {
                                sb.Length = (i + 3 >= path.Length && s == skip) ? s + 1 : s; // to avoid removing the complete "\tmp\" segment in cases like \\?\C:\tmp\..\, C:\tmp\..
                                break;
                            }
                        }
                        if (s < skip)
                        {
                            sb.Length = skip;
                        }

                        i += 2;
                        continue;
                    }
                }

                // Normalize the directory separator if needed
                if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar)
                {
                    c = PathInternal.DirectorySeparatorChar;
                    flippedSeparator = true;
                }

                sb.Append(c);
            }

            // If we haven't changed the source path, return the original
            if (!flippedSeparator && sb.Length == path.Length)
            {
                sb.Dispose();
                return(path);
            }

            return(sb.Length < rootLength?path.Substring(0, rootLength) : sb.ToString());
        }
示例#4
0
    private string GetFieldsDirective()
    {
        // 152 is the length of the default fields directive
        var sb = new ValueStringBuilder(152);

        sb.Append("#Fields:");
        if (_loggingFields.HasFlag(W3CLoggingFields.Date))
        {
            sb.Append(" date");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.Time))
        {
            sb.Append(" time");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ClientIpAddress))
        {
            sb.Append(" c-ip");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.UserName))
        {
            sb.Append(" cs-username");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ServerName))
        {
            sb.Append(" s-computername");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ServerIpAddress))
        {
            sb.Append(" s-ip");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ServerPort))
        {
            sb.Append(" s-port");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.Method))
        {
            sb.Append(" cs-method");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.UriStem))
        {
            sb.Append(" cs-uri-stem");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.UriQuery))
        {
            sb.Append(" cs-uri-query");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ProtocolStatus))
        {
            sb.Append(" sc-status");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.TimeTaken))
        {
            sb.Append(" time-taken");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.ProtocolVersion))
        {
            sb.Append(" cs-version");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.Host))
        {
            sb.Append(" cs-host");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.UserAgent))
        {
            sb.Append(" cs(User-Agent)");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.Cookie))
        {
            sb.Append(" cs(Cookie)");
        }
        if (_loggingFields.HasFlag(W3CLoggingFields.Referer))
        {
            sb.Append(" cs(Referer)");
        }

        if (_additionalRequestHeaders != null)
        {
            foreach (var header in _additionalRequestHeaders)
            {
                sb.Append($" cs({header})");
            }
        }

        return(sb.ToString());
    }
示例#5
0
        public static string Combine(params string[] paths)
        {
            if (paths == null)
            {
                throw new ArgumentNullException(nameof(paths));
            }

            int maxSize        = 0;
            int firstComponent = 0;

            // We have two passes, the first calculates how large a buffer to allocate and does some precondition
            // checks on the paths passed in.  The second actually does the combination.

            for (int i = 0; i < paths.Length; i++)
            {
                if (paths[i] == null)
                {
                    throw new ArgumentNullException(nameof(paths));
                }

                if (paths[i].Length == 0)
                {
                    continue;
                }

                if (IsPathRooted(paths[i]))
                {
                    firstComponent = i;
                    maxSize        = paths[i].Length;
                }
                else
                {
                    maxSize += paths[i].Length;
                }

                char ch = paths[i][paths[i].Length - 1];
                if (!PathInternal.IsDirectorySeparator(ch))
                {
                    maxSize++;
                }
            }

            Span <char> initialBuffer = stackalloc char[260];    // MaxShortPath on Windows
            var         builder       = new ValueStringBuilder(initialBuffer);

            builder.EnsureCapacity(maxSize);

            for (int i = firstComponent; i < paths.Length; i++)
            {
                if (paths[i].Length == 0)
                {
                    continue;
                }

                if (builder.Length == 0)
                {
                    builder.Append(paths[i]);
                }
                else
                {
                    char ch = builder[builder.Length - 1];
                    if (!PathInternal.IsDirectorySeparator(ch))
                    {
                        builder.Append(PathInternal.DirectorySeparatorChar);
                    }

                    builder.Append(paths[i]);
                }
            }

            return(builder.ToString());
        }
示例#6
0
        //
        // IRI normalization for strings containing characters that are not allowed or
        // escaped characters that should be unescaped in the context of the specified Uri component.
        //
        internal static unsafe string EscapeUnescapeIri(char *pInput, int start, int end, UriComponents component)
        {
            int size = end - start;
            ValueStringBuilder dest = new ValueStringBuilder(size);

            byte[]? bytes = null;

            const int percentEncodingLen = 3; // Escaped UTF-8 will take 3 chars: %AB.
            int       bufferRemaining    = 0;

            int  next = start;
            char ch;
            bool escape        = false;
            bool surrogatePair = false;

            for (; next < end; ++next)
            {
                escape        = false;
                surrogatePair = false;

                if ((ch = pInput[next]) == '%')
                {
                    if (next + 2 < end)
                    {
                        ch = UriHelper.EscapedAscii(pInput[next + 1], pInput[next + 2]);

                        // Do not unescape a reserved char
                        if (ch == Uri.c_DummyChar || ch == '%' || CheckIsReserved(ch, component) || UriHelper.IsNotSafeForUnescape(ch))
                        {
                            // keep as is
                            dest.Append(pInput[next++]);
                            dest.Append(pInput[next++]);
                            dest.Append(pInput[next]);
                            continue;
                        }
                        else if (ch <= '\x7F')
                        {
                            Debug.Assert(ch < 0xFF, "Expecting ASCII character.");
                            //ASCII
                            dest.Append(ch);
                            next += 2;
                            continue;
                        }
                        else
                        {
                            // possibly utf8 encoded sequence of unicode

                            // check if safe to unescape according to Iri rules

                            Debug.Assert(ch < 0xFF, "Expecting ASCII character.");

                            int startSeq  = next;
                            int byteCount = 1;
                            // lazy initialization of max size, will reuse the array for next sequences
                            if ((object?)bytes == null)
                            {
                                bytes = new byte[end - next];
                            }

                            bytes[0] = (byte)ch;
                            next    += 3;
                            while (next < end)
                            {
                                // Check on exit criterion
                                if ((ch = pInput[next]) != '%' || next + 2 >= end)
                                {
                                    break;
                                }

                                // already made sure we have 3 characters in str
                                ch = UriHelper.EscapedAscii(pInput[next + 1], pInput[next + 2]);

                                //invalid hex sequence ?
                                if (ch == Uri.c_DummyChar)
                                {
                                    break;
                                }
                                // character is not part of a UTF-8 sequence ?
                                else if (ch < '\x80')
                                {
                                    break;
                                }
                                else
                                {
                                    //a UTF-8 sequence
                                    bytes[byteCount++] = (byte)ch;
                                    next += 3;
                                }

                                Debug.Assert(ch < 0xFF, "Expecting ASCII character.");
                            }
                            next--; // for loop will increment


                            // Using encoder with no replacement fall-back will skip all invalid UTF-8 sequences.
                            Encoding noFallbackCharUTF8 = Encoding.GetEncoding(
                                Encoding.UTF8.CodePage,
                                new EncoderReplacementFallback(""),
                                new DecoderReplacementFallback(""));

                            char[] unescapedChars = new char[bytes.Length];
                            int    charCount      = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0);


                            if (charCount != 0)
                            {
                                // If invalid sequences were present in the original escaped string, we need to
                                // copy the escaped versions of those sequences.
                                // Decoded Unicode values will be kept only when they are allowed by the URI/IRI RFC
                                // rules.
                                UriHelper.MatchUTF8Sequence(ref dest, unescapedChars, charCount, bytes,
                                                            byteCount, component == UriComponents.Query, true);
                            }
                            else
                            {
                                // copy escaped sequence as is
                                for (int i = startSeq; i <= next; ++i)
                                {
                                    dest.Append(pInput[i]);
                                }
                            }
                        }
                    }
                    else
                    {
                        dest.Append(pInput[next]);
                    }
                }
                else if (ch > '\x7f')
                {
                    // unicode

                    char ch2;

                    if ((char.IsHighSurrogate(ch)) && (next + 1 < end))
                    {
                        ch2    = pInput[next + 1];
                        escape = !CheckIriUnicodeRange(ch, ch2, ref surrogatePair, component == UriComponents.Query);
                        if (!escape)
                        {
                            // copy the two chars
                            dest.Append(pInput[next++]);
                            dest.Append(pInput[next]);
                        }
                    }
                    else
                    {
                        if (CheckIriUnicodeRange(ch, component == UriComponents.Query))
                        {
                            // copy it
                            dest.Append(pInput[next]);
                        }
                        else
                        {
                            // escape it
                            escape = true;
                        }
                    }
                }
                else
                {
                    // just copy the character
                    dest.Append(pInput[next]);
                }

                if (escape)
                {
                    const int MaxNumberOfBytesEncoded = 4;

                    byte[] encodedBytes = new byte[MaxNumberOfBytesEncoded];
                    fixed(byte *pEncodedBytes = &encodedBytes[0])
                    {
                        int encodedBytesCount = Encoding.UTF8.GetBytes(pInput + next, surrogatePair ? 2 : 1, pEncodedBytes, MaxNumberOfBytesEncoded);

                        Debug.Assert(encodedBytesCount <= MaxNumberOfBytesEncoded, "UTF8 encoder should not exceed specified byteCount");

                        bufferRemaining -= encodedBytesCount * percentEncodingLen;

                        for (int count = 0; count < encodedBytesCount; ++count)
                        {
                            UriHelper.EscapeAsciiChar((char)encodedBytes[count], ref dest);
                        }
                    }
                }
            }

            string result = dest.ToString();

            return(result);
        }
示例#7
0
            static string GetJoinedStringValueFromArray(string[] values)
            {
                // Calculate final length
                int length = 0;

                for (int i = 0; i < values.Length; i++)
                {
                    string value = values[i];
                    // Skip null and empty values
                    if (value != null && value.Length > 0)
                    {
                        if (length > 0)
                        {
                            // Add seperator
                            length++;
                        }

                        length += value.Length;
                    }
                }
#if NETCOREAPP
                // Create the new string
                return(string.Create(length, values, (span, strings) => {
                    int offset = 0;
                    // Skip null and empty values
                    for (int i = 0; i < strings.Length; i++)
                    {
                        string value = strings[i];
                        if (value != null && value.Length > 0)
                        {
                            if (offset > 0)
                            {
                                // Add seperator
                                span[offset] = ',';
                                offset++;
                            }

                            value.AsSpan().CopyTo(span.Slice(offset));
                            offset += value.Length;
                        }
                    }
                }));
#else
                var  sb       = new ValueStringBuilder(length);
                bool hasAdded = false;
                // Skip null and empty values
                for (int i = 0; i < values.Length; i++)
                {
                    string value = values[i];
                    if (value != null && value.Length > 0)
                    {
                        if (hasAdded)
                        {
                            // Add seperator
                            sb.Append(',');
                        }

                        sb.Append(value);
                        hasAdded = true;
                    }
                }

                return(sb.ToString());
#endif
            }
示例#8
0
        private static string FormatBigIntegerToHex(BigInteger value, char format, int digits, NumberFormatInfo info)
        {
            Debug.Assert(format == 'x' || format == 'X');

            // Get the bytes that make up the BigInteger.
            Span <byte> bits = stackalloc byte[64]; // arbitrary limit to switch from stack to heap

            bits = value.TryWriteBytes(bits, out int bytesWritten) ?
                   bits.Slice(0, bytesWritten) :
                   value.ToByteArray();

            Span <char> stackSpace = stackalloc char[128]; // each byte is typically two chars
            var         sb         = new ValueStringBuilder(stackSpace);
            int         cur        = bits.Length - 1;

            if (cur > -1)
            {
                // [FF..F8] drop the high F as the two's complement negative number remains clear
                // [F7..08] retain the high bits as the two's complement number is wrong without it
                // [07..00] drop the high 0 as the two's complement positive number remains clear
                bool clearHighF = false;
                byte head       = bits[cur];

                if (head > 0xF7)
                {
                    head      -= 0xF0;
                    clearHighF = true;
                }

                if (head < 0x08 || clearHighF)
                {
                    // {0xF8-0xFF} print as {8-F}
                    // {0x00-0x07} print as {0-7}
                    sb.Append(head < 10 ?
                              (char)(head + '0') :
                              format == 'X' ? (char)((head & 0xF) - 10 + 'A') : (char)((head & 0xF) - 10 + 'a'));
                    cur--;
                }
            }

            if (cur > -1)
            {
                Span <char> chars     = sb.AppendSpan((cur + 1) * 2);
                int         charsPos  = 0;
                string      hexValues = format == 'x' ? "0123456789abcdef" : "0123456789ABCDEF";
                while (cur > -1)
                {
                    byte b = bits[cur--];
                    chars[charsPos++] = hexValues[b >> 4];
                    chars[charsPos++] = hexValues[b & 0xF];
                }
            }

            if (digits > sb.Length)
            {
                // Insert leading zeros, e.g. user specified "X5" so we create "0ABCD" instead of "ABCD"
                sb.Insert(
                    0,
                    value._sign >= 0 ? '0' : (format == 'x') ? 'f' : 'F',
                    digits - sb.Length);
            }

            return(sb.ToString());
        }
示例#9
0
        internal static string Normalize(string path)
        {
            Span <char> initialBuffer = stackalloc char[PathInternal.MaxShortPath];
            var         builder       = new ValueStringBuilder(initialBuffer);

            // Get the full path
            GetFullPathName(path.AsSpan(), ref builder);

            // If we have the exact same string we were passed in, don't allocate another string.
            // TryExpandShortName does this input identity check.
            string result = builder.AsSpan().IndexOf('~') >= 0
                ? TryExpandShortFileName(ref builder, originalPath: path)
                : builder.AsSpan().Equals(path.AsSpan(), StringComparison.Ordinal) ? path : builder.ToString();

            // Clear the buffer
            builder.Dispose();
            return(result);
        }
示例#10
0
        internal static string NormalizeDirectorySeparators(string path)
        {
            if (string.IsNullOrEmpty(path))
            {
                return(path);
            }

            char current;

            // Make a pass to see if we need to normalize so we can potentially skip allocating
            bool normalized = true;

            for (int i = 0; i < path.Length; i++)
            {
                current = path[i];
                if (IsDirectorySeparator(current) &&
                    (current != DirectorySeparatorChar
                     // Check for sequential separators past the first position (we need to keep initial two for UNC/extended)
                     || (i > 0 && i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))))
                {
                    normalized = false;
                    break;
                }
            }

            if (normalized)
            {
                return(path);
            }

            Span <char>        initialBuffer = stackalloc char[MaxShortPath];
            ValueStringBuilder builder       = new ValueStringBuilder(initialBuffer);

            int start = 0;

            if (IsDirectorySeparator(path[start]))
            {
                start++;
                builder.Append(DirectorySeparatorChar);
            }

            for (int i = start; i < path.Length; i++)
            {
                current = path[i];

                // If we have a separator
                if (IsDirectorySeparator(current))
                {
                    // If the next is a separator, skip adding this
                    if (i + 1 < path.Length && IsDirectorySeparator(path[i + 1]))
                    {
                        continue;
                    }

                    // Ensure it is the primary separator
                    current = DirectorySeparatorChar;
                }

                builder.Append(current);
            }

            return(builder.ToString());
        }
示例#11
0
        //
        // IRI normalization for strings containing characters that are not allowed or
        // escaped characters that should be unescaped in the context of the specified Uri component.
        //
        internal static unsafe string EscapeUnescapeIri(char *pInput, int start, int end, UriComponents component)
        {
            int size = end - start;
            ValueStringBuilder dest = new ValueStringBuilder(size);

            byte[]? bytes = null;

            int  next = start;
            char ch;

            for (; next < end; ++next)
            {
                if ((ch = pInput[next]) == '%')
                {
                    if (next + 2 < end)
                    {
                        ch = UriHelper.EscapedAscii(pInput[next + 1], pInput[next + 2]);

                        // Do not unescape a reserved char
                        if (ch == Uri.c_DummyChar || ch == '%' || CheckIsReserved(ch, component) || UriHelper.IsNotSafeForUnescape(ch))
                        {
                            // keep as is
                            dest.Append(pInput[next++]);
                            dest.Append(pInput[next++]);
                            dest.Append(pInput[next]);
                            continue;
                        }
                        else if (ch <= '\x7F')
                        {
                            Debug.Assert(ch < 0xFF, "Expecting ASCII character.");
                            //ASCII
                            dest.Append(ch);
                            next += 2;
                            continue;
                        }
                        else
                        {
                            // possibly utf8 encoded sequence of unicode

                            // check if safe to unescape according to Iri rules

                            Debug.Assert(ch < 0xFF, "Expecting ASCII character.");

                            int startSeq  = next;
                            int byteCount = 1;
                            // lazy initialization of max size, will reuse the array for next sequences
                            if ((object?)bytes == null)
                            {
                                bytes = new byte[end - next];
                            }

                            bytes[0] = (byte)ch;
                            next    += 3;
                            while (next < end)
                            {
                                // Check on exit criterion
                                if ((ch = pInput[next]) != '%' || next + 2 >= end)
                                {
                                    break;
                                }

                                // already made sure we have 3 characters in str
                                ch = UriHelper.EscapedAscii(pInput[next + 1], pInput[next + 2]);

                                //invalid hex sequence ?
                                if (ch == Uri.c_DummyChar)
                                {
                                    break;
                                }
                                // character is not part of a UTF-8 sequence ?
                                else if (ch < '\x80')
                                {
                                    break;
                                }
                                else
                                {
                                    //a UTF-8 sequence
                                    bytes[byteCount++] = (byte)ch;
                                    next += 3;
                                }

                                Debug.Assert(ch < 0xFF, "Expecting ASCII character.");
                            }
                            next--; // for loop will increment


                            // Using encoder with no replacement fall-back will skip all invalid UTF-8 sequences.
                            Encoding noFallbackCharUTF8 = Encoding.GetEncoding(
                                Encoding.UTF8.CodePage,
                                new EncoderReplacementFallback(""),
                                new DecoderReplacementFallback(""));

                            char[] unescapedChars = new char[bytes.Length];
                            int    charCount      = noFallbackCharUTF8.GetChars(bytes, 0, byteCount, unescapedChars, 0);


                            if (charCount != 0)
                            {
                                // If invalid sequences were present in the original escaped string, we need to
                                // copy the escaped versions of those sequences.
                                // Decoded Unicode values will be kept only when they are allowed by the URI/IRI RFC
                                // rules.
                                UriHelper.MatchUTF8Sequence(ref dest, unescapedChars, charCount, bytes,
                                                            byteCount, component == UriComponents.Query, true);
                            }
                            else
                            {
                                // copy escaped sequence as is
                                for (int i = startSeq; i <= next; ++i)
                                {
                                    dest.Append(pInput[i]);
                                }
                            }
                        }
                    }
                    else
                    {
                        dest.Append(pInput[next]);
                    }
                }
                else if (ch > '\x7f')
                {
                    // unicode

                    bool escape;
                    bool surrogatePair = false;

                    char ch2 = '\0';

                    if ((char.IsHighSurrogate(ch)) && (next + 1 < end))
                    {
                        ch2    = pInput[next + 1];
                        escape = !CheckIriUnicodeRange(ch, ch2, ref surrogatePair, component == UriComponents.Query);
                    }
                    else
                    {
                        escape = !CheckIriUnicodeRange(ch, component == UriComponents.Query);
                    }

                    if (escape)
                    {
                        Span <byte> encodedBytes = stackalloc byte[4];

                        Rune rune;
                        if (surrogatePair)
                        {
                            rune = new Rune(ch, ch2);
                        }
                        else if (!Rune.TryCreate(ch, out rune))
                        {
                            rune = Rune.ReplacementChar;
                        }

                        int bytesWritten = rune.EncodeToUtf8(encodedBytes);
                        encodedBytes = encodedBytes.Slice(0, bytesWritten);

                        foreach (byte b in encodedBytes)
                        {
                            UriHelper.EscapeAsciiChar(b, ref dest);
                        }
                    }
                    else
                    {
                        dest.Append(ch);
                        if (surrogatePair)
                        {
                            dest.Append(ch2);
                        }
                    }

                    if (surrogatePair)
                    {
                        next++;
                    }
                }
                else
                {
                    // just copy the character
                    dest.Append(pInput[next]);
                }
            }

            string result = dest.ToString();

            return(result);
        }
示例#12
0
        private static string?FormatBigIntegerToHex(bool targetSpan, BigInteger value, char format, int digits, NumberFormatInfo info, Span <char> destination, out int charsWritten, out bool spanSuccess)
        {
            Debug.Assert(format == 'x' || format == 'X');

            // Get the bytes that make up the BigInteger.
            byte[]? arrayToReturnToPool = null;
            Span <byte> bits = stackalloc byte[64]; // arbitrary threshold

            if (!value.TryWriteOrCountBytes(bits, out int bytesWrittenOrNeeded))
            {
                bits = arrayToReturnToPool = ArrayPool <byte> .Shared.Rent(bytesWrittenOrNeeded);

                bool success = value.TryWriteBytes(bits, out bytesWrittenOrNeeded);
                Debug.Assert(success);
            }
            bits = bits.Slice(0, bytesWrittenOrNeeded);

            Span <char> stackSpace = stackalloc char[128]; // each byte is typically two chars
            var         sb         = new ValueStringBuilder(stackSpace);

            int cur = bits.Length - 1;

            if (cur > -1)
            {
                // [FF..F8] drop the high F as the two's complement negative number remains clear
                // [F7..08] retain the high bits as the two's complement number is wrong without it
                // [07..00] drop the high 0 as the two's complement positive number remains clear
                bool clearHighF = false;
                byte head       = bits[cur];

                if (head > 0xF7)
                {
                    head      -= 0xF0;
                    clearHighF = true;
                }

                if (head < 0x08 || clearHighF)
                {
                    // {0xF8-0xFF} print as {8-F}
                    // {0x00-0x07} print as {0-7}
                    sb.Append(head < 10 ?
                              (char)(head + '0') :
                              format == 'X' ? (char)((head & 0xF) - 10 + 'A') : (char)((head & 0xF) - 10 + 'a'));
                    cur--;
                }
            }

            if (cur > -1)
            {
                Span <char> chars     = sb.AppendSpan((cur + 1) * 2);
                int         charsPos  = 0;
                string      hexValues = format == 'x' ? "0123456789abcdef" : "0123456789ABCDEF";
                while (cur > -1)
                {
                    byte b = bits[cur--];
                    chars[charsPos++] = hexValues[b >> 4];
                    chars[charsPos++] = hexValues[b & 0xF];
                }
            }

            if (digits > sb.Length)
            {
                // Insert leading zeros, e.g. user specified "X5" so we create "0ABCD" instead of "ABCD"
                sb.Insert(
                    0,
                    value._sign >= 0 ? '0' : (format == 'x') ? 'f' : 'F',
                    digits - sb.Length);
            }

            if (arrayToReturnToPool != null)
            {
                ArrayPool <byte> .Shared.Return(arrayToReturnToPool);
            }

            if (targetSpan)
            {
                spanSuccess = sb.TryCopyTo(destination, out charsWritten);
                return(null);
            }
            else
            {
                charsWritten = 0;
                spanSuccess  = false;
                return(sb.ToString());
            }
        }
        public string CreateReagentListString(string separator)
        {
            ValueStringBuilder sb = new ValueStringBuilder();
            {
                for (int i = 0; i < Regs.Length; i++)
                {
                    switch (Regs[i])
                    {
                    // britanian reagents
                    case Reagents.BlackPearl:
                        sb.Append(ResGeneral.BlackPearl);

                        break;

                    case Reagents.Bloodmoss:
                        sb.Append(ResGeneral.Bloodmoss);

                        break;

                    case Reagents.Garlic:
                        sb.Append(ResGeneral.Garlic);

                        break;

                    case Reagents.Ginseng:
                        sb.Append(ResGeneral.Ginseng);

                        break;

                    case Reagents.MandrakeRoot:
                        sb.Append(ResGeneral.MandrakeRoot);

                        break;

                    case Reagents.Nightshade:
                        sb.Append(ResGeneral.Nightshade);

                        break;

                    case Reagents.SulfurousAsh:
                        sb.Append(ResGeneral.SulfurousAsh);

                        break;

                    case Reagents.SpidersSilk:
                        sb.Append(ResGeneral.SpidersSilk);

                        break;

                    // pagan reagents
                    case Reagents.BatWing:
                        sb.Append(ResGeneral.BatWing);

                        break;

                    case Reagents.GraveDust:
                        sb.Append(ResGeneral.GraveDust);

                        break;

                    case Reagents.DaemonBlood:
                        sb.Append(ResGeneral.DaemonBlood);

                        break;

                    case Reagents.NoxCrystal:
                        sb.Append(ResGeneral.NoxCrystal);

                        break;

                    case Reagents.PigIron:
                        sb.Append(ResGeneral.PigIron);

                        break;

                    default:

                        if (Regs[i] < Reagents.None)
                        {
                            sb.Append(StringHelper.AddSpaceBeforeCapital(Regs[i].ToString()));
                        }

                        break;
                    }

                    if (i < Regs.Length - 1)
                    {
                        sb.Append(separator);
                    }
                }

                string ss = sb.ToString();
                sb.Dispose();
                return(ss);
            }
        }
示例#14
0
        private static void LogPacket(byte[] buffer, int length, bool toServer)
        {
            if (_logFile == null)
            {
                _logFile = new LogFile(FileSystemHelper.CreateFolderIfNotExists(CUOEnviroment.ExecutablePath, "Logs", "Network"), "packets.log");
            }

            Span <char>        span   = stackalloc char[256];
            ValueStringBuilder output = new ValueStringBuilder(span);
            {
                int off = sizeof(ulong) + 2;

                output.Append(' ', off);
                output.Append(string.Format("Ticks: {0} | {1} |  ID: {2:X2}   Length: {3}\n", Time.Ticks, (toServer ? "Client -> Server" : "Server -> Client"), buffer[0], length));

                if (buffer[0] == 0x80 || buffer[0] == 0x91)
                {
                    output.Append(' ', off);
                    output.Append("[ACCOUNT CREDENTIALS HIDDEN]\n");
                }
                else
                {
                    output.Append(' ', off);
                    output.Append("0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F\n");

                    output.Append(' ', off);
                    output.Append("-- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --\n");

                    ulong address = 0;

                    for (int i = 0; i < length; i += 16, address += 16)
                    {
                        output.Append($"{address:X8}");

                        for (int j = 0; j < 16; ++j)
                        {
                            if ((j % 8) == 0)
                            {
                                output.Append(" ");
                            }

                            if (i + j < length)
                            {
                                output.Append($" {buffer[i + j]:X2}");
                            }
                            else
                            {
                                output.Append("   ");
                            }
                        }

                        output.Append("  ");

                        for (int j = 0; j < 16 && i + j < length; ++j)
                        {
                            byte c = buffer[i + j];

                            if (c >= 0x20 && c < 0x80)
                            {
                                output.Append((char)c);
                            }
                            else
                            {
                                output.Append('.');
                            }
                        }

                        output.Append('\n');
                    }
                }

                output.Append('\n');
                output.Append('\n');

                _logFile.Write(output.ToString());

                output.Dispose();
            }
        }
示例#15
0
        public override object?ConvertTo(ITypeDescriptorContext?context, CultureInfo?culture, object?value, Type destinationType)
        {
            if (value is Font font)
            {
                if (destinationType == typeof(string))
                {
                    if (culture == null)
                    {
                        culture = CultureInfo.CurrentCulture;
                    }

                    ValueStringBuilder sb = default;
                    sb.Append(font.Name);
                    sb.Append(culture.TextInfo.ListSeparator[0]);
                    sb.Append(" ");
                    sb.Append(font.Size.ToString(culture.NumberFormat));

                    switch (font.Unit)
                    {
                    // MS throws ArgumentException, if unit is set
                    // to GraphicsUnit.Display
                    // Don't know what to append for GraphicsUnit.Display
                    case GraphicsUnit.Display:
                        sb.Append("display");
                        break;

                    case GraphicsUnit.Document:
                        sb.Append("doc");
                        break;

                    case GraphicsUnit.Point:
                        sb.Append("pt");
                        break;

                    case GraphicsUnit.Inch:
                        sb.Append("in");
                        break;

                    case GraphicsUnit.Millimeter:
                        sb.Append("mm");
                        break;

                    case GraphicsUnit.Pixel:
                        sb.Append("px");
                        break;

                    case GraphicsUnit.World:
                        sb.Append("world");
                        break;
                    }

                    if (font.Style != FontStyle.Regular)
                    {
                        sb.Append(culture.TextInfo.ListSeparator[0]);
                        sb.Append(" style=");
                        sb.Append(font.Style.ToString());
                    }

                    return(sb.ToString());
                }

                if (destinationType == typeof(InstanceDescriptor))
                {
                    ConstructorInfo?met  = typeof(Font).GetConstructor(new Type[] { typeof(string), typeof(float), typeof(FontStyle), typeof(GraphicsUnit) });
                    object[]        args = new object[4];
                    args[0] = font.Name;
                    args[1] = font.Size;
                    args[2] = font.Style;
                    args[3] = font.Unit;

                    return(new InstanceDescriptor(met, args));
                }
            }

            return(base.ConvertTo(context, culture, value, destinationType));
        }
示例#16
0
        public void TestStringBuilders()
        {
            {
                Span <char> buf = stackalloc char[128];
                var         bdr = new FixedStringBuilder(buf);
                bdr.AppendLine("Hello World");
                bdr.Append("Hello");
                bdr.Append(' ');
                bdr.Append(12);
                bdr.Append(' ');
                bdr.AppendLine("Worlds");
                int numReplaced = bdr.Replace('e', 'u');
                Assert.AreEqual(2, numReplaced);

                var expected = "Hullo World" + Environment.NewLine + "Hullo 12 Worlds" + Environment.NewLine;
                Assert.AreEqual(expected.Length, bdr.Length);
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));

                numReplaced = bdr.Replace("Hullo", "Hi");
                Assert.AreEqual(2, numReplaced);
                expected = expected.Replace("Hullo", "Hi");
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));

                numReplaced = bdr.Replace("Hi", "");
                Assert.AreEqual(2, numReplaced);
                expected = expected.Replace("Hi", "");
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));

                bdr.Replace("World", "World");
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));
                bdr.Replace("Florka", "--");
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));
                bdr.Replace("Florka", "Florka");
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual(expected));

                bdr.Clear();
                Assert.AreEqual(0, bdr.Length);
                Assert.AreEqual("", bdr.ToString());
                bdr.Append("Koko");
                bdr.Append('s');
                Assert.AreEqual("Kokos".Length, bdr.Length);
                Assert.IsTrue(bdr.ReadOnlySpan.SequenceEqual("Kokos"));
            }

            {
                var sbdr = new ValueStringBuilder(8);
                sbdr.AppendLine("Hello World");
                sbdr.Append("Hello");
                sbdr.Append(' ');
                sbdr.Append(12u);
                sbdr.Append(' ');
                sbdr.AppendLine("Worlds");
                var numReplaced = sbdr.Replace('e', 'u');
                Assert.AreEqual(2, numReplaced);

                var expected = "Hullo World" + Environment.NewLine + "Hullo 12 Worlds" + Environment.NewLine;
                Assert.AreEqual(expected.Length, sbdr.Length);
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));

                numReplaced = sbdr.Replace("Hullo", "Hi");
                Assert.AreEqual(2, numReplaced);
                expected = expected.Replace("Hullo", "Hi");
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));

                numReplaced = sbdr.Replace("Hi", "");
                Assert.AreEqual(2, numReplaced);
                expected = expected.Replace("Hi", "");
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));

                sbdr.Replace("World", "World");
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));
                sbdr.Replace("Florka", "--");
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));
                sbdr.Replace("Florka", "Florka");
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual(expected));

                sbdr.Clear();
                Assert.AreEqual(0, sbdr.Length);
                Assert.AreEqual("", sbdr.ToString());
                sbdr.Append("Koko");
                sbdr.Append('s');
                Assert.AreEqual("Kokos".Length, sbdr.Length);
                Assert.IsTrue(sbdr.ReadOnlySpan.SequenceEqual("Kokos"));
            }
        }
示例#17
0
        private readonly int[] _rules;      // negative -> group #, positive -> string #

        /// <summary>
        /// Since RegexReplacement shares the same parser as Regex,
        /// the constructor takes a RegexNode which is a concatenation
        /// of constant strings and backreferences.
        /// </summary>
        public RegexReplacement(string rep, RegexNode concat, Hashtable _caps)
        {
            if (concat.Type != RegexNode.Concatenate)
            {
                throw ThrowHelper.CreateArgumentException(ExceptionResource.ReplacementError);
            }

            Span <char>      vsbStack     = stackalloc char[256];
            var              vsb          = new ValueStringBuilder(vsbStack);
            FourStackStrings stackStrings = default;
            var              strings      = new ValueListBuilder <string>(MemoryMarshal.CreateSpan(ref stackStrings.Item1 !, 4));
            var              rules        = new ValueListBuilder <int>(stackalloc int[64]);

            int childCount = concat.ChildCount();

            for (int i = 0; i < childCount; i++)
            {
                RegexNode child = concat.Child(i);

                switch (child.Type)
                {
                case RegexNode.Multi:
                    vsb.Append(child.Str !);
                    break;

                case RegexNode.One:
                    vsb.Append(child.Ch);
                    break;

                case RegexNode.Ref:
                    if (vsb.Length > 0)
                    {
                        rules.Append(strings.Length);
                        strings.Append(vsb.ToString());
                        vsb = new ValueStringBuilder(vsbStack);
                    }
                    int slot = child.M;

                    if (_caps != null && slot >= 0)
                    {
                        slot = (int)_caps[slot] !;
                    }

                    rules.Append(-Specials - 1 - slot);
                    break;

                default:
                    throw ThrowHelper.CreateArgumentException(ExceptionResource.ReplacementError);
                }
            }

            if (vsb.Length > 0)
            {
                rules.Append(strings.Length);
                strings.Append(vsb.ToString());
            }

            Pattern  = rep;
            _strings = strings.AsSpan().ToArray();
            _rules   = rules.AsSpan().ToArray();

            rules.Dispose();
        }
示例#18
0
        public static void HandleMessage
        (
            Entity parent,
            string text,
            string name,
            ushort hue,
            MessageType type,
            byte font,
            TextType textType,
            bool unicode = false,
            string lang  = null
        )
        {
            if (string.IsNullOrEmpty(text))
            {
                return;
            }

            Profile currentProfile = ProfileManager.CurrentProfile;

            if (currentProfile != null && currentProfile.OverrideAllFonts)
            {
                font    = currentProfile.ChatFont;
                unicode = currentProfile.OverrideAllFontsIsUnicode;
            }

            switch (type)
            {
            case MessageType.Command:
            case MessageType.Encoded:
            case MessageType.System:
            case MessageType.Party:
                break;

            case MessageType.Guild:
                if (currentProfile.IgnoreGuildMessages)
                {
                    return;
                }
                break;

            case MessageType.Alliance:
                if (currentProfile.IgnoreAllianceMessages)
                {
                    return;
                }
                break;

            case MessageType.Spell:
            {
                //server hue color per default
                if (!string.IsNullOrEmpty(text) && SpellDefinition.WordToTargettype.TryGetValue(text, out SpellDefinition spell))
                {
                    if (currentProfile != null && currentProfile.EnabledSpellFormat && !string.IsNullOrWhiteSpace(currentProfile.SpellDisplayFormat))
                    {
                        ValueStringBuilder sb = new ValueStringBuilder(currentProfile.SpellDisplayFormat.AsSpan());
                        {
                            sb.Replace("{power}".AsSpan(), spell.PowerWords.AsSpan());
                            sb.Replace("{spell}".AsSpan(), spell.Name.AsSpan());

                            text = sb.ToString().Trim();
                        }
                        sb.Dispose();
                    }

                    //server hue color per default if not enabled
                    if (currentProfile != null && currentProfile.EnabledSpellHue)
                    {
                        if (spell.TargetType == TargetType.Beneficial)
                        {
                            hue = currentProfile.BeneficHue;
                        }
                        else if (spell.TargetType == TargetType.Harmful)
                        {
                            hue = currentProfile.HarmfulHue;
                        }
                        else
                        {
                            hue = currentProfile.NeutralHue;
                        }
                    }
                }

                goto case MessageType.Label;
            }

            default:
            case MessageType.Focus:
            case MessageType.Whisper:
            case MessageType.Yell:
            case MessageType.Regular:
            case MessageType.Label:
            case MessageType.Limit3Spell:

                if (parent == null)
                {
                    break;
                }

                TextObject msg = CreateMessage
                                 (
                    text,
                    hue,
                    font,
                    unicode,
                    type,
                    textType
                                 );

                msg.Owner = parent;

                if (parent is Item it && !it.OnGround)
                {
                    msg.X          = DelayedObjectClickManager.X;
                    msg.Y          = DelayedObjectClickManager.Y;
                    msg.IsTextGump = true;
                    bool found = false;

                    for (LinkedListNode <Gump> gump = UIManager.Gumps.Last; gump != null; gump = gump.Previous)
                    {
                        Control g = gump.Value;

                        if (!g.IsDisposed)
                        {
                            switch (g)
                            {
                            case PaperDollGump paperDoll when g.LocalSerial == it.Container:
                                paperDoll.AddText(msg);
                                found = true;

                                break;

                            case ContainerGump container when g.LocalSerial == it.Container:
                                container.AddText(msg);
                                found = true;

                                break;

                            case TradingGump trade when trade.ID1 == it.Container || trade.ID2 == it.Container:
                                trade.AddText(msg);
                                found = true;

                                break;
                            }
                        }

                        if (found)
                        {
                            break;
                        }
                    }
                }

                parent.AddMessage(msg);

                break;
            }

            MessageReceived.Raise
            (
                new MessageEventArgs
                (
                    parent,
                    text,
                    name,
                    hue,
                    type,
                    font,
                    textType,
                    unicode,
                    lang
                ),
                parent
            );
        }