alone_encoder.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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. struct lzma_coder_s {
  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. };
  24. static lzma_ret
  25. alone_encode(lzma_coder *coder,
  26. lzma_allocator *allocator lzma_attribute((__unused__)),
  27. const uint8_t *LZMA_RESTRICT in, size_t *LZMA_RESTRICT in_pos,
  28. size_t in_size, uint8_t *LZMA_RESTRICT out,
  29. size_t *LZMA_RESTRICT out_pos, size_t out_size,
  30. lzma_action action)
  31. {
  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(lzma_coder *coder, lzma_allocator *allocator)
  54. {
  55. lzma_next_end(&coder->next, allocator);
  56. lzma_free(coder, allocator);
  57. return;
  58. }
  59. // At least for now, this is not used by any internal function.
  60. static lzma_ret
  61. alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
  62. const lzma_options_lzma *options)
  63. {
  64. uint32_t d;
  65. // Initialize the LZMA encoder.
  66. const lzma_filter_info filters[2] = {
  67. { 0, &lzma_lzma_encoder_init, (void *)(options) },
  68. { 0, NULL, NULL }
  69. };
  70. lzma_next_coder_init(&alone_encoder_init, next, allocator);
  71. if (next->coder == NULL) {
  72. next->coder = lzma_alloc(sizeof(lzma_coder), allocator);
  73. if (next->coder == NULL)
  74. return LZMA_MEM_ERROR;
  75. next->code = &alone_encode;
  76. next->end = &alone_encoder_end;
  77. next->coder->next = LZMA_NEXT_CODER_INIT;
  78. }
  79. // Basic initializations
  80. next->coder->sequence = SEQ_HEADER;
  81. next->coder->header_pos = 0;
  82. // Encode the header:
  83. // - Properties (1 byte)
  84. if (lzma_lzma_lclppb_encode(options, next->coder->header))
  85. return LZMA_OPTIONS_ERROR;
  86. // - Dictionary size (4 bytes)
  87. if (options->dict_size < LZMA_DICT_SIZE_MIN)
  88. return LZMA_OPTIONS_ERROR;
  89. // Round up to the next 2^n or 2^n + 2^(n - 1) depending on which
  90. // one is the next unless it is UINT32_MAX. While the header would
  91. // allow any 32-bit integer, we do this to keep the decoder of liblzma
  92. // accepting the resulting files.
  93. d = options->dict_size - 1;
  94. d |= d >> 2;
  95. d |= d >> 3;
  96. d |= d >> 4;
  97. d |= d >> 8;
  98. d |= d >> 16;
  99. if (d != UINT32_MAX)
  100. ++d;
  101. unaligned_write32le(next->coder->header + 1, d);
  102. // - Uncompressed size (always unknown and using EOPM)
  103. memset(next->coder->header + 1 + 4, 0xFF, 8);
  104. return lzma_next_filter_init(&next->coder->next, allocator, filters);
  105. }
  106. /*
  107. extern lzma_ret
  108. lzma_alone_encoder_init(lzma_next_coder *next, lzma_allocator *allocator,
  109. const lzma_options_alone *options)
  110. {
  111. lzma_next_coder_init(&alone_encoder_init, next, allocator, options);
  112. }
  113. */
  114. extern LZMA_API(lzma_ret)
  115. lzma_alone_encoder(lzma_stream *strm, const lzma_options_lzma *options)
  116. {
  117. lzma_next_strm_init1(alone_encoder_init, strm, options);
  118. strm->internal->supported_actions[LZMA_RUN] = true;
  119. strm->internal->supported_actions[LZMA_FINISH] = true;
  120. return LZMA_OK;
  121. }