Apple's LZF algorithm parsing and AppleLZF algorithm Parsing
There are few parsing documents about the LZF algorithm, but Apple's open-source LZF allows us to simply parse the algorithm. LZFSE is based on Lempel-Ziv and uses finite state entropy encoding. LZF adopts a hybrid code similar to lz77 and lzss. Three start tags are used to represent the data strings output in each segment.
Next, let's take a look at the source code of the open-source LZF algorithm.
1. Global fields defined:
private readonly long[] _hashTable = new long[Hsize]; private const uint Hlog = 14; private const uint Hsize = (1 << 14); private const uint MaxLit = (1 << 5); private const uint MaxOff = (1 << 13); private const uint MaxRef = ((1 << 8) + (1 << 3));
2. Use the LibLZF algorithm to compress data:
/// <Summary> /// use the LibLZF algorithm to compress data /// </summary> /// <param name = "input"> data to be compressed </param> /// <param name = "inputLength"> length of the data to be compressed </param> /// <param name = "output"> reference the buffer that will contain the compressed data </param> // <param name = "outputLength"> the length of the compression buffer (must be greater than the input buffer) </param> // <returns> size of compressed archives in the output buffer </returns> public int Compress (byte [] input, int inputLength, byte [] output, int outputLength) {Array. clear (_ hashTable, 0, (int) Hsize ); Uint iidx = 0; uint oidx = 0; var hval = (uint) (input [iidx]) <8) | input [iidx + 1]); var response = 0; for (;) {if (iidx <inputLength-2) {hval = (hval <8) | input [iidx + 2]; long hslot = (hval ^ (hval <5)> (int) (3*8-Hlog)-hval * 5) & (Hsize-1); var reference = _ hashTable [hslot]; _ hashTable [hslot] = iidx; long off; if (off = iidx-reference-1) <MaxOff & iidx + 4 <InputLength & reference> 0 & input [reference + 0] = input [iidx + 0] & input [reference + 1] = input [iidx + 1] & & input [reference + 2] = input [iidx + 2]) {uint len = 2; var maxlen = (uint) inputLength-iidx-len; maxlen = maxlen> MaxRef? MaxRef: maxlen; if (oidx + rows + 1 + 3> = outputLength) return 0; do len ++; while (len <maxlen & input [reference + len] = input [iidx + len]); if (response! = 0) {output [oidx ++] = (byte) (bytes-1); bytes =-bytes; do output [oidx ++] = input [iidx + bytes]; while (++ uploads )! = 0);} len-= 2; iidx ++; if (len <7) {output [oidx ++] = (byte) (off> 8) + (len <5);} else {output [oidx ++] = (byte) (off> 8) + (7 <5 )); output [oidx ++] = (byte) (len-7);} output [oidx ++] = (byte) off; iidx + = len-1; hval = (uint) (input [iidx]) <8) | input [iidx + 1]); hval = (hval <8) | input [iidx + 2]; _ hashTable [(hval ^ (hval <5)> (int) (3*8-Hlog )) -hval * 5) & (Hsize -1)] = iidx; iidx ++; hval = (hval <8) | input [iidx + 2]; _ hashTable [(hval ^ (hval <5)> (int) (3*8-Hlog)-hval * 5) & (Hsize-1)] = iidx; iidx ++; continue ;}} else if (iidx = inputLength) break; expires ++; iidx ++; if (response! = Maxcompute) continue; if (oidx + 1 + maxcompute> = outputLength) return 0; output [oidx ++] = (byte) (maxcompute-1); bytes =-bytes; do output [oidx ++] = input [iidx + inputs]; while (++ inputs )! = 0);} if (response = 0) return (int) oidx; if (oidx + response + 1> = outputLength) return 0; output [oidx ++] = (byte) (bytes-1); bytes =-bytes; do output [oidx ++] = input [iidx + bytes]; while (++ uploads )! = 0); return (int) oidx ;}
3.
/// <Summary> /// extract data using the LibLZF algorithm /// </summary> /// <param name = "input"> extract data by referring to the data </param> /// <param name = "inputLength"> length of the data to be extracted </param> /// <param name = "output"> reference the buffer that contains the extracted data </ param> /// <param name = "outputLength"> size of compressed archives in the output buffer </param> /// <returns> return decompression size </returns> public int Decompress (byte [] input, int inputLength, byte [] output, int outputLength) {uint iidx = 0; uint oidx = 0; do {uint ct Rl = input [iidx ++]; if (ctrl <(1 <5) {ctrl ++; if (oidx + ctrl> outputLength) {return 0 ;} do output [oidx ++] = input [iidx ++]; while (-- ctrl )! = 0);} else {var len = ctrl> 5; var reference = (int) (oidx-(ctrl & 0x1f) <8)-1 ); if (len = 7) len + = input [iidx ++]; reference-= input [iidx ++]; if (oidx + len + 2> outputLength) {return 0;} if (reference <0) {return 0;} output [oidx ++] = output [reference ++]; output [oidx ++] = output [reference ++]; do output [oidx ++] = output [reference ++]; while (-- len )! = 0) ;}} while (iidx <inputLength); return (int) oidx ;}
The above is the LZF algorithm code.