alone_encoder.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. /// \file alone_encoder.c
  4. /// \brief Encoder for LZMA_Alone files
  5. //
  6. // Author: Lasse Collin
  7. //
  8. // This file has been put into the public domain.
  9. // You can do whatever you want with this file.
  10. //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include "common.h"
  13. #include "lzma_encoder.h"
  14. #define ALONE_HEADER_SIZE (1 + 4 + 8)
  15. typedef struct {
  16. lzma_next_coder next;
  17. enum {
  18. SEQ_HEADER,
  19. SEQ_CODE,
  20. } sequence;
  21. size_t header_pos;
  22. uint8_t header[ALONE_HEADER_SIZE];
  23. } lzma_alone_coder;
  24. static lzma_ret
  25. alone_encode(void *coder_ptr, const lzma_allocator *allocator,
  26. const uint8_t *restrict in, size_t *restrict in_pos,
  27. size_t in_size, uint8_t *restrict out,
  28. size_t *restrict out_pos, size_t out_size,
  29. lzma_action action)
  30. {
  31. lzma_alone_coder *coder = coder_ptr;
  32. while (*out_pos < out_size)
  33. switch (coder->sequence) {
  34. case SEQ_HEADER:
  35. lzma_bufcpy(coder->header, &coder->header_pos,
  36. ALONE_HEADER_SIZE,
  37. out, out_pos, out_size);
  38. if (coder->header_pos < ALONE_HEADER_SIZE)
  39. return LZMA_OK;
  40. coder->sequence = SEQ_CODE;
  41. break;
  42. case SEQ_CODE:
  43. return coder->next.code(coder->next.coder,
  44. allocator, in, in_pos, in_size,
  45. out, out_pos, out_size, action);
  46. default:
  47. assert(0);
  48. return LZMA_PROG_ERROR;
  49. }
  50. return LZMA_OK;
  51. }
  52. static void
  53. alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
  54. {
  55. lzma_alone_coder *coder = coder_ptr;
  56. lzma_next_end(&coder->next, allocator);
  57. lzma_free(coder, allocator);
  58. return;
  59. }
  60. // At least for now, this is not used by any internal function.
  61. static lzma_ret
  62. alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
  63. const lzma_options_lzma *options)
  64. {
  65. lzma_next_coder_init(&alone_encoder_init, next, allocator);
  66. lzma_alone_coder *coder = next->coder;
  67. if (coder == NULL) {
  68. coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
  69. if (coder == NULL)
  70. return LZMA_MEM_ERROR;
  71. next->coder = coder;
  72. next->code = &alone_encode;
  73. next->end = &alone_encoder_end;
  74. coder->next = LZMA_NEXT_CODER_INIT;
  75. }
  76. // Basic initializations
  77. coder->sequence = SEQ_HEADER;
  78. coder->header_pos = 0;
  79. // Encode the header:
  80. // - Properties (1 byte)
  81. if (lzma_lzma_lclppb_encode(options, coder->header))
  82. return LZMA_OPTIONS_ERROR;
  83. // - Dictionary size (4 bytes)
  84. if (options->dict_size < LZMA_DICT_SIZE_MIN)
  85. return LZMA_OPTIONS_ERROR;
  86. // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
  87. // one is the next unless it is UINT32_MAX. While the header would
  88. // allow any 32-bit integer, we do this to keep the decoder of liblzma
  89. // accepting the resulting files.
  90. uint32_t d = options->dict_size - 1;
  91. d |= d >> 2;
  92. d |= d >> 3;
  93. d |= d >> 4;
  94. d |= d >> 8;
  95. d |= d >> 16;
  96. if (d != UINT32_MAX)
  97. ++d;
  98. write32le(coder->header + 1, d);
  99. // - Uncompressed size (always unknown and using EOPM)
  100. memset(coder->header + 1 + 4, 0xFF, 8);
  101. // Initialize the LZMA encoder.
  102. const lzma_filter_info filters[2] = {
  103. {
  104. .id = LZMA_FILTER_LZMA1,
  105. .init = &lzma_lzma_encoder_init,
  106. .options = (void *)(options),
  107. }, {
  108. .init = NULL,
  109. }
  110. };
  111. return lzma_next_filter_init(&coder->next, allocator, filters);
  112. }
  113. /*
  114. extern lzma_ret
  115. lzma_alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
  116. const lzma_options_alone *options)
  117. {
  118. lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
  119. }
  120. */
  121. extern LZMA_API(lzma_ret)
  122. lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
  123. {
  124. lzma_next_strm_init(alone_encoder_init, strm, options);
  125. strm->internal->supported_actions[LZMA_RUN] = true;
  126. strm->internal->supported_actions[LZMA_FINISH] = true;
  127. return LZMA_OK;
  128. }