Ejemplo n.º 1
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));
        }