Add functions to compress/decompress vector of bytes

pull/3186/head
elsid 3 years ago
parent 17f7a1a2ea
commit e5413c0664
No known key found for this signature in database
GPG Key ID: B845CB9FEE18AB40

@ -25,6 +25,7 @@ if (GTEST_FOUND AND GMOCK_FOUND)
misc/test_stringops.cpp
misc/test_endianness.cpp
misc/progressreporter.cpp
misc/compression.cpp
nifloader/testbulletnifloader.cpp

@ -0,0 +1,31 @@
#include <components/misc/compression.hpp>
#include <gtest/gtest.h>
#include <algorithm>
#include <cstdlib>
#include <cstring>
namespace
{
using namespace testing;
using namespace Misc;
TEST(MiscCompressionTest, compressShouldAddPrefixWithDataSize)
{
const std::vector<std::byte> data(1234);
const std::vector<std::byte> compressed = compress(data);
int size = 0;
std::memcpy(&size, compressed.data(), sizeof(size));
EXPECT_EQ(size, data.size());
}
TEST(MiscCompressionTest, decompressIsInverseToCompress)
{
const std::vector<std::byte> data(1024);
const std::vector<std::byte> compressed = compress(data);
EXPECT_LT(compressed.size(), data.size());
const std::vector<std::byte> decompressed = decompress(compressed);
EXPECT_EQ(decompressed, data);
}
}

@ -93,6 +93,7 @@ add_component_dir (esmterrain
add_component_dir (misc
constants utf8stream stringops resourcehelpers rng messageformatparser weakcache thread
compression
)
add_component_dir (debug

@ -0,0 +1,48 @@
#include "compression.hpp"
#include <lz4.h>
#include <cstddef>
#include <cstring>
#include <stdexcept>
#include <string>
#include <vector>
namespace Misc
{
std::vector<std::byte> compress(const std::vector<std::byte>& data)
{
const std::size_t originalSize = data.size();
std::vector<std::byte> result(static_cast<std::size_t>(LZ4_compressBound(static_cast<int>(originalSize)) + sizeof(originalSize)));
const int size = LZ4_compress_default(
reinterpret_cast<const char*>(data.data()),
reinterpret_cast<char*>(result.data()) + sizeof(originalSize),
static_cast<int>(data.size()),
static_cast<int>(result.size() - sizeof(originalSize))
);
if (size == 0)
throw std::runtime_error("Failed to compress");
std::memcpy(result.data(), &originalSize, sizeof(originalSize));
result.resize(static_cast<std::size_t>(size) + sizeof(originalSize));
return result;
}
std::vector<std::byte> decompress(const std::vector<std::byte>& data)
{
std::size_t originalSize;
std::memcpy(&originalSize, data.data(), sizeof(originalSize));
std::vector<std::byte> result(originalSize);
const int size = LZ4_decompress_safe(
reinterpret_cast<const char*>(data.data()) + sizeof(originalSize),
reinterpret_cast<char*>(result.data()),
static_cast<int>(data.size() - sizeof(originalSize)),
static_cast<int>(result.size())
);
if (size < 0)
throw std::runtime_error("Failed to decompress");
if (originalSize != static_cast<std::size_t>(size))
throw std::runtime_error("Size of decompressed data (" + std::to_string(size)
+ ") doesn't match stored (" + std::to_string(originalSize) + ")");
return result;
}
}

@ -0,0 +1,14 @@
#ifndef OPENMW_COMPONENTS_MISC_COMPRESSION_H
#define OPENMW_COMPONENTS_MISC_COMPRESSION_H
#include <cstddef>
#include <vector>
namespace Misc
{
std::vector<std::byte> compress(const std::vector<std::byte>& data);
std::vector<std::byte> decompress(const std::vector<std::byte>& data);
}
#endif
Loading…
Cancel
Save