Lzma86Enc.c 2.9 KB

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