/** * 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)); }
/** * Constructor for a new Document * * @param name the name of the POIFSDocument * @param stream the InputStream we read data from */ public NPOIFSDocument(string name, NPOIFSFileSystem filesystem, Stream stream) { _filesystem = filesystem; // sotre it int length = Store(stream); // Build the property for it _property = new DocumentProperty(name, length); _property.StartBlock = _stream.GetStartBlock(); }
protected override void Dispose(bool disposing) { base.Dispose(disposing); // Do we have a pending buffer for the mini stream? if (_buffer != null) { // It's not much data, so ask NPOIFSDocument to do it for us _document.ReplaceContents(new MemoryStream(_buffer.ToArray())); } else { // We've been writing to the stream as we've gone along // Update the details on the property now _stream_output.Dispose(); _property.UpdateSize(_document_size); _property.StartBlock = (_stream.GetStartBlock()); } // No more! _closed = true; }