/// <summary>Validates the current character is a digit.</summary> private void ValidateDigit() { if (!this.IsValidDigit) { throw ParseError(ODataErrorStrings.ExpressionLexer_DigitExpected(this.textPos, this.text)); } }
/// <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)); }
/// <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); } }
/// <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)); } }
/// <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)); }
/// <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); }
/// <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)); } }
/// <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); }
/// <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); }
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)); }