lizard_decompress_lz4.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*! Lizard_decompress_LZ4() :
  2. * This generic decompression function cover all use cases.
  3. * It shall be instantiated several times, using different sets of directives
  4. * Note that it is important this generic function is really inlined,
  5. * in order to remove useless branches during compilation optimization.
  6. */
  7. FORCE_INLINE int Lizard_decompress_LZ4(
  8. Lizard_dstream_t* ctx,
  9. BYTE* const dest,
  10. int outputSize, /* this value is the max size of Output Buffer. */
  11. int partialDecoding, /* full, partial */
  12. int targetOutputSize, /* only used if partialDecoding==partial */
  13. int dict, /* noDict, withPrefix64k, usingExtDict */
  14. const BYTE* const lowPrefix, /* == dest if dict == noDict */
  15. const BYTE* const dictStart, /* only if dict==usingExtDict */
  16. const size_t dictSize, /* note : = 0 if noDict */
  17. int compressionLevel
  18. )
  19. {
  20. /* Local Variables */
  21. int inputSize = (int)(ctx->flagsEnd - ctx->flagsPtr);
  22. const BYTE* const blockBase = ctx->flagsPtr;
  23. const BYTE* const iend = ctx->literalsEnd;
  24. BYTE* op = dest;
  25. BYTE* const oend = op + outputSize;
  26. BYTE* cpy = NULL;
  27. BYTE* oexit = op + targetOutputSize;
  28. const BYTE* const lowLimit = lowPrefix - dictSize;
  29. const BYTE* const dictEnd = (const BYTE*)dictStart + dictSize;
  30. const int checkOffset = (dictSize < (int)(LIZARD_DICT_SIZE));
  31. intptr_t length = 0;
  32. (void)compressionLevel;
  33. /* Special cases */
  34. if (unlikely(outputSize==0)) return ((inputSize==1) && (*ctx->flagsPtr==0)) ? 0 : -1; /* Empty output buffer */
  35. /* Main Loop : decode sequences */
  36. while (ctx->flagsPtr < ctx->flagsEnd) {
  37. unsigned token;
  38. const BYTE* match;
  39. size_t offset;
  40. /* get literal length */
  41. token = *ctx->flagsPtr++;
  42. if ((length=(token & RUN_MASK_LZ4)) == RUN_MASK_LZ4) {
  43. if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4("0"); goto _output_error; }
  44. length = *ctx->literalsPtr;
  45. if unlikely(length >= 254) {
  46. if (length == 254) {
  47. length = MEM_readLE16(ctx->literalsPtr+1);
  48. ctx->literalsPtr += 2;
  49. } else {
  50. length = MEM_readLE24(ctx->literalsPtr+1);
  51. ctx->literalsPtr += 3;
  52. }
  53. }
  54. length += RUN_MASK_LZ4;
  55. ctx->literalsPtr++;
  56. if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4("1"); goto _output_error; } /* overflow detection */
  57. if (unlikely((size_t)(ctx->literalsPtr+length)<(size_t)(ctx->literalsPtr))) { LIZARD_LOG_DECOMPRESS_LZ4("2"); goto _output_error; } /* overflow detection */
  58. }
  59. /* copy literals */
  60. cpy = op + length;
  61. if (unlikely(cpy > oend - WILDCOPYLENGTH || ctx->literalsPtr + length > iend - (2 + WILDCOPYLENGTH))) { LIZARD_LOG_DECOMPRESS_LZ4("offset outside buffers\n"); goto _output_error; } /* Error : offset outside buffers */
  62. #if 1
  63. Lizard_wildCopy16(op, ctx->literalsPtr, cpy);
  64. op = cpy;
  65. ctx->literalsPtr += length;
  66. #else
  67. Lizard_copy8(op, ctx->literalsPtr);
  68. Lizard_copy8(op+8, ctx->literalsPtr+8);
  69. if (length > 16)
  70. Lizard_wildCopy16(op + 16, ctx->literalsPtr + 16, cpy);
  71. op = cpy;
  72. ctx->literalsPtr += length;
  73. #endif
  74. if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);
  75. /* get offset */
  76. offset = MEM_readLE16(ctx->literalsPtr);
  77. ctx->literalsPtr += 2;
  78. match = op - offset;
  79. if ((checkOffset) && (unlikely(match < lowLimit))) { LIZARD_LOG_DECOMPRESS_LZ4("lowPrefix[%p]-dictSize[%d]=lowLimit[%p] match[%p]=op[%p]-offset[%d]\n", lowPrefix, (int)dictSize, lowLimit, match, op, (int)offset); goto _output_error; } /* Error : offset outside buffers */
  80. /* get matchlength */
  81. length = token >> RUN_BITS_LZ4;
  82. if (length == ML_MASK_LZ4) {
  83. if (unlikely(ctx->literalsPtr > iend - 5)) { LIZARD_LOG_DECOMPRESS_LZ4("4"); goto _output_error; }
  84. length = *ctx->literalsPtr;
  85. if unlikely(length >= 254) {
  86. if (length == 254) {
  87. length = MEM_readLE16(ctx->literalsPtr+1);
  88. ctx->literalsPtr += 2;
  89. } else {
  90. length = MEM_readLE24(ctx->literalsPtr+1);
  91. ctx->literalsPtr += 3;
  92. }
  93. }
  94. length += ML_MASK_LZ4;
  95. ctx->literalsPtr++;
  96. if (unlikely((size_t)(op+length)<(size_t)(op))) { LIZARD_LOG_DECOMPRESS_LZ4("5"); goto _output_error; } /* overflow detection */
  97. }
  98. length += MINMATCH;
  99. /* check external dictionary */
  100. if ((dict==usingExtDict) && (match < lowPrefix)) {
  101. if (unlikely(op + length > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4("6"); goto _output_error; } /* doesn't respect parsing restriction */
  102. if (length <= (intptr_t)(lowPrefix - match)) {
  103. /* match can be copied as a single segment from external dictionary */
  104. memmove(op, dictEnd - (lowPrefix-match), length);
  105. op += length;
  106. } else {
  107. /* match encompass external dictionary and current block */
  108. size_t const copySize = (size_t)(lowPrefix-match);
  109. size_t const restSize = length - copySize;
  110. memcpy(op, dictEnd - copySize, copySize);
  111. op += copySize;
  112. if (restSize > (size_t)(op-lowPrefix)) { /* overlap copy */
  113. BYTE* const endOfMatch = op + restSize;
  114. const BYTE* copyFrom = lowPrefix;
  115. while (op < endOfMatch) *op++ = *copyFrom++;
  116. } else {
  117. memcpy(op, lowPrefix, restSize);
  118. op += restSize;
  119. } }
  120. continue;
  121. }
  122. /* copy match within block */
  123. cpy = op + length;
  124. if (unlikely(cpy > oend - WILDCOPYLENGTH)) { LIZARD_LOG_DECOMPRESS_LZ4("1match=%p lowLimit=%p\n", match, lowLimit); goto _output_error; } /* Error : offset outside buffers */
  125. Lizard_copy8(op, match);
  126. Lizard_copy8(op+8, match+8);
  127. if (length > 16)
  128. Lizard_wildCopy16(op + 16, match + 16, cpy);
  129. op = cpy;
  130. if ((partialDecoding) && (op >= oexit)) return (int) (op-dest);
  131. }
  132. /* last literals */
  133. length = ctx->literalsEnd - ctx->literalsPtr;
  134. cpy = op + length;
  135. if ((ctx->literalsPtr+length != iend) || (cpy > oend)) { LIZARD_LOG_DECOMPRESS_LZ4("9"); goto _output_error; } /* Error : input must be consumed */
  136. memcpy(op, ctx->literalsPtr, length);
  137. ctx->literalsPtr += length;
  138. op += length;
  139. /* end of decoding */
  140. return (int) (op-dest); /* Nb of output bytes decoded */
  141. /* Overflow error detected */
  142. _output_error:
  143. LIZARD_LOG_DECOMPRESS_LZ4("_output_error=%d ctx->flagsPtr=%p blockBase=%p\n", (int) (-(ctx->flagsPtr-blockBase))-1, ctx->flagsPtr, blockBase);
  144. LIZARD_LOG_DECOMPRESS_LZ4("cpy=%p oend=%p ctx->literalsPtr+length[%d]=%p iend=%p\n", cpy, oend, (int)length, ctx->literalsPtr+length, iend);
  145. return (int) (-(ctx->flagsPtr-blockBase))-1;
  146. }