add compression utils

This commit is contained in:
robert-yates
2025-01-11 16:32:44 +01:00
parent f9f980fbc5
commit c1d7fa7e8b
7 changed files with 133 additions and 0 deletions

5
.gitmodules vendored
View File

@@ -14,3 +14,8 @@
[submodule "deps/googletest"]
path = deps/googletest
url = https://github.com/google/googletest.git
[submodule "deps/zlib"]
path = deps/zlib
url = https://github.com/madler/zlib.git
branch = develop
ignore = dirty

1
deps/CMakeLists.txt vendored
View File

@@ -13,3 +13,4 @@ target_include_directories(reflect INTERFACE
include(mini-gdbstub.cmake)
include(googletest.cmake)
include(zlib.cmake)

1
deps/zlib vendored Submodule

Submodule deps/zlib added at ef24c4c750

4
deps/zlib.cmake vendored Normal file
View File

@@ -0,0 +1,4 @@
set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(zlib)
target_compile_definitions(zlibstatic PUBLIC ZLIB_CONST=1)
target_include_directories(zlibstatic PUBLIC ${zlib_SOURCE_DIR} ${zlib_BINARY_DIR})

View File

@@ -13,4 +13,5 @@ set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(emulator-common PUBLIC
Threads::Threads
zlibstatic
)

View File

@@ -0,0 +1,105 @@
#include "compression.hpp"
#include <zlib.h>
#include <cstring>
namespace utils::compression
{
namespace zlib
{
namespace
{
class zlib_stream
{
public:
zlib_stream()
{
memset(&stream_, 0, sizeof(stream_));
valid_ = inflateInit(&stream_) == Z_OK;
}
zlib_stream(zlib_stream&&) = delete;
zlib_stream(const zlib_stream&) = delete;
zlib_stream& operator=(zlib_stream&&) = delete;
zlib_stream& operator=(const zlib_stream&) = delete;
~zlib_stream()
{
if (valid_)
{
inflateEnd(&stream_);
}
}
z_stream& get()
{
return stream_; //
}
bool is_valid() const
{
return valid_;
}
private:
bool valid_{false};
z_stream stream_{};
};
}
std::vector<std::uint8_t> decompress(const std::vector<std::uint8_t>& data)
{
std::vector<std::uint8_t> buffer{};
zlib_stream stream_container{};
if (!stream_container.is_valid())
{
return {};
}
int ret{};
size_t offset = 0;
static thread_local uint8_t dest[CHUNK] = {0};
auto& stream = stream_container.get();
do
{
const auto input_size = std::min(sizeof(dest), data.size() - offset);
stream.avail_in = static_cast<uInt>(input_size);
stream.next_in = reinterpret_cast<const Bytef*>(data.data()) + offset;
offset += stream.avail_in;
do
{
stream.avail_out = sizeof(dest);
stream.next_out = dest;
ret = inflate(&stream, Z_NO_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END)
{
return {};
}
buffer.insert(buffer.end(), dest, dest + sizeof(dest) - stream.avail_out);
} while (stream.avail_out == 0);
} while (ret != Z_STREAM_END);
return buffer;
}
std::vector<std::uint8_t> compress(const std::vector<std::uint8_t>& data)
{
std::vector<std::uint8_t> result{};
auto length = compressBound(static_cast<uLong>(data.size()));
result.resize(length);
if (compress2(reinterpret_cast<Bytef*>(result.data()), &length, reinterpret_cast<const Bytef*>(data.data()),
static_cast<uLong>(data.size()), Z_BEST_COMPRESSION) != Z_OK)
{
return {};
}
result.resize(length);
return result;
}
}
}

View File

@@ -0,0 +1,16 @@
#pragma once
#include <string>
#include <vector>
#include <cstdint>
#define CHUNK 16384u
namespace utils::compression
{
namespace zlib
{
std::vector<std::uint8_t> compress(const std::vector<std::uint8_t>& data);
std::vector<std::uint8_t> decompress(const std::vector<std::uint8_t>& data);
}
};