/// <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 }
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); }
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); }
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); }