[+] Brotli [de]compressor

This commit is contained in:
Reece Wilson 2023-03-12 21:03:47 +00:00
parent 1ba0519d8d
commit 2745ef23a0
6 changed files with 294 additions and 3 deletions

View File

@ -21,7 +21,8 @@
"glm",
"bzip2",
"liblzma",
"lz4"
"lz4",
"brotli"
],
"depends": [
"auROXTL",

View File

@ -17,6 +17,7 @@ namespace Aurora::Compression
eZip,
eGZip,
eLZ4,
eBZIP2
eBZIP2,
eBrotli
));
}

View File

@ -26,6 +26,10 @@
#include "Compressors/BZip2Compressor.hpp"
#endif
#if defined(_AUHAS_BROTLI)
#include "Compressors/BrotliCompressor.hpp"
#endif
namespace Aurora::Compression
{
AUKN_SYM ICompressionStream *CompressorNew(const AuSPtr<IO::IStreamReader> &pReader, const CompressInfo &ref)
@ -54,7 +58,12 @@ namespace Aurora::Compression
#endif
#if defined(_AUHAS_LZ4)
case ECompressionType::eLZ4:
pRet = new LZ4Deflate(info);
pRet = _new LZ4Deflate(info);
break;
#endif
#if defined(_AUHAS_BROTLI)
case ECompressionType::eBrotli:
pRet = _new BrotliDeflate(info);
break;
#endif
#if defined(_AUHAS_ZLIB)

View File

@ -26,6 +26,10 @@
#include "Compressors/BZip2Decompressor.hpp"
#endif
#if defined(_AUHAS_BROTLI)
#include "Compressors/BrotliDecompressor.hpp"
#endif
namespace Aurora::Compression
{
AUKN_SYM ICompressionStream *DecompressorNew(const AuSPtr<IO::IStreamReader> &pReader, const DecompressInfo &ref)
@ -58,6 +62,11 @@ namespace Aurora::Compression
pRet = _new LZ4Inflate(info);
break;
#endif
#if defined(_AUHAS_BROTLI)
case ECompressionType::eBrotli:
pRet = _new BrotliInflate(info);
break;
#endif
#if defined(_AUHAS_ZLIB)
case ECompressionType::eDeflate:
case ECompressionType::eZip:

View File

@ -0,0 +1,163 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: BrotliCompressor.hpp
Date: 2023-3-12
Author: Reece
***/
#pragma once
#include "brotli/encode.h"
namespace Aurora::Compression
{
struct BrotliDeflate : BaseStream
{
CompressInfo meta;
BrotliDeflate(const CompressInfo &meta) : meta(meta), BaseStream(meta.uInternalStreamSize)
{ }
~BrotliDeflate()
{
if (this->pState)
{
BrotliEncoderDestroyInstance(this->pState);
}
}
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
{
this->pReader_ = reader;
if (!this->IsValid())
{
SysPushErrorMem();
return false;
}
this->pState = BrotliEncoderCreateInstance(nullptr, nullptr, nullptr);
if (!this->pState)
{
SysPushErrorMem("No brotli encoder");
return false;
}
this->SetArray(this->din_);
return true;
}
AuStreamReadWrittenPair_t Ingest_s(AuUInt32 input) override
{
AuUInt32 done {}, read {};
if (!this->pReader_)
{
return {};
}
if (!this->pState)
{
return {};
}
while (read < input)
{
read += IngestForInPointer<uint8_t, size_t>(this->pReader_, this->pInBuffer, this->uAvailIn, input - read);
if (!this->uAvailIn)
{
return { read, done };
}
size_t outNext {};
uint8_t *pOut {};
do
{
outNext = AuArraySize(this->dout_);
pOut = this->dout_;
auto ret = BrotliEncoderCompressStream(this->pState, BrotliEncoderOperation::BROTLI_OPERATION_PROCESS, &this->uAvailIn, (const uint8_t **) & this->pInBuffer, &outNext, &pOut, nullptr);
if (ret == BROTLI_FALSE)
{
SysPushErrorIO("Brotli Error");
this->pReader_.reset();
return AuMakePair(read, 0);
}
auto have = AuArraySize(this->dout_) - outNext;
done += have;
if (!Write(reinterpret_cast<const AuUInt8 *>(this->dout_), have))
{
this->pReader_.reset();
SysPushErrorIO("Compression Out of Overhead");
return AuMakePair(read, 0);
}
}
while (outNext == 0 || BrotliEncoderHasMoreOutput(this->pState));
}
return { read, done };
}
bool Flush() override
{
return RunFlush(BrotliEncoderOperation::BROTLI_OPERATION_FLUSH);
}
bool Finish() override
{
return RunFlush(BrotliEncoderOperation::BROTLI_OPERATION_FINISH);
}
bool RunFlush(BrotliEncoderOperation type)
{
if (!this->pReader_)
{
return false;
}
if (!this->pState)
{
return false;
}
AuUInt read {};
{
size_t outNext {};
uint8_t *pOut {};
while (outNext == 0 || BrotliEncoderHasMoreOutput(this->pState));
{
outNext = AuArraySize(this->dout_);
pOut = this->dout_;
auto ret = BrotliEncoderCompressStream(this->pState, type, &this->uAvailIn, (const uint8_t **)&this->pInBuffer, &outNext, &pOut, nullptr);
if (ret == BROTLI_FALSE)
{
SysPushErrorIO("Brotli Error");
this->pReader_.reset();
return false;
}
auto have = AuArraySize(this->dout_) - outNext;
if (!Write(reinterpret_cast<const AuUInt8 *>(this->dout_), have))
{
this->pReader_.reset();
SysPushErrorIO("Compression Out of Overhead");
return false;
}
}
}
return true;
}
private:
AuSPtr<IO::IStreamReader> pReader_;
unsigned char din_[kChunkSize];
unsigned char dout_[kChunkSize];
uint8_t *pInBuffer;
size_t uAvailIn {};
BrotliEncoderState *pState {};
};
}

View File

@ -0,0 +1,108 @@
/***
Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: BrotliDecompressor.hpp
Date: 2023-3-12
Author: Reece
***/
#pragma once
#include "brotli/decode.h"
namespace Aurora::Compression
{
struct BrotliInflate : BaseStream
{
DecompressInfo meta;
BrotliInflate(const DecompressInfo &meta) : meta(meta), BaseStream(meta.uInternalStreamSize)
{ }
~BrotliInflate()
{
if (this->pState)
{
BrotliDecoderDestroyInstance(this->pState);
}
}
bool Init(const AuSPtr<IO::IStreamReader> &reader) override
{
int ret;
this->pReader_ = reader;
if (!this->IsValid())
{
SysPushErrorMem();
return false;
}
this->pState = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
if (!this->pState)
{
SysPushErrorMem("No brotli decoder");
return false;
}
this->SetArray(this->din_);
return true;
}
AuStreamReadWrittenPair_t Ingest_s(AuUInt32 input) override
{
AuUInt32 done {}, read {};
if (!this->pReader_)
{
return {};
}
while (read < input)
{
read += IngestForInPointer<uint8_t, size_t>(this->pReader_, this->pInBuffer, this->uAvailIn, input - read);
if (!this->uAvailIn)
{
return { read, done };
}
size_t outNext {};
uint8_t *pOut {};
do
{
outNext = AuArraySize(this->dout_);
pOut = this->dout_;
auto ret = BrotliDecoderDecompressStream(this->pState, &this->uAvailIn, (const uint8_t **)&this->pInBuffer, &outNext, &pOut, nullptr);
if (ret == BROTLI_DECODER_RESULT_ERROR)
{
SysPushErrorIO("Brotli Error");
this->pReader_.reset();
return AuMakePair(read, 0);
}
auto have = AuArraySize(this->dout_) - outNext;
done += have;
if (!Write(reinterpret_cast<const AuUInt8 *>(this->dout_), have))
{
this->pReader_.reset();
SysPushErrorIO("Compression Out of Overhead");
return AuMakePair(read, 0);
}
}
while (outNext == 0);
}
return { read, done };
}
private:
AuSPtr<IO::IStreamReader> pReader_;
unsigned char din_[kChunkSize];
unsigned char dout_[kChunkSize];
uint8_t *pInBuffer;
size_t uAvailIn {};
BrotliDecoderState *pState {};
};
}