[+] Brotli [de]compressor
This commit is contained in:
parent
1ba0519d8d
commit
2745ef23a0
@ -21,7 +21,8 @@
|
||||
"glm",
|
||||
"bzip2",
|
||||
"liblzma",
|
||||
"lz4"
|
||||
"lz4",
|
||||
"brotli"
|
||||
],
|
||||
"depends": [
|
||||
"auROXTL",
|
||||
|
@ -17,6 +17,7 @@ namespace Aurora::Compression
|
||||
eZip,
|
||||
eGZip,
|
||||
eLZ4,
|
||||
eBZIP2
|
||||
eBZIP2,
|
||||
eBrotli
|
||||
));
|
||||
}
|
@ -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)
|
||||
|
@ -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:
|
||||
|
163
Source/Compression/Compressors/BrotliCompressor.hpp
Normal file
163
Source/Compression/Compressors/BrotliCompressor.hpp
Normal 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 {};
|
||||
};
|
||||
}
|
108
Source/Compression/Compressors/BrotliDecompressor.hpp
Normal file
108
Source/Compression/Compressors/BrotliDecompressor.hpp
Normal 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 {};
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user