/**
         * Reads a small amount of data from across the boundary between two blocks.
         * The {@link #_readIndex} of this (the second) block is updated accordingly.
         * Note- this method (and other code) assumes that the second {@link DataInputBlock}
         * always is big enough to complete the read without being exhausted.
         */
        private void ReadSpanning(DataInputBlock prevBlock, int prevBlockAvailable, byte[] buf)
        {
            Array.Copy(prevBlock._buf, prevBlock._readIndex, buf, 0, prevBlockAvailable);
            int secondReadLen = buf.Length - prevBlockAvailable;

            Array.Copy(_buf, 0, buf, prevBlockAvailable, secondReadLen);
            _readIndex = secondReadLen;
        }
        /**
         * Reads a <c>short</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public int ReadUshortLE(DataInputBlock prevBlock)
        {
            // simple case - will always be one byte in each block
            int i = prevBlock._buf.Length - 1;

            int b0 = prevBlock._buf[i++] & 0xFF;
            int b1 = _buf[_readIndex++] & 0xFF;
            return (b1 << 8) + (b0 << 0);
        }
        /**
         * Reads a <c>short</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public int ReadUshortLE(DataInputBlock prevBlock)
        {
            // simple case - will always be one byte in each block
            int i = prevBlock._buf.Length - 1;

            int b0 = prevBlock._buf[i++] & 0xFF;
            int b1 = _buf[_readIndex++] & 0xFF;

            return((b1 << 8) + (b0 << 0));
        }
        /**
         * Reads an <c>int</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public int ReadIntLE(DataInputBlock prevBlock, int prevBlockAvailable)
        {
            byte[] buf = new byte[4];

            ReadSpanning(prevBlock, prevBlockAvailable, buf);
            int b0 = buf[0] & 0xFF;
            int b1 = buf[1] & 0xFF;
            int b2 = buf[2] & 0xFF;
            int b3 = buf[3] & 0xFF;

            return((b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0));
        }
        /**
         * Create an InputStream from the specified DocumentEntry
         * 
         * @param document the DocumentEntry to be read
         * 
         * @exception IOException if the DocumentEntry cannot be opened (like, maybe it has
         *                been deleted?)
         */
        public ODocumentInputStream(DocumentEntry document)
        {
            if (!(document is DocumentNode))
            {
                throw new IOException("Cannot open internal document storage");
            }
            DocumentNode documentNode = (DocumentNode)document;
            if (documentNode.Document == null)
            {
                throw new IOException("Cannot open internal document storage");
            }

            _current_offset = 0;
            _marked_offset = 0;
            _document_size = document.Size;
            _closed = false;
            _document = documentNode.Document;
            _currentBlock = GetDataInputBlock(0);
        }
        /**
         * Reads a <c>long</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public long ReadLongLE(DataInputBlock prevBlock, int prevBlockAvailable)
        {
            byte[] buf = new byte[8];

            ReadSpanning(prevBlock, prevBlockAvailable, buf);

            int b0 = buf[0] & 0xFF;
            int b1 = buf[1] & 0xFF;
            int b2 = buf[2] & 0xFF;
            int b3 = buf[3] & 0xFF;
            int b4 = buf[4] & 0xFF;
            int b5 = buf[5] & 0xFF;
            int b6 = buf[6] & 0xFF;
            int b7 = buf[7] & 0xFF;

            return(((long)b7 << 56) +
                   ((long)b6 << 48) +
                   ((long)b5 << 40) +
                   ((long)b4 << 32) +
                   ((long)b3 << 24) +
                   (b2 << 16) +
                   (b1 << 8) +
                   (b0 << 0));
        }
        /**
         * Reads a <c>long</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public long ReadLongLE(DataInputBlock prevBlock, int prevBlockAvailable)
        {
            byte[] buf = new byte[8];

            ReadSpanning(prevBlock, prevBlockAvailable, buf);

            int b0 = buf[0] & 0xFF;
            int b1 = buf[1] & 0xFF;
            int b2 = buf[2] & 0xFF;
            int b3 = buf[3] & 0xFF;
            int b4 = buf[4] & 0xFF;
            int b5 = buf[5] & 0xFF;
            int b6 = buf[6] & 0xFF;
            int b7 = buf[7] & 0xFF;
            return (((long)b7 << 56) +
                    ((long)b6 << 48) +
                    ((long)b5 << 40) +
                    ((long)b4 << 32) +
                    ((long)b3 << 24) +
                    (b2 << 16) +
                    (b1 << 8) +
                    (b0 << 0));
        }
        /**
         * Reads an <c>int</c> which spans the end of <c>prevBlock</c> and the start of this block.
         */
        public int ReadIntLE(DataInputBlock prevBlock, int prevBlockAvailable)
        {
            byte[] buf = new byte[4];

            ReadSpanning(prevBlock, prevBlockAvailable, buf);
            int b0 = buf[0] & 0xFF;
            int b1 = buf[1] & 0xFF;
            int b2 = buf[2] & 0xFF;
            int b3 = buf[3] & 0xFF;
            return (b3 << 24) + (b2 << 16) + (b1 << 8) + (b0 << 0);
        }
        /**
         * Repositions this stream to the position at the time the mark() method was
         * last called on this input stream. If mark() has not been called this
         * method repositions the stream to its beginning.
         */

        public override void Reset()
        {
            _current_offset = _marked_offset;
            _currentBlock = GetDataInputBlock(_current_offset);
        }
 public override int ReadUByte()
 {
     CheckAvaliable(1);
     int result = _currentBlock.ReadUByte();
     _current_offset++;
     if (_currentBlock.Available() < 1)
     {
         _currentBlock = GetDataInputBlock(_current_offset);
     }
     return result;
 }
 public override int ReadUShort()
 {
     CheckAvaliable(SIZE_SHORT);
     int blockAvailable = _currentBlock.Available();
     int result;
     if (blockAvailable > SIZE_SHORT)
     {
         result = _currentBlock.ReadUshortLE();
     }
     else
     {
         DataInputBlock nextBlock = GetDataInputBlock(_current_offset + blockAvailable);
         if (blockAvailable == SIZE_SHORT)
         {
             result = _currentBlock.ReadUshortLE();
         }
         else
         {
             result = nextBlock.ReadUshortLE(_currentBlock);
         }
         _currentBlock = nextBlock;
     }
     _current_offset += SIZE_SHORT;
     return result;
 }
 public override long ReadLong()
 {
     CheckAvaliable(SIZE_LONG);
     int blockAvailable = _currentBlock.Available();
     long result;
     if (blockAvailable > SIZE_LONG)
     {
         result = _currentBlock.ReadLongLE();
     }
     else
     {
         DataInputBlock nextBlock = GetDataInputBlock(_current_offset + blockAvailable);
         if (blockAvailable == SIZE_LONG)
         {
             result = _currentBlock.ReadLongLE();
         }
         else
         {
             result = nextBlock.ReadLongLE(_currentBlock, blockAvailable);
         }
         _currentBlock = nextBlock;
     }
     _current_offset += SIZE_LONG;
     return result;
 }
 public override void ReadFully(byte[] buf, int off, int len)
 {
     CheckAvaliable(len);
     int blockAvailable = _currentBlock.Available();
     if (blockAvailable > len)
     {
         _currentBlock.ReadFully(buf, off, len);
         _current_offset += len;
         return;
     }
     // else read big amount in chunks
     int remaining = len;
     int WritePos = off;
     while (remaining > 0)
     {
         bool blockIsExpiring = remaining >= blockAvailable;
         int reqSize;
         if (blockIsExpiring)
         {
             reqSize = blockAvailable;
         }
         else
         {
             reqSize = remaining;
         }
         _currentBlock.ReadFully(buf, WritePos, reqSize);
         remaining -= reqSize;
         WritePos += reqSize;
         _current_offset += reqSize;
         if (blockIsExpiring)
         {
             if (_current_offset == _document_size)
             {
                 if (remaining > 0)
                 {
                     throw new InvalidOperationException(
                             "reached end of document stream unexpectedly");
                 }
                 _currentBlock = null;
                 break;
             }
             _currentBlock = GetDataInputBlock(_current_offset);
             blockAvailable = _currentBlock.Available();
         }
     }
 }
        public override long Skip(long n)
        {
            dieIfClosed();
            if (n < 0)
            {
                return 0;
            }
            long new_offset = _current_offset + (int)n;

            if (new_offset < _current_offset)
            {

                // wrap around in Converting a VERY large long to an int
                new_offset = _document_size;
            }
            else if (new_offset > _document_size)
            {
                new_offset = _document_size;
            }
            long rval = new_offset - _current_offset;

            _current_offset = new_offset;
            _currentBlock = GetDataInputBlock(_current_offset);
            return rval;
        }
 /**
  * Reads a small amount of data from across the boundary between two blocks.  
  * The {@link #_readIndex} of this (the second) block is updated accordingly.
  * Note- this method (and other code) assumes that the second {@link DataInputBlock}
  * always is big enough to complete the read without being exhausted.
  */
 private void ReadSpanning(DataInputBlock prevBlock, int prevBlockAvailable, byte[] buf)
 {
     Array.Copy(prevBlock._buf, prevBlock._readIndex, buf, 0, prevBlockAvailable);
     int secondReadLen = buf.Length - prevBlockAvailable;
     Array.Copy(_buf, 0, buf, prevBlockAvailable, secondReadLen);
     _readIndex = secondReadLen;
 }
 /**
  * Create an InputStream from the specified Document
  * 
  * @param document the Document to be read
  */
 public ODocumentInputStream(POIFSDocument document)
 {
     _current_offset = 0;
     _marked_offset = 0;
     _document_size = document.Size;
     _closed = false;
     _document = document;
     _currentBlock = GetDataInputBlock(0);
 }
 public override int Read()
 {
     dieIfClosed();
     if (atEOD())
     {
         return EOF;
     }
     int result = _currentBlock.ReadUByte();
     _current_offset++;
     if (_currentBlock.Available() < 1)
     {
         _currentBlock = GetDataInputBlock(_current_offset);
     }
     return result;
 }