/// <include file='doc\OracleLob.uex' path='docs/doc[@for="OracleLob.Read"]/*' /> public override int Read( byte[] buffer, int offset, int count ) { AssertObjectNotDisposed(); if (count < 0) { throw ADP.MustBePositive("count"); } if (offset < 0) { throw ADP.MustBePositive("offset"); } if (null == buffer) { throw ADP.ArgumentNull("buffer"); } if ((long)buffer.Length < ((long)offset + (long)count)) { throw ADP.BufferExceeded(); } if (IsNull || 0 == count) { return(0); } AssertConnectionIsOpen(); AssertAmountIsValidOddOK(offset, "offset"); AssertAmountIsValidOddOK(count, "count"); int amount; uint readPosition = (uint)_currentPosition; // Bless their hearts: Oracle won't let us use odd addresses to read // character data, nor will they let us read a single byte from a // character lob. Instead, we allocate our own buffer and copy the // value to the caller's buffer. int oddPosition = 0; int oddOffset = 0; int oddCount = 0; byte[] readBuffer = buffer; int readOffset = offset; int readCount = count; if (IsCharacterLob) { oddPosition = (int)(readPosition & 0x1); oddOffset = offset & 0x1; oddCount = count & 0x1; readPosition /= 2; if (1 == oddOffset || 1 == oddPosition || 1 == oddCount) { readOffset = 0; readCount = count + oddCount + (2 * oddPosition); readBuffer = new byte[readCount]; } } short charsetId = IsCharacterLob ? OCI.OCI_UCS2ID : (short)0; int rc = 0; amount = AdjustOffsetToOracle(readCount); #if EXPOSELOBBUFFERING EnsureBuffering(_bufferedRequested); #endif //EXPOSELOBBUFFERING // We need to pin the buffer and get the address of the offset that // the user requested; Oracle doesn't allow us to specify an offset // into the buffer. GCHandle handle = new GCHandle(); try { try { handle = GCHandle.Alloc(readBuffer, GCHandleType.Pinned); IntPtr bufferPtr = new IntPtr((long)handle.AddrOfPinnedObject() + readOffset); rc = TracedNativeMethods.OCILobRead( ServiceContextHandle, ErrorHandle, Descriptor, ref amount, readPosition + 1, bufferPtr, readCount, ADP.NullHandleRef, ADP.NullHandleRef, charsetId, _charsetForm ); } finally { if (handle.IsAllocated) { handle.Free(); // Unpin the buffer } } } catch // Prevent exception filters from running in our space { throw; } if ((int)OCI.RETURNCODE.OCI_NEED_DATA == rc) { rc = 0; } if ((int)OCI.RETURNCODE.OCI_NO_DATA == rc) { return(0); } if (0 != rc) { Connection.CheckError(ErrorHandle, rc); } amount = AdjustOracleToOffset(amount); if (readBuffer as object != buffer as object) { if (amount >= count) { amount = count; } else { amount -= oddPosition; } Buffer.BlockCopy(readBuffer, oddPosition, buffer, offset, amount); readBuffer = null; } _currentPosition += amount; return(amount); }
public override int Read(byte[] buffer, int offset, int count) { this.AssertObjectNotDisposed(); if (count < 0) { throw System.Data.Common.ADP.MustBePositive("count"); } if (offset < 0) { throw System.Data.Common.ADP.MustBePositive("offset"); } if (buffer == null) { throw System.Data.Common.ADP.ArgumentNull("buffer"); } if (buffer.Length < (offset + count)) { throw System.Data.Common.ADP.BufferExceeded("count"); } if (this.IsNull || (count == 0)) { return(0); } this.AssertConnectionIsOpen(); this.AssertAmountIsValidOddOK((long)offset, "offset"); this.AssertAmountIsValidOddOK((long)count, "count"); uint num5 = (uint)this._currentPosition; int srcOffset = 0; int num8 = 0; int num6 = 0; byte[] buffer2 = buffer; int num7 = offset; int amount = count; if (this.IsCharacterLob) { srcOffset = ((int)num5) & 1; num8 = offset & 1; num6 = count & 1; num5 /= 2; if (((1 == num8) || (1 == srcOffset)) || (1 == num6)) { num7 = 0; amount = (count + num6) + (2 * srcOffset); buffer2 = new byte[amount]; } } ushort csid = this.IsCharacterLob ? ((ushort)0x3e8) : ((ushort)0); int rc = 0; int amtp = this.AdjustOffsetToOracle(amount); GCHandle handle = new GCHandle(); try { handle = GCHandle.Alloc(buffer2, GCHandleType.Pinned); IntPtr bufp = new IntPtr(((long)handle.AddrOfPinnedObject()) + num7); rc = TracedNativeMethods.OCILobRead(this.ServiceContextHandle, this.ErrorHandle, this.Descriptor, ref amtp, num5 + 1, bufp, (uint)amount, csid, this._charsetForm); } finally { if (handle.IsAllocated) { handle.Free(); } } if (0x63 == rc) { rc = 0; } if (100 == rc) { return(0); } if (rc != 0) { this.Connection.CheckError(this.ErrorHandle, rc); } amtp = this.AdjustOracleToOffset(amtp); if (buffer2 != buffer) { if (amtp >= count) { amtp = count; } else { amtp -= srcOffset; } Buffer.BlockCopy(buffer2, srcOffset, buffer, offset, amtp); buffer2 = null; } this._currentPosition += amtp; return(amtp); }