lizard_parser_fastsmall.h 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /**************************************
  2. * Hash Functions
  3. **************************************/
  4. static size_t Lizard_hashPositionSmall(const void* p)
  5. {
  6. if (MEM_64bits())
  7. return Lizard_hash5Ptr(p, LIZARD_HASHLOG_LZ4SM);
  8. return Lizard_hash4Ptr(p, LIZARD_HASHLOG_LZ4SM);
  9. }
  10. static void Lizard_putPositionOnHashSmall(const BYTE* p, size_t h, U32* hashTable, const BYTE* srcBase)
  11. {
  12. hashTable[h] = (U32)(p-srcBase);
  13. }
  14. static void Lizard_putPositionSmall(const BYTE* p, U32* hashTable, const BYTE* srcBase)
  15. {
  16. size_t const h = Lizard_hashPositionSmall(p);
  17. Lizard_putPositionOnHashSmall(p, h, hashTable, srcBase);
  18. }
  19. static U32 Lizard_getPositionOnHashSmall(size_t h, U32* hashTable)
  20. {
  21. return hashTable[h];
  22. }
  23. static U32 Lizard_getPositionSmall(const BYTE* p, U32* hashTable)
  24. {
  25. size_t const h = Lizard_hashPositionSmall(p);
  26. return Lizard_getPositionOnHashSmall(h, hashTable);
  27. }
  28. FORCE_INLINE int Lizard_compress_fastSmall(
  29. Lizard_stream_t* const ctx,
  30. const BYTE* ip,
  31. const BYTE* const iend)
  32. {
  33. const U32 acceleration = 1;
  34. const BYTE* base = ctx->base;
  35. const U32 dictLimit = ctx->dictLimit;
  36. const BYTE* const lowPrefixPtr = base + dictLimit;
  37. const BYTE* const dictBase = ctx->dictBase;
  38. const BYTE* const dictEnd = dictBase + dictLimit;
  39. const BYTE* const mflimit = iend - MFLIMIT;
  40. const BYTE* const matchlimit = iend - LASTLITERALS;
  41. const BYTE* anchor = ip;
  42. size_t forwardH, matchIndex;
  43. const U32 maxDistance = (1 << ctx->params.windowLog) - 1;
  44. const U32 lowLimit = (ctx->lowLimit + maxDistance >= (U32)(ip - base)) ? ctx->lowLimit : (U32)(ip - base) - maxDistance;
  45. /* Init conditions */
  46. if ((U32)(iend-ip) > (U32)LIZARD_MAX_INPUT_SIZE) goto _output_error; /* Unsupported inputSize, too large (or negative) */
  47. if ((U32)(iend-ip) < Lizard_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
  48. /* First Byte */
  49. Lizard_putPositionSmall(ip, ctx->hashTable, base);
  50. ip++; forwardH = Lizard_hashPositionSmall(ip);
  51. /* Main Loop */
  52. for ( ; ; ) {
  53. const BYTE* match;
  54. size_t matchLength;
  55. /* Find a match */
  56. { const BYTE* forwardIp = ip;
  57. unsigned step = 1;
  58. unsigned searchMatchNb = acceleration << Lizard_skipTrigger;
  59. while (1) {
  60. size_t const h = forwardH;
  61. ip = forwardIp;
  62. forwardIp += step;
  63. step = (searchMatchNb++ >> Lizard_skipTrigger);
  64. if (unlikely(forwardIp > mflimit)) goto _last_literals;
  65. matchIndex = Lizard_getPositionOnHashSmall(h, ctx->hashTable);
  66. forwardH = Lizard_hashPositionSmall(forwardIp);
  67. Lizard_putPositionOnHashSmall(ip, h, ctx->hashTable, base);
  68. if ((matchIndex < lowLimit) || (matchIndex >= (U32)(ip - base)) || (base + matchIndex + maxDistance < ip)) continue;
  69. if (matchIndex >= dictLimit) {
  70. match = base + matchIndex;
  71. #if LIZARD_FAST_MIN_OFFSET > 0
  72. if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
  73. #endif
  74. if (MEM_read32(match) == MEM_read32(ip))
  75. {
  76. int back = 0;
  77. matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
  78. while ((ip+back > anchor) && (match+back > lowPrefixPtr) && (ip[back-1] == match[back-1])) back--;
  79. matchLength -= back;
  80. #if LIZARD_FAST_LONGOFF_MM > 0
  81. if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
  82. #endif
  83. {
  84. ip += back;
  85. match += back;
  86. break;
  87. }
  88. }
  89. } else {
  90. match = dictBase + matchIndex;
  91. #if LIZARD_FAST_MIN_OFFSET > 0
  92. if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
  93. #endif
  94. if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
  95. if (MEM_read32(match) == MEM_read32(ip)) {
  96. const U32 newLowLimit = (lowLimit + maxDistance >= (U32)(ip-base)) ? lowLimit : (U32)(ip - base) - maxDistance;
  97. int back = 0;
  98. matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
  99. while ((ip+back > anchor) && (matchIndex+back > newLowLimit) && (ip[back-1] == match[back-1])) back--;
  100. matchLength -= back;
  101. match = base + matchIndex + back;
  102. #if LIZARD_FAST_LONGOFF_MM > 0
  103. if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
  104. #endif
  105. {
  106. ip += back;
  107. break;
  108. }
  109. }
  110. }
  111. } // while (1)
  112. }
  113. _next_match:
  114. if (Lizard_encodeSequence_LZ4(ctx, &ip, &anchor, matchLength+MINMATCH, match)) goto _output_error;
  115. /* Test end of chunk */
  116. if (ip > mflimit) break;
  117. /* Fill table */
  118. Lizard_putPositionSmall(ip-2, ctx->hashTable, base);
  119. /* Test next position */
  120. matchIndex = Lizard_getPositionSmall(ip, ctx->hashTable);
  121. Lizard_putPositionSmall(ip, ctx->hashTable, base);
  122. if ((matchIndex >= lowLimit) && (matchIndex < (U32)(ip - base)) && (base + matchIndex + maxDistance >= ip))
  123. {
  124. if (matchIndex >= dictLimit) {
  125. match = base + matchIndex;
  126. #if LIZARD_FAST_MIN_OFFSET > 0
  127. if ((U32)(ip - match) >= LIZARD_FAST_MIN_OFFSET)
  128. #endif
  129. if (MEM_read32(match) == MEM_read32(ip))
  130. {
  131. matchLength = Lizard_count(ip+MINMATCH, match+MINMATCH, matchlimit);
  132. #if LIZARD_FAST_LONGOFF_MM > 0
  133. if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
  134. #endif
  135. goto _next_match;
  136. }
  137. } else {
  138. match = dictBase + matchIndex;
  139. #if LIZARD_FAST_MIN_OFFSET > 0
  140. if ((U32)(ip - (base + matchIndex)) >= LIZARD_FAST_MIN_OFFSET)
  141. #endif
  142. if ((U32)((dictLimit-1) - matchIndex) >= 3) /* intentional overflow */
  143. if (MEM_read32(match) == MEM_read32(ip)) {
  144. matchLength = Lizard_count_2segments(ip+MINMATCH, match+MINMATCH, matchlimit, dictEnd, lowPrefixPtr);
  145. match = base + matchIndex;
  146. #if LIZARD_FAST_LONGOFF_MM > 0
  147. if ((matchLength >= LIZARD_FAST_LONGOFF_MM) || ((U32)(ip - match) < LIZARD_MAX_16BIT_OFFSET))
  148. #endif
  149. goto _next_match;
  150. }
  151. }
  152. }
  153. /* Prepare next loop */
  154. forwardH = Lizard_hashPositionSmall(++ip);
  155. }
  156. _last_literals:
  157. /* Encode Last Literals */
  158. ip = iend;
  159. if (Lizard_encodeLastLiterals_LZ4(ctx, &ip, &anchor)) goto _output_error;
  160. /* End */
  161. return 1;
  162. _output_error:
  163. return 0;
  164. }