/// <summary> /// Skips all the data in the stream until a boundary is found. /// </summary> /// <param name="isEndBoundary">true if the boundary that was found is an end boundary; otherwise false.</param> /// <param name="isParentBoundary">true if the detected boundary is a parent boundary (i.e., the expected boundary is missing).</param> /// <returns>true if a boundary was found; otherwise false.</returns> internal bool SkipToBoundary(out bool isEndBoundary, out bool isParentBoundary) { DebugUtils.CheckNoExternalCallers(); // Ensure we have a batch encoding; if not detect it on the first read/skip. this.EnsureBatchEncoding(); ODataBatchReaderStreamScanResult scanResult = ODataBatchReaderStreamScanResult.NoMatch; while (scanResult != ODataBatchReaderStreamScanResult.Match) { int boundaryStartPosition, boundaryEndPosition; scanResult = this.batchBuffer.ScanForBoundary( this.CurrentBoundaries, /*stopAfterIfNotFound*/ int.MaxValue, out boundaryStartPosition, out boundaryEndPosition, out isEndBoundary, out isParentBoundary); switch (scanResult) { case ODataBatchReaderStreamScanResult.NoMatch: if (this.underlyingStreamExhausted) { // there is nothing else to load from the underlying stream; the requested boundary does not exist this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer); return(false); } // skip everything in the buffer and refill it from the underlying stream; continue scanning this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ ODataBatchReaderStreamBuffer.BufferLength); break; case ODataBatchReaderStreamScanResult.PartialMatch: if (this.underlyingStreamExhausted) { // there is nothing else to load from the underlying stream; the requested boundary does not exist this.batchBuffer.SkipTo(this.batchBuffer.CurrentReadPosition + this.batchBuffer.NumberOfBytesInBuffer); return(false); } this.underlyingStreamExhausted = this.batchBuffer.RefillFrom(this.inputContext.Stream, /*preserveFrom*/ boundaryStartPosition); break; case ODataBatchReaderStreamScanResult.Match: // If we found the expected boundary, position the reader on the position after the boundary end. // If we found a parent boundary, position the reader on the boundary start so we'll detect the boundary // again on the next Read call. this.batchBuffer.SkipTo(isParentBoundary ? boundaryStartPosition : boundaryEndPosition + 1); return(true); default: throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary)); } } throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataBatchReaderStream_SkipToBoundary)); }
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)); }
/// <summary> /// Reads a line (all bytes until a line resource set) from the underlying stream. /// </summary> /// <returns>Returns the string that was read from the underlying stream (not including a terminating line resource set), or null if the end of input was reached.</returns> private string ReadLine() { 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) { // TODO: [Design] Consider security limits for data being read ODataBatchUtils.EnsureArraySize(ref bytesForString, lineBufferSize, byteCount); Buffer.BlockCopy(this.BatchBuffer.Bytes, this.BatchBuffer.CurrentReadPosition, bytesForString, lineBufferSize, byteCount); lineBufferSize += byteCount; } if (this.underlyingStreamExhausted) { if (lineBufferSize == 0) { // If there's nothing more to pull from the underlying stream, and we didn't read anything // in this invocation of ReadLine(), return null to indicate end of input. return(null); } // Nothing more to read; stop looping scanResult = ODataBatchReaderStreamScanResult.Match; this.BatchBuffer.SkipTo(this.BatchBuffer.CurrentReadPosition + byteCount); } else { this.underlyingStreamExhausted = this.BatchBuffer.RefillFrom(this.multipartMixedBatchInputContext.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.multipartMixedBatchInputContext.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)); } } Debug.Assert(bytesForString != null, "bytesForString != null"); 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 override int ReadWithDelimiter(byte[] userBuffer, int userBufferOffset, int count) { 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.multipartMixedBatchInputContext.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 potentially 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.multipartMixedBatchInputContext.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)); }
/// <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> /// 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) { 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)); } } }
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)); }