示例#1
0
            internal override int EncodeUtf16(Rune value, Span <char> destination)
            {
                uint utf8lsb = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)value.Value);

                if (!SpanUtility.IsValidIndex(destination, 2))
                {
                    goto OutOfSpace;
                }
                destination[0] = '%';
                HexConverter.ToCharsBuffer((byte)utf8lsb, destination, startingIndex: 1);
                if ((utf8lsb >>= 8) == 0)
                {
                    return(3);
                }                                       // "%XX"

                if (!SpanUtility.IsValidIndex(destination, 5))
                {
                    goto OutOfSpace;
                }
                destination[3] = '%';
                HexConverter.ToCharsBuffer((byte)utf8lsb, destination, startingIndex: 4);
                if ((utf8lsb >>= 8) == 0)
                {
                    return(6);
                }                                       // "%XX%YY"

                if (!SpanUtility.IsValidIndex(destination, 8))
                {
                    goto OutOfSpace;
                }
                destination[6] = '%';
                HexConverter.ToCharsBuffer((byte)utf8lsb, destination, startingIndex: 7);
                if ((utf8lsb >>= 8) == 0)
                {
                    return(9);
                }                                       // "%XX%YY%ZZ"

                if (!SpanUtility.IsValidIndex(destination, 11))
                {
                    goto OutOfSpace;
                }
                destination[9] = '%';
                HexConverter.ToCharsBuffer((byte)utf8lsb, destination, startingIndex: 10);
                return(12);  // "%XX%YY%ZZ%WW"

OutOfSpace:

                return(-1);
            }
示例#2
0
            // Writes a scalar value as a JavaScript-escaped character (or sequence of characters).
            // See ECMA-262, Sec. 7.8.4, and ECMA-404, Sec. 9
            // https://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4
            // https://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
            //
            // ECMA-262 allows encoding U+000B as "\v", but ECMA-404 does not.
            // Both ECMA-262 and ECMA-404 allow encoding U+002F SOLIDUS as "\/"
            // (in ECMA-262 this character is a NonEscape character); however, we
            // don't encode SOLIDUS by default unless the caller has provided an
            // explicit bitmap which does not contain it. In this case we'll assume
            // that the caller didn't want a SOLIDUS written to the output at all,
            // so it should be written using "\u002F" encoding.
            // HTML-specific characters (including apostrophe and quotes) will
            // be written out as numeric entities for defense-in-depth.

            internal override int EncodeUtf8(Rune value, Span <byte> destination)
            {
                if (_preescapedMap.TryLookup(value, out byte preescapedForm))
                {
                    if (!SpanUtility.IsValidIndex(destination, 1))
                    {
                        goto OutOfSpace;
                    }
                    destination[0] = (byte)'\\';
                    destination[1] = preescapedForm;
                    return(2);

OutOfSpace:
                    return(-1);
                }

                return(TryEncodeScalarAsHex(this, value, destination));
示例#3
0
#pragma warning disable IDE0060 // 'this' taken explicitly to avoid argument shuffling by caller
                static int TryEncodeScalarAsHex(object @this, Rune value, Span <byte> destination)
#pragma warning restore IDE0060
                {
                    if (value.IsBmp)
                    {
                        // Write 6 bytes: "\uXXXX"
                        if (!SpanUtility.IsValidIndex(destination, 5))
                        {
                            goto OutOfSpaceInner;
                        }
                        destination[0] = (byte)'\\';
                        destination[1] = (byte)'u';
                        HexConverter.ToBytesBuffer((byte)value.Value, destination, 4);
                        HexConverter.ToBytesBuffer((byte)((uint)value.Value >> 8), destination, 2);
                        return(6);
                    }
                    else
                    {
                        // Write 12 bytes: "\uXXXX\uYYYY"
                        UnicodeHelpers.GetUtf16SurrogatePairFromAstralScalarValue((uint)value.Value, out char highSurrogate, out char lowSurrogate);
                        if (!SpanUtility.IsValidIndex(destination, 11))
                        {
                            goto OutOfSpaceInner;
                        }
                        destination[0] = (byte)'\\';
                        destination[1] = (byte)'u';
                        HexConverter.ToBytesBuffer((byte)highSurrogate, destination, 4);
                        HexConverter.ToBytesBuffer((byte)((uint)highSurrogate >> 8), destination, 2);
                        destination[6] = (byte)'\\';
                        destination[7] = (byte)'u';
                        HexConverter.ToBytesBuffer((byte)lowSurrogate, destination, 10);
                        HexConverter.ToBytesBuffer((byte)((uint)lowSurrogate >> 8), destination, 8);
                        return(12);
                    }

OutOfSpaceInner:

                    return(-1);
                }
示例#4
0
#pragma warning disable IDE0060 // 'this' taken explicitly to avoid argument shuffling by caller
                static int TryEncodeScalarAsHex(object @this, uint scalarValue, Span <byte> destination)
#pragma warning restore IDE0060
                {
                    UnicodeDebug.AssertIsValidScalar(scalarValue);

                    // See comments in the UTF-16 equivalent method later in this file.

                    int idxOfSemicolon = (int)((uint)BitOperations.Log2(scalarValue) / 4) + 4;

                    Debug.Assert(4 <= idxOfSemicolon && idxOfSemicolon <= 9, "Expected '&#x0;'..'&#x10FFFF;'.");

                    if (!SpanUtility.IsValidIndex(destination, idxOfSemicolon))
                    {
                        goto OutOfSpaceInner;
                    }
                    destination[idxOfSemicolon] = (byte)';';

                    if (!SpanUtility.TryWriteBytes(destination, (byte)'&', (byte)'#', (byte)'x', (byte)'0'))
                    {
                        Debug.Fail("We should've had enough room to write 4 bytes.");
                    }

                    destination = destination.Slice(3, idxOfSemicolon - 3);
                    for (int i = destination.Length - 1; SpanUtility.IsValidIndex(destination, i); i--)
                    {
                        char asUpperHex = HexConverter.ToCharUpper((int)scalarValue);
                        destination[i] = (byte)asUpperHex;
                        scalarValue  >>= 4; // write a nibble - not a byte - at a time
                    }

                    return(destination.Length + 4);

OutOfSpaceInner:

                    return(-1);
                }
示例#5
0
        public void IsValidIndex_Span(string inputData, int index, bool expectedValue)
        {
            Span <char> span = inputData.ToCharArray();

            Assert.Equal(expectedValue, SpanUtility.IsValidIndex(span, index));
        }
示例#6
0
        public void IsValidIndex_ReadOnlySpan(string inputData, int index, bool expectedValue)
        {
            ReadOnlySpan <char> span = inputData.AsSpan();

            Assert.Equal(expectedValue, SpanUtility.IsValidIndex(span, index));
        }