Lzma86Enc.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. /* Lzma86Enc.c -- LZMA + x86 (BCJ) Filter Encoder
  2. 2016-05-16 : Igor Pavlov : Public domain */
  3. #include "Precomp.h"
  4. #include <string.h>
  5. #include "Lzma86.h"
  6. #include "Alloc.h"
  7. #include "Bra.h"
  8. #include "LzmaEnc.h"
  9. #define SZE_OUT_OVERFLOW SZE_DATA_ERROR
  10. int Lzma86_Encode(Byte *dest, size_t *destLen, const Byte *src, size_t srcLen,
  11. int level, UInt32 dictSize, int filterMode)
  12. {
  13. size_t outSize2 = *destLen;
  14. Byte *filteredStream;
  15. Bool useFilter;
  16. int mainResult = SZ_ERROR_OUTPUT_EOF;
  17. CLzmaEncProps props;
  18. LzmaEncProps_Init(&props);
  19. props.level = level;
  20. props.dictSize = dictSize;
  21. *destLen = 0;
  22. if (outSize2 < LZMA86_HEADER_SIZE)
  23. return SZ_ERROR_OUTPUT_EOF;
  24. {
  25. int i;
  26. UInt64 t = srcLen;
  27. for (i = 0; i < 8; i++, t >>= 8)
  28. dest[LZMA86_SIZE_OFFSET + i] = (Byte)t;
  29. }
  30. filteredStream = 0;
  31. useFilter = (filterMode != SZ_FILTER_NO);
  32. if (useFilter)
  33. {
  34. if (srcLen != 0)
  35. {
  36. filteredStream = (Byte *)MyAlloc(srcLen);
  37. if (filteredStream == 0)
  38. return SZ_ERROR_MEM;
  39. memcpy(filteredStream, src, srcLen);
  40. }
  41. {
  42. UInt32 x86State;
  43. x86_Convert_Init(x86State);
  44. x86_Convert(filteredStream, srcLen, 0, &x86State, 1);
  45. }
  46. }
  47. {
  48. size_t minSize = 0;
  49. Bool bestIsFiltered = False;
  50. /* passes for SZ_FILTER_AUTO:
  51. 0 - BCJ + LZMA
  52. 1 - LZMA
  53. 2 - BCJ + LZMA agaian, if pass 0 (BCJ + LZMA) is better.
  54. */
  55. int numPasses = (filterMode == SZ_FILTER_AUTO) ? 3 : 1;
  56. int i;
  57. for (i = 0; i < numPasses; i++)
  58. {
  59. size_t outSizeProcessed = outSize2 - LZMA86_HEADER_SIZE;
  60. size_t outPropsSize = 5;
  61. SRes curRes;
  62. Bool curModeIsFiltered = (numPasses > 1 && i == numPasses - 1);
  63. if (curModeIsFiltered && !bestIsFiltered)
  64. break;
  65. if (useFilter && i == 0)
  66. curModeIsFiltered = True;
  67. curRes = LzmaEncode(dest + LZMA86_HEADER_SIZE, &outSizeProcessed,
  68. curModeIsFiltered ? filteredStream : src, srcLen,
  69. &props, dest + 1, &outPropsSize, 0,
  70. NULL, &g_Alloc, &g_Alloc);
  71. if (curRes != SZ_ERROR_OUTPUT_EOF)
  72. {
  73. if (curRes != SZ_OK)
  74. {
  75. mainResult = curRes;
  76. break;
  77. }
  78. if (outSizeProcessed <= minSize || mainResult != SZ_OK)
  79. {
  80. minSize = outSizeProcessed;
  81. bestIsFiltered = curModeIsFiltered;
  82. mainResult = SZ_OK;
  83. }
  84. }
  85. }
  86. dest[0] = (Byte)(bestIsFiltered ? 1 : 0);
  87. *destLen = LZMA86_HEADER_SIZE + minSize;
  88. }
  89. if (useFilter)
  90. MyFree(filteredStream);
  91. return mainResult;
  92. }