lz4_compression.cpp 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include <algorithm>
  4. #include <lz4hc.h>
  5. #include "common/assert.h"
  6. #include "common/lz4_compression.h"
  7. namespace Common::Compression {
  8. std::vector<u8> CompressDataLZ4(const u8* source, std::size_t source_size) {
  9. ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size");
  10. const auto source_size_int = static_cast<int>(source_size);
  11. const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int));
  12. std::vector<u8> compressed(max_compressed_size);
  13. const int compressed_size = LZ4_compress_default(
  14. reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()),
  15. source_size_int, static_cast<int>(max_compressed_size));
  16. if (compressed_size <= 0) {
  17. // Compression failed
  18. return {};
  19. }
  20. compressed.resize(static_cast<std::size_t>(compressed_size));
  21. return compressed;
  22. }
  23. std::vector<u8> CompressDataLZ4HC(const u8* source, std::size_t source_size,
  24. s32 compression_level) {
  25. ASSERT_MSG(source_size <= LZ4_MAX_INPUT_SIZE, "Source size exceeds LZ4 maximum input size");
  26. compression_level = std::clamp(compression_level, LZ4HC_CLEVEL_MIN, LZ4HC_CLEVEL_MAX);
  27. const auto source_size_int = static_cast<int>(source_size);
  28. const auto max_compressed_size = static_cast<std::size_t>(LZ4_compressBound(source_size_int));
  29. std::vector<u8> compressed(max_compressed_size);
  30. const int compressed_size = LZ4_compress_HC(
  31. reinterpret_cast<const char*>(source), reinterpret_cast<char*>(compressed.data()),
  32. source_size_int, static_cast<int>(max_compressed_size), compression_level);
  33. if (compressed_size <= 0) {
  34. // Compression failed
  35. return {};
  36. }
  37. compressed.resize(static_cast<std::size_t>(compressed_size));
  38. return compressed;
  39. }
  40. std::vector<u8> CompressDataLZ4HCMax(const u8* source, std::size_t source_size) {
  41. return CompressDataLZ4HC(source, source_size, LZ4HC_CLEVEL_MAX);
  42. }
  43. std::vector<u8> DecompressDataLZ4(std::span<const u8> compressed, std::size_t uncompressed_size) {
  44. std::vector<u8> uncompressed(uncompressed_size);
  45. const int size_check = LZ4_decompress_safe(reinterpret_cast<const char*>(compressed.data()),
  46. reinterpret_cast<char*>(uncompressed.data()),
  47. static_cast<int>(compressed.size()),
  48. static_cast<int>(uncompressed.size()));
  49. if (static_cast<int>(uncompressed_size) != size_check) {
  50. // Decompression failed
  51. return {};
  52. }
  53. return uncompressed;
  54. }
  55. int DecompressLZ4(void* dst, size_t dst_size, const void* src, size_t src_size) {
  56. // This is just a thin wrapper around LZ4.
  57. return LZ4_decompress_safe(reinterpret_cast<const char*>(src), reinterpret_cast<char*>(dst),
  58. static_cast<int>(src_size), static_cast<int>(dst_size));
  59. }
  60. } // namespace Common::Compression