Esempio n. 1
0
        public static Int64 FetchBytes(ref chmFileInfo h, ref byte[] buf, UInt64 os, Int64 len)
        {
            Int64 readLen = 0;
            long cur = 0;

            if (h.fd == null)
                return readLen;

            h.mutex.WaitOne();
            cur = h.fd.Seek((long)os, SeekOrigin.Begin);
            readLen = h.fd.Read(buf, 0, (int)len);
            h.mutex.ReleaseMutex();

            return readLen;
        }
Esempio n. 2
0
        /* 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];
            ulong 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, ref 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, ref 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;
        }
Esempio n. 3
0
        /* get the bounds of a compressed block.  return 0 on failure */
        public static bool GetCmpBlockBounds(ref chmFileInfo h, UInt64 block, 
            ref UInt64 start, ref Int64 len)
        {
            byte[] buffer = new byte[8];
            uint remain;
            uint pos = 0;

            /* for all but the last block, use the reset table */
            if (block < h.reset_table.block_count - 1) {
                /* unpack the start address */
                pos = 0;
                remain = 8;
                if (Storage.FetchBytes(ref h, ref buffer,
                                     (UInt64)h.data_offset
                                        + (UInt64)h.rt_unit.start
                                        + (UInt64)h.reset_table.table_offset
                                        + (UInt64)block * 8,
                                     remain) != remain                            ||
                    !Unmarshal.ToUInt64(ref buffer, ref pos, ref remain, ref start))
                    return false;

                /* unpack the end address */
                pos = 0;
                remain = 8;
                if (Storage.FetchBytes(ref h, ref buffer,
                                 (UInt64)h.data_offset
                                        + (UInt64)h.rt_unit.start
                                        + (UInt64)h.reset_table.table_offset
                                        + (UInt64)block * 8 + 8,
                                 remain) != remain                                ||
                    !Unmarshal.ToInt64(ref buffer, ref pos, ref remain, ref len))
                    return false;
            }

            /* for the last block, use the span in addition to the reset table */
            else {
                /* unpack the start address */
                pos = 0;
                remain = 8;
                if (Storage.FetchBytes(ref h, ref buffer,
                                     (UInt64)h.data_offset
                                        + (UInt64)h.rt_unit.start
                                        + (UInt64)h.reset_table.table_offset
                                        + (UInt64)block * 8,
                                     remain) != remain                            ||
                    !Unmarshal.ToUInt64(ref buffer, ref pos, ref remain, ref start))
                    return false;

                len = (Int64)h.reset_table.compressed_len;
            }

            /* compute the length and absolute start address */
            len -= (Int64)start;
            start += h.data_offset + h.cn_unit.start;

            return true;
        }
Esempio n. 4
0
        /* grab a region from a compressed block */
        public static Int64 DecompressRegion(ref chmFileInfo h, ref byte[] buf, 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,
                    (int)((nBlock % (LONGUINT64)h.cache_num_blocks) + nOffset),
                    buf,
                    0,
                    (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, 0, (int)nLen);
            h.lzx_mutex.ReleaseMutex();

            return (Int64)nLen;
        }
Esempio n. 5
0
 private chmFile(string filename)
 {
     _h = new chmFileInfo();
     _filename = filename;
 }