예제 #1
0
        /// <summary>
        /// Parses string literal text, processes escaped sequences.
        /// </summary>
        /// <param name="buffer">Characters buffer to read from.</param>
        /// <param name="start">Offset in <paramref name="buffer"/> of first character.</param>
        /// <param name="length">Number of characters.</param>
        /// <param name="tryprocess">Callback that handles escaped character sequences. Returns new buffer position in case the sequence was processed, otherwise <c>-1</c>.</param>
        /// <param name="binary">Whether to force a binary string output.</param>
        /// <returns>Parsed text, either <see cref="string"/> or <see cref="byte"/>[].</returns>
        object ProcessStringText(char[] buffer, int start, int length, ProcessStringDelegate tryprocess, bool binary = false)
        {
            Debug.Assert(start >= 0);
            Debug.Assert(length >= 0);
            Debug.Assert(tryprocess != null);

            if (length == 0)
            {
                return(string.Empty);
            }

            int to = start + length;

            Debug.Assert(start >= 0);
            Debug.Assert(to <= buffer.Length);

            PhpStringBuilder lazyBuilder = null;

            // find first backslash quickly
            int index = start;

            while (index < to && buffer[index] != '\\')
            {
                index++;
            }

            //
            for (; index < to; index++)
            {
                var c = buffer[index];
                if (c == '\\' && index + 1 < to)
                {
                    // ensure string builder lazily
                    if (lazyBuilder == null)
                    {
                        lazyBuilder = new PhpStringBuilder(_encoding, binary, length);
                        lazyBuilder.Append(buffer, start, index - start);
                    }

                    int processed = tryprocess(buffer, index + 1, lazyBuilder);
                    if (processed > 0)
                    {
                        Debug.Assert(processed >= index + 1);
                        index = processed;
                        continue;
                    }
                }

                if (lazyBuilder != null)
                {
                    lazyBuilder.Append(c);
                }
            }

            //
            return(lazyBuilder == null
                ? Intern(buffer, start, length)
                : lazyBuilder.StringResult); // TODO: .Result; and handle String or byte[] properly
        }
예제 #2
0
        protected object GetTokenAsSinglyQuotedString(string text, Encoding /*!*/ encoding, bool forceBinaryString)
        {
            PhpStringBuilder result = new PhpStringBuilder(encoding, forceBinaryString, TokenLength);

            int  pos = 1;
            char c;

            while (pos < text.Length)
            {
                c = text[pos++];
                if (c == '\\' && pos < text.Length)
                {
                    switch (c = text[pos++])
                    {
                    case '\\':
                    case '\'':
                        result.Append(c);
                        break;

                    default:
                        result.Append('\\');
                        result.Append(c);
                        break;
                    }
                }
                else
                {
                    if (c == '\'')
                    {
                        break;
                    }
                    result.Append(c);
                }
            }

            return(result.Result);
        }
예제 #3
0
        int _processDoubleQuotedString(char[] buffer, int pos, PhpStringBuilder result)
        {
            switch (buffer[pos])
            {
            case 'n':
                result.Append('\n');
                return(pos);

            case 'r':
                result.Append('\r');
                return(pos);

            case 't':
                result.Append('\t');
                return(pos);

            case 'v':
                result.Append('\v');
                return(pos);

            case 'e':
                result.Append((char)0x1B);
                return(pos);

            case 'f':
                result.Append('\f');
                return(pos);

            case '\\':
            case '$':
            case '"':
                result.Append(buffer[pos]);
                return(pos);

            case '`':
                if (CurrentLexicalState == LexicalStates.ST_IN_SHELL)
                {
                    result.Append(buffer[pos]);
                    return(pos);
                }
                break;

            case 'u':
                if (EnableUtfCodepoints)
                {
                    pos++;
                    result.Append(ParseCodePoint(buffer, ref pos, 4));
                    return(pos - 1);
                }
                else
                {
                    break;
                }

            case 'x':
            {
                // \x[0-9A-Fa-f]{1,2}
                int digit;
                if ((digit = Convert.AlphaNumericToDigit(buffer[++pos])) < 16)
                {
                    int hex_code = digit;
                    if ((digit = Convert.AlphaNumericToDigit(buffer[++pos])) < 16)
                    {
                        hex_code = (hex_code << 4) + digit;
                    }
                    else
                    {
                        pos--;          // rollback
                    }

                    result.Append((byte)hex_code);
                    return(pos);
                }

                break;
            }

            default:
            {
                // \[0-7]{1,3}
                int digit;
                if ((digit = Convert.NumericToDigit(buffer[pos])) < 8)          // 1
                {
                    int octal_code = digit;

                    if ((digit = Convert.NumericToDigit(buffer[++pos])) < 8)            // 2
                    {
                        octal_code = (octal_code << 3) + digit;

                        if ((digit = Convert.NumericToDigit(buffer[++pos])) < 8)            // 3
                        {
                            octal_code = (octal_code << 3) + digit;
                        }
                        else
                        {
                            pos--;         // rollback
                        }
                    }
                    else
                    {
                        pos--;         // rollback
                    }

                    result.Append((byte)octal_code);
                    return(pos);
                }

                break;
            }
            }

            // not handled:
            return(-1);
        }
예제 #4
0
        protected object ProcessEscapedString(string text, Encoding /*!*/ encoding, bool forceBinaryString)
        {
            if (text.Length == 0)
            {
                return(string.Empty);
            }

            PhpStringBuilder result = new PhpStringBuilder(encoding, forceBinaryString, text.Length);

            int  pos = 0;
            char c;

            while (pos < text.Length)
            {
                c = text[pos++];
                if (c == '\\' && pos < text.Length)
                {
                    switch (c = text[pos++])
                    {
                    case 'n':
                        result.Append('\n');
                        break;

                    case 'r':
                        result.Append('\r');
                        break;

                    case 't':
                        result.Append('\t');
                        break;

                    case '\\':
                    case '$':
                    case '"':
                        result.Append(c);
                        break;

                    case 'C':
                        //if (!inUnicodeString) goto default;
                        result.Append(ParseCodePointName(ref pos));
                        break;

                    case 'u':
                    case 'U':
                        //if (!inUnicodeString) goto default;
                        result.Append(ParseCodePoint(c == 'u' ? 4 : 6, ref pos));
                        break;

                    case 'x':
                    {
                        int digit;
                        if (pos < text.Length && (digit = Convert.AlphaNumericToDigit(text[pos])) < 16)
                        {
                            int hex_code = digit;
                            pos++;
                            if (pos < text.Length && (digit = Convert.AlphaNumericToDigit(text[pos])) < 16)
                            {
                                pos++;
                                hex_code = (hex_code << 4) + digit;
                            }

                            //encodeBytes[0] = (byte)hex_code;
                            //result.Append(encodeChars, 0, encoding.GetChars(encodeBytes, 0, 1, encodeChars, 0));
                            result.Append((byte)hex_code);
                        }
                        else
                        {
                            result.Append('\\');
                            result.Append('x');
                        }
                        break;
                    }

                    default:
                    {
                        int digit;
                        if ((digit = Convert.NumericToDigit(c)) < 8)
                        {
                            int octal_code = digit;

                            if (pos < text.Length && (digit = Convert.NumericToDigit(text[pos])) < 8)
                            {
                                octal_code = (octal_code << 3) + digit;
                                pos++;

                                if (pos < text.Length && (digit = Convert.NumericToDigit(text[pos])) < 8)
                                {
                                    pos++;
                                    octal_code = (octal_code << 3) + digit;
                                }
                            }
                            //encodeBytes[0] = (byte)octal_code;
                            //result.Append(encodeChars, 0, encoding.GetChars(encodeBytes, 0, 1, encodeChars, 0));
                            result.Append((byte)octal_code);
                        }
                        else
                        {
                            result.Append('\\');
                            result.Append(c);
                        }
                        break;
                    }
                    }
                }
                else
                {
                    result.Append(c);
                }
            }

            return(result.Result);
        }