MCPcopy Create free account
hub / github.com/DFHack/dfhack / encodeLZ77

Function encodeLZ77

depends/lodepng/lodepng.cpp:1593–1740  ·  view source on GitHub ↗

LZ77-encode the data. Return value is error code. The input are raw bytes, the output is in the form of unsigned integers with codes representing for example literal bytes, or length/distance pairs. It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a sliding window (of windowsize) is used, and all past bytes in that window can be used as the "dictionary". A brute fo

Source from the content-addressed store, hash-verified

1591this hash technique is one out of several ways to speed this up.
1592*/
1593static unsigned encodeLZ77(uivector* out, Hash* hash,
1594 const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize,
1595 unsigned minmatch, unsigned nicematch, unsigned lazymatching) {
1596 size_t pos;
1597 unsigned i, error = 0;
1598 /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/
1599 unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8u;
1600 unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64;
1601
1602 unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/
1603 unsigned numzeros = 0;
1604
1605 unsigned offset; /*the offset represents the distance in LZ77 terminology*/
1606 unsigned length;
1607 unsigned lazy = 0;
1608 unsigned lazylength = 0, lazyoffset = 0;
1609 unsigned hashval;
1610 unsigned current_offset, current_length;
1611 unsigned prev_offset;
1612 const unsigned char *lastptr, *foreptr, *backptr;
1613 unsigned hashpos;
1614
1615 if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/
1616 if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/
1617
1618 if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH;
1619
1620 for(pos = inpos; pos < insize; ++pos) {
1621 size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/
1622 unsigned chainlength = 0;
1623
1624 hashval = getHash(in, insize, pos);
1625
1626 if(usezeros && hashval == 0) {
1627 if(numzeros == 0) numzeros = countZeros(in, insize, pos);
1628 else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros;
1629 } else {
1630 numzeros = 0;
1631 }
1632
1633 updateHashChain(hash, wpos, hashval, numzeros);
1634
1635 /*the length and offset found for the current position*/
1636 length = 0;
1637 offset = 0;
1638
1639 hashpos = hash->chain[wpos];
1640
1641 lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH];
1642
1643 /*search for the longest string*/
1644 prev_offset = 0;
1645 for(;;) {
1646 if(chainlength++ >= maxchainlength) break;
1647 current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize);
1648
1649 if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/
1650 prev_offset = current_offset;

Callers 2

deflateDynamicFunction · 0.85
deflateFixedFunction · 0.85

Calls 5

getHashFunction · 0.85
countZerosFunction · 0.85
updateHashChainFunction · 0.85
uivector_push_backFunction · 0.85
addLengthDistanceFunction · 0.85

Tested by

no test coverage detected