7zDecode.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /* 7zDecode.c */
  2. #include "7zDecode.h"
  3. #include "LzmaStateDecode.h" /* NOTE : Modified to use LzmaStateDecode(.c,.h) instead of LzmaDecode(.c,.h) and hardcoded _SZ_ONE_DIRECTORY behaviour */
  4. CMethodID k_Copy = { { 0x0 }, 1 };
  5. CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
  6. #ifdef _LZMA_IN_CB
  7. typedef struct _CLzmaInCallbackImp
  8. {
  9. ILzmaInCallback InCallback;
  10. ISzInStream *InStream;
  11. size_t Size;
  12. } CLzmaInCallbackImp;
  13. int LzmaReadImp(void *object, const unsigned char **buffer, size_t *size)
  14. {
  15. CLzmaInCallbackImp *cb = (CLzmaInCallbackImp *)object;
  16. size_t processedSize;
  17. SZ_RESULT res;
  18. *size = 0;
  19. res = cb->InStream->Read((void *)cb->InStream, (void **)buffer, cb->Size, &processedSize);
  20. *size = (size_t)processedSize;
  21. if (processedSize > cb->Size)
  22. return (int)SZE_FAIL;
  23. cb->Size -= processedSize;
  24. if (res == SZ_OK)
  25. return 0;
  26. return (int)res;
  27. }
  28. #endif
  29. SZ_RESULT SzDecode(const CFileSize *packSizes, const CFolder *folder,
  30. #ifdef _LZMA_IN_CB
  31. ISzInStream *inStream,
  32. #else
  33. const Byte *inBuffer,
  34. #endif
  35. Byte *outBuffer, size_t outSize,
  36. size_t *outSizeProcessed, ISzAlloc *allocMain)
  37. {
  38. UInt32 si;
  39. size_t inSize = 0;
  40. CCoderInfo *coder;
  41. if (folder->NumPackStreams != 1)
  42. return SZE_NOTIMPL;
  43. if (folder->NumCoders != 1)
  44. return SZE_NOTIMPL;
  45. coder = folder->Coders;
  46. *outSizeProcessed = 0;
  47. for (si = 0; si < folder->NumPackStreams; si++)
  48. inSize += (size_t)packSizes[si];
  49. if (AreMethodsEqual(&coder->MethodID, &k_Copy))
  50. {
  51. size_t i;
  52. if (inSize != outSize)
  53. return SZE_DATA_ERROR;
  54. #ifdef _LZMA_IN_CB
  55. for (i = 0; i < inSize;)
  56. {
  57. size_t j;
  58. Byte *inBuffer;
  59. size_t bufferSize;
  60. RINOK(inStream->Read((void *)inStream, (void **)&inBuffer, inSize - i, &bufferSize));
  61. if (bufferSize == 0)
  62. return SZE_DATA_ERROR;
  63. if (bufferSize > inSize - i)
  64. return SZE_FAIL;
  65. *outSizeProcessed += bufferSize;
  66. for (j = 0; j < bufferSize && i < inSize; j++, i++)
  67. outBuffer[i] = inBuffer[j];
  68. }
  69. #else
  70. for (i = 0; i < inSize; i++)
  71. outBuffer[i] = inBuffer[i];
  72. *outSizeProcessed = inSize;
  73. #endif
  74. return SZ_OK;
  75. }
  76. if (AreMethodsEqual(&coder->MethodID, &k_LZMA))
  77. {
  78. #ifdef _LZMA_IN_CB
  79. CLzmaInCallbackImp lzmaCallback;
  80. #else
  81. size_t inProcessed;
  82. #endif
  83. CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */
  84. int result;
  85. size_t outSizeProcessedLoc;
  86. #ifdef _LZMA_IN_CB
  87. lzmaCallback.Size = inSize;
  88. lzmaCallback.InStream = inStream;
  89. lzmaCallback.InCallback.Read = LzmaReadImp;
  90. #endif
  91. if (LzmaDecodeProperties(&state.Properties, coder->Properties.Items,
  92. coder->Properties.Capacity) != LZMA_RESULT_OK)
  93. return SZE_FAIL;
  94. state.Probs = (CProb *)allocMain->Alloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
  95. if (state.Probs == 0)
  96. return SZE_OUTOFMEMORY;
  97. #ifdef _LZMA_OUT_READ
  98. if (state.Properties.DictionarySize == 0)
  99. state.Dictionary = 0;
  100. else
  101. {
  102. state.Dictionary = (unsigned char *)allocMain->Alloc(state.Properties.DictionarySize);
  103. if (state.Dictionary == 0)
  104. {
  105. allocMain->Free(state.Probs);
  106. return SZE_OUTOFMEMORY;
  107. }
  108. }
  109. LzmaDecoderInit(&state);
  110. #endif
  111. result = LzmaDecode(&state,
  112. #ifdef _LZMA_IN_CB
  113. &lzmaCallback.InCallback,
  114. #else
  115. inBuffer, (size_t)inSize, &inProcessed,
  116. #endif
  117. outBuffer, (size_t)outSize, &outSizeProcessedLoc,
  118. 1); /* NOTE : Added by Dennis Schridde to make SzDecode be compatible with LzmaStateDecode(.c,.h) */
  119. *outSizeProcessed = (size_t)outSizeProcessedLoc;
  120. allocMain->Free(state.Probs);
  121. #ifdef _LZMA_OUT_READ
  122. allocMain->Free(state.Dictionary);
  123. #endif
  124. if (result == LZMA_RESULT_DATA_ERROR)
  125. return SZE_DATA_ERROR;
  126. if (result != LZMA_RESULT_OK)
  127. return SZE_FAIL;
  128. return SZ_OK;
  129. }
  130. return SZE_NOTIMPL;
  131. }