Пример #1
0
        private static SqlTokenInfo ReadLiteral(char[] peekBuffer, int peekLength, SqlCharReader reader)
        {
            Debug.Assert(peekBuffer != null);
            Debug.Assert(peekBuffer.Length >= 1);
            Debug.Assert(peekLength >= 1);
            Debug.Assert(reader != null);

            // Sql literals are generally short
            var cap    = peekLength + 32;
            var buffer = new char[cap];
            var sb     = new StringBuilder(cap);

            // We already know the incoming data is "<literal>", so keep it
            sb.Append(peekBuffer, 0, 1);

            // Undo any extraneous data
            if (peekLength >= 2)
            {
                reader.Undo(peekBuffer, 1, peekLength - 1);
            }

            while (true)
            {
                reader.FillRemaining(buffer, 0, out var count);
                if (count <= 0)
                {
                    break;
                }

                for (var i = 0; i < count; i++)
                {
                    switch (buffer[i])
                    {
                    // Math
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                    case '%':

                    // Logical
                    case '&':
                    case '|':
                    case '^':
                    case '~':

                    // Comparison
                    case '>':
                    case '<':
                    case '!':
                    case '=':

                    // Quote
                    case '\'':
                    case '"':

                    // Symbol
                    case ',':
                    case '.':
                    case ';':
                    case ':':
                    case '(':
                    case ')':
                        // Exit if delimiter
                        break;

                    default:
                        // Exit if whitespace
                        if (char.IsWhiteSpace(buffer[i]))
                        {
                            break;
                        }

                        // Loop if not whitespace
                        continue;
                    }

                    if (i >= 1)
                    {
                        sb.Append(buffer, 0, i);
                    }

                    reader.Undo(buffer, i, count - i);

                    var t1 = new SqlTokenInfo(SqlTokenKind.Literal, sb);
                    return(t1);
                }

                sb.Append(buffer, 0, count);
            }

            var token = new SqlTokenInfo(SqlTokenKind.Literal, sb);

            return(token);
        }
Пример #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="peekBuffer"></param>
        /// <param name="peekLength"></param>
        /// <param name="reader"></param>
        /// <param name="skipSundry">Do not emit sundry tokens (such as comments and whitespace) in the output.</param>
        /// <returns></returns>
        private static SqlTokenInfo ReadWhitespace(char[] peekBuffer, int peekLength, SqlCharReader reader, bool skipSundry)
        {
            Debug.Assert(peekBuffer != null);
            Debug.Assert(peekBuffer.Length >= 1);
            Debug.Assert(peekLength >= 1);
            Debug.Assert(reader != null);

            // Fast path for single whitespace
            if (peekLength >= 2 &&
                !char.IsWhiteSpace(peekBuffer[1]))
            {
                // Undo any extraneous data
                reader.Undo(peekBuffer, 1, peekLength - 1);

                var t0 = new SqlTokenInfo(SqlTokenKind.Whitespace, peekBuffer[0]);
                return(t0);
            }

            // Perf: Assume whitespace is N chars
            const int averageLen = 10;
            var       cap        = peekLength + averageLen;
            var       buffer     = new char[cap];
            var       sb         = skipSundry ? null : new StringBuilder(cap);

            // We already know the incoming data is "<whitespace>", so keep it
            if (!skipSundry)
            {
                sb.Append(peekBuffer, 0, peekLength);
            }

            while (true)
            {
                reader.FillRemaining(buffer, 0, out var count);
                if (count <= 0)
                {
                    break;
                }

                // Try find any non-whitespace in current batch
                var idx = -1;
                for (var i = 0; i < count; i++)
                {
                    if (!char.IsWhiteSpace(buffer[i]))
                    {
                        idx = i;
                        break;
                    }
                }

                // If we found any non-whitespace
                if (idx >= 0)
                {
                    // Undo any extraneous data and exit the loop
                    if (!skipSundry)
                    {
                        sb.Append(buffer, 0, idx);
                    }

                    reader.Undo(buffer, idx, count - idx);
                    break;
                }

                // Else keep the whitespace and check next batch
                if (!skipSundry)
                {
                    sb.Append(buffer, 0, count);
                }
            }

            var token = new SqlTokenInfo(SqlTokenKind.Whitespace, sb);

            return(token);
        }