alone_encoder.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. /// \file alone_decoder.c
  4. /// \brief Decoder 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,
  26. const lzma_allocator *allocator lzma_attribute((__unused__)),
  27. const uint8_t *restrict in, size_t *restrict in_pos,
  28. size_t in_size, uint8_t *restrict out,
  29. size_t *restrict out_pos, size_t out_size,
  30. lzma_action action)
  31. {
  32. lzma_alone_coder *coder = coder_ptr;
  33. while (*out_pos < out_size)
  34. switch (coder->sequence) {
  35. case SEQ_HEADER:
  36. lzma_bufcpy(coder->header, &coder->header_pos,
  37. ALONE_HEADER_SIZE,
  38. out, out_pos, out_size);
  39. if (coder->header_pos < ALONE_HEADER_SIZE)
  40. return LZMA_OK;
  41. coder->sequence = SEQ_CODE;
  42. break;
  43. case SEQ_CODE:
  44. return coder->next.code(coder->next.coder,
  45. allocator, in, in_pos, in_size,
  46. out, out_pos, out_size, action);
  47. default:
  48. assert(0);
  49. return LZMA_PROG_ERROR;
  50. }
  51. return LZMA_OK;
  52. }
  53. static void
  54. alone_encoder_end(void *coder_ptr, const lzma_allocator *allocator)
  55. {
  56. lzma_alone_coder *coder = coder_ptr;
  57. lzma_next_end(&coder->next, allocator);
  58. lzma_free(coder, allocator);
  59. return;
  60. }
  61. // At least for now, this is not used by any internal function.
  62. static lzma_ret
  63. alone_encoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
  64. const lzma_options_lzma *options)
  65. {
  66. lzma_next_coder_init(&alone_encoder_init, next, allocator);
  67. lzma_alone_coder *coder = next->coder;
  68. if (coder == NULL) {
  69. coder = lzma_alloc(sizeof(lzma_alone_coder), allocator);
  70. if (coder == NULL)
  71. return LZMA_MEM_ERROR;
  72. next->coder = coder;
  73. next->code = &alone_encode;
  74. next->end = &alone_encoder_end;
  75. coder->next = LZMA_NEXT_CODER_INIT;
  76. }
  77. // Basic initializations
  78. coder->sequence = SEQ_HEADER;
  79. coder->header_pos = 0;
  80. // Encode the header:
  81. // - Properties (1 byte)
  82. if (lzma_lzma_lclppb_encode(options, coder->header))
  83. return LZMA_OPTIONS_ERROR;
  84. // - Dictionary size (4 bytes)
  85. if (options->dict_size < LZMA_DICT_SIZE_MIN)
  86. return LZMA_OPTIONS_ERROR;
  87. // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
  88. // one is the next unless it is UINT32_MAX. While the header would
  89. // allow any 32-bit integer, we do this to keep the decoder of liblzma
  90. // accepting the resulting files.
  91. uint32_t d = options->dict_size - 1;
  92. d |= d >> 2;
  93. d |= d >> 3;
  94. d |= d >> 4;
  95. d |= d >> 8;
  96. d |= d >> 16;
  97. if (d != UINT32_MAX)
  98. ++d;
  99. unaligned_write32le(coder->header + 1, d);
  100. // - Uncompressed size (always unknown and using EOPM)
  101. memset(coder->header + 1 + 4, 0xFF, 8);
  102. // Initialize the LZMA encoder.
  103. const lzma_filter_info filters[2] = {
  104. {
  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. }