Перейти к содержимому



LHArc lh5 extracting class

LHArc -lh5- extractor decode decompress LHA CSharp

  • Авторизуйтесь для ответа в теме
В этой теме нет ответов

#1 admin

admin

    Администратор

  • Администраторы
  • 76 сообщений

Отправлено 19 Март 2014 - 19:26

This class extracts data from LHA archives version -lh4- -lh5-
This source based on code of Open Source library StSound http://leonard.oxg.f...StSoundGPL.html

// LZH.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace AYPlayer //change to yours namespace
{
	unsafe class LZH
	{
		const int BUFSIZE = (1024 * 4);
		const byte CHAR_BIT = 8;
		const int UCHAR_MAX = 255;
		const int BITBUFSIZ = (CHAR_BIT * sizeof(ushort));
		const byte DICBIT = 13;			 /* 12(-lh4-) or 13(-lh5-) */
		const uint DICSIZ = (1U << DICBIT);
		const int MAXMATCH = 256;		   /* formerly F (not more than UCHAR_MAX + 1) */
		const byte THRESHOLD = 3;		   /* choose optimal value */
		const int NC = (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD);  /* alphabet = {0, 1, 2, ..., NC - 1} */
		const byte CBIT = 9;
		const byte CODE_BIT = 16;		   /* codeword length */
		const int NP = (DICBIT + 1);
		const int NT = (CODE_BIT + 3);
		const byte PBIT = 4;	  /* smallest integer such that (1U << PBIT) > NP */
		const byte TBIT = 5;	  /* smallest integer such that (1U << TBIT) > NT */
		const int NPT = NT; // or NP if NP > NT
		int fillbufsize;
		byte[] buf = new byte[BUFSIZE];
		byte[] outbuf = new byte[DICSIZ];
		ushort[] left = new ushort[2 * NC - 1];
		ushort[] right = new ushort[2 * NC - 1];
		int bitbuf;
		int bitcount;
		int subbitbuf;
		int decode_j;	/* remaining bytes to copy */
		byte[] c_len = new byte[NC];
		byte[] pt_len = new byte[NPT];
		int blocksize;
		ushort[] c_table = new ushort[4096];
		ushort[] pt_table = new ushort[256];
		int with_error = 0;
		uint fillbuf_i;			   // NOTE: these ones are not initialized at constructor time but inside the fillbuf and decode func.
		long decode_i;
		int m_srcSize;
		int m_dstSize;
		int m_inIndex;
		int m_outIndex;
		byte[] m_in_buf;
		byte[] m_out_buf;

		int DataIn(ref byte[] pBuffer,int nBytes)
		{
		 int np = (nBytes < m_srcSize) ? nBytes : m_srcSize;
		 if (np > 0)
		 {
				for(int i = 0; i < np; i++)
					pBuffer[i] = m_in_buf[m_inIndex++];
		  m_srcSize -= np;
		 }
		 return np;
		}
		int DataOut(ref byte[] pBuffer,int nBytes)
		{
		 int np = (nBytes < m_dstSize) ? nBytes : m_dstSize;
		 if (np > 0)
		 {
				for (int i = 0; i < np; i++)
					m_out_buf[m_outIndex++] = pBuffer[i];
		  m_dstSize -= np;
		 }
		 return np;
		}

		/** Shift bitbuf n bits left, read n bits */
		void fillbuf (int n)
		{
			bitbuf = (bitbuf << n) & 0xFFFF;
			while (n > bitcount)
			{
				n -= bitcount;
				bitbuf |= subbitbuf << n;
				bitbuf &= 0xFFFF;
				if (fillbufsize == 0)
				{
		   fillbuf_i = 0;
					fillbufsize = DataIn(ref buf, BUFSIZE - 32);
		  }
		  if (fillbufsize != 0)
				{
					fillbufsize--;
					subbitbuf = buf[fillbuf_i++];
				}
				else
					subbitbuf = 0;
				bitcount = CHAR_BIT;
			}
			bitcount-=n;
			bitbuf |= subbitbuf >> bitcount;
			bitbuf &= 0xFFFF;
		}

		int getbits(int n)
		{
			int x;
			x = bitbuf >> (BITBUFSIZ - n);
			fillbuf(n);
			return x;
		}

		int make_table(int nchar, ref byte[] bitlen, int tablebits, ref ushort[] table)
		{
			ushort[] count = new ushort[17];
			ushort[] weight = new ushort[17];
			ushort[] start = new ushort[18];
			uint jutbits,mask,avail;
		 int i,len;
			int nextcode;
			for (i = 1; i <= 16; i++)
				count[i] = 0;
			for (i = 0; i < nchar; i++)
				count[bitlen[i]]++;
			start[1] = 0;
			for (i = 1; i <= 16; i++)
				 start[i + 1] = (ushort)(start[i] + (count[i] << (16 - i)));
			if (start[17] != 0 )
				return (1); /* error: bad table */
			jutbits = (uint)(16 - tablebits);
			for (i = 1; i <= tablebits; i++)
			{
				start[i] >>= (ushort)jutbits;
				weight[i] = (ushort)(1U << (tablebits - i));
			}
		 while (i <= 16)
		 {
				weight[i] = (ushort)(1U << (16 - i));
		  i++;
		 }
			i = start[tablebits + 1] >> (int)jutbits;
			if (i != 0)
			{
				int k = (int)(1U << tablebits);
				while (i != k)
					table[i++] = 0;
			}
			avail = (uint)nchar;
			mask = 1U << (15 - tablebits);
			for(ushort ch = 0; ch < nchar; ch++)
			{
				if ((len = bitlen[ch]) == 0)
					continue;
				nextcode = start[len] + weight[len];
				if (len <= tablebits )
				{
					for (i = (int)start[len]; i < nextcode; i++)
						table[i] = ch;
				}
				else
				{
					fixed(ushort* tbl = table, rght = right, lft = left)
					{
						uint k = start[len];
						ushort* p = &tbl[k >> (int)jutbits];
						i = len - tablebits;
						while (i != 0)
						{
							if (*p == 0)
							{
								right[avail] = left[avail] = 0;
								*p = (ushort)avail;
								avail++;
							}
							if ((k & mask) != 0)
							{
								p = &rght[*p];
							}
							else
							{
								p = &lft[*p];
							}
							k <<= 1;
							i--;
						}
						*p = ch;
					}
				}
				start[len] = (ushort)nextcode;
			}
			return (0);
		}
		/*
		* huf.c
		*/
		void read_pt_len (int nn, int nbit, int i_special)
		{
			int i, n, c;
			uint mask;
			n = getbits(nbit);
			if (n == 0)
			{
				c = getbits(nbit);
				for (i = 0; i < nn; i++)
					pt_len[i] = 0;
				for (i = 0; i < 256; i++)
					pt_table[i] = (ushort)c;
			}
			else
			{
				i = 0;
				while (i < n)
				{
					if (i >= NT)
					{
						with_error = 1;
						break;
					}
					c = bitbuf >> (BITBUFSIZ - 3);
					if (c == 7)
					{
						mask = 1U << (BITBUFSIZ - 4);
						while ((mask & bitbuf) != 0)
						{
							mask >>= 1;
							c++;
						}
					}
				   
					fillbuf ((c < 7) ? 3 : c - 3);
					pt_len[i++] = (byte)c;
					if (i == i_special)
					{
						c = getbits(2);
						while (--c >= 0)
							pt_len[i++] = 0;
					}
				}
				while (i < nn)
					pt_len[i++] = 0;
				make_table (nn, ref pt_len, 8, ref pt_table);
			}
		}
		void read_c_len ()
		{
			int i;
			int c,n;
			uint mask;
			n = getbits(CBIT);
			if (n == 0)
			{
				c = getbits(CBIT);
				for (i = 0; i < NC; i++)
					c_len[i] = 0;
				for (i = 0; i < 4096; i++)
					c_table[i] = (ushort)c;
			}
			else
			{
				i = 0;
				while (i < n)
				{
					c = pt_table[bitbuf >> (BITBUFSIZ - 8)];
					if (c >= NT)
					{
						mask = 1U << (BITBUFSIZ - 9);
						do
						{
							if ((bitbuf & mask) != 0)
					   c = right[c];
							else
					   c = left[c];
							mask >>= 1;
						} while (c >= NT);
					}
					fillbuf(pt_len[c]);
					if (c <= 2)
					{
						if (c == 0)
							c = 1;
						else if (c == 1)
							c = getbits(4) + 3;
						else if (c == 2)
							c = getbits(CBIT) + 20;
						while (--c >= 0)
						{
							c_len[i++] = 0;
						}
					}
					else
						c_len[i++] = (byte)(c - 2);
				}
				while (i < NC)
					c_len[i++] = 0;
				make_table (NC,ref c_len, 12, ref c_table);
			}
		}
		int decode_c ()
		{
			int j;
			uint mask;
			if (blocksize == 0)
			{
				blocksize = getbits(CODE_BIT);
				read_pt_len (NT, TBIT, 3);
				read_c_len ();
				read_pt_len (NP, PBIT, -1);
			}
			blocksize--;
			j = c_table[bitbuf >> (BITBUFSIZ - 12)];
			if (j >= NC)
			{
				mask = 1U << (BITBUFSIZ - 13);
				do
				{
					if ((bitbuf & mask) != 0)
			j = right[j];
					else
			j = left[j];
					mask >>= 1;
				}
		  while (j >= NC);
			}
			fillbuf(c_len[j]);
			return j;
		}
		ushort decode_p ()
		{
			ushort j;
			uint mask;
			j = (ushort)pt_table[bitbuf >> (BITBUFSIZ - 8)];
			if (j >= NP)
			{
				mask = 1U << (BITBUFSIZ - 9);
				do
				{
					if ((bitbuf & mask) != 0)
				  j = right[j];
					else
				  j = left[j];
					mask >>= 1;
				} while (j >= NP);
			}
			fillbuf (pt_len[j]);
			if (j != 0)
			{
				j--;
				j = (ushort)((1U << j) + getbits(j));
			}
			return j;
		}

		/*
		* The calling function must keep the number of bytes to be processed.  This
		* function decodes either 'count' bytes or 'DICSIZ' bytes, whichever is
		* smaller, into the array 'buffer[]' of size 'DICSIZ' or more. Call
		* decode_start() once for each new file before calling this function.
		*/
		void decode(uint count, ref byte[] buffer)
		{
			int r, c;
			r = 0;
			decode_j--;
			while (decode_j >= 0)
			{
				buffer[r] = buffer[decode_i];
				decode_i = (decode_i + 1) & (DICSIZ - 1);
				if (++r == count)
					return;
				decode_j--;
			}
			for (;;)
			{
				c = decode_c();
				if (c <= UCHAR_MAX)
				{
					buffer[r++] = (byte)c;
					if (r == count)
						return;
				}
				else
				{
					decode_j = (ushort)(c - (UCHAR_MAX + 1 - THRESHOLD));
					decode_i = (r - decode_p() - 1) & (DICSIZ - 1);
					while (--decode_j >= 0)
					{
						buffer[r] = buffer[decode_i];
						decode_i = (decode_i + 1) & (DICSIZ - 1);
						if (++r == count)
							return;
					}
				}
			}
		}
		public bool LzUnpack(ref byte[] in_buf,int in_index, int srcSize,ref byte[] out_buf,int dstSize)
		{
			with_error = 0;
			if (dstSize < srcSize) dstSize = srcSize;
			m_inIndex = in_index;
			m_outIndex = 0;
			m_srcSize = srcSize;
		 m_dstSize = dstSize;
			m_in_buf = in_buf;
			m_out_buf = out_buf;
			bitbuf = 0;
			subbitbuf = 0;
			bitcount = 0;
			fillbufsize = 0;
			decode_i = 0;
			blocksize = 0;
			decode_j = 0;
			fillbuf(BITBUFSIZ);
			int origsize = dstSize;
			while (origsize > 0)
			{
				uint n = (origsize > DICSIZ) ? DICSIZ : (uint)origsize;
				decode (n, ref outbuf);
		  if (with_error > 0)
		   break;
		  DataOut(ref outbuf,(int)n);
				origsize -= (int)n;
		  if (with_error > 0)
		   break;
			}
			return (0 == with_error);
		}
	}
}

using this class

LZH lz = new LZH();
byte[] dbuf = new byte[Uncompressed_Data_Size];
if (lz.LzUnpack(ref in_buf, (int)(offset), (int)Compressed_Data_Size, ref dbuf, (int)Uncompressed_Data_Size) == false)
{
  // Error in unpacking happened
}

in_buf - byte array of source data
Compressed_Data_Size - size of source data array
dbuf - byte array for unpacked data
Uncompressed_Data_Size - size of uncompressed data
offset - offset in in_buf where compressed data starts (may have LHA header before)

It was not so easy to convert this code, so if it is usefull, please - donate :)





Темы с аналогичным тегами LHArc, -lh5-, extractor, decode, decompress, LHA, CSharp

Количество пользователей, читающих эту тему: 0

0 пользователей, 0 гостей, 0 скрытых пользователей

Рейтинг@Mail.ru