delta_decoder.c 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // SPDX-License-Identifier: 0BSD
  2. ///////////////////////////////////////////////////////////////////////////////
  3. //
  4. /// \file delta_decoder.c
  5. /// \brief Delta filter decoder
  6. //
  7. // Author: Lasse Collin
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "delta_decoder.h"
  11. #include "delta_private.h"
  12. static void
  13. decode_buffer(lzma_delta_coder *coder, uint8_t *buffer, size_t size)
  14. {
  15. const size_t distance = coder->distance;
  16. for (size_t i = 0; i < size; ++i) {
  17. buffer[i] += coder->history[(distance + coder->pos) & 0xFF];
  18. coder->history[coder->pos-- & 0xFF] = buffer[i];
  19. }
  20. }
  21. // For an unknown reason NVIDIA HPC Compiler needs this pragma
  22. // to produce working code.
  23. #ifdef __NVCOMPILER
  24. # pragma routine novector
  25. #endif
  26. static lzma_ret
  27. delta_decode(void *coder_ptr, const lzma_allocator *allocator,
  28. const uint8_t *restrict in, size_t *restrict in_pos,
  29. size_t in_size, uint8_t *restrict out,
  30. size_t *restrict out_pos, size_t out_size, lzma_action action)
  31. {
  32. lzma_delta_coder *coder = coder_ptr;
  33. assert(coder->next.code != NULL);
  34. const size_t out_start = *out_pos;
  35. const lzma_ret ret = coder->next.code(coder->next.coder, allocator,
  36. in, in_pos, in_size, out, out_pos, out_size,
  37. action);
  38. // out might be NULL. In that case size == 0. Null pointer + 0 is
  39. // undefined behavior so skip the call in that case as it would
  40. // do nothing anyway.
  41. const size_t size = *out_pos - out_start;
  42. if (size > 0)
  43. decode_buffer(coder, out + out_start, size);
  44. return ret;
  45. }
  46. extern lzma_ret
  47. lzma_delta_decoder_init(lzma_next_coder *next, const lzma_allocator *allocator,
  48. const lzma_filter_info *filters)
  49. {
  50. next->code = &delta_decode;
  51. return lzma_delta_coder_init(next, allocator, filters);
  52. }
  53. extern lzma_ret
  54. lzma_delta_props_decode(void **options, const lzma_allocator *allocator,
  55. const uint8_t *props, size_t props_size)
  56. {
  57. if (props_size != 1)
  58. return LZMA_OPTIONS_ERROR;
  59. lzma_options_delta *opt
  60. = lzma_alloc(sizeof(lzma_options_delta), allocator);
  61. if (opt == NULL)
  62. return LZMA_MEM_ERROR;
  63. opt->type = LZMA_DELTA_TYPE_BYTE;
  64. opt->dist = props[0] + 1U;
  65. *options = opt;
  66. return LZMA_OK;
  67. }