public static int NeedsEscaping(ReadOnlySpan <char> value, JavaScriptEncoder encoder)
        {
            if (encoder != null)
            {
                return(encoder.FindFirstCharacterToEncodeUtf8(MemoryMarshal.Cast <char, byte>(value)));
            }

            int idx;

            for (idx = 0; idx < value.Length; idx++)
            {
                if (NeedsEscaping(value[idx]))
                {
                    goto Return;
                }
            }

            idx = -1; // all characters allowed

Return:
            return(idx);
        }
        public static int NeedsEscaping(ReadOnlySpan <byte> value, JavaScriptEncoder encoder)
        {
            int idx;

            if (encoder != null)
            {
                idx = encoder.FindFirstCharacterToEncodeUtf8(value);
                goto Return;
            }

            for (idx = 0; idx < value.Length; idx++)
            {
                if (NeedsEscaping(value[idx]))
                {
                    goto Return;
                }
            }

            idx = -1; // all characters allowed

Return:
            return(idx);
        }
Example #3
0
        public static unsafe int NeedsEscaping(ReadOnlySpan <byte> value, JavaScriptEncoder encoder)
        {
            fixed(byte *ptr = value)
            {
                int idx = 0;

                if (encoder != null)
                {
                    idx = encoder.FindFirstCharacterToEncodeUtf8(value);
                    goto Return;
                }

#if BUILDING_INBOX_LIBRARY
                if (Sse2.IsSupported)
                {
                    sbyte *startingAddress = (sbyte *)ptr;
                    while (value.Length - 16 >= idx)
                    {
                        Debug.Assert(startingAddress >= ptr && startingAddress <= (ptr + value.Length - 16));

                        // Load the next 16 bytes.
                        Vector128 <sbyte> sourceValue = Sse2.LoadVector128(startingAddress);

                        // Check if any of the 16 bytes need to be escaped.
                        Vector128 <sbyte> mask = CreateEscapingMask(sourceValue);

                        int index = Sse2.MoveMask(mask.AsByte());
                        // If index == 0, that means none of the 16 bytes needed to be escaped.
                        // TrailingZeroCount is relatively expensive, avoid it if possible.
                        if (index != 0)
                        {
                            // Found at least one byte that needs to be escaped, figure out the index of
                            // the first one found that needed to be escaped within the 16 bytes.
                            Debug.Assert(index > 0 && index <= 65_535);
                            int tzc = BitOperations.TrailingZeroCount(index);
                            Debug.Assert(tzc >= 0 && tzc <= 16);
                            idx += tzc;
                            goto Return;
                        }
                        idx             += 16;
                        startingAddress += 16;
                    }

                    // Process the remaining characters.
                    Debug.Assert(value.Length - idx < 16);
                }
#endif

                for (; idx < value.Length; idx++)
                {
                    Debug.Assert((ptr + idx) <= (ptr + value.Length));
                    if (NeedsEscaping(*(ptr + idx)))
                    {
                        goto Return;
                    }
                }

                idx = -1; // all characters allowed

Return:
                return(idx);
            }
        }