78static constexpr std::array<unsigned, 8> inc32table = {0, 1, 2, 1, 0, 4, 4, 4};
79static constexpr std::array<int , 8> dec64table = {0, 0, 0, -1, -4, 1, 2, 3};
279 const uint8_t* ip = src;
282 const uint8_t* anchor = src;
283 const uint8_t*
const iend = ip + inputSize;
284 const uint8_t*
const mflimitPlusOne = iend - MFLIMIT + 1;
285 const uint8_t*
const matchlimit = iend - LASTLITERALS;
289 if (inputSize < MIN_LENGTH)
goto _last_literals;
292 hashTable.putPosition(ip, src);
294 forwardH = hashTable.hashPosition(ip);
298 const uint8_t* match;
299 if constexpr (!L64K && !ARCH64) {
300 const uint8_t* forwardIp = ip;
302 int searchMatchNb = ACCELERATION << SKIP_TRIGGER;
304 uint32_t h = forwardH;
307 step = searchMatchNb++ >> SKIP_TRIGGER;
309 if (forwardIp > mflimitPlusOne) [[unlikely]]
goto _last_literals;
311 match = hashTable.getPositionOnHash(h, src);
312 forwardH = hashTable.hashPosition(forwardIp);
313 hashTable.putPositionOnHash(ip, h, src);
314 }
while ((match + DISTANCE_MAX < ip) ||
318 const uint8_t* forwardIp = ip;
320 int searchMatchNb = ACCELERATION << SKIP_TRIGGER;
323 auto current = uint32_t(forwardIp - src);
324 auto matchIndex = hashTable.getIndexOnHash(h);
327 step = searchMatchNb++ >> SKIP_TRIGGER;
329 if (forwardIp > mflimitPlusOne) [[unlikely]]
goto _last_literals;
331 match = src + matchIndex;
332 forwardH = hashTable.hashPosition(forwardIp);
333 hashTable.putIndexOnHash(current, h);
335 if (!L64K && (matchIndex + DISTANCE_MAX < current)) {
346 while (((ip > anchor) & (match > src)) && ((ip[-1] == match[-1]))) {
352 auto litLength = unsigned(ip - anchor);
353 uint8_t* token = op++;
354 if (litLength >= RUN_MASK) {
355 auto len = int(litLength - RUN_MASK);
356 *token = RUN_MASK << ML_BITS;
361 *op++ = uint8_t(len);
363 *token = uint8_t(litLength << ML_BITS);
367 wildCopy8(op, anchor, op + litLength);
381 unsigned matchCode =
count(ip + MINMATCH, match + MINMATCH, matchlimit);
382 ip += size_t(matchCode) + MINMATCH;
384 if (matchCode >= ML_MASK) {
386 matchCode -= ML_MASK;
388 while (matchCode >= 4 * 255) {
391 matchCode -= 4 * 255;
393 op += matchCode / 255;
394 *op++ = uint8_t(matchCode % 255);
396 *token += uint8_t(matchCode);
402 if (ip >= mflimitPlusOne)
break;
405 hashTable.putPosition(ip - 2, src);
408 if constexpr (!L64K && !ARCH64) {
409 match = hashTable.getPosition(ip, src);
410 hashTable.putPosition(ip, src);
417 auto h = hashTable.hashPosition(ip);
418 auto current = uint32_t(ip - src);
419 auto matchIndex = hashTable.getIndexOnHash(h);
420 match = src + matchIndex;
421 hashTable.putIndexOnHash(current, h);
422 if ((L64K || (matchIndex + DISTANCE_MAX >= current)) &&
431 forwardH = hashTable.hashPosition(++ip);
436 auto lastRun = size_t(iend - anchor);
437 if (lastRun >= RUN_MASK) {
438 size_t accumulator = lastRun - RUN_MASK;
439 *op++ = RUN_MASK << ML_BITS;
440 while (accumulator >= 255) {
444 *op++ = uint8_t(accumulator);
446 *op++ = uint8_t(lastRun << ML_BITS);
448 memcpy(op, anchor, lastRun);
449 ip = anchor + lastRun;
452 return int(op - dst);
479int decompress(
const uint8_t* src, uint8_t* dst,
int compressedSize,
int dstCapacity)
481 const uint8_t* ip = src;
482 const uint8_t*
const iend = ip + compressedSize;
485 uint8_t*
const oend = op + dstCapacity;
489 const uint8_t*
const shortiend = iend - 14 - 2 ;
490 const uint8_t*
const shortoend = oend - 14 - 18 ;
492 const uint8_t* match;
497 if ((oend - op) >= FASTLOOP_SAFE_DISTANCE) {
502 length = token >> ML_BITS;
505 if (length == RUN_MASK) {
506 length += read_variable_length(&ip);
510 if ((cpy > oend - 32) || (ip + length > iend - 32)) {
511 goto safe_literal_copy;
513 wildCopy32(op, ip, cpy);
519 if (ip > iend - (16 + 1)) {
520 goto safe_literal_copy;
534 length = token & ML_MASK;
536 if (length == ML_MASK) {
537 length += read_variable_length(&ip);
539 if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
540 goto safe_match_copy;
544 if (op + length >= oend - FASTLOOP_SAFE_DISTANCE) {
545 goto safe_match_copy;
549 if ((match >= dst) && (offset >= 8)) {
550 memcpy(op + 0, match + 0, 8);
551 memcpy(op + 8, match + 8, 8);
552 memcpy(op + 16, match + 16, 2);
561 if (offset < 16) [[unlikely]] {
562 memcpy_using_offset(op, match, cpy, offset);
564 wildCopy32(op, match, cpy);
574 length = token >> ML_BITS;
584 if ((length != RUN_MASK) &&
586 ((ip < shortiend) & (op <= shortoend))) {
594 length = token & ML_MASK;
600 if ((length != ML_MASK) && (offset >= 8) && (match >= dst)) {
602 memcpy(op + 0, match + 0, 8);
603 memcpy(op + 8, match + 8, 8);
604 memcpy(op + 16, match + 16, 2);
605 op += length + MINMATCH;
616 if (length == RUN_MASK) {
617 length += read_variable_length(&ip);
623 if ((cpy > oend - MFLIMIT) || (ip + length > iend - (2 + 1 + LASTLITERALS))) {
628 memmove(op, ip, length);
633 wildCopy8(op, ip, cpy);
644 length = token & ML_MASK;
647 if (length == ML_MASK) {
648 length += read_variable_length(&ip);
656 if (offset < 8) [[unlikely]] {
662 match += inc32table[offset];
663 memcpy(op + 4, match, 4);
664 match -= dec64table[offset];
666 memcpy(op, match, 8);
671 if (cpy > oend - MATCH_SAFEGUARD_DISTANCE) [[unlikely]] {
672 uint8_t*
const oCopyLimit = oend - (WILDCOPYLENGTH - 1);
673 if (op < oCopyLimit) {
674 wildCopy8(op, match, oCopyLimit);
675 match += oCopyLimit - op;
682 memcpy(op, match, 8);
684 wildCopy8(op + 8, match + 8, cpy);
690 return int(op - dst);