Exemplo n.º 1
0
        /// <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);
        }