コード例 #1
0
ファイル: NPOIFSStream.cs プロジェクト: ruo2012/Npoi.Core
 protected internal StreamBlockByteBuffer(NPOIFSStream pStream)
 {
     this.pStream = pStream;
     loopDetector = pStream.blockStore.GetChainLoopDetector();
     prevBlock    = POIFSConstants.END_OF_CHAIN;
     nextBlock    = pStream.startBlock;
 }
コード例 #2
0
        /**
         * Load the block, extending the underlying stream if needed
         */

        public override ByteBuffer CreateBlockIfNeeded(int offset)
        {
            bool firstInStore = false;

            // If we are the first block to be allocated, initialise the stream
            if (_mini_stream.GetStartBlock() == POIFSConstants.END_OF_CHAIN)
            {
                firstInStore = true;
            }

            // Try to Get it without extending the stream
            if (!firstInStore)
            {
                try
                {
                    return(GetBlockAt(offset));
                }
                catch (IndexOutOfRangeException) { }
            }

            // Need to extend the stream
            // TODO Replace this with proper append support
            // For now, do the extending by hand...

            // Ask for another block
            int newBigBlock = _filesystem.GetFreeBlock();

            _filesystem.CreateBlockIfNeeded(newBigBlock);
            // If we are the first block to be allocated, initialise the stream
            if (firstInStore)
            {
                _filesystem.PropertyTable.Root.StartBlock = (newBigBlock);
                _mini_stream = new NPOIFSStream(_filesystem, newBigBlock);
            }
            else
            {
                // Tack it onto the end of our chain
                ChainLoopDetector loopDetector = _filesystem.GetChainLoopDetector();
                int block = _mini_stream.GetStartBlock();
                while (true)
                {
                    loopDetector.Claim(block);
                    int next = _filesystem.GetNextBlock(block);
                    if (next == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    block = next;
                }
                _filesystem.SetNextBlock(block, newBigBlock);
            }
            _filesystem.SetNextBlock(newBigBlock, POIFSConstants.END_OF_CHAIN);

            // Now try again, to get the real small block
            return(CreateBlockIfNeeded(offset));
        }
コード例 #3
0
        private void ReadBAT(int batAt, ChainLoopDetector loopDetector)
        {
            loopDetector.Claim(batAt);
            ByteBuffer fatData = GetBlockAt(batAt);
            // byte[] fatData = GetBlockAt(batAt);
            BATBlock bat = BATBlock.CreateBATBlock(bigBlockSize, fatData);

            bat.OurBlockIndex = batAt;
            _bat_blocks.Add(bat);
        }
コード例 #4
0
ファイル: NPOIFSStream.cs プロジェクト: ruo2012/Npoi.Core
        internal void Free(ChainLoopDetector loopDetector)
        {
            int nextBlock = startBlock;

            while (nextBlock != POIFSConstants.END_OF_CHAIN)
            {
                int thisBlock = nextBlock;
                loopDetector.Claim(thisBlock);
                nextBlock = blockStore.GetNextBlock(thisBlock);
                blockStore.SetNextBlock(thisBlock, POIFSConstants.UNUSED_BLOCK);
            }
            startBlock = POIFSConstants.END_OF_CHAIN;
        }
コード例 #5
0
ファイル: NPOIFSStream.cs プロジェクト: ruo2012/Npoi.Core
 public StreamBlockByteBufferIterator(NPOIFSStream pStream, int firstBlock)
 {
     this.pStream = pStream;
     nextBlock    = firstBlock;
     try
     {
         loopDetector = pStream.blockStore.GetChainLoopDetector();
     }
     catch (IOException e)
     {
         //throw new System.RuntimeException(e);
         throw new Exception(e.Message);
     }
 }
コード例 #6
0
ファイル: NPOIFSStream.cs プロジェクト: ruo2012/Npoi.Core
        // TODO Streaming write support
        // TODO  then convert fixed sized write to use streaming internally
        // TODO Append write support (probably streaming)

        /**
         * Frees all blocks in the stream
         */

        public void Free()
        {
            ChainLoopDetector loopDetector = blockStore.GetChainLoopDetector();

            Free(loopDetector);
        }
コード例 #7
0
        /**
         * Read and process the PropertiesTable and the
         *  FAT / XFAT blocks, so that we're Ready to
         *  work with the file
         */

        private void ReadCoreContents()
        {
            // Grab the block size
            bigBlockSize = _header.BigBlockSize;

            // Each block should only ever be used by one of the
            //  FAT, XFAT or Property Table. Ensure it does
            ChainLoopDetector loopDetector = GetChainLoopDetector();

            // Read the FAT blocks
            foreach (int fatAt in _header.BATArray)
            {
                ReadBAT(fatAt, loopDetector);
            }
            // Work out how many FAT blocks remain in the XFATs
            int remainingFATs = _header.BATCount - _header.BATArray.Length;

            // Now read the XFAT blocks, and the FATs within them
            BATBlock xfat;
            int      nextAt = _header.XBATIndex;

            for (int i = 0; i < _header.XBATCount; i++)
            {
                loopDetector.Claim(nextAt);
                ByteBuffer fatData = GetBlockAt(nextAt);
                xfat = BATBlock.CreateBATBlock(bigBlockSize, fatData);
                xfat.OurBlockIndex = nextAt;
                nextAt             = xfat.GetValueAt(bigBlockSize.GetXBATEntriesPerBlock());
                _xbat_blocks.Add(xfat);
                // Process all the (used) FATs from this XFAT
                int xbatFATs = Math.Min(remainingFATs, bigBlockSize.GetXBATEntriesPerBlock());
                for (int j = 0; j < xbatFATs; j++)
                {
                    int fatAt = xfat.GetValueAt(j);
                    if (fatAt == POIFSConstants.UNUSED_BLOCK || fatAt == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    ReadBAT(fatAt, loopDetector);
                }
                remainingFATs -= xbatFATs;
            }

            // We're now able to load steams
            // Use this to read in the properties
            _property_table = new NPropertyTable(_header, this);

            // Finally read the Small Stream FAT (SBAT) blocks
            BATBlock        sfat;
            List <BATBlock> sbats = new List <BATBlock>();

            _mini_store = new NPOIFSMiniStore(this, _property_table.Root, sbats, _header);
            nextAt      = _header.SBATStart;
            for (int i = 0; i < _header.SBATCount; i++)
            {
                loopDetector.Claim(nextAt);
                ByteBuffer fatData = GetBlockAt(nextAt);
                sfat = BATBlock.CreateBATBlock(bigBlockSize, fatData);
                sfat.OurBlockIndex = nextAt;
                sbats.Add(sfat);
                nextAt = GetNextBlock(nextAt);
            }
        }
コード例 #8
0
        /**
         * Finds a free block, and returns its offset.
         * This method will extend the file if needed, and if doing
         *  so, allocate new FAT blocks to Address the extra space.
         */

        public override int GetFreeBlock()
        {
            int sectorsPerSBAT = _filesystem.GetBigBlockSizeDetails().GetBATEntriesPerBlock();

            // First up, do we have any spare ones?
            int offset = 0;

            for (int i = 0; i < _sbat_blocks.Count; i++)
            {
                // Check this one
                BATBlock sbat = _sbat_blocks[i];
                if (sbat.HasFreeSectors)
                {
                    // Claim one of them and return it
                    for (int j = 0; j < sectorsPerSBAT; j++)
                    {
                        int sbatValue = sbat.GetValueAt(j);
                        if (sbatValue == POIFSConstants.UNUSED_BLOCK)
                        {
                            // Bingo
                            return(offset + j);
                        }
                    }
                }

                // Move onto the next SBAT
                offset += sectorsPerSBAT;
            }

            // If we Get here, then there aren't any
            //  free sectors in any of the SBATs
            // So, we need to extend the chain and add another

            // Create a new BATBlock
            BATBlock newSBAT    = BATBlock.CreateEmptyBATBlock(_filesystem.GetBigBlockSizeDetails(), false);
            int      batForSBAT = _filesystem.GetFreeBlock();

            newSBAT.OurBlockIndex = batForSBAT;

            // Are we the first SBAT?
            if (_header.SBATCount == 0)
            {
                // Tell the header that we've got our first SBAT there
                _header.SBATStart      = batForSBAT;
                _header.SBATBlockCount = 1;
            }
            else
            {
                // Find the end of the SBAT stream, and add the sbat in there
                ChainLoopDetector loopDetector = _filesystem.GetChainLoopDetector();
                int batOffset = _header.SBATStart;
                while (true)
                {
                    loopDetector.Claim(batOffset);
                    int nextBat = _filesystem.GetNextBlock(batOffset);
                    if (nextBat == POIFSConstants.END_OF_CHAIN)
                    {
                        break;
                    }
                    batOffset = nextBat;
                }

                // Add it in at the end
                _filesystem.SetNextBlock(batOffset, batForSBAT);

                // And update the count
                _header.SBATBlockCount = _header.SBATCount + 1;
            }

            // Finish allocating
            _filesystem.SetNextBlock(batForSBAT, POIFSConstants.END_OF_CHAIN);
            _sbat_blocks.Add(newSBAT);

            // Return our first spot
            return(offset);
        }