Exemple #1
0
        public bool MoveNext()
        {
            while (true)
            {
                if (_scalars.MoveNext())
                {
                    Rune scalar     = _scalars.Current;
                    byte lbProperty = GetLineBreakProperty(scalar.Value);
                    byte newState;
                    if (_posInScalars == 0)
                    {
                        _state = newState = lbProperty;
                    }
                    else
                    {
                        int i = _state * LinebreakCategoryCount + lbProperty;
                        newState = LinebreakStateMachine[i];
                    }
                    int pos = _posInScalars++;
                    _lenInScalars++;
                    if ((sbyte)newState < 0)
                    {
                        _state = (byte)(newState & 0x3F);
                        SetCurrent(pos, newState);
                        return(true);
                    }
                    _state = newState;
                }
                else
                {
                    if (_posInScalars == _lenInScalars)
                    {
                        _posInScalars++;
                        int  i     = _state * LinebreakCategoryCount;
                        byte state = LinebreakStateMachine[i];
                        SetCurrent(_lenInScalars, state);
                        return(true);
                    }

                    return(false);
                }
            }
        }
Exemple #2
0
        private static void EscapeStringToBuilder(
            ReadOnlySpan <char> stringToEscape, ref ValueStringBuilder vsb,
            ReadOnlySpan <bool> noEscape, bool checkExistingEscaped)
        {
            // Allocate enough stack space to hold any Rune's UTF8 encoding.
            Span <byte> utf8Bytes = stackalloc byte[4];

            // Then enumerate every rune in the input.
            SpanRuneEnumerator e = stringToEscape.EnumerateRunes();

            while (e.MoveNext())
            {
                Rune r = e.Current;

                if (!r.IsAscii)
                {
                    // The rune is non-ASCII, so encode it as UTF8, and escape each UTF8 byte.
                    r.TryEncodeToUtf8(utf8Bytes, out int bytesWritten);
                    foreach (byte b in utf8Bytes.Slice(0, bytesWritten))
                    {
                        vsb.Append('%');
                        HexConverter.ToCharsBuffer(b, vsb.AppendSpan(2), 0, HexConverter.Casing.Upper);
                    }
                    continue;
                }

                // If the value doesn't need to be escaped, append it and continue.
                byte value = (byte)r.Value;
                if (noEscape[value])
                {
                    vsb.Append((char)value);
                    continue;
                }

                // If we're checking for existing escape sequences, then if this is the beginning of
                // one, check the next two characters in the sequence.  This is a little tricky to do
                // as we're using an enumerator, but luckily it's a ref struct-based enumerator: we can
                // make a copy and iterate through the copy without impacting the original, and then only
                // push the original ahead if we find what we're looking for in the copy.
                if (checkExistingEscaped && value == '%')
                {
                    // If the next two characters are valid escaped ASCII, then just output them as-is.
                    SpanRuneEnumerator tmpEnumerator = e;
                    if (tmpEnumerator.MoveNext())
                    {
                        Rune r1 = tmpEnumerator.Current;
                        if (r1.IsAscii && IsHexDigit((char)r1.Value) && tmpEnumerator.MoveNext())
                        {
                            Rune r2 = tmpEnumerator.Current;
                            if (r2.IsAscii && IsHexDigit((char)r2.Value))
                            {
                                vsb.Append('%');
                                vsb.Append((char)r1.Value);
                                vsb.Append((char)r2.Value);
                                e = tmpEnumerator;
                                continue;
                            }
                        }
                    }
                }

                // Otherwise, append the escaped character.
                vsb.Append('%');
                HexConverter.ToCharsBuffer(value, vsb.AppendSpan(2), 0, HexConverter.Casing.Upper);
            }
        }