コード例 #1
0
ファイル: chmFile.cs プロジェクト: nataren/libchmsharp2
        /* close an ITS archive */
        public void Close()
        {
            if (_h.fd != null)
            {
                _h.fd.Close();
            }
            _h.fd = null;

            if (_h.lzx_state != null)
            {
                Lzx.LZXteardown(_h.lzx_state);
            }
            _h.lzx_state = null;

            _h.cache_blocks        = null;
            _h.cache_block_indices = null;
        }
コード例 #2
0
ファイル: Lzxc.cs プロジェクト: nataren/libchmsharp2
        /* decompress the block.  must have lzx_mutex. */
        public static Int64 DecompressBlock(ref ChmFileInfo h, UInt64 block, ref byte[] ubuffer)
        {
            byte[] cbuffer    = new byte[h.reset_table.block_len + 6144];
            long   cbufferpos = 0;
            UInt64 cmpStart   = 0;                                  /* compressed start  */
            Int64  cmpLen     = 0;                                  /* compressed len    */
            int    indexSlot;                                       /* cache index slot  */
            uint   lbuffer;                                         /* local buffer ptr  */
            UInt32 blockAlign = (UInt32)(block % h.reset_blkcount); /* reset intvl. aln. */
            UInt32 i;                                               /* local loop index  */

            /* let the caching system pull its weight! */
            if ((int)(block - blockAlign) <= h.lzx_last_block &&
                (int)block >= h.lzx_last_block)
            {
                blockAlign = (uint)((int)block - h.lzx_last_block);
            }

            /* check if we need previous blocks */
            if (blockAlign != 0)
            {
                /* fetch all required previous blocks since last reset */
                for (i = blockAlign; i > 0; i--)
                {
                    UInt32 curBlockIdx = (UInt32)(block - (LONGUINT64)i);

                    /* check if we most recently decompressed the previous block */
                    if (h.lzx_last_block != curBlockIdx)
                    {
                        if ((curBlockIdx % h.reset_blkcount) == 0)
                        {
                            Lzx.LZXreset(h.lzx_state);
                        }

                        indexSlot = (int)((curBlockIdx) % h.cache_num_blocks);
                        if (h.cache_blocks[indexSlot] == null)
                        {
                            h.cache_blocks[indexSlot] = new byte[h.reset_table.block_len];
                        }

                        h.cache_block_indices[indexSlot] = curBlockIdx;
                        lbuffer = (uint)indexSlot;

                        /* decompress the previous block */
                        if (!GetCmpBlockBounds(ref h, curBlockIdx, ref cmpStart, ref cmpLen) ||
                            cmpLen < 0 ||
                            cmpLen > (LONGINT64)h.reset_table.block_len + 6144 ||
                            Storage.FetchBytes(ref h, ref cbuffer, cmpStart, cmpLen) != cmpLen ||
                            Lzx.LZXdecompress(h.lzx_state, ref cbuffer, cbufferpos,
                                              ref h.cache_blocks[lbuffer], 0, (int)cmpLen,
                                              (int)h.reset_table.block_len) != Lzx.DECR_OK)
                        {
                            return((Int64)0);
                        }

                        h.lzx_last_block = (int)curBlockIdx;
                    }
                }
            }
            else
            {
                if ((block % h.reset_blkcount) == 0)
                {
                    Lzx.LZXreset(h.lzx_state);
                }
            }

            /* allocate slot in cache */
            indexSlot = (int)(block % (LONGUINT64)h.cache_num_blocks);
            if (h.cache_blocks[indexSlot] == null)
            {
                h.cache_blocks[indexSlot] = new byte[h.reset_table.block_len];
            }

            h.cache_block_indices[indexSlot] = block;
            lbuffer = (uint)indexSlot;
            ubuffer = h.cache_blocks[lbuffer];

            /* decompress the block we actually want */
            if (!GetCmpBlockBounds(ref h, block, ref cmpStart, ref cmpLen) ||
                Storage.FetchBytes(ref h, ref cbuffer, cmpStart, cmpLen) != cmpLen ||
                Lzx.LZXdecompress(h.lzx_state, ref cbuffer, cbufferpos,
                                  ref h.cache_blocks[lbuffer], 0, (int)cmpLen,
                                  (int)h.reset_table.block_len) != Lzx.DECR_OK)
            {
                return((Int64)0);
            }
            h.lzx_last_block = (int)block;

            /* XXX: modify LZX routines to return the length of the data they
             * decompressed and return that instead, for an extra sanity check.
             */
            return((Int64)h.reset_table.block_len);
        }
コード例 #3
0
ファイル: Lzxc.cs プロジェクト: nataren/libchmsharp2
        /* grab a region from a compressed block */
        public static Int64 DecompressRegion(ref ChmFileInfo h, ref byte[] buf, ulong bufpos, UInt64 start, Int64 len)
        {
            UInt64 nBlock, nOffset;
            UInt64 nLen;
            UInt64 gotLen;

            byte[] ubuffer = null;

            if (len <= 0)
            {
                return((Int64)0);
            }

            /* figure out what we need to read */
            nBlock  = start / h.reset_table.block_len;
            nOffset = start % h.reset_table.block_len;
            nLen    = (LONGUINT64)len;
            if (nLen > (h.reset_table.block_len - nOffset))
            {
                nLen = h.reset_table.block_len - nOffset;
            }

            /* if block is cached, return data from it. */
            h.lzx_mutex.WaitOne();
            h.cache_mutex.WaitOne();
            if (h.cache_block_indices[nBlock % (LONGUINT64)h.cache_num_blocks] == nBlock &&
                h.cache_blocks[nBlock % (LONGUINT64)h.cache_num_blocks] != null)
            {
                Array.Copy(
                    h.cache_blocks[nBlock % (LONGUINT64)h.cache_num_blocks],
                    (int)nOffset,
                    buf,
                    (int)bufpos,
                    (long)nLen);
                h.cache_mutex.ReleaseMutex();
                h.lzx_mutex.ReleaseMutex();

                return((Int64)nLen);
            }
            h.cache_mutex.ReleaseMutex();

            /* data request not satisfied, so... start up the decompressor machine */
            if (!h.lzx_init)
            {
                int window_size = ffs(h.window_size) - 1;
                h.lzx_last_block = -1;
                h.lzx_state      = Lzx.LZXinit(window_size);
                h.lzx_init       = true;
            }

            /* decompress some data */
            gotLen = (UInt64)DecompressBlock(ref h, nBlock, ref ubuffer);
            if (gotLen < nLen)
            {
                nLen = gotLen;
            }
            Array.Copy(ubuffer, (int)nOffset, buf, (int)bufpos, (int)nLen);
            h.lzx_mutex.ReleaseMutex();

            return((Int64)nLen);
        }