lizard_decompress_liz.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. [0_MMMM_LLL] - 16-bit offset, 4-bit match length (4-15+), 3-bit literal length (0-7+)
  3. [1_MMMM_LLL] - last offset, 4-bit match length (0-15+), 3-bit literal length (0-7+)
  4. flag 31 - 24-bit offset, match length (47+), no literal length
  5. flag 0-30 - 24-bit offset, 31 match lengths (16-46), no literal length
  6. */
  7. /*! Lizard_decompress_LIZv1() :
  8. * This generic decompression function cover all use cases.
  9. * It shall be instantiated several times, using different sets of directives
  10. * Note that it is important this generic function is really inlined,
  11. * in order to remove useless branches during compilation optimization.
  12. */
  13. FORCE_INLINE int Lizard_decompress_LIZv1(
  14. Lizard_dstream_t* ctx,
  15. BYTE* const dest,
  16. int outputSize, /* this value is the max size of Output Buffer. */
  17. int partialDecoding, /* full, partial */
  18. int targetOutputSize, /* only used if partialDecoding==partial */
  19. int dict, /* noDict, withPrefix64k, usingExtDict */
  20. const BYTE* const lowPrefix, /* == dest if dict == noDict */
  21. const BYTE* const dictStart, /* only if dict==usingExtDict */
  22. const size_t dictSize, /* note : = 0 if noDict */
  23. int compressionLevel
  24. )
  25. {
  26. /* Local Variables */
  27. int inputSize = (int)(ctx->flagsEnd - ctx->flagsPtr);
  28. const BYTE* const blockBase = ctx->flagsPtr;
  29. const BYTE* const iend = ctx->literalsEnd;
  30. BYTE* op = dest;
  31. BYTE* const oend = op + outputSize;
  32. BYTE* cpy = NULL;
  33. BYTE* oexit = op + targetOutputSize;
  34. const BYTE* const lowLimit = lowPrefix - dictSize;
  35. const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
  36. const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));
  37. intptr_t last_off = ctx->last_off;
  38. intptr_t length = 0;
  39. (void)compressionLevel;
  40. /* Special cases */
  41. if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1; /* Empty output buffer */
  42. /* Main Loop : decode sequences */
  43. while (ctx->flagsPtr < ctx->flagsEnd) {
  44. unsigned token;
  45. const BYTE* match;
  46. // intptr_t litLength;
  47. if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);
  48. /* get literal length */
  49. token = *ctx->flagsPtr++;
  50. if (token >= 32)
  51. {
  52. if ((length=(token & MAX_SHORT_LITLEN)) == MAX_SHORT_LITLEN) {
  53. if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("1"); goto _output_error; }
  54. length = *ctx->literalsPtr;
  55. if unlikely(length >= 254) {
  56. if (length == 254) {
  57. length = MEM_readLE16(ctx->literalsPtr+1);
  58. ctx->literalsPtr += 2;
  59. } else {
  60. length = MEM_readLE24(ctx->literalsPtr+1);
  61. ctx->literalsPtr += 3;
  62. }
  63. }
  64. length += MAX_SHORT_LITLEN;
  65. ctx->literalsPtr++;
  66. if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1("2"); goto _output_error; } /* overflow detection */
  67. if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LIZv1("3"); goto _output_error; } /* overflow detection */
  68. }
  69. /* copy literals */
  70. cpy = op + length;
  71. if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr > iend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
  72. #if 1
  73. Lizard_wildCopy16(op, ctx->literalsPtr, cpy);
  74. op = cpy;
  75. ctx->literalsPtr += length;
  76. #else
  77. Lizard_copy8(op, ctx->literalsPtr);
  78. Lizard_copy8(op+8, ctx->literalsPtr+8);
  79. if (length > 16)
  80. Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
  81. op = cpy;
  82. ctx->literalsPtr += length;
  83. #endif
  84. /* get offset */
  85. if (unlikely(ctx->offset16Ptr > ctx->offset16End)) { LIZARD_LOG_DECOMPRESS_LIZv1("(ctx->offset16Ptr > ctx->offset16End\n"); goto _output_error; }
  86. #if 1
  87. { /* branchless */
  88. intptr_t new_off = MEM_readLE16(ctx->offset16Ptr);
  89. uintptr_t not_repCode = (uintptr_t)(token >> ML_RUN_BITS) - 1;
  90. last_off ^= not_repCode & (last_off ^ -new_off);
  91. ctx->offset16Ptr = (BYTE*)((uintptr_t)ctx->offset16Ptr + (not_repCode & 2));
  92. }
  93. #else
  94. if ((token >> ML_RUN_BITS_LIZv1) == 0)
  95. {
  96. last_off = -(intptr_t)MEM_readLE16(ctx->offset16Ptr);
  97. ctx->offset16Ptr += 2;
  98. }
  99. #endif
  100. /* get matchlength */
  101. length = (token >> RUN_BITS_LIZv1) & MAX_SHORT_MATCHLEN;
  102. if (length == MAX_SHORT_MATCHLEN) {
  103. if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("6"); goto _output_error; }
  104. length = *ctx->literalsPtr;
  105. if unlikely(length >= 254) {
  106. if (length == 254) {
  107. length = MEM_readLE16(ctx->literalsPtr+1);
  108. ctx->literalsPtr += 2;
  109. } else {
  110. length = MEM_readLE24(ctx->literalsPtr+1);
  111. ctx->literalsPtr += 3;
  112. }
  113. }
  114. length += MAX_SHORT_MATCHLEN;
  115. ctx->literalsPtr++;
  116. if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LIZv1("7"); goto _output_error; } /* overflow detection */
  117. }
  118. DECOMPLOG_CODEWORDS_LIZv1("T32+ literal=%u match=%u offset=%d ipos=%d opos=%d\n", (U32)litLength, (U32)length, (int)-last_off, (U32)(ctx->flagsPtr-blockBase), (U32)(op-dest));
  119. }
  120. else
  121. if (token < LIZARD_LAST_LONG_OFF)
  122. {
  123. if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1("8"); goto _output_error; }
  124. length = token + MM_LONGOFF;
  125. last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr);
  126. ctx->offset24Ptr += 3;
  127. DECOMPLOG_CODEWORDS_LIZv1("T0-30 literal=%u match=%u offset=%d\n", 0, (U32)length, (int)-last_off);
  128. }
  129. else
  130. {
  131. if (unlikely(ctx->literalsPtr > iend - 1)) { LIZARD_LOG_DECOMPRESS_LIZv1("9"); goto _output_error; }
  132. length = *ctx->literalsPtr;
  133. if unlikely(length >= 254) {
  134. if (length == 254) {
  135. length = MEM_readLE16(ctx->literalsPtr+1);
  136. ctx->literalsPtr += 2;
  137. } else {
  138. length = MEM_readLE24(ctx->literalsPtr+1);
  139. ctx->literalsPtr += 3;
  140. }
  141. }
  142. ctx->literalsPtr++;
  143. length += LIZARD_LAST_LONG_OFF + MM_LONGOFF;
  144. if (unlikely(ctx->offset24Ptr > ctx->offset24End - 3)) { LIZARD_LOG_DECOMPRESS_LIZv1("10"); goto _output_error; }
  145. last_off = -(intptr_t)MEM_readLE24(ctx->offset24Ptr);
  146. ctx->offset24Ptr += 3;
  147. }
  148. match = op + last_off;
  149. if ((checkOffset) && ((unlikely((uintptr_t)(-last_off) > (uintptr_t)op) || (match < lowLimit)))) { LIZARD_LOG_DECOMPRESS_LIZv1("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-last_off[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)last_off); goto _output_error; } /* Error : offset outside buffers */
  150. /* check external dictionary */
  151. if ((dict==usingExtDict) && (match < lowPrefix)) {
  152. if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("12"); goto _output_error; } /* doesn't respect parsing restriction */
  153. if (length <= (intptr_t)(lowPrefix - match)) {
  154. /* match can be copied as a single segment from external dictionary */
  155. memmove(op, dictEnd - (lowPrefix-match), length);
  156. op += length;
  157. } else {
  158. /* match encompass external dictionary and current block */
  159. size_t const copySize = (size_t)(lowPrefix-match);
  160. size_t const restSize = length - copySize;
  161. memcpy(op, dictEnd - copySize, copySize);
  162. op += copySize;
  163. if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */
  164. BYTE* const endOfMatch = op + restSize;
  165. const BYTE* copyFrom = lowPrefix;
  166. while (op < endOfMatch) *op++ = *copyFrom++;
  167. } else {
  168. memcpy(op, lowPrefix, restSize);
  169. op += restSize;
  170. } }
  171. continue;
  172. }
  173. /* copy match within block */
  174. cpy = op + length;
  175. if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LIZv1("13match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
  176. Lizard_copy8(op, match);
  177. Lizard_copy8(op+8, match+8);
  178. if (length > 16)
  179. Lizard_wildCopy16(op + 16, match + 16, cpy);
  180. op = cpy;
  181. }
  182. /* last literals */
  183. length = ctx->literalsEnd - ctx->literalsPtr;
  184. cpy = op + length;
  185. if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LIZv1("14"); goto _output_error; } /* Error : input must be consumed */
  186. memcpy(op, ctx->literalsPtr, length);
  187. ctx->literalsPtr += length;
  188. op += length;
  189. /* end of decoding */
  190. ctx->last_off = last_off;
  191. return (int) (op-dest); /* Nb of output bytes decoded */
  192. /* Overflow error detected */
  193. _output_error:
  194. LIZARD_LOG_DECOMPRESS_LIZv1("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
  195. LIZARD_LOG_DECOMPRESS_LIZv1("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
  196. return (int) (-(ctx->flagsPtr-blockBase))-1;
  197. }