Example #1
0
 /// <summary>Validates the current character is a digit.</summary>
 private void ValidateDigit()
 {
     if (!this.IsValidDigit)
     {
         throw ParseError(ODataErrorStrings.ExpressionLexer_DigitExpected(this.textPos, this.text));
     }
 }
Example #2
0
        /// <summary>
        /// If the source node is not of the specified type, then we check if type promotion is possible and inject a convert node.
        /// If the source node is the same type as the target type (or if the target type is null), we just return the source node as is.
        /// </summary>
        /// <param name="source">The source node to apply the convertion to.</param>
        /// <param name="targetTypeReference">The target primitive type. May be null - this method will do nothing in that case.</param>
        /// <returns>The converted query node, or the original source node unchanged.</returns>
        internal static SingleValueNode ConvertToTypeIfNeeded(SingleValueNode source, IEdmTypeReference targetTypeReference)
        {
            DebugUtils.CheckNoExternalCallers();
            Debug.Assert(source != null, "source != null");

            if (targetTypeReference == null)
            {
                return(source);
            }

            if (source.TypeReference != null)
            {
                if (source.TypeReference.IsEquivalentTo(targetTypeReference))
                {
                    return(source);
                }

                if (!TypePromotionUtils.CanConvertTo(source.TypeReference, targetTypeReference))
                {
                    throw new ODataException(ODataErrorStrings.MetadataBinder_CannotConvertToType(source.TypeReference.ODataFullName(), targetTypeReference.ODataFullName()));
                }
            }

            // If the source doesn't have a type (possibly an open property), then it's possible to convert it
            // cause we don't know for sure.
            return(new ConvertNode(source, targetTypeReference));
        }
Example #3
0
        /// <summary>
        /// Create a BinaryOperatorNode
        /// </summary>
        /// <param name="operatorKind">The binary operator type.</param>
        /// <param name="left">The left operand.</param>
        /// <param name="right">The right operand.</param>
        /// <exception cref="System.ArgumentNullException">Throws if the left or right inputs are null.</exception>
        /// <exception cref="ODataException">Throws if the two operands don't have the same type.</exception>
        public BinaryOperatorNode(BinaryOperatorKind operatorKind, SingleValueNode left, SingleValueNode right)
        {
            ExceptionUtils.CheckArgumentNotNull(left, "left");
            ExceptionUtils.CheckArgumentNotNull(right, "right");
            this.operatorKind = operatorKind;
            this.left         = left;
            this.right        = right;

            // set the TypeReerence based on the Operands.
            if (this.Left == null || this.Right == null || this.Left.TypeReference == null || this.Right.TypeReference == null)
            {
                this.typeReference = null;
            }
            else
            {
                // Ensure that both operands have the same type
                if (!this.Left.TypeReference.Definition.IsEquivalentTo(this.Right.TypeReference.Definition))
                {
                    throw new ODataException(
                              ODataErrorStrings.BinaryOperatorQueryNode_OperandsMustHaveSameTypes(
                                  this.Left.TypeReference.ODataFullName(), this.Right.TypeReference.ODataFullName()));
                }

                // Get a primitive type reference; this must not fail since we checked that the type is of kind 'primitive'.
                IEdmPrimitiveTypeReference primitiveOperatorTypeReference =
                    this.Left.TypeReference.AsPrimitive();

                this.typeReference = QueryNodeUtils.GetBinaryOperatorResultType(primitiveOperatorTypeReference, this.OperatorKind);
            }
        }
Example #4
0
        /// <summary>Validates the current token is of the specified kind.</summary>
        /// <param name="t">Expected token kind.</param>
        internal void ValidateToken(ExpressionTokenKind t)
        {
            DebugUtils.CheckNoExternalCallers();

            if (this.token.Kind != t)
            {
                throw ParseError(ODataErrorStrings.ExpressionLexer_SyntaxError(this.textPos, this.text));
            }
        }
Example #5
0
        /// <summary>Reads the next token, checks that it is a literal token type, converts to to a Common Language Runtime value as appropriate, and returns the value.</summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <returns>The value represented by the next token.</returns>
        internal static object ReadLiteralToken(this ExpressionLexer expressionLexer)
        {
            DebugUtils.CheckNoExternalCallers();

            expressionLexer.NextToken();

            if (expressionLexer.CurrentToken.Kind.IsLiteralType())
            {
                return(TryParseLiteral(expressionLexer));
            }

            throw new ODataException(ODataErrorStrings.ExpressionLexer_ExpectedLiteralToken(expressionLexer.CurrentToken.Text));
        }
Example #6
0
        /// <summary>
        /// Parses typed literals.
        /// </summary>
        /// <param name="expressionLexer">The expression lexer.</param>
        /// <param name="targetTypeReference">Expected type to be parsed.</param>
        /// <returns>The literal token produced by building the given literal.</returns>
        private static object ParseTypedLiteral(this ExpressionLexer expressionLexer, IEdmPrimitiveTypeReference targetTypeReference)
        {
            object targetValue;

            if (!UriPrimitiveTypeParser.TryUriStringToPrimitive(expressionLexer.CurrentToken.Text, targetTypeReference, out targetValue))
            {
                string message = ODataErrorStrings.UriQueryExpressionParser_UnrecognizedLiteral(
                    targetTypeReference.FullName(),
                    expressionLexer.CurrentToken.Text,
                    expressionLexer.CurrentToken.Position,
                    expressionLexer.ExpressionText);
                throw new ODataException(message);
            }

            expressionLexer.NextToken();
            return(targetValue);
        }
Example #7
0
        /// <summary>
        /// Throws if the type is not related to the type of the given set.
        /// </summary>
        /// <param name="type">Type to check.</param>
        /// <param name="secondType">Second type, which should be related to the first type.</param>
        /// <param name="segmentName">The segment that is checking this.</param>
        public static void ThrowIfTypesUnrelated(IEdmType type, IEdmType secondType, string segmentName)
        {
            ExceptionUtils.CheckArgumentNotNull(type, "type");
            ExceptionUtils.CheckArgumentNotNull(secondType, "secondType");
            IEdmType           unwrappedType  = type;
            IEdmCollectionType collectionType = type as IEdmCollectionType;

            if (collectionType != null)
            {
                unwrappedType = collectionType.ElementType.Definition;
            }

            if (!unwrappedType.IsOrInheritsFrom(secondType) && !secondType.IsOrInheritsFrom(unwrappedType))
            {
                throw new ODataException(ODataErrorStrings.PathParser_TypeMustBeRelatedToSet(type, secondType, segmentName));
            }
        }
Example #8
0
        /// <summary>
        /// Starting from an identifier, reads a sequence of dots and
        /// identifiers, and returns the text for it, with whitespace
        /// stripped.
        /// </summary>
        /// <param name="acceptStar">do we allow a star in this identifier</param>
        /// <returns>The dotted identifier starting at the current identifier.</returns>
        internal string ReadDottedIdentifier(bool acceptStar)
        {
            DebugUtils.CheckNoExternalCallers();

            this.ValidateToken(ExpressionTokenKind.Identifier);
            StringBuilder builder = null;
            string        result  = this.CurrentToken.Text;

            this.NextToken();
            while (this.CurrentToken.Kind == ExpressionTokenKind.Dot)
            {
                this.NextToken();
                if (this.CurrentToken.Kind != ExpressionTokenKind.Identifier)
                {
                    if (this.CurrentToken.Kind == ExpressionTokenKind.Star)
                    {
                        // if we accept a star and this is the last token in the identifier, then we're ok... otherwise we throw.
                        if (!acceptStar || (this.PeekNextToken().Kind != ExpressionTokenKind.End && this.PeekNextToken().Kind != ExpressionTokenKind.Comma))
                        {
                            throw ParseError(ODataErrorStrings.ExpressionLexer_SyntaxError(this.textPos, this.text));
                        }
                    }
                    else
                    {
                        throw ParseError(ODataErrorStrings.ExpressionLexer_SyntaxError(this.textPos, this.text));
                    }
                }

                if (builder == null)
                {
                    builder = new StringBuilder(result, result.Length + 1 + this.CurrentToken.Text.Length);
                }

                builder.Append('.');
                builder.Append(this.CurrentToken.Text);
                this.NextToken();
            }

            if (builder != null)
            {
                result = builder.ToString();
            }

            return(result);
        }
Example #9
0
        /// <summary>Handles lexemes that are formed by an identifier followed by a quoted string.</summary>
        /// <remarks>This method modified the token field as necessary.</remarks>
        private void HandleTypePrefixedLiterals()
        {
            ExpressionTokenKind id = this.token.Kind;

            if (id != ExpressionTokenKind.Identifier)
            {
                return;
            }

            bool quoteFollows = this.ch == '\'';

            if (!quoteFollows)
            {
                return;
            }

            string tokenText = this.token.Text;

            if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixDateTime, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.DateTimeLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixDateTimeOffset, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.DateTimeOffsetLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixTime, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.TimeLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixGuid, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.GuidLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixBinary, StringComparison.OrdinalIgnoreCase) ||
                     String.Equals(tokenText, ExpressionConstants.LiteralPrefixShortBinary, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.BinaryLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixGeography, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.GeographyLiteral;
            }
            else if (String.Equals(tokenText, ExpressionConstants.LiteralPrefixGeometry, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.GeometryLiteral;
            }
            else if (this.parsingFunctionParameters && string.Equals(tokenText, ExpressionConstants.KeywordNull, StringComparison.OrdinalIgnoreCase))
            {
                id = ExpressionTokenKind.NullLiteral;
            }
            else
            {
                return;
            }

            int tokenPos = this.token.Position;

            do
            {
                this.NextChar();
            }while (this.ch.HasValue && this.ch != '\'');

            if (this.ch == null)
            {
                throw ParseError(ODataErrorStrings.ExpressionLexer_UnterminatedLiteral(this.textPos, this.text));
            }

            this.NextChar();
            this.token.Kind = id;
            this.token.Text = this.text.Substring(tokenPos, this.textPos - tokenPos);
        }
Example #10
0
        private ExpressionToken NextTokenImplementation(out Exception error)
        {
            DebugUtils.CheckNoExternalCallers();
            error = null;

            if (this.ignoreWhitespace)
            {
                this.ParseWhitespace();
            }

            ExpressionTokenKind t;
            int tokenPos = this.textPos;

            switch (this.ch)
            {
            case '(':
                this.NextChar();
                t = ExpressionTokenKind.OpenParen;
                break;

            case ')':
                this.NextChar();
                t = ExpressionTokenKind.CloseParen;
                break;

            case ',':
                this.NextChar();
                t = ExpressionTokenKind.Comma;
                break;

            case '-':
                bool hasNext = this.textPos + 1 < this.textLen;
                if (hasNext && Char.IsDigit(this.text[this.textPos + 1]))
                {
                    this.NextChar();
                    t = this.ParseFromDigit();
                    if (ExpressionLexerUtils.IsNumeric(t))
                    {
                        break;
                    }

                    // If it looked like a numeric but wasn't (because it was a binary 0x... value for example),
                    // we'll rewind and fall through to a simple '-' token.
                    this.SetTextPos(tokenPos);
                }
                else if (hasNext && this.text[tokenPos + 1] == ExpressionConstants.InfinityLiteral[0])
                {
                    this.NextChar();
                    this.ParseIdentifier();
                    string currentIdentifier = this.text.Substring(tokenPos + 1, this.textPos - tokenPos - 1);

                    if (ExpressionLexerUtils.IsInfinityLiteralDouble(currentIdentifier))
                    {
                        t = ExpressionTokenKind.DoubleLiteral;
                        break;
                    }
                    else if (ExpressionLexerUtils.IsInfinityLiteralSingle(currentIdentifier))
                    {
                        t = ExpressionTokenKind.SingleLiteral;
                        break;
                    }

                    // If it looked like '-INF' but wasn't we'll rewind and fall through to a simple '-' token.
                    this.SetTextPos(tokenPos);
                }

                this.NextChar();
                t = ExpressionTokenKind.Minus;
                break;

            case '=':
                this.NextChar();
                t = ExpressionTokenKind.Equal;
                break;

            case '/':
                this.NextChar();
                t = ExpressionTokenKind.Slash;
                break;

            case '?':
                this.NextChar();
                t = ExpressionTokenKind.Question;
                break;

            case '.':
                this.NextChar();
                t = ExpressionTokenKind.Dot;
                break;

            case '\'':
                char quote = this.ch.Value;
                do
                {
                    this.AdvanceToNextOccuranceOf(quote);

                    if (this.textPos == this.textLen)
                    {
                        error = ParseError(ODataErrorStrings.ExpressionLexer_UnterminatedStringLiteral(this.textPos, this.text));
                    }

                    this.NextChar();
                }while (this.ch.HasValue && (this.ch == quote));
                t = ExpressionTokenKind.StringLiteral;
                break;

            case '*':
                this.NextChar();
                t = ExpressionTokenKind.Star;
                break;

            case ':':
                this.NextChar();
                t = ExpressionTokenKind.Colon;
                break;

            case '{':
                this.ParseBracketedExpression('{', '}');
                t = ExpressionTokenKind.BracketedExpression;
                break;

            case '[':
                this.ParseBracketedExpression('[', ']');
                t = ExpressionTokenKind.BracketedExpression;
                break;

            default:
                if (this.IsValidWhiteSpace)
                {
                    Debug.Assert(!this.ignoreWhitespace, "should not hit ws while ignoring it");
                    this.ParseWhitespace();
                    t = ExpressionTokenKind.Unknown;
                    break;
                }

                if (this.IsValidStartingCharForIdentifier)
                {
                    this.ParseIdentifier();
                    t = ExpressionTokenKind.Identifier;
                    break;
                }

                if (this.IsValidDigit)
                {
                    t = this.ParseFromDigit();
                    break;
                }

                if (this.textPos == this.textLen)
                {
                    t = ExpressionTokenKind.End;
                    break;
                }

                if (this.useSemicolonDelimeter && this.ch == ';')
                {
                    this.NextChar();
                    t = ExpressionTokenKind.SemiColon;
                    break;
                }

                if (this.parsingFunctionParameters && this.ch == '@')
                {
                    this.NextChar();

                    if (this.textPos == this.textLen)
                    {
                        error = ParseError(ODataErrorStrings.ExpressionLexer_SyntaxError(this.textPos, this.text));
                        t     = ExpressionTokenKind.Unknown;
                        break;
                    }

                    if (!this.IsValidStartingCharForIdentifier)
                    {
                        error = ParseError(ODataErrorStrings.ExpressionLexer_InvalidCharacter(this.ch, this.textPos, this.text));
                        t     = ExpressionTokenKind.Unknown;
                        break;
                    }

                    this.ParseIdentifier();
                    t = ExpressionTokenKind.ParameterAlias;
                    break;
                }

                error = ParseError(ODataErrorStrings.ExpressionLexer_InvalidCharacter(this.ch, this.textPos, this.text));
                t     = ExpressionTokenKind.Unknown;
                break;
            }

            this.token.Kind     = t;
            this.token.Text     = this.text.Substring(tokenPos, this.textPos - tokenPos);
            this.token.Position = tokenPos;

            // Handle type-prefixed literals such as binary, datetime or guid.
            this.HandleTypePrefixedLiterals();

            // Handle keywords.
            if (this.token.Kind == ExpressionTokenKind.Identifier)
            {
                if (ExpressionLexerUtils.IsInfinityOrNaNDouble(this.token.Text))
                {
                    this.token.Kind = ExpressionTokenKind.DoubleLiteral;
                }
                else if (ExpressionLexerUtils.IsInfinityOrNanSingle(this.token.Text))
                {
                    this.token.Kind = ExpressionTokenKind.SingleLiteral;
                }
                else if (this.token.Text == ExpressionConstants.KeywordTrue || this.token.Text == ExpressionConstants.KeywordFalse)
                {
                    this.token.Kind = ExpressionTokenKind.BooleanLiteral;
                }
                else if (this.token.Text == ExpressionConstants.KeywordNull)
                {
                    this.token.Kind = ExpressionTokenKind.NullLiteral;
                }
            }

            return(this.token);
        }
        internal int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count)
        {
            if (count == 0)
            {
                return(0);
            }
            int maxDataBytesToScan = count;
            ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch;

            while ((maxDataBytesToScan > 0) && (noMatch != ODataBatchReaderStreamScanResult.Match))
            {
                int  num2;
                int  num3;
                bool flag;
                bool flag2;
                int  num4;
                switch (this.batchBuffer.ScanForBoundary(this.CurrentBoundaries, maxDataBytesToScan, out num2, out num3, out flag, out flag2))
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                    if (this.batchBuffer.NumberOfBytesInBuffer < maxDataBytesToScan)
                    {
                        break;
                    }
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, maxDataBytesToScan);
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + maxDataBytesToScan);
                    return(count);

                case ODataBatchReaderStreamScanResult.PartialMatch:
                {
                    if (!this.underlyingStreamExhausted)
                    {
                        goto Label_0168;
                    }
                    int num6 = Math.Min(this.batchBuffer.NumberOfBytesInBuffer, maxDataBytesToScan);
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num6);
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + num6);
                    maxDataBytesToScan -= num6;
                    return(count - maxDataBytesToScan);
                }

                case ODataBatchReaderStreamScanResult.Match:
                    num4 = num2 - this.batchBuffer.CurrentReadPosition;
                    Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num4);
                    maxDataBytesToScan -= num4;
                    userBufferOffset   += num4;
                    this.batchBuffer.SkipTo(num2);
                    return(count - maxDataBytesToScan);

                default:
                {
                    continue;
                }
                }
                int numberOfBytesInBuffer = this.batchBuffer.NumberOfBytesInBuffer;
                Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, numberOfBytesInBuffer);
                maxDataBytesToScan -= numberOfBytesInBuffer;
                userBufferOffset   += numberOfBytesInBuffer;
                if (this.underlyingStreamExhausted)
                {
                    this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + numberOfBytesInBuffer);
                    return(count - maxDataBytesToScan);
                }
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40);
                continue;
Label_0168:
                num4 = num2 - this.batchBuffer.CurrentReadPosition;
                Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, num4);
                maxDataBytesToScan            -= num4;
                userBufferOffset              += num4;
                this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num2);
            }
            throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadWithDelimiter));
        }
        internal string ReadLine()
        {
            int numberOfBytesInBuffer = 0;

            byte[] lineBuffer = this.lineBuffer;
            ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch;

            while (noMatch != ODataBatchReaderStreamScanResult.Match)
            {
                int num2;
                int num3;
                int num4;
                noMatch = this.batchBuffer.ScanForLineEnd(out num3, out num4);
                switch (noMatch)
                {
                case ODataBatchReaderStreamScanResult.NoMatch:
                {
                    num2 = this.batchBuffer.NumberOfBytesInBuffer;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    if (this.underlyingStreamExhausted)
                    {
                        noMatch = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + num2);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40);
                    }
                    continue;
                }

                case ODataBatchReaderStreamScanResult.PartialMatch:
                {
                    num2 = num3 - this.batchBuffer.CurrentReadPosition;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    if (this.underlyingStreamExhausted)
                    {
                        noMatch = ODataBatchReaderStreamScanResult.Match;
                        this.batchBuffer.SkipTo(num3 + 1);
                    }
                    else
                    {
                        this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num3);
                    }
                    continue;
                }

                case ODataBatchReaderStreamScanResult.Match:
                {
                    num2 = num3 - this.batchBuffer.CurrentReadPosition;
                    if (num2 > 0)
                    {
                        ODataBatchUtils.EnsureArraySize(ref lineBuffer, numberOfBytesInBuffer, num2);
                        Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, lineBuffer, numberOfBytesInBuffer, num2);
                        numberOfBytesInBuffer += num2;
                    }
                    this.batchBuffer.SkipTo(num4 + 1);
                    continue;
                }
                }
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine));
            }
            if (lineBuffer == null)
            {
                return(string.Empty);
            }
            return(this.CurrentEncoding.GetString(lineBuffer, 0, numberOfBytesInBuffer));
        }