public void Write(ArchiveListing listing, out ArchiveListingBlockInfo[] blocksInfo, out ArchiveListingEntryInfoV2[] entriesInfoV2)
        {
            using (MemoryStream ms = new MemoryStream(32768))
            {
                int blockNumber = 0, unpackedBlockOffset = 0;
                entriesInfoV2 = new ArchiveListingEntryInfoV2[listing.Count];
                List <ArchiveListingBlockInfo> blocks = new List <ArchiveListingBlockInfo>(128);
                using (FormattingStreamWriter sw = new FormattingStreamWriter(ms, Encoding.ASCII, 4096, true, CultureInfo.InvariantCulture))
                {
                    sw.AutoFlush = true;
                    for (int i = 0; i < listing.Count; i++)
                    {
                        ArchiveEntry entry = listing[i];

                        ArchiveListingEntryInfoV2 info = new ArchiveListingEntryInfoV2 {
                            BlockNumber = (short)(ms.Position / 8192)
                        };
                        info.Flag = (info.BlockNumber % 2 != 0);

                        entriesInfoV2[i] = info;

                        if (blockNumber != info.BlockNumber)
                        {
                            int blockSize = (int)(ms.Position - unpackedBlockOffset);
                            ms.Position = unpackedBlockOffset;
                            ArchiveListingBlockInfo block = new ArchiveListingBlockInfo {
                                Offset = (int)_output.Position, UncompressedSize = blockSize
                            };
                            block.CompressedSize = ZLibHelper.Compress(ms, _output, block.UncompressedSize);
                            blocks.Add(block);

                            blockNumber++;
                            unpackedBlockOffset = (int)ms.Position;
                            sw.Write("{0:x}:{1:x}:{2:x}:{3}\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name);
                        }
                        else if (i == listing.Count - 1)
                        {
                            info.Offset = (short)(ms.Position - unpackedBlockOffset);
                            sw.Write("{0:x}:{1:x}:{2:x}:{3}\0end\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name);
                            int blockSize = (int)(ms.Position - unpackedBlockOffset);
                            ms.Position = unpackedBlockOffset;
                            ArchiveListingBlockInfo block = new ArchiveListingBlockInfo {
                                Offset = (int)_output.Position, UncompressedSize = blockSize
                            };
                            block.CompressedSize = ZLibHelper.Compress(ms, _output, block.UncompressedSize);
                            blocks.Add(block);
                        }
                        else
                        {
                            info.Offset = (short)(ms.Position - unpackedBlockOffset);
                            sw.Write("{0:x}:{1:x}:{2:x}:{3}\0", entry.Sector, entry.UncompressedSize, entry.Size, entry.Name);
                        }
                    }
                }
                blocksInfo = blocks.ToArray();
            }
        }
Example #2
0
        public void OnWritingCompleted(ArchiveEntry entry, MemoryStream ms, bool?compression)
        {
            ms.Position = 0;

            int compressedSize   = 0;
            int uncompressedSize = (int)ms.Length;

            byte[] copyBuff = new byte[Math.Min(uncompressedSize, 32 * 1024)];

            try
            {
                bool compress = uncompressedSize > 256 && (compression ?? entry.IsCompressed);
                if (compress)
                {
                    using (SafeUnmanagedArray buff = new SafeUnmanagedArray(uncompressedSize + 256))
                        using (UnmanagedMemoryStream buffStream = buff.OpenStream(FileAccess.ReadWrite))
                        {
                            compressedSize = ZLibHelper.Compress(ms, buffStream, uncompressedSize);
                            if (uncompressedSize - compressedSize > 256)
                            {
                                using (Stream output = OpenOrAppendBinary(entry, compressedSize))
                                {
                                    buffStream.Position = 0;
                                    buffStream.CopyToStream(output, compressedSize, copyBuff);
                                }
                                return;
                            }
                        }
                }

                ms.Position    = 0;
                compressedSize = uncompressedSize;
                using (Stream output = OpenOrAppendBinary(entry, uncompressedSize))
                    ms.CopyToStream(output, uncompressedSize, copyBuff);
            }
            finally
            {
                entry.Size             = compressedSize;
                entry.UncompressedSize = uncompressedSize;
            }
        }
Example #3
0
        private void UncompressBlocks(ArchiveListingBlockInfo[] blocks, Stream stream)
        {
            try
            {
                for (int i = 0; i < blocks.Length; i++)
                {
                    ArchiveListingBlockInfo block = blocks[i];
                    int uncompressedSize          = block.UncompressedSize;

                    stream.Position        = _header.InfoOffset + block.Offset;
                    _uncompressedBlocks[i] = ZLibHelper.Uncompress(stream, uncompressedSize);
                }
            }
            catch (ObjectDisposedException)
            {
            }
            catch (Exception ex)
            {
                _exception = ex;
            }
        }
Example #4
0
        public static Stream BackgroundExtractIfCompressed(Stream input, ArchiveEntry entry)
        {
            if (!entry.IsCompressed)
            {
                return(input);
            }

            int uncompressedSize = (int)entry.UncompressedSize;

            if (uncompressedSize == 0)
            {
                return(new MemoryStream(0));
            }

            Stream writer, reader;

            Flute.CreatePipe(uncompressedSize, out writer, out reader);

            //if (!ThreadPool.QueueUserWorkItem((o) => ZLibHelper.UncompressAndDisposeStreams(input, writer, uncompressedSize, CancellationToken.None)))
            ThreadHelper.StartBackground("UncompressAndDisposeSourceAsync", () => ZLibHelper.UncompressAndDisposeStreams(input, writer, uncompressedSize, CancellationToken.None));
            return(reader);
        }