reduce allocations while reading chunks data

This commit is contained in:
MihailRis 2025-12-06 00:58:13 +03:00
parent 21f7390265
commit 9dc9441902
12 changed files with 93 additions and 43 deletions

View file

@ -85,12 +85,12 @@ std::unique_ptr<ubyte[]> compression::decompress(
throw std::invalid_argument("compression method is NONE");
case Method::EXTRLE8: {
auto decompressed = std::make_unique<ubyte[]>(dstlen);
extrle::decode(src, srclen, decompressed.get());
extrle::decode(src, srclen, decompressed.get(), dstlen);
return decompressed;
}
case Method::EXTRLE16: {
auto decompressed = std::make_unique<ubyte[]>(dstlen);
size_t decoded = extrle::decode16(src, srclen, decompressed.get());
size_t decoded = extrle::decode16(src, srclen, decompressed.get(), dstlen);
if (decoded != dstlen) {
throw std::runtime_error(
"expected decompressed size " + std::to_string(dstlen) +
@ -110,6 +110,39 @@ std::unique_ptr<ubyte[]> compression::decompress(
return decompressed;
}
default:
throw std::runtime_error("not implemented");
throw std::runtime_error("method not implemented");
}
}
void compression::decompress(const util::span<ubyte> src, ubyte* dst, size_t dstlen, Method method) {
switch (method) {
case Method::NONE:
throw std::invalid_argument("compression method is NONE");
case Method::EXTRLE8:
extrle::decode(src.data(), src.size(), dst, dstlen);
break;
case Method::EXTRLE16: {
size_t decoded =
extrle::decode16(src.data(), src.size(), dst, dstlen);
if (decoded != dstlen) {
throw std::runtime_error(
"expected decompressed size " + std::to_string(dstlen) +
" got " + std::to_string(decoded)
);
}
break;
}
case Method::GZIP: {
auto buffer = gzip::decompress(src.data(), src.size());
if (buffer.size() != dstlen) {
throw std::runtime_error(
"expected decompressed size " + std::to_string(dstlen) +
" got " + std::to_string(buffer.size())
);
}
std::memcpy(dst, buffer.data(), buffer.size());
}
default:
throw std::runtime_error("method not implemented");
}
}

View file

@ -3,6 +3,7 @@
#include <memory>
#include "typedefs.hpp"
#include "util/span.hpp"
namespace compression {
enum class Method {
@ -27,4 +28,8 @@ namespace compression {
/// @return decompressed bytes array
std::unique_ptr<ubyte[]> decompress(
const ubyte* src, size_t srclen, size_t dstlen, Method method);
void decompress(
const util::span<ubyte> src, ubyte* dst, size_t dstlen, Method method
);
}

View file

@ -1,12 +1,17 @@
#include "rle.hpp"
#include <stdexcept>
#include "util/data_io.hpp"
size_t rle::decode(const ubyte* src, size_t srclen, ubyte* dst) {
size_t rle::decode(const ubyte* src, size_t srclen, ubyte* dst, size_t dstLength) {
size_t offset = 0;
for (size_t i = 0; i < srclen;) {
ubyte len = src[i++];
ubyte c = src[i++];
if (offset + len >= dstLength) {
throw std::runtime_error("buffer overflow");
}
for (size_t j = 0; j <= len; j++) {
dst[offset++] = c;
}
@ -37,13 +42,16 @@ size_t rle::encode(const ubyte* src, size_t srclen, ubyte* dst) {
return offset;
}
size_t rle::decode16(const ubyte* src, size_t srclen, ubyte* dst) {
size_t rle::decode16(const ubyte* src, size_t srclen, ubyte* dst, size_t dstLength) {
auto src16 = reinterpret_cast<const uint16_t*>(src);
auto dst16 = reinterpret_cast<uint16_t*>(dst);
size_t offset = 0;
for (size_t i = 0; i < srclen / 2;) {
uint16_t len = dataio::le2h(src16[i++]);
uint16_t c = dataio::le2h(src16[i++]);
if (offset + len >= dstLength) {
throw std::runtime_error("buffer overflow");
}
for (size_t j = 0; j <= len; j++) {
dst16[offset++] = c;
}
@ -76,7 +84,7 @@ size_t rle::encode16(const ubyte* src, size_t srclen, ubyte* dst) {
return offset * 2;
}
size_t extrle::decode(const ubyte* src, size_t srclen, ubyte* dst) {
size_t extrle::decode(const ubyte* src, size_t srclen, ubyte* dst, size_t dstLength) {
size_t offset = 0;
for (size_t i = 0; i < srclen;) {
uint len = src[i++];
@ -85,6 +93,9 @@ size_t extrle::decode(const ubyte* src, size_t srclen, ubyte* dst) {
len |= (static_cast<uint>(src[i++])) << 7;
}
ubyte c = src[i++];
if (offset + len >= dstLength) {
throw std::runtime_error("buffer overflow");
}
for (size_t j = 0; j <= len; j++) {
dst[offset++] = c;
}
@ -125,7 +136,7 @@ size_t extrle::encode(const ubyte* src, size_t srclen, ubyte* dst) {
return offset;
}
size_t extrle::decode16(const ubyte* src, size_t srclen, ubyte* dst8) {
size_t extrle::decode16(const ubyte* src, size_t srclen, ubyte* dst8, size_t dstLength) {
auto dst = reinterpret_cast<uint16_t*>(dst8);
size_t offset = 0;
for (size_t i = 0; i < srclen;) {
@ -141,6 +152,9 @@ size_t extrle::decode16(const ubyte* src, size_t srclen, ubyte* dst8) {
if (widechar) {
c |= ((static_cast<uint>(src[i++])) << 8);
}
if (offset + len >= dstLength) {
throw std::runtime_error("buffer overflow");
}
for (size_t j = 0; j <= len; j++) {
dst[offset++] = c;
}

View file

@ -4,18 +4,18 @@
namespace rle {
size_t encode(const ubyte* src, size_t length, ubyte* dst);
size_t decode(const ubyte* src, size_t length, ubyte* dst);
size_t decode(const ubyte* src, size_t length, ubyte* dst, size_t dstLength);
size_t encode16(const ubyte* src, size_t length, ubyte* dst);
size_t decode16(const ubyte* src, size_t length, ubyte* dst);
size_t decode16(const ubyte* src, size_t length, ubyte* dst, size_t dstLength);
}
namespace extrle {
constexpr uint max_sequence = 0x7FFF;
size_t encode(const ubyte* src, size_t length, ubyte* dst);
size_t decode(const ubyte* src, size_t length, ubyte* dst);
size_t decode(const ubyte* src, size_t length, ubyte* dst, size_t dstLength);
constexpr uint max_sequence16 = 0x3FFF;
size_t encode16(const ubyte* src, size_t length, ubyte* dst);
size_t decode16(const ubyte* src, size_t length, ubyte* dst);
size_t decode16(const ubyte* src, size_t length, ubyte* dst, size_t dstLength);
}