Advertisement
Guest User

Untitled

a guest
Aug 11th, 2015
246
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.69 KB | None | 0 0
  1. /*
  2. * Improved version to C# LibLZF Port:
  3. * Copyright (c) 2010 Roman Atachiants <kelindar@gmail.com>
  4. *
  5. * Original CLZF Port:
  6. * Copyright (c) 2005 Oren J. Maurice <oymaurice@hazorea.org.il>
  7. *
  8. * Original LibLZF Library Algorithm:
  9. * Copyright (c) 2000-2008 Marc Alexander Lehmann <schmorp@schmorp.de>
  10. *
  11. * Redistribution and use in source and binary forms, with or without modifica-
  12. * tion, are permitted provided that the following conditions are met:
  13. *
  14. * 1. Redistributions of source code must retain the above copyright notice,
  15. * this list of conditions and the following disclaimer.
  16. *
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. *
  21. * 3. The name of the author may not be used to endorse or promote products
  22. * derived from this software without specific prior written permission.
  23. *
  24. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
  25. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
  26. * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
  27. * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
  28. * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  29. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  30. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  31. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
  32. * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  33. * OF THE POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * Alternatively, the contents of this file may be used under the terms of
  36. * the GNU General Public License version 2 (the "GPL"), in which case the
  37. * provisions of the GPL are applicable instead of the above. If you wish to
  38. * allow the use of your version of this file only under the terms of the
  39. * GPL and not to allow others to use your version of this file under the
  40. * BSD license, indicate your decision by deleting the provisions above and
  41. * replace them with the notice and other provisions required by the GPL. If
  42. * you do not delete the provisions above, a recipient may use your version
  43. * of this file under either the BSD or the GPL.
  44. */
  45. using System;
  46.  
  47. /* Benchmark with Alice29 Canterbury Corpus
  48. ---------------------------------------
  49. (Compression) Original CLZF C#
  50. Raw = 152089, Compressed = 101092
  51. 8292,4743 ms.
  52. ---------------------------------------
  53. (Compression) My LZF C#
  54. Raw = 152089, Compressed = 101092
  55. 33,0019 ms.
  56. ---------------------------------------
  57. (Compression) Zlib using SharpZipLib
  58. Raw = 152089, Compressed = 54388
  59. 8389,4799 ms.
  60. ---------------------------------------
  61. (Compression) QuickLZ C#
  62. Raw = 152089, Compressed = 83494
  63. 80,0046 ms.
  64. ---------------------------------------
  65. (Decompression) Original CLZF C#
  66. Decompressed = 152089
  67. 16,0009 ms.
  68. ---------------------------------------
  69. (Decompression) My LZF C#
  70. Decompressed = 152089
  71. 15,0009 ms.
  72. ---------------------------------------
  73. (Decompression) Zlib using SharpZipLib
  74. Decompressed = 152089
  75. 3577,2046 ms.
  76. ---------------------------------------
  77. (Decompression) QuickLZ C#
  78. Decompressed = 152089
  79. 21,0012 ms.
  80. */
  81.  
  82. #if NETFX_CORE && (UNITY_4_6 || UNITY_4_5)
  83. using UnityEngine.Windows;
  84. #endif
  85.  
  86. /// <summary>
  87. /// Improved C# LZF Compressor, a very small data compression library. The compression algorithm is extremely fast.
  88. public static class CLZF2
  89. {
  90. private static readonly uint HLOG = 14;
  91. private static readonly uint HSIZE = (1 << 14);
  92. private static readonly uint MAX_LIT = (1 << 5);
  93. private static readonly uint MAX_OFF = (1 << 13);
  94. private static readonly uint MAX_REF = ((1 << 8) + (1 << 3));
  95.  
  96. /// <summary>
  97. /// Hashtable, that can be allocated only once
  98. /// </summary>
  99. private static readonly long[] HashTable = new long[HSIZE];
  100.  
  101. // Compresses inputBytes
  102. public static byte[] Compress(byte[] inputBytes)
  103. {
  104. // Starting guess, increase it later if needed
  105. int outputByteCountGuess = inputBytes.Length * 2;
  106. byte[] tempBuffer = new byte[outputByteCountGuess];
  107. int byteCount = lzf_compress (inputBytes, ref tempBuffer);
  108.  
  109. // If byteCount is 0, then increase buffer and try again
  110. while (byteCount == 0)
  111. {
  112. outputByteCountGuess *=2;
  113. tempBuffer = new byte[outputByteCountGuess];
  114. byteCount = lzf_compress (inputBytes, ref tempBuffer);
  115. }
  116.  
  117. byte[] outputBytes = new byte[byteCount];
  118. Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
  119. return outputBytes;
  120. }
  121.  
  122. // Decompress outputBytes
  123. public static byte[] Decompress(byte[] inputBytes)
  124. {
  125. // Starting guess, increase it later if needed
  126. int outputByteCountGuess = inputBytes.Length * 2;
  127. byte[] tempBuffer = new byte[outputByteCountGuess];
  128. int byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  129.  
  130. // If byteCount is 0, then increase buffer and try again
  131. while (byteCount == 0)
  132. {
  133. outputByteCountGuess *=2;
  134. tempBuffer = new byte[outputByteCountGuess];
  135. byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  136. }
  137.  
  138. byte[] outputBytes = new byte[byteCount];
  139. Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
  140. return outputBytes;
  141. }
  142.  
  143. #if !NETFX_CORE
  144. private static System.Threading.Thread decompressionThread;
  145. #endif
  146. public static void DecompressBytesAsync(byte[] input, Action<byte[]> callback)
  147. {
  148. runActOnBytesWithCallback = true;
  149. #if !NETFX_CORE
  150. if (decompressionThread==null) {
  151. UnityEngine.Debug.Log ("STARTING DECOMPRESSION THREAD");
  152. decompressionThread =
  153. new System.Threading.Thread (
  154. () => DecompressWithCallback (
  155. input,
  156. callback)
  157. );
  158. decompressionThread.Start ();
  159. }
  160. #else
  161. Windows.System.Threading.ThreadPool.RunAsync(
  162. (x) => DecompressWithCallback (
  163. input,
  164. callback)
  165. );
  166. #endif
  167. }
  168.  
  169. public static void CancelDecompression()
  170. {
  171. runActOnBytesWithCallback = false;
  172. }
  173.  
  174. public static bool runActOnBytesWithCallback;
  175. public static void DecompressWithCallback(byte[] inputBytes, Action<byte[]> callback)
  176. {
  177. // Starting guess, increase it later if needed
  178. int outputByteCountGuess = inputBytes.Length * 2;
  179. byte[] tempBuffer = new byte[outputByteCountGuess];
  180. int byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  181.  
  182. // If byteCount is 0, then increase buffer and try again
  183. while (byteCount == 0)
  184. {
  185. if(!runActOnBytesWithCallback)
  186. {
  187. if (callback != null)
  188. callback (null);
  189. return;
  190. }
  191.  
  192. outputByteCountGuess *=2;
  193. tempBuffer = new byte[outputByteCountGuess];
  194. byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  195. }
  196.  
  197. byte[] outputBytes = new byte[byteCount];
  198. Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
  199. if (callback != null)
  200. callback (outputBytes);
  201. }
  202.  
  203. /// <summary>
  204. /// Compresses the data using LibLZF algorithm
  205. /// </summary>
  206. /// <param name="input">Reference to the data to compress</param>
  207. /// <param name="output">Reference to a buffer which will contain the compressed data</param>
  208. /// <returns>The size of the compressed archive in the output buffer</returns>
  209. public static int lzf_compress(byte[] input, ref byte[] output)
  210. {
  211. int inputLength = input.Length;
  212. int outputLength = output.Length;
  213.  
  214. Array.Clear(HashTable, 0, (int)HSIZE);
  215.  
  216. long hslot;
  217. uint iidx = 0;
  218. uint oidx = 0;
  219. long reference;
  220.  
  221. uint hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]); // FRST(in_data, iidx);
  222. long off;
  223. int lit = 0;
  224.  
  225. for (; ;)
  226. {
  227. if (iidx < inputLength - 2)
  228. {
  229. hval = (hval << 8) | input[iidx + 2];
  230. hslot = ((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1));
  231. reference = HashTable[hslot];
  232. HashTable[hslot] = (long)iidx;
  233.  
  234.  
  235. if ((off = iidx - reference - 1) < MAX_OFF
  236. && iidx + 4 < inputLength
  237. && reference > 0
  238. && input[reference + 0] == input[iidx + 0]
  239. && input[reference + 1] == input[iidx + 1]
  240. && input[reference + 2] == input[iidx + 2]
  241. )
  242. {
  243. /* match found at *reference++ */
  244. uint len = 2;
  245. uint maxlen = (uint)inputLength - iidx - len;
  246. maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
  247.  
  248. if (oidx + lit + 1 + 3 >= outputLength)
  249. return 0;
  250.  
  251. do
  252. len++;
  253. while (len < maxlen && input[reference + len] == input[iidx + len]);
  254.  
  255. if (lit != 0)
  256. {
  257. output[oidx++] = (byte)(lit - 1);
  258. lit = -lit;
  259. do
  260. output[oidx++] = input[iidx + lit];
  261. while ((++lit) != 0);
  262. }
  263.  
  264. len -= 2;
  265. iidx++;
  266.  
  267. if (len < 7)
  268. {
  269. output[oidx++] = (byte)((off >> 8) + (len << 5));
  270. }
  271. else
  272. {
  273. output[oidx++] = (byte)((off >> 8) + (7 << 5));
  274. output[oidx++] = (byte)(len - 7);
  275. }
  276.  
  277. output[oidx++] = (byte)off;
  278.  
  279. iidx += len - 1;
  280. hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]);
  281.  
  282. hval = (hval << 8) | input[iidx + 2];
  283. HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
  284. iidx++;
  285.  
  286. hval = (hval << 8) | input[iidx + 2];
  287. HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
  288. iidx++;
  289. continue;
  290. }
  291. }
  292. else if (iidx == inputLength)
  293. break;
  294.  
  295. /* one more literal byte we must copy */
  296. lit++;
  297. iidx++;
  298.  
  299. if (lit == MAX_LIT)
  300. {
  301. if (oidx + 1 + MAX_LIT >= outputLength)
  302. return 0;
  303.  
  304. output[oidx++] = (byte)(MAX_LIT - 1);
  305. lit = -lit;
  306. do
  307. output[oidx++] = input[iidx + lit];
  308. while ((++lit) != 0);
  309. }
  310. }
  311.  
  312. if (lit != 0)
  313. {
  314. if (oidx + lit + 1 >= outputLength)
  315. return 0;
  316.  
  317. output[oidx++] = (byte)(lit - 1);
  318. lit = -lit;
  319. do
  320. output[oidx++] = input[iidx + lit];
  321. while ((++lit) != 0);
  322. }
  323.  
  324. return (int)oidx;
  325. }
  326.  
  327.  
  328. /// <summary>
  329. /// Decompresses the data using LibLZF algorithm
  330. /// </summary>
  331. /// <param name="input">Reference to the data to decompress</param>
  332. /// <param name="output">Reference to a buffer which will contain the decompressed data</param>
  333. /// <returns>Returns decompressed size</returns>
  334. public static int lzf_decompress(byte[] input, ref byte[] output)
  335. {
  336. int inputLength = input.Length;
  337. int outputLength = output.Length;
  338.  
  339. uint iidx = 0;
  340. uint oidx = 0;
  341.  
  342. do
  343. {
  344. uint ctrl = input[iidx++];
  345.  
  346. if (ctrl < (1 << 5)) /* literal run */
  347. {
  348. ctrl++;
  349.  
  350. if (oidx + ctrl > outputLength)
  351. {
  352. //SET_ERRNO (E2BIG);
  353. return 0;
  354. }
  355.  
  356. do
  357. output[oidx++] = input[iidx++];
  358. while ((--ctrl) != 0);
  359. }
  360. else /* back reference */
  361. {
  362. uint len = ctrl >> 5;
  363.  
  364. int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1);
  365.  
  366. if (len == 7)
  367. len += input[iidx++];
  368.  
  369. reference -= input[iidx++];
  370.  
  371. if (oidx + len + 2 > outputLength)
  372. {
  373. //SET_ERRNO (E2BIG);
  374. return 0;
  375. }
  376.  
  377. if (reference < 0)
  378. {
  379. //SET_ERRNO (EINVAL);
  380. return 0;
  381. }
  382.  
  383. output[oidx++] = output[reference++];
  384. output[oidx++] = output[reference++];
  385.  
  386. do
  387. output[oidx++] = output[reference++];
  388. while ((--len) != 0);
  389. }
  390. }
  391. while (iidx < inputLength);
  392.  
  393. return (int)oidx;
  394. }
  395.  
  396. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement