/// <summary> /// Creates a new <see cref="Scope"/> for the specified <paramref name="state"/> with the provided /// <paramref name="name"/> and <paramref name="value"/> and pushes it on the stack of scopes. /// </summary> /// <param name="state">The <see cref="ODataParameterReaderState"/> to use for the new scope.</param> /// <param name="name">The paramter name to attach with the state in the new scope.</param> /// <param name="value">The paramter value to attach with the state in the new scope.</param> protected void EnterScope(ODataParameterReaderState state, string name, object value) { if (state == ODataParameterReaderState.Value) { if (value != null && !(value is ODataComplexValue) && !EdmLibraryExtensions.IsPrimitiveType(value.GetType())) { throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReaderCore_ValueMustBePrimitiveOrComplexOrNull)); } } Debug.Assert(this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception || state == ODataParameterReaderState.Exception, "If the reader is already in Exception state, we shouldn't call EnterScope() except for another Exception."); // We only need to enter the exception state once. if (this.scopes.Count == 0 || this.State != ODataParameterReaderState.Exception) { Debug.Assert( state == ODataParameterReaderState.Exception || state == ODataParameterReaderState.Start && this.scopes.Count == 0 || state == ODataParameterReaderState.Completed && this.scopes.Count == 0 || this.scopes.Count == 1 && this.scopes.Peek().State == ODataParameterReaderState.Start, "Unexpected state in the scopes stack."); // Make sure there aren't any missing parameter in the payload. if (state == ODataParameterReaderState.Completed) { List <string> missingParameters = new List <string>(); // Note that the binding parameter will be specified on the Uri rather than the payload, skip the binding parameter. foreach (IEdmFunctionParameter parameter in this.FunctionImport.Parameters.Skip(this.FunctionImport.IsBindable ? 1 : 0)) { if (!this.parametersRead.Contains(parameter.Name) && !parameter.Type.IsNullable) { missingParameters.Add(parameter.Name); } } if (missingParameters.Count > 0) { this.scopes.Push(new Scope(ODataParameterReaderState.Exception, null, null)); throw new ODataException(Strings.ODataParameterReaderCore_ParametersMissingInPayload(this.FunctionImport.Name, string.Join(",", missingParameters.ToArray()))); } } this.scopes.Push(new Scope(state, name, value)); } }
/// <summary> /// Asynchronously creates an instance of the input context for this format. /// </summary> /// <param name="readerPayloadKind">The <see cref="ODataPayloadKind"/> to read.</param> /// <param name="message">The message to use.</param> /// <param name="contentType">The content type of the message to read.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> /// <param name="payloadKindDetectionFormatState">Format specific state stored during payload kind detection /// using the <see cref="ODataPayloadKindDetectionInfo.SetPayloadKindDetectionFormatState"/>.</param> /// <returns>Task which when completed returned the newly created input context.</returns> internal override Task <ODataInputContext> CreateInputContextAsync( ODataPayloadKind readerPayloadKind, ODataMessage message, MediaType contentType, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver, object payloadKindDetectionFormatState) { DebugUtils.CheckNoExternalCallers(); ExceptionUtils.CheckArgumentNotNull(message, "message"); ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings"); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataMetadataFormat_CreateInputContextAsync)); }
/// <summary> /// Converts a given <see cref="AtomTextConstructKind"/> to a string appropriate for Atom format. /// </summary> /// <param name="textConstructKind">The text construct kind to convert.</param> /// <returns>The string version of the text construct format in Atom format.</returns> internal static string ToString(AtomTextConstructKind textConstructKind) { DebugUtils.CheckNoExternalCallers(); switch (textConstructKind) { case AtomTextConstructKind.Text: return(AtomConstants.AtomTextConstructTextKind); case AtomTextConstructKind.Html: return(AtomConstants.AtomTextConstructHtmlKind); case AtomTextConstructKind.Xhtml: return(AtomConstants.AtomTextConstructXHtmlKind); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataAtomConvert_ToString)); } }
internal bool SkipToBoundary(out bool isEndBoundary, out bool isParentBoundary) { this.EnsureBatchEncoding(); ODataBatchReaderStreamScanResult noMatch = ODataBatchReaderStreamScanResult.NoMatch; while (noMatch != ODataBatchReaderStreamScanResult.Match) { int num; int num2; switch (this.batchBuffer.ScanForBoundary(this.CurrentBoundaries, 0x7fffffff, out num, out num2, out isEndBoundary, out isParentBoundary)) { case ODataBatchReaderStreamScanResult.NoMatch: if (!this.underlyingStreamExhausted) { break; } this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer); return(false); case ODataBatchReaderStreamScanResult.PartialMatch: if (!this.underlyingStreamExhausted) { goto Label_00BE; } this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer); return(false); case ODataBatchReaderStreamScanResult.Match: this.batchBuffer.SkipTo(isParentBoundary ? num : (num2 + 1)); return(true); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary)); } this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, 0x1f40); continue; Label_00BE: this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, num); } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary)); }
private bool ReadImplementation() { switch (this.State) { case ODataBatchReaderState.Initial: this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Operation: if (this.operationState == OperationState.None) { throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation); } this.operationState = OperationState.None; if (this.contentIdToAddOnNextRead != null) { this.urlResolver.AddContentId(this.contentIdToAddOnNextRead); this.contentIdToAddOnNextRead = null; } this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetStart: this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetEnd: this.ResetChangeSetSize(); this.batchStream.ResetChangeSetBoundary(); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Completed: case ODataBatchReaderState.Exception: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); } return((this.batchReaderState != ODataBatchReaderState.Completed) && (this.batchReaderState != ODataBatchReaderState.Exception)); }
/// <summary> /// Converts a given <paramref name="version"/> to its <see cref="System.Version"/> representation. /// </summary> /// <param name="version">The <see cref="ODataVersion"/> instance to convert.</param> /// <returns>The <see cref="System.Version"/> representation of the <paramref name="version"/>.</returns> internal static Version ToDataServiceVersion(this ODataVersion version) { DebugUtils.CheckNoExternalCallers(); switch (version) { case ODataVersion.V1: return(new Version(1, 0)); case ODataVersion.V2: return(new Version(2, 0)); case ODataVersion.V3: return(new Version(3, 0)); default: string errorMessage = Strings.General_InternalError(InternalErrorCodes.ODataUtilsInternal_ToDataServiceVersion_UnreachableCodePath); Debug.Assert(false, errorMessage); throw new ODataException(errorMessage); } }
/// <summary> /// Returns the next state of the batch reader after an end boundary has been found. /// </summary> /// <returns>The next state of the batch reader.</returns> private ODataBatchReaderState GetEndBoundaryState() { switch (this.batchReaderState) { case ODataBatchReaderState.Initial: // If we find an end boundary when in state 'Initial' it means that we // have an empty batch. The next state will be 'Completed'. return(ODataBatchReaderState.Completed); case ODataBatchReaderState.Operation: // If we find an end boundary in state 'Operation' we have finished // processing an operation and found the end boundary of either the // current changeset or the batch. return(this.batchStream.ChangeSetBoundary == null ? ODataBatchReaderState.Completed : ODataBatchReaderState.ChangesetEnd); case ODataBatchReaderState.ChangesetStart: // If we find an end boundary when in state 'ChangeSetStart' it means that // we have an empty changeset. The next state will be 'ChangeSetEnd' return(ODataBatchReaderState.ChangesetEnd); case ODataBatchReaderState.ChangesetEnd: // If we are at the end of a changeset and find an end boundary // we reached the end of the batch return(ODataBatchReaderState.Completed); case ODataBatchReaderState.Completed: // We should never get here when in Completed state. throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_Completed)); case ODataBatchReaderState.Exception: // We should never get here when in Exception state. throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_Exception)); default: // Invalid enum value throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_GetEndBoundary_UnknownValue)); } }
/// <summary> /// Indexer to get the cached item when given the ODataVersion. /// </summary> /// <param name="version">The ODataVersion to look up.</param> /// <returns>The cached item.</returns> internal T this[ODataVersion version] { get { DebugUtils.CheckNoExternalCallers(); switch (version) { case ODataVersion.V1: return(this.v1.Value); case ODataVersion.V2: return(this.v2.Value); case ODataVersion.V3: return(this.v3.Value); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataVersionCache_UnknownVersion)); } } }
/// <summary> /// Scans the current buffer for the specified boundary. /// </summary> /// <param name="boundaries">The boundary strings to search for; this enumerable is sorted from the inner-most boundary /// to the top-most boundary. The boundary strings don't include the leading line terminator or the leading dashes.</param> /// <param name="maxDataBytesToScan">Stop if no boundary (or boundary start) is found after this number of bytes.</param> /// <param name="boundaryStartPosition">The start position of the boundary or -1 if not found. /// Note that the start position is the first byte of the leading line terminator.</param> /// <param name="boundaryEndPosition">The end position of the boundary or -1 if not found. /// Note that the end position is the last byte of the trailing line terminator.</param> /// <param name="isEndBoundary">true if the boundary is an end boundary (followed by two dashes); otherwise false.</param> /// <param name="isParentBoundary">true if the detected boundary is the parent boundary; otherwise false.</param> /// <returns>An enumeration value indicating whether the boundary was completely, partially or not found in the buffer.</returns> internal ODataBatchReaderStreamScanResult ScanForBoundary( IEnumerable <string> boundaries, int maxDataBytesToScan, out int boundaryStartPosition, out int boundaryEndPosition, out bool isEndBoundary, out bool isParentBoundary) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(boundaries != null, "boundaries != null"); boundaryStartPosition = -1; boundaryEndPosition = -1; isEndBoundary = false; isParentBoundary = false; int lineScanStartIndex = this.currentReadPosition; while (true) { // NOTE: a boundary has to start with a line terminator followed by two dashes ('-'), // the actual boundary string, another two dashes (for an end boundary), // optional whitespace characters and another line terminator. // NOTE: for WCF DS compatibility we do not require the leading line terminator. int lineEndStartPosition, boundaryDelimiterStartPosition; ODataBatchReaderStreamScanResult lineEndScanResult = this.ScanForBoundaryStart( lineScanStartIndex, maxDataBytesToScan, out lineEndStartPosition, out boundaryDelimiterStartPosition); switch (lineEndScanResult) { case ODataBatchReaderStreamScanResult.NoMatch: // Did not find a line end or boundary delimiter in the buffer or after reading maxDataBytesToScan bytes. // Report no boundary match. return(ODataBatchReaderStreamScanResult.NoMatch); case ODataBatchReaderStreamScanResult.PartialMatch: // Found a partial line end or boundary delimiter at the end of the buffer but before reading maxDataBytesToScan. // Report a partial boundary match. boundaryStartPosition = lineEndStartPosition < 0 ? boundaryDelimiterStartPosition : lineEndStartPosition; return(ODataBatchReaderStreamScanResult.PartialMatch); case ODataBatchReaderStreamScanResult.Match: // Found a full line end or boundary delimiter start ('--') before reading maxDataBytesToScan or // hitting the end of the buffer. Start matching the boundary delimiters. // // Start with the expected boundary (the first one in the enumerable): // * if we find a full match - return match because we are done // * if we find a partial match - return partial match because we have to continue checking the expected boundary. // * if we find no match - we know that it is not the expected boundary; check the parent boundary (if it exists). isParentBoundary = false; foreach (string boundary in boundaries) { ODataBatchReaderStreamScanResult boundaryMatch = this.MatchBoundary( lineEndStartPosition, boundaryDelimiterStartPosition, boundary, out boundaryStartPosition, out boundaryEndPosition, out isEndBoundary); switch (boundaryMatch) { case ODataBatchReaderStreamScanResult.Match: return(ODataBatchReaderStreamScanResult.Match); case ODataBatchReaderStreamScanResult.PartialMatch: boundaryEndPosition = -1; isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); case ODataBatchReaderStreamScanResult.NoMatch: // try the parent boundary (if any) or continue scanning boundaryStartPosition = -1; boundaryEndPosition = -1; isEndBoundary = false; isParentBoundary = true; break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary)); } } // If we could not match the boundary, try again starting at the current boundary start index. Or if we already did that // move one character ahead. lineScanStartIndex = lineScanStartIndex == boundaryDelimiterStartPosition ? boundaryDelimiterStartPosition + 1 : boundaryDelimiterStartPosition; break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary)); } } }
/// <summary> /// Creates an instance of the input context for the specified format. /// </summary> /// <param name="format">The format to create the context for.</param> /// <param name="readerPayloadKind">The <see cref="ODataPayloadKind"/> to read.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageReaderSettings">Configuration settings of the OData reader.</param> /// <param name="version">The OData protocol version to be used for reading the payload.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs read from the payload.</param> /// <returns>The newly created input context.</returns> internal static ODataInputContext CreateInputContext( ODataFormat format, ODataPayloadKind readerPayloadKind, ODataMessage message, Encoding encoding, ODataMessageReaderSettings messageReaderSettings, ODataVersion version, bool readingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); if (format == ODataFormat.Atom) { return(ODataAtomInputContext.Create( format, message, encoding, messageReaderSettings, version, readingResponse, model, urlResolver)); } if (format == ODataFormat.VerboseJson) { return(ODataJsonInputContext.Create( format, message, encoding, messageReaderSettings, version, readingResponse, model, urlResolver)); } if (format == ODataFormat.Metadata) { return(ODataMetadataInputContext.Create( format, message, encoding, messageReaderSettings, version, readingResponse, model, urlResolver)); } if (format == ODataFormat.Batch || format == ODataFormat.RawValue) { return(ODataRawInputContext.Create( format, message, encoding, messageReaderSettings, version, readingResponse, model, urlResolver, readerPayloadKind)); } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataInputContext_CreateInputContext_UnrecognizedFormat)); }
/// <summary> /// Continues reading from the batch message payload. /// </summary> /// <returns>true if more items were read; otherwise false.</returns> private bool ReadImplementation() { Debug.Assert(this.operationState != OperationState.StreamRequested, "Should have verified that no operation stream is still active."); switch (this.State) { case ODataBatchReaderState.Initial: // The stream should be positioned at the beginning of the batch content, // that is before the first boundary (or the preamble if there is one). this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Operation: // When reaching this state we already read the MIME headers of the operation. // Clients MUST call CreateOperationRequestMessage // or CreateOperationResponseMessage to read at least the headers of the operation. // This is important since we need to read the ContentId header (if present) and // add it to the URL resolver. if (this.operationState == OperationState.None) { // No message was created; fail throw new ODataException(Strings.ODataBatchReader_NoMessageWasCreatedForOperation); } // Reset the operation state; the operation state only // tracks the state of a batch operation while in state Operation. this.operationState = OperationState.None; // Also add a pending ContentId header to the URL resolver now. We ensured above // that a message has been created for this operation and thus the headers (incl. // a potential content ID header) have been read. if (this.contentIdToAddOnNextRead != null) { this.urlResolver.AddContentId(this.contentIdToAddOnNextRead); this.contentIdToAddOnNextRead = null; } // When we are done with an operation, we have to skip ahead to the next part // when Read is called again. Note that if the operation stream was never requested // and the content of the operation has not been read, we'll skip it here. Debug.Assert(this.operationState == OperationState.None, "Operation state must be 'None' at the end of the operation."); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetStart: // When at the start of a changeset, skip ahead to the first operation in the // changeset (or the end boundary of the changeset). Debug.Assert(this.batchStream.ChangeSetBoundary != null, "Changeset boundary must have been set by now."); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.ChangesetEnd: // When at the end of a changeset, reset the changeset boundary and the // changeset size and then skip to the next part. this.ResetChangeSetSize(); this.batchStream.ResetChangeSetBoundary(); this.batchReaderState = this.SkipToNextPartAndReadHeaders(); break; case ODataBatchReaderState.Exception: // fall through case ODataBatchReaderState.Completed: Debug.Assert(false, "Should have checked in VerifyCanRead that we are not in one of these states."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); default: Debug.Assert(false, "Unsupported reader state " + this.State + " detected."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReader_ReadImplementation)); } return(this.batchReaderState != ODataBatchReaderState.Completed && this.batchReaderState != ODataBatchReaderState.Exception); }
private ODataBatchReaderStreamScanResult MatchBoundary(int lineEndStartPosition, int boundaryDelimiterStartPosition, string boundary, out int boundaryStartPosition, out int boundaryEndPosition, out bool isEndBoundary) { bool flag; int num3; boundaryStartPosition = -1; boundaryEndPosition = -1; int num = (this.currentReadPosition + this.numberOfBytesInBuffer) - 1; int num2 = (((boundaryDelimiterStartPosition + 2) + boundary.Length) + 2) - 1; if (num < (num2 + 2)) { flag = true; num3 = (Math.Min(num, num2) - boundaryDelimiterStartPosition) + 1; } else { flag = false; num3 = (num2 - boundaryDelimiterStartPosition) + 1; } if (this.MatchBoundary(boundary, boundaryDelimiterStartPosition, num3, out isEndBoundary)) { int num4; int num5; bool flag2; boundaryStartPosition = (lineEndStartPosition < 0) ? boundaryDelimiterStartPosition : lineEndStartPosition; if (flag) { isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); } boundaryEndPosition = ((boundaryDelimiterStartPosition + 2) + boundary.Length) - 1; if (isEndBoundary) { boundaryEndPosition += 2; } switch (this.ScanForLineEnd(boundaryEndPosition + 1, 0x7fffffff, true, out num4, out num5, out flag2)) { case ODataBatchReaderStreamScanResult.NoMatch: if (flag2) { if (boundaryStartPosition == 0) { throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(0x1f40)); } isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); } break; case ODataBatchReaderStreamScanResult.PartialMatch: if (boundaryStartPosition == 0) { throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(0x1f40)); } isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); case ODataBatchReaderStreamScanResult.Match: boundaryEndPosition = num5; return(ODataBatchReaderStreamScanResult.Match); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary)); } } return(ODataBatchReaderStreamScanResult.NoMatch); }
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)); }
/// <summary> /// Creates an instance of the output context for the specified format. /// </summary> /// <param name="format">The format to create the context for.</param> /// <param name="message">The message to use.</param> /// <param name="encoding">The encoding to use.</param> /// <param name="messageWriterSettings">Configuration settings of the OData writer.</param> /// <param name="writingResponse">true if writing a response message; otherwise false.</param> /// <param name="model">The model to use.</param> /// <param name="urlResolver">The optional URL resolver to perform custom URL resolution for URLs written to the payload.</param> /// <returns>The newly created output context.</returns> internal static ODataOutputContext CreateOutputContext( ODataFormat format, ODataMessage message, Encoding encoding, ODataMessageWriterSettings messageWriterSettings, bool writingResponse, IEdmModel model, IODataUrlResolver urlResolver) { DebugUtils.CheckNoExternalCallers(); if (format == ODataFormat.Atom) { return(ODataAtomOutputContext.Create( format, message, encoding, messageWriterSettings, writingResponse, model, urlResolver)); } if (format == ODataFormat.VerboseJson) { return(ODataJsonOutputContext.Create( format, message, encoding, messageWriterSettings, writingResponse, model, urlResolver)); } if (format == ODataFormat.Metadata) { return(ODataMetadataOutputContext.Create( format, message, encoding, messageWriterSettings, writingResponse, model, urlResolver)); } if (format == ODataFormat.Batch || format == ODataFormat.RawValue) { return(ODataRawOutputContext.Create( format, message, encoding, messageWriterSettings, writingResponse, model, urlResolver)); } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataOutputContext_CreateOutputContext_UnrecognizedFormat)); }
/// <summary> /// Reads the next <see cref="ODataItem"/> from the message payload. /// </summary> /// <returns>true if more items were read; otherwise false.</returns> protected bool ReadImplementation() { bool result = false; switch (this.State) { case ODataParameterReaderState.Start: result = this.ReadAtStartImplementation(); Debug.Assert( this.State == ODataParameterReaderState.Value || #if SUPPORT_ENTITY_PARAMETER this.State == ODataParameterReaderState.Entry || this.State == ODataParameterReaderState.Feed || #endif this.State == ODataParameterReaderState.Collection || this.State == ODataParameterReaderState.Completed, "ReadAtParameterStartImplementation should transition the state to ODataParameterReaderState.Value, ODataParameterReaderState.Entry, ODataParameterReaderState.Feed, ODataParameterReaderState.Collection or ODataParameterReaderState.Completed. The current state is: " + this.State); break; case ODataParameterReaderState.Value: #if SUPPORT_ENTITY_PARAMETER case ODataParameterReaderState.Entry: case ODataParameterReaderState.Feed: #endif case ODataParameterReaderState.Collection: Debug.Assert(this.State == ODataParameterReaderState.Value || this.subReaderState == SubReaderState.Completed, "this.State == ODataParameterReaderState.Value || this.subReaderState == SubReaderState.Completed"); this.subReaderState = SubReaderState.None; result = this.ReadNextParameterImplementation(); Debug.Assert( this.State == ODataParameterReaderState.Value || #if SUPPORT_ENTITY_PARAMETER this.State == ODataParameterReaderState.Entry || this.State == ODataParameterReaderState.Feed || #endif this.State == ODataParameterReaderState.Collection || this.State == ODataParameterReaderState.Completed, "ReadAtParameterStartImplementation should transition the state to ODataParameterReaderState.Value, ODataParameterReaderState.Entry, ODataParameterReaderState.Feed, ODataParameterReaderState.Collection or ODataParameterReaderState.Completed. The current state is: " + this.State); break; case ODataParameterReaderState.Exception: // fall through case ODataParameterReaderState.Completed: Debug.Assert(false, "This case should have been caught earlier."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReader_ReadImplementation)); default: Debug.Assert(false, "Unsupported parameter reader state " + this.State + " detected."); throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataParameterReader_ReadImplementation)); } if (this.State != ODataParameterReaderState.Completed) { Debug.Assert(!string.IsNullOrEmpty(this.Name), "!string.IsNullOrEmpty(this.Name)"); if (this.parametersRead.Contains(this.Name)) { throw new ODataException(Strings.ODataParameterReaderCore_DuplicateParametersInPayload(this.Name)); } this.parametersRead.Add(this.Name); } return(result); }
/// <summary> /// Check whether the bytes in the buffer at the specified start index match the expected boundary string. /// </summary> /// <param name="lineEndStartPosition">The start of the line feed preceding the boundary (if present).</param> /// <param name="boundaryDelimiterStartPosition">The start position of the boundary delimiter.</param> /// <param name="boundary">The boundary string to check for.</param> /// <param name="boundaryStartPosition">If a match is detected, the start of the boundary delimiter, /// i.e., either the start of the leading line feed or of the leading dashes.</param> /// <param name="boundaryEndPosition">If a match is detected, the position of the boundary end; otherwise -1.</param> /// <param name="isEndBoundary">true if the detected boundary is an end boundary; otherwise false.</param> /// <returns>An <see cref="ODataBatchReaderStreamScanResult"/> indicating whether a match, a partial match or no match was found.</returns> private ODataBatchReaderStreamScanResult MatchBoundary( int lineEndStartPosition, int boundaryDelimiterStartPosition, string boundary, out int boundaryStartPosition, out int boundaryEndPosition, out bool isEndBoundary) { boundaryStartPosition = -1; boundaryEndPosition = -1; int bufferLastByte = this.currentReadPosition + this.numberOfBytesInBuffer - 1; int boundaryEndPositionAfterLineFeed = boundaryDelimiterStartPosition + TwoDashesLength + boundary.Length + TwoDashesLength - 1; // NOTE: for simplicity reasons we require that the full end (!) boundary plus the maximum size // of the line terminator fits into the buffer to get a non-partial match. // By doing so we can reliably detect whether we are dealing with an end boundary or not. // Otherwise the logic to figure out whether we found a boundary or not is riddled with // corner cases that only complicate the code. bool isPartialMatch; int matchLength; if (bufferLastByte < boundaryEndPositionAfterLineFeed + MaxLineFeedLength) { isPartialMatch = true; matchLength = Math.Min(bufferLastByte, boundaryEndPositionAfterLineFeed) - boundaryDelimiterStartPosition + 1; } else { isPartialMatch = false; matchLength = boundaryEndPositionAfterLineFeed - boundaryDelimiterStartPosition + 1; } if (this.MatchBoundary(boundary, boundaryDelimiterStartPosition, matchLength, out isEndBoundary)) { boundaryStartPosition = lineEndStartPosition < 0 ? boundaryDelimiterStartPosition : lineEndStartPosition; if (isPartialMatch) { isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); } else { // If we fully matched the boundary compute the boundary end position boundaryEndPosition = boundaryDelimiterStartPosition + TwoDashesLength + boundary.Length - 1; if (isEndBoundary) { boundaryEndPosition += TwoDashesLength; } // Once we could match all the characters and delimiters of the boundary string // (and the optional trailing '--') we now have to continue reading until the next // line feed that terminates the boundary. Only whitespace characters may exist // after the boundary and before the line feed. int terminatingLineFeedStartPosition, terminatingLineFeedEndPosition; bool endOfBufferReached; ODataBatchReaderStreamScanResult terminatingLineFeedScanResult = this.ScanForLineEnd( boundaryEndPosition + 1, int.MaxValue, /*allowLeadingWhitespaceOnly*/ true, out terminatingLineFeedStartPosition, out terminatingLineFeedEndPosition, out endOfBufferReached); switch (terminatingLineFeedScanResult) { case ODataBatchReaderStreamScanResult.NoMatch: if (endOfBufferReached) { // Reached the end of the buffer and only found whitespaces. if (boundaryStartPosition == 0) { // If the boundary starts at the first position in the buffer // and we still could not find the end of it because there are // so many whitespaces before the terminating line feed - fail // (security limit on the whitespaces) throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(BufferLength)); } // Report a partial match. isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); } else { // Found a different character than whitespace or end-of-line // so we did not match the boundary. break; } case ODataBatchReaderStreamScanResult.PartialMatch: // Found only a partial line end at the end of the buffer. if (boundaryStartPosition == 0) { // If the boundary starts at the first position in the buffer // and we still could not find the end of it because there are // so many whitespaces before the terminating line feed - fail // (security limit on the whitespaces) throw new ODataException(Strings.ODataBatchReaderStreamBuffer_BoundaryLineSecurityLimitReached(BufferLength)); } // Report a partial match. isEndBoundary = false; return(ODataBatchReaderStreamScanResult.PartialMatch); case ODataBatchReaderStreamScanResult.Match: // At this point we only found whitespace characters and then the terminating line feed; // adjust the boundary end position boundaryEndPosition = terminatingLineFeedEndPosition; return(ODataBatchReaderStreamScanResult.Match); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStreamBuffer_ScanForBoundary)); } } } return(ODataBatchReaderStreamScanResult.NoMatch); }
/// <summary> /// Reads a line (all bytes until a line feed) from the underlying stream. /// </summary> /// <returns>Returns the string that was read from the underyling stream (not including a terminating line feed).</returns> internal string ReadLine() { DebugUtils.CheckNoExternalCallers(); Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary."); Debug.Assert(this.lineBuffer != null && this.lineBuffer.Length == LineBufferLength, "Line buffer should have been created."); // The number of bytes in the line buffer that make up the line. int lineBufferSize = 0; // Start with the pre-allocated line buffer array. byte[] bytesForString = this.lineBuffer; ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch; while (scanResult != ODataBatchReaderStreamScanResult.Match) { int byteCount, lineEndStartPosition, lineEndEndPosition; scanResult = this.batchBuffer.ScanForLineEnd(out lineEndStartPosition, out lineEndEndPosition); switch (scanResult) { case ODataBatchReaderStreamScanResult.NoMatch: // Copy all the bytes in the batchBuffer into the result byte[] and then continue byteCount = this.batchBuffer.NumberOfBytesInBuffer; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } if (this.underlyingStreamExhausted) { // Nothing more to read; stop looping scanResult = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + byteCount); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength); } break; case ODataBatchReaderStreamScanResult.PartialMatch: // We found the start of a line end in the buffer but could not verify whether we saw all of it. // This can happen if a line end is represented as \r\n and we found \r at the very last position in the buffer. // In this case we copy the bytes into the result byte[] and continue at the start of the line end; this will guarantee // that the next scan will find the full line end, not find any additional bytes and then skip the full line end. // It is safe to copy the string right here because we will also accept \r as a line end; we are just not sure whether there // will be a subsequent \n. // This can also happen if the last byte in the stream is \r. byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } if (this.underlyingStreamExhausted) { // Nothing more to read; stop looping scanResult = ODataBatchReaderStreamScanResult.Match; this.batchBuffer.SkipTo(lineEndStartPosition + 1); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ lineEndStartPosition); } break; case ODataBatchReaderStreamScanResult.Match: // We found a line end in the buffer Debug.Assert(lineEndStartPosition >= this.batchBuffer.CurrentReadPosition, "Line end must be at or after current position."); Debug.Assert(lineEndEndPosition < this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer, "Line end must finish withing buffer range."); byteCount = lineEndStartPosition - this.batchBuffer.CurrentReadPosition; if (byteCount > 0) { ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } this.batchBuffer.SkipTo(lineEndEndPosition + 1); break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadLine)); } } if (bytesForString == null) { return(string.Empty); } return(this.CurrentEncoding.GetString(bytesForString, 0, lineBufferSize)); }
/// <summary> /// Reads from the batch stream while ensuring that we stop reading at each boundary. /// </summary> /// <param name="userBuffer">The byte array to read bytes into.</param> /// <param name="userBufferOffset">The offset in the buffer where to start reading bytes into.</param> /// <param name="count">The number of bytes to read.</param> /// <returns>The number of bytes actually read.</returns> internal int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(userBuffer != null, "userBuffer != null"); Debug.Assert(userBufferOffset >= 0 && userBufferOffset < userBuffer.Length, "Offset must be within the range of the user buffer."); Debug.Assert(count >= 0, "count >= 0"); Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary."); if (count == 0) { // Nothing to read. return(0); } int remainingNumberOfBytesToRead = count; ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch; while (remainingNumberOfBytesToRead > 0 && scanResult != ODataBatchReaderStreamScanResult.Match) { int boundaryStartPosition, boundaryEndPosition; bool isEndBoundary, isParentBoundary; scanResult = this.batchBuffer.ScanForBoundary( this.CurrentBoundaries, remainingNumberOfBytesToRead, out boundaryStartPosition, out boundaryEndPosition, out isEndBoundary, out isParentBoundary); int bytesBeforeBoundaryStart; switch (scanResult) { case ODataBatchReaderStreamScanResult.NoMatch: // The boundary was not found in the buffer or after the required number of bytes to be read; // Check whether we can satisfy the full read request from the buffer // or whether we have to split the request and read more data into the buffer. if (this.batchBuffer.NumberOfBytesInBuffer >= remainingNumberOfBytesToRead) { // we can satisfy the full read request from the buffer Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, remainingNumberOfBytesToRead); this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + remainingNumberOfBytesToRead); return(count); } else { // we can only partially satisfy the read request int availableBytesToRead = this.batchBuffer.NumberOfBytesInBuffer; Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, availableBytesToRead); remainingNumberOfBytesToRead -= availableBytesToRead; userBufferOffset += availableBytesToRead; // we exhausted the buffer; if the underlying stream is not exceeded, refill the buffer if (this.underlyingStreamExhausted) { // We cannot fully satisfy the read request since there are not enough bytes in the stream. // Return the number of bytes we read. this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + availableBytesToRead); return(count - remainingNumberOfBytesToRead); } else { this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength); } } break; case ODataBatchReaderStreamScanResult.PartialMatch: // A partial match for the boundary was found at the end of the buffer. // If the underlying stream is not exceeded, refill the buffer. Otherwise return // the available bytes. if (this.underlyingStreamExhausted) { // We cannot fully satisfy the read request since there are not enough bytes in the stream. // Return the remaining bytes in the buffer independently of where a portentially boundary // start was detected since no full boundary can ever be detected if the stream is exhausted. int bytesToReturn = Math.Min(this.batchBuffer.NumberOfBytesInBuffer, remainingNumberOfBytesToRead); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesToReturn); this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + bytesToReturn); remainingNumberOfBytesToRead -= bytesToReturn; return(count - remainingNumberOfBytesToRead); } else { // Copy the bytes prior to the potential boundary start into the user buffer, refill the buffer and continue. bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition; Debug.Assert(bytesBeforeBoundaryStart < remainingNumberOfBytesToRead, "When reporting a partial match we should never have read all the remaining bytes to read (or more)."); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart); remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart; userBufferOffset += bytesBeforeBoundaryStart; this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ boundaryStartPosition); } break; case ODataBatchReaderStreamScanResult.Match: // We found the full boundary match; copy everything before the boundary to the buffer bytesBeforeBoundaryStart = boundaryStartPosition - this.batchBuffer.CurrentReadPosition; Debug.Assert(bytesBeforeBoundaryStart <= remainingNumberOfBytesToRead, "When reporting a full match we should never have read more than the remaining bytes to read."); Buffer.BlockCopy(this.batchBuffer.Bytes, this.batchBuffer.CurrentReadPosition, userBuffer, userBufferOffset, bytesBeforeBoundaryStart); remainingNumberOfBytesToRead -= bytesBeforeBoundaryStart; userBufferOffset += bytesBeforeBoundaryStart; // position the reader on the position of the boundary start this.batchBuffer.SkipTo(boundaryStartPosition); // return the number of bytes that were read return(count - remainingNumberOfBytesToRead); default: break; } } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_ReadWithDelimiter)); }
private void ValidateTransition(BatchWriterState newState) { if (IsErrorState(this.state) || !IsErrorState(newState)) { if ((newState == BatchWriterState.ChangeSetStarted) && (this.changeSetBoundary != null)) { throw new ODataException(Strings.ODataBatchWriter_CannotStartChangeSetWithActiveChangeSet); } if ((newState == BatchWriterState.ChangeSetCompleted) && (this.changeSetBoundary == null)) { throw new ODataException(Strings.ODataBatchWriter_CannotCompleteChangeSetWithoutActiveChangeSet); } if ((newState == BatchWriterState.BatchCompleted) && (this.changeSetBoundary != null)) { throw new ODataException(Strings.ODataBatchWriter_CannotCompleteBatchWithActiveChangeSet); } switch (this.state) { case BatchWriterState.Start: if (newState != BatchWriterState.BatchStarted) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromStart); } break; case BatchWriterState.BatchStarted: if (((newState != BatchWriterState.ChangeSetStarted) && (newState != BatchWriterState.OperationCreated)) && (newState != BatchWriterState.BatchCompleted)) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromBatchStarted); } break; case BatchWriterState.ChangeSetStarted: if ((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.ChangeSetCompleted)) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromChangeSetStarted); } break; case BatchWriterState.OperationCreated: if ((((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.OperationStreamRequested)) && ((newState != BatchWriterState.ChangeSetStarted) && (newState != BatchWriterState.ChangeSetCompleted))) && (newState != BatchWriterState.BatchCompleted)) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationCreated); } break; case BatchWriterState.OperationStreamRequested: if (newState != BatchWriterState.OperationStreamDisposed) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationContentStreamRequested); } break; case BatchWriterState.OperationStreamDisposed: if (((newState != BatchWriterState.OperationCreated) && (newState != BatchWriterState.ChangeSetStarted)) && ((newState != BatchWriterState.ChangeSetCompleted) && (newState != BatchWriterState.BatchCompleted))) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromOperationContentStreamDisposed); } break; case BatchWriterState.ChangeSetCompleted: if (((newState != BatchWriterState.BatchCompleted) && (newState != BatchWriterState.ChangeSetStarted)) && (newState != BatchWriterState.OperationCreated)) { throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromChangeSetCompleted); } break; case BatchWriterState.BatchCompleted: throw new ODataException(Strings.ODataBatchWriter_InvalidTransitionFromBatchCompleted); case BatchWriterState.Error: if (newState != BatchWriterState.Error) { throw new ODataException(Strings.ODataWriterCore_InvalidTransitionFromError(this.state.ToString(), newState.ToString())); } break; default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchWriter_ValidateTransition_UnreachableCodePath)); } } }
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)); }
/// <summary> /// Converts a string to a primitive value. /// </summary> /// <param name="text">The string text to convert.</param> /// <param name="targetTypeReference">Type to convert the string to.</param> /// <returns>The value converted to the target type.</returns> /// <remarks>This method does not convert null value.</remarks> internal static object ConvertStringToPrimitive(string text, IEdmPrimitiveTypeReference targetTypeReference) { DebugUtils.CheckNoExternalCallers(); Debug.Assert(text != null, "text != null"); Debug.Assert(targetTypeReference != null, "targetTypeReference != null"); try { EdmPrimitiveTypeKind primitiveKind = targetTypeReference.PrimitiveKind(); switch (primitiveKind) { case EdmPrimitiveTypeKind.Binary: return(Convert.FromBase64String(text)); case EdmPrimitiveTypeKind.Boolean: return(ConvertXmlBooleanValue(text)); case EdmPrimitiveTypeKind.Byte: return(XmlConvert.ToByte(text)); case EdmPrimitiveTypeKind.DateTime: return(PlatformHelper.ConvertStringToDateTime(text)); case EdmPrimitiveTypeKind.DateTimeOffset: return(PlatformHelper.ConvertStringToDateTimeOffset(text)); case EdmPrimitiveTypeKind.Decimal: return(XmlConvert.ToDecimal(text)); case EdmPrimitiveTypeKind.Double: return(XmlConvert.ToDouble(text)); case EdmPrimitiveTypeKind.Guid: return(new Guid(text)); case EdmPrimitiveTypeKind.Int16: return(XmlConvert.ToInt16(text)); case EdmPrimitiveTypeKind.Int32: return(XmlConvert.ToInt32(text)); case EdmPrimitiveTypeKind.Int64: return(XmlConvert.ToInt64(text)); case EdmPrimitiveTypeKind.SByte: return(XmlConvert.ToSByte(text)); case EdmPrimitiveTypeKind.Single: return(XmlConvert.ToSingle(text)); case EdmPrimitiveTypeKind.String: return(text); case EdmPrimitiveTypeKind.Time: return(XmlConvert.ToTimeSpan(text)); case EdmPrimitiveTypeKind.Stream: case EdmPrimitiveTypeKind.None: case EdmPrimitiveTypeKind.Geography: case EdmPrimitiveTypeKind.GeographyCollection: case EdmPrimitiveTypeKind.GeographyPoint: case EdmPrimitiveTypeKind.GeographyLineString: case EdmPrimitiveTypeKind.GeographyPolygon: case EdmPrimitiveTypeKind.GeometryCollection: case EdmPrimitiveTypeKind.GeographyMultiPolygon: case EdmPrimitiveTypeKind.GeographyMultiLineString: case EdmPrimitiveTypeKind.GeographyMultiPoint: case EdmPrimitiveTypeKind.Geometry: case EdmPrimitiveTypeKind.GeometryPoint: case EdmPrimitiveTypeKind.GeometryLineString: case EdmPrimitiveTypeKind.GeometryPolygon: case EdmPrimitiveTypeKind.GeometryMultiPolygon: case EdmPrimitiveTypeKind.GeometryMultiLineString: case EdmPrimitiveTypeKind.GeometryMultiPoint: default: // Note that Astoria supports XElement and Binary as well, but they are serialized as string or byte[] // and the metadata will actually talk about string and byte[] as well. Astoria will perform the conversion if necessary. throw new ODataException(Strings.General_InternalError(InternalErrorCodes.AtomValueUtils_ConvertStringToPrimitive)); } } catch (Exception e) { if (!ExceptionUtils.IsCatchableExceptionType(e)) { throw; } throw ReaderValidationUtils.GetPrimitiveTypeConversionException(targetTypeReference, e); } }
protected override Task <bool> ReadAsynchronously() { Task <bool> result; switch (this.State) { case ODataReaderState.Start: result = this.ReadAtStartImplementationAsync(); break; case ODataReaderState.FeedStart: result = this.ReadAtFeedStartImplementationAsync(); break; case ODataReaderState.FeedEnd: result = this.ReadAtFeedEndImplementationAsync(); break; case ODataReaderState.EntryStart: result = TaskUtils.GetTaskForSynchronousOperation(() => this.IncreaseEntryDepth()) .FollowOnSuccessWithTask(t => this.ReadAtEntryStartImplementationAsync()); break; case ODataReaderState.EntryEnd: result = TaskUtils.GetTaskForSynchronousOperation(() => this.DecreaseEntryDepth()) .FollowOnSuccessWithTask(t => this.ReadAtEntryEndImplementationAsync()); break; case ODataReaderState.NavigationLinkStart: result = this.ReadAtNavigationLinkStartImplementationAsync(); break; case ODataReaderState.NavigationLinkEnd: result = this.ReadAtNavigationLinkEndImplementationAsync(); break; case ODataReaderState.EntityReferenceLink: result = this.ReadAtEntityReferenceLinkAsync(); break; case ODataReaderState.Exception: // fall through case ODataReaderState.Completed: result = TaskUtils.GetFaultedTask <bool>(new ODataException(Strings.ODataReaderCore_NoReadCallsAllowed(this.State))); break; default: Debug.Assert(false, "Unsupported reader state " + this.State + " detected."); result = TaskUtils.GetFaultedTask <bool>(new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataReaderCoreAsync_ReadAsynchronously))); break; } return(result.FollowOnSuccessWith(t => { if ((this.State == ODataReaderState.EntryStart || this.State == ODataReaderState.EntryEnd) && this.Item != null) { ReaderValidationUtils.ValidateEntry(this.CurrentEntry); } return t.Result; })); }