FestusTheBestus

CLZF compression

Aug 21st, 2025 (edited)
482
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.73 KB | None | 0 0
  1. using System;
  2.  
  3. public static class CLZF2 {
  4.     private static readonly uint HLOG = 14;
  5.     private static readonly uint HSIZE = (1 << 14);
  6.     private static readonly uint MAX_LIT = (1 << 5);
  7.     private static readonly uint MAX_OFF = (1 << 13);
  8.     private static readonly uint MAX_REF = ((1 << 8) + (1 << 3));
  9.    
  10.     /// <summary>
  11.     /// Hashtable, that can be allocated only once
  12.     /// </summary>
  13.     private static readonly long[] HashTable = new long[HSIZE];
  14.     private static byte[] compressBuffer = new byte[0];
  15.    
  16.     // Compresses inputBytes
  17.     public static byte[] Compress(byte[] inputBytes) {
  18.         // Starting guess, increase it later if needed
  19.         int outputByteCountGuess = inputBytes.Length * 2;
  20.         if (compressBuffer.Length < outputByteCountGuess) {
  21.             compressBuffer = new byte[outputByteCountGuess];
  22.         }
  23.         int byteCount = lzf_compress (inputBytes, ref compressBuffer);
  24.        
  25.         // If byteCount is 0, then increase buffer and try again
  26.         while (byteCount == 0) {
  27.             outputByteCountGuess *= 2;
  28.             if (compressBuffer.Length < outputByteCountGuess) {
  29.                 compressBuffer = new byte[outputByteCountGuess];
  30.             }
  31.             byteCount = lzf_compress (inputBytes, ref compressBuffer);
  32.         }
  33.        
  34.         byte[] outputBytes = new byte[byteCount];
  35.         Buffer.BlockCopy(compressBuffer, 0, outputBytes, 0, byteCount);
  36.         return outputBytes;
  37.     }
  38.    
  39.     // Decompress outputBytes
  40.     public static byte[] Decompress(byte[] inputBytes) {
  41.         // Starting guess, increase it later if needed
  42.         int outputByteCountGuess = inputBytes.Length * 2;
  43.         byte[] tempBuffer = new byte[outputByteCountGuess];
  44.         int byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  45.        
  46.         // If byteCount is 0, then increase buffer and try again
  47.         while (byteCount == 0)
  48.         {
  49.             outputByteCountGuess *=2;
  50.             tempBuffer = new byte[outputByteCountGuess];
  51.             byteCount = lzf_decompress (inputBytes, ref tempBuffer);
  52.         }
  53.        
  54.         byte[] outputBytes = new byte[byteCount];
  55.         Buffer.BlockCopy(tempBuffer, 0, outputBytes, 0, byteCount);
  56.         return outputBytes;
  57.     }
  58.  
  59.     /// <summary>
  60.     /// Compresses the data using LibLZF algorithm
  61.     /// </summary>
  62.     /// <param name="input">Reference to the data to compress</param>
  63.     /// <param name="output">Reference to a buffer which will contain the compressed data</param>
  64.     /// <returns>The size of the compressed archive in the output buffer</returns>
  65.     public static int lzf_compress(byte[] input, ref byte[] output) {
  66.         int inputLength = input.Length;
  67.         int outputLength = output.Length;
  68.    
  69.         Array.Clear(HashTable, 0, (int)HSIZE);
  70.  
  71.         long hslot;
  72.         uint iidx = 0;
  73.         uint oidx = 0;
  74.         long reference;
  75.  
  76.         uint hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]); // FRST(in_data, iidx);
  77.         long off;
  78.         int lit = 0;
  79.  
  80.         for (; ; ) {
  81.             if (iidx < inputLength - 2) {
  82.                 hval = (hval << 8) | input[iidx + 2];
  83.                 hslot = ((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1));
  84.                 reference = HashTable[hslot];
  85.                 HashTable[hslot] = (long)iidx;
  86.  
  87.  
  88.                     if ((off = iidx - reference - 1) < MAX_OFF
  89.                         && iidx + 4 < inputLength
  90.                         && reference > 0
  91.                         && input[reference + 0] == input[iidx + 0]
  92.                         && input[reference + 1] == input[iidx + 1]
  93.                         && input[reference + 2] == input[iidx + 2]
  94.                     ) {
  95.                         /* match found at *reference++ */
  96.                         uint len = 2;
  97.                         uint maxlen = (uint)inputLength - iidx - len;
  98.                         maxlen = maxlen > MAX_REF ? MAX_REF : maxlen;
  99.  
  100.                         if (oidx + lit + 1 + 3 >= outputLength)
  101.                             return 0;
  102.  
  103.                         do
  104.                             len++;
  105.                         while (len < maxlen && input[reference + len] == input[iidx + len]);
  106.  
  107.                         if (lit != 0)
  108.                         {
  109.                             output[oidx++] = (byte)(lit - 1);
  110.                             lit = -lit;
  111.                             do
  112.                                 output[oidx++] = input[iidx + lit];
  113.                             while ((++lit) != 0);
  114.                         }
  115.  
  116.                         len -= 2;
  117.                         iidx++;
  118.  
  119.                         if (len < 7) {
  120.                             output[oidx++] = (byte)((off >> 8) + (len << 5));
  121.                         } else {
  122.                             output[oidx++] = (byte)((off >> 8) + (7 << 5));
  123.                             output[oidx++] = (byte)(len - 7);
  124.                         }
  125.  
  126.                         output[oidx++] = (byte)off;
  127.  
  128.                         iidx += len - 1;
  129.                         hval = (uint)(((input[iidx]) << 8) | input[iidx + 1]);
  130.  
  131.                         hval = (hval << 8) | input[iidx + 2];
  132.                         HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
  133.                         iidx++;
  134.  
  135.                         hval = (hval << 8) | input[iidx + 2];
  136.                         HashTable[((hval ^ (hval << 5)) >> (int)(((3 * 8 - HLOG)) - hval * 5) & (HSIZE - 1))] = iidx;
  137.                         iidx++;
  138.                         continue;
  139.                     }
  140.                 }
  141.             else if (iidx == inputLength)
  142.                 break;
  143.  
  144.             /* one more literal byte we must copy */
  145.             lit++;
  146.             iidx++;
  147.  
  148.             if (lit == MAX_LIT) {
  149.                 if (oidx + 1 + MAX_LIT >= outputLength)
  150.                     return 0;
  151.  
  152.                 output[oidx++] = (byte)(MAX_LIT - 1);
  153.                 lit = -lit;
  154.                 do
  155.                     output[oidx++] = input[iidx + lit];
  156.                 while ((++lit) != 0);
  157.             }
  158.         }
  159.  
  160.         if (lit != 0) {
  161.             if (oidx + lit + 1 >= outputLength)
  162.                 return 0;
  163.  
  164.             output[oidx++] = (byte)(lit - 1);
  165.             lit = -lit;
  166.             do
  167.                 output[oidx++] = input[iidx + lit];
  168.             while ((++lit) != 0);
  169.         }
  170.  
  171.         return (int)oidx;
  172.     }
  173.  
  174.     /// <summary>
  175.     /// Decompresses the data using LibLZF algorithm
  176.     /// </summary>
  177.     /// <param name="input">Reference to the data to decompress</param>
  178.     /// <param name="output">Reference to a buffer which will contain the decompressed data</param>
  179.     /// <returns>Returns decompressed size</returns>
  180.     public static int lzf_decompress(byte[] input, ref byte[] output) {
  181.         int inputLength = input.Length;
  182.         int outputLength = output.Length;
  183.    
  184.         uint iidx = 0;
  185.         uint oidx = 0;
  186.  
  187.         do
  188.             {
  189.                 uint ctrl = input[iidx++];
  190.  
  191.                 if (ctrl < (1 << 5)) /* literal run */
  192.                 {
  193.                     ctrl++;
  194.  
  195.                     if (oidx + ctrl > outputLength)
  196.                     {
  197.                         //SET_ERRNO (E2BIG);
  198.                         return 0;
  199.                     }
  200.  
  201.                     do
  202.                         output[oidx++] = input[iidx++];
  203.                     while ((--ctrl) != 0);
  204.                 }
  205.                 else /* back reference */
  206.                 {
  207.                     uint len = ctrl >> 5;
  208.  
  209.                     int reference = (int)(oidx - ((ctrl & 0x1f) << 8) - 1);
  210.  
  211.                     if (len == 7)
  212.                         len += input[iidx++];
  213.  
  214.                     reference -= input[iidx++];
  215.  
  216.                     if (oidx + len + 2 > outputLength)
  217.                     {
  218.                         //SET_ERRNO (E2BIG);
  219.                         return 0;
  220.                     }
  221.  
  222.                     if (reference < 0)
  223.                     {
  224.                         //SET_ERRNO (EINVAL);
  225.                         return 0;
  226.                     }
  227.  
  228.                     output[oidx++] = output[reference++];
  229.                     output[oidx++] = output[reference++];
  230.  
  231.                     do
  232.                         output[oidx++] = output[reference++];
  233.                     while ((--len) != 0);
  234.                 }
  235.             }
  236.         while (iidx < inputLength);
  237.  
  238.         return (int)oidx;
  239.     }
  240. }
Advertisement
Add Comment
Please, Sign In to add comment