Add B[Zlib]CompressionAlgorithm
* BCompressionAlgorithm is a base class for classes that provide compression/decompression functionality. There are methods for compressing/decompressing a single buffer and factory methods for a compressing/decompressing input/output BDataIO. * BZlibCompressionAlgorithm is a BCompressionAlgorithm implementation using zlib.
This commit is contained in:
parent
6a89a36aa0
commit
dcdc33b0af
1
headers/build/private/support/CompressionAlgorithm.h
Normal file
1
headers/build/private/support/CompressionAlgorithm.h
Normal file
@ -0,0 +1 @@
|
||||
#include <../private/support/CompressionAlgorithm.h>
|
1
headers/build/private/support/ZlibCompressionAlgorithm.h
Normal file
1
headers/build/private/support/ZlibCompressionAlgorithm.h
Normal file
@ -0,0 +1 @@
|
||||
#include <../private/support/ZlibCompressionAlgorithm.h>
|
121
headers/private/support/CompressionAlgorithm.h
Normal file
121
headers/private/support/CompressionAlgorithm.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _COMPRESSION_ALGORITHM_H_
|
||||
#define _COMPRESSION_ALGORITHM_H_
|
||||
|
||||
|
||||
#include <DataIO.h>
|
||||
|
||||
|
||||
class BCompressionParameters {
|
||||
public:
|
||||
BCompressionParameters();
|
||||
virtual ~BCompressionParameters();
|
||||
};
|
||||
|
||||
|
||||
class BDecompressionParameters {
|
||||
public:
|
||||
BDecompressionParameters();
|
||||
virtual ~BDecompressionParameters();
|
||||
};
|
||||
|
||||
|
||||
class BCompressionAlgorithm {
|
||||
public:
|
||||
BCompressionAlgorithm();
|
||||
virtual ~BCompressionAlgorithm();
|
||||
|
||||
virtual status_t CreateCompressingInputStream(BDataIO* input,
|
||||
const BCompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateCompressingOutputStream(BDataIO* output,
|
||||
const BCompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateDecompressingInputStream(BDataIO* input,
|
||||
const BDecompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateDecompressingOutputStream(BDataIO* output,
|
||||
const BDecompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
|
||||
virtual status_t CompressBuffer(const void* input,
|
||||
size_t inputSize, void* output,
|
||||
size_t outputSize, size_t& _compressedSize,
|
||||
const BCompressionParameters* parameters
|
||||
= NULL);
|
||||
virtual status_t DecompressBuffer(const void* input,
|
||||
size_t inputSize, void* output,
|
||||
size_t outputSize,
|
||||
size_t& _uncompressedSize,
|
||||
const BDecompressionParameters* parameters
|
||||
= NULL);
|
||||
|
||||
protected:
|
||||
class BAbstractStream;
|
||||
class BAbstractInputStream;
|
||||
class BAbstractOutputStream;
|
||||
};
|
||||
|
||||
|
||||
class BCompressionAlgorithm::BAbstractStream : public BDataIO {
|
||||
public:
|
||||
BAbstractStream();
|
||||
virtual ~BAbstractStream();
|
||||
|
||||
status_t Init(size_t bufferSize);
|
||||
|
||||
protected:
|
||||
virtual status_t ProcessData(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize,
|
||||
size_t& bytesConsumed,
|
||||
size_t& bytesProduced) = 0;
|
||||
// must consume or produce at least 1 byte
|
||||
// or return an error
|
||||
virtual status_t FlushPendingData(void* output,
|
||||
size_t outputSize,
|
||||
size_t& bytesProduced) = 0;
|
||||
|
||||
protected:
|
||||
uint8* fBuffer;
|
||||
size_t fBufferCapacity;
|
||||
size_t fBufferOffset;
|
||||
size_t fBufferSize;
|
||||
};
|
||||
|
||||
|
||||
class BCompressionAlgorithm::BAbstractInputStream : public BAbstractStream {
|
||||
public:
|
||||
BAbstractInputStream(BDataIO* input);
|
||||
virtual ~BAbstractInputStream();
|
||||
|
||||
virtual ssize_t Read(void* buffer, size_t size);
|
||||
|
||||
private:
|
||||
BDataIO* fInput;
|
||||
bool fEndOfInput;
|
||||
bool fNoMorePendingData;
|
||||
};
|
||||
|
||||
|
||||
class BCompressionAlgorithm::BAbstractOutputStream : public BAbstractStream {
|
||||
public:
|
||||
BAbstractOutputStream(BDataIO* output);
|
||||
virtual ~BAbstractOutputStream();
|
||||
|
||||
virtual ssize_t Write(const void* buffer, size_t size);
|
||||
|
||||
virtual status_t Flush();
|
||||
|
||||
private:
|
||||
ssize_t _Write(const void* buffer, size_t size,
|
||||
bool flush);
|
||||
|
||||
private:
|
||||
BDataIO* fOutput;
|
||||
};
|
||||
|
||||
|
||||
#endif // _COMPRESSION_ALGORITHM_H_
|
96
headers/private/support/ZlibCompressionAlgorithm.h
Normal file
96
headers/private/support/ZlibCompressionAlgorithm.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _ZLIB_COMPRESSION_ALGORITHM_H_
|
||||
#define _ZLIB_COMPRESSION_ALGORITHM_H_
|
||||
|
||||
|
||||
#include <CompressionAlgorithm.h>
|
||||
|
||||
|
||||
// compression level
|
||||
enum {
|
||||
B_ZLIB_COMPRESSION_NONE = 0,
|
||||
B_ZLIB_COMPRESSION_FASTEST = 1,
|
||||
B_ZLIB_COMPRESSION_BEST = 9,
|
||||
B_ZLIB_COMPRESSION_DEFAULT = -1,
|
||||
};
|
||||
|
||||
|
||||
class BZlibCompressionParameters : public BCompressionParameters {
|
||||
public:
|
||||
BZlibCompressionParameters(
|
||||
int compressionLevel
|
||||
= B_ZLIB_COMPRESSION_DEFAULT);
|
||||
virtual ~BZlibCompressionParameters();
|
||||
|
||||
int32 CompressionLevel() const;
|
||||
void SetCompressionLevel(int32 level);
|
||||
|
||||
size_t BufferSize() const;
|
||||
void SetBufferSize(size_t size);
|
||||
|
||||
private:
|
||||
int32 fCompressionLevel;
|
||||
size_t fBufferSize;
|
||||
};
|
||||
|
||||
|
||||
class BZlibDecompressionParameters : public BDecompressionParameters {
|
||||
public:
|
||||
BZlibDecompressionParameters();
|
||||
virtual ~BZlibDecompressionParameters();
|
||||
|
||||
size_t BufferSize() const;
|
||||
void SetBufferSize(size_t size);
|
||||
|
||||
private:
|
||||
size_t fBufferSize;
|
||||
};
|
||||
|
||||
|
||||
class BZlibCompressionAlgorithm : public BCompressionAlgorithm {
|
||||
public:
|
||||
BZlibCompressionAlgorithm();
|
||||
virtual ~BZlibCompressionAlgorithm();
|
||||
|
||||
virtual status_t CreateCompressingInputStream(BDataIO* input,
|
||||
const BCompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateCompressingOutputStream(BDataIO* output,
|
||||
const BCompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateDecompressingInputStream(BDataIO* input,
|
||||
const BDecompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
virtual status_t CreateDecompressingOutputStream(BDataIO* output,
|
||||
const BDecompressionParameters* parameters,
|
||||
BDataIO*& _stream);
|
||||
|
||||
virtual status_t CompressBuffer(const void* input,
|
||||
size_t inputSize, void* output,
|
||||
size_t outputSize, size_t& _compressedSize,
|
||||
const BCompressionParameters* parameters
|
||||
= NULL);
|
||||
virtual status_t DecompressBuffer(const void* input,
|
||||
size_t inputSize, void* output,
|
||||
size_t outputSize,
|
||||
size_t& _uncompressedSize,
|
||||
const BDecompressionParameters* parameters
|
||||
= NULL);
|
||||
|
||||
private:
|
||||
struct CompressionStrategy;
|
||||
struct DecompressionStrategy;
|
||||
|
||||
template<typename BaseClass, typename Strategy> struct Stream;
|
||||
template<typename BaseClass, typename Strategy>
|
||||
friend struct Stream;
|
||||
|
||||
private:
|
||||
static status_t _TranslateZlibError(int error);
|
||||
};
|
||||
|
||||
|
||||
#endif // _ZLIB_COMPRESSION_ALGORITHM_H_
|
@ -10,6 +10,7 @@ BuildPlatformMergeObjectPIC <libbe_build>support_kit.o :
|
||||
Archivable.cpp
|
||||
BlockCache.cpp
|
||||
ByteOrder.cpp
|
||||
CompressionAlgorithm.cpp
|
||||
DataIO.cpp
|
||||
Flattenable.cpp
|
||||
List.cpp
|
||||
@ -18,6 +19,7 @@ BuildPlatformMergeObjectPIC <libbe_build>support_kit.o :
|
||||
Referenceable.cpp
|
||||
String.cpp
|
||||
StringList.cpp
|
||||
ZlibCompressionAlgorithm.cpp
|
||||
ZlibCompressionBase.cpp
|
||||
ZlibCompressor.cpp
|
||||
ZlibDecompressor.cpp
|
||||
|
328
src/kits/support/CompressionAlgorithm.cpp
Normal file
328
src/kits/support/CompressionAlgorithm.cpp
Normal file
@ -0,0 +1,328 @@
|
||||
/*
|
||||
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <CompressionAlgorithm.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Errors.h>
|
||||
|
||||
|
||||
// #pragma mark - BCompressionParameters
|
||||
|
||||
|
||||
BCompressionParameters::BCompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCompressionParameters::~BCompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BDecompressionParameters
|
||||
|
||||
|
||||
BDecompressionParameters::BDecompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BDecompressionParameters::~BDecompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BCompressionAlgorithm
|
||||
|
||||
|
||||
BCompressionAlgorithm::BCompressionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCompressionAlgorithm::~BCompressionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::CreateCompressingInputStream(BDataIO* input,
|
||||
const BCompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::CreateCompressingOutputStream(BDataIO* output,
|
||||
const BCompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::CreateDecompressingInputStream(BDataIO* input,
|
||||
const BDecompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
|
||||
const BDecompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::CompressBuffer(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize, size_t& _compressedSize,
|
||||
const BCompressionParameters* parameters)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::DecompressBuffer(const void* input,
|
||||
size_t inputSize, void* output, size_t outputSize,
|
||||
size_t& _uncompressedSize, const BDecompressionParameters* parameters)
|
||||
{
|
||||
return B_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BAbstractStream
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractStream::BAbstractStream()
|
||||
:
|
||||
BDataIO(),
|
||||
fBuffer(NULL),
|
||||
fBufferCapacity(0),
|
||||
fBufferOffset(0),
|
||||
fBufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractStream::~BAbstractStream()
|
||||
{
|
||||
free(fBuffer);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::BAbstractStream::Init(size_t bufferSize)
|
||||
{
|
||||
fBuffer = (uint8*)malloc(bufferSize);
|
||||
fBufferCapacity = bufferSize;
|
||||
|
||||
return fBuffer != NULL ? B_OK : B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BAbstractInputStream
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractInputStream::BAbstractInputStream(
|
||||
BDataIO* input)
|
||||
:
|
||||
BAbstractStream(),
|
||||
fInput(input),
|
||||
fEndOfInput(false),
|
||||
fNoMorePendingData(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractInputStream::~BAbstractInputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BCompressionAlgorithm::BAbstractInputStream::Read(void* buffer, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
size_t bytesRemaining = size;
|
||||
uint8* output = (uint8*)buffer;
|
||||
|
||||
while (bytesRemaining > 0) {
|
||||
// process the data still in the input buffer
|
||||
if (fBufferSize > 0) {
|
||||
size_t bytesConsumed;
|
||||
size_t bytesProduced;
|
||||
status_t error = ProcessData(fBuffer + fBufferOffset, fBufferSize,
|
||||
output, bytesRemaining, bytesConsumed, bytesProduced);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fBufferOffset += bytesConsumed;
|
||||
fBufferSize -= bytesConsumed;
|
||||
output += bytesProduced;
|
||||
bytesRemaining -= bytesProduced;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We couldn't process anything, because we don't have any or not enough
|
||||
// bytes in the input buffer.
|
||||
|
||||
if (fEndOfInput)
|
||||
break;
|
||||
|
||||
// Move any remaining data to the start of the buffer.
|
||||
if (fBufferSize > 0) {
|
||||
if (fBufferSize == fBufferCapacity)
|
||||
return B_ERROR;
|
||||
|
||||
if (fBufferOffset > 0)
|
||||
memmove(fBuffer, fBuffer + fBufferOffset, fBufferSize);
|
||||
}
|
||||
|
||||
fBufferOffset = 0;
|
||||
|
||||
// read from the source
|
||||
ssize_t bytesRead = fInput->Read(fBuffer + fBufferSize,
|
||||
fBufferCapacity - fBufferSize);
|
||||
if (bytesRead < 0)
|
||||
return bytesRead;
|
||||
if (bytesRead == 0) {
|
||||
fEndOfInput = true;
|
||||
break;
|
||||
}
|
||||
|
||||
fBufferSize += bytesRead;
|
||||
}
|
||||
|
||||
// If we've reached the end of the input and still have room in the output
|
||||
// buffer, we have consumed all input data and want to flush all pending
|
||||
// data, now.
|
||||
if (fEndOfInput && bytesRemaining > 0 && !fNoMorePendingData) {
|
||||
size_t bytesProduced;
|
||||
status_t error = FlushPendingData(output, bytesRemaining,
|
||||
bytesProduced);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
if (bytesProduced < bytesRemaining)
|
||||
fNoMorePendingData = true;
|
||||
|
||||
output += bytesProduced;
|
||||
bytesRemaining -= bytesProduced;
|
||||
}
|
||||
|
||||
return size - bytesRemaining;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BAbstractOutputStream
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractOutputStream::BAbstractOutputStream(
|
||||
BDataIO* output)
|
||||
:
|
||||
BAbstractStream(),
|
||||
fOutput(output)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BCompressionAlgorithm::BAbstractOutputStream::~BAbstractOutputStream()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ssize_t
|
||||
BCompressionAlgorithm::BAbstractOutputStream::Write(const void* buffer,
|
||||
size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
size_t bytesRemaining = size;
|
||||
uint8* input = (uint8*)buffer;
|
||||
|
||||
while (bytesRemaining > 0) {
|
||||
// try to process more data
|
||||
if (fBufferSize < fBufferCapacity) {
|
||||
size_t bytesConsumed;
|
||||
size_t bytesProduced;
|
||||
status_t error = ProcessData(input, bytesRemaining,
|
||||
fBuffer + fBufferSize, fBufferCapacity - fBufferSize,
|
||||
bytesConsumed, bytesProduced);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
input += bytesConsumed;
|
||||
bytesRemaining -= bytesConsumed;
|
||||
fBufferSize += bytesProduced;
|
||||
continue;
|
||||
}
|
||||
|
||||
// We couldn't process anything, because we don't have any or not enough
|
||||
// room in the output buffer.
|
||||
|
||||
if (fBufferSize == 0)
|
||||
return B_ERROR;
|
||||
|
||||
// write to the target
|
||||
ssize_t bytesWritten = fOutput->Write(fBuffer, fBufferSize);
|
||||
if (bytesWritten < 0)
|
||||
return bytesWritten;
|
||||
if (bytesWritten == 0)
|
||||
break;
|
||||
|
||||
// Move any remaining data to the start of the buffer.
|
||||
fBufferSize -= bytesWritten;
|
||||
if (fBufferSize > 0)
|
||||
memmove(fBuffer, fBuffer + bytesWritten, fBufferSize);
|
||||
}
|
||||
|
||||
return size - bytesRemaining;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BCompressionAlgorithm::BAbstractOutputStream::Flush()
|
||||
{
|
||||
bool noMorePendingData = false;
|
||||
|
||||
for (;;) {
|
||||
// let the derived class flush all pending data
|
||||
if (fBufferSize < fBufferCapacity && !noMorePendingData) {
|
||||
size_t bytesProduced;
|
||||
status_t error = FlushPendingData(fBuffer + fBufferSize,
|
||||
fBufferCapacity - fBufferSize, bytesProduced);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
noMorePendingData = bytesProduced < fBufferCapacity - fBufferSize;
|
||||
|
||||
fBufferSize += bytesProduced;
|
||||
}
|
||||
|
||||
// write buffered data to output
|
||||
if (fBufferSize == 0)
|
||||
break;
|
||||
|
||||
status_t error = fOutput->WriteExactly(fBuffer, fBufferSize);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
fBufferSize = 0;
|
||||
}
|
||||
|
||||
return fOutput->Flush();
|
||||
}
|
@ -24,6 +24,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
BufferedDataIO.cpp
|
||||
BufferIO.cpp
|
||||
ByteOrder.cpp
|
||||
CompressionAlgorithm.cpp
|
||||
DataIO.cpp
|
||||
DateTime.cpp
|
||||
Flattenable.cpp
|
||||
@ -36,6 +37,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
|
||||
StringList.cpp
|
||||
Url.cpp
|
||||
Uuid.cpp
|
||||
ZlibCompressionAlgorithm.cpp
|
||||
ZlibCompressionBase.cpp
|
||||
ZlibCompressor.cpp
|
||||
ZlibDecompressor.cpp
|
||||
|
407
src/kits/support/ZlibCompressionAlgorithm.cpp
Normal file
407
src/kits/support/ZlibCompressionAlgorithm.cpp
Normal file
@ -0,0 +1,407 @@
|
||||
/*
|
||||
* Copyright 2014, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <ZlibCompressionAlgorithm.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include <DataIO.h>
|
||||
|
||||
|
||||
// build compression support only for userland
|
||||
#if !defined(_KERNEL_MODE) && !defined(_BOOT_MODE)
|
||||
# define B_ZLIB_COMPRESSION_SUPPORT 1
|
||||
#endif
|
||||
|
||||
|
||||
static const size_t kMinBufferSize = 1024;
|
||||
static const size_t kMaxBufferSize = 1024 * 1024;
|
||||
static const size_t kDefaultBufferSize = 4 * 1024;
|
||||
|
||||
|
||||
static size_t
|
||||
sanitize_buffer_size(size_t size)
|
||||
{
|
||||
if (size < kMinBufferSize)
|
||||
return kMinBufferSize;
|
||||
return std::min(size, kMaxBufferSize);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BZlibCompressionParameters
|
||||
|
||||
|
||||
BZlibCompressionParameters::BZlibCompressionParameters(
|
||||
int compressionLevel)
|
||||
:
|
||||
BCompressionParameters(),
|
||||
fCompressionLevel(compressionLevel),
|
||||
fBufferSize(kDefaultBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BZlibCompressionParameters::~BZlibCompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int32
|
||||
BZlibCompressionParameters::CompressionLevel() const
|
||||
{
|
||||
return fCompressionLevel;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BZlibCompressionParameters::SetCompressionLevel(int32 level)
|
||||
{
|
||||
fCompressionLevel = level;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BZlibCompressionParameters::BufferSize() const
|
||||
{
|
||||
return fBufferSize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BZlibCompressionParameters::SetBufferSize(size_t size)
|
||||
{
|
||||
fBufferSize = sanitize_buffer_size(size);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - BZlibDecompressionParameters
|
||||
|
||||
|
||||
BZlibDecompressionParameters::BZlibDecompressionParameters()
|
||||
:
|
||||
BDecompressionParameters(),
|
||||
fBufferSize(kDefaultBufferSize)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BZlibDecompressionParameters::~BZlibDecompressionParameters()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
BZlibDecompressionParameters::BufferSize() const
|
||||
{
|
||||
return fBufferSize;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BZlibDecompressionParameters::SetBufferSize(size_t size)
|
||||
{
|
||||
fBufferSize = sanitize_buffer_size(size);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - CompressionStrategy
|
||||
|
||||
|
||||
#ifdef B_ZLIB_COMPRESSION_SUPPORT
|
||||
|
||||
|
||||
struct BZlibCompressionAlgorithm::CompressionStrategy {
|
||||
typedef BZlibCompressionParameters Parameters;
|
||||
|
||||
static const bool kNeedsFinalFlush = true;
|
||||
|
||||
static int Init(z_stream& stream,
|
||||
const BZlibCompressionParameters* parameters)
|
||||
{
|
||||
return deflateInit(&stream,
|
||||
parameters != NULL
|
||||
? parameters->CompressionLevel()
|
||||
: B_ZLIB_COMPRESSION_DEFAULT);
|
||||
}
|
||||
|
||||
static void Uninit(z_stream& stream)
|
||||
{
|
||||
deflateEnd(&stream);
|
||||
}
|
||||
|
||||
static int Process(z_stream& stream, bool flush)
|
||||
{
|
||||
return deflate(&stream, flush ? Z_FINISH : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif // B_ZLIB_COMPRESSION_SUPPORT
|
||||
|
||||
|
||||
// #pragma mark - DecompressionStrategy
|
||||
|
||||
|
||||
struct BZlibCompressionAlgorithm::DecompressionStrategy {
|
||||
typedef BZlibDecompressionParameters Parameters;
|
||||
|
||||
static const bool kNeedsFinalFlush = false;
|
||||
|
||||
static int Init(z_stream& stream,
|
||||
const BZlibDecompressionParameters* /*parameters*/)
|
||||
{
|
||||
return inflateInit(&stream);
|
||||
}
|
||||
|
||||
static void Uninit(z_stream& stream)
|
||||
{
|
||||
inflateEnd(&stream);
|
||||
}
|
||||
|
||||
static int Process(z_stream& stream, bool flush)
|
||||
{
|
||||
return inflate(&stream, flush ? Z_FINISH : 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - Stream
|
||||
|
||||
|
||||
template<typename BaseClass, typename Strategy>
|
||||
struct BZlibCompressionAlgorithm::Stream : BaseClass {
|
||||
Stream(BDataIO* io)
|
||||
:
|
||||
BaseClass(io),
|
||||
fStreamInitialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
~Stream()
|
||||
{
|
||||
if (fStreamInitialized) {
|
||||
if (Strategy::kNeedsFinalFlush)
|
||||
this->Flush();
|
||||
Strategy::Uninit(fStream);
|
||||
}
|
||||
}
|
||||
|
||||
status_t Init(const typename Strategy::Parameters* parameters)
|
||||
{
|
||||
status_t error = this->BaseClass::Init(parameters->BufferSize());
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
memset(&fStream, 0, sizeof(fStream));
|
||||
|
||||
int zlibError = Strategy::Init(fStream, parameters);
|
||||
if (zlibError != Z_OK)
|
||||
return _TranslateZlibError(zlibError);
|
||||
|
||||
fStreamInitialized = true;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
virtual status_t ProcessData(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize, size_t& bytesConsumed,
|
||||
size_t& bytesProduced)
|
||||
{
|
||||
return _ProcessData(input, inputSize, output, outputSize,
|
||||
bytesConsumed, bytesProduced, false);
|
||||
}
|
||||
|
||||
virtual status_t FlushPendingData(void* output, size_t outputSize,
|
||||
size_t& bytesProduced)
|
||||
{
|
||||
size_t bytesConsumed;
|
||||
return _ProcessData(NULL, 0, output, outputSize,
|
||||
bytesConsumed, bytesProduced, true);
|
||||
}
|
||||
|
||||
template<typename BaseParameters>
|
||||
static status_t Create(BDataIO* io, BaseParameters* _parameters,
|
||||
BDataIO*& _stream)
|
||||
{
|
||||
const typename Strategy::Parameters* parameters
|
||||
= dynamic_cast<const typename Strategy::Parameters*>(_parameters);
|
||||
Stream* stream = new(std::nothrow) Stream(io);
|
||||
if (stream == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t error = stream->Init(parameters);
|
||||
if (error != B_OK) {
|
||||
delete stream;
|
||||
return error;
|
||||
}
|
||||
|
||||
_stream = stream;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
status_t _ProcessData(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize, size_t& bytesConsumed,
|
||||
size_t& bytesProduced, bool flush)
|
||||
{
|
||||
fStream.next_in = (Bytef*)input;
|
||||
fStream.avail_in = inputSize;
|
||||
fStream.next_out = (Bytef*)output;
|
||||
fStream.avail_out = outputSize;
|
||||
|
||||
int zlibError = Strategy::Process(fStream, flush);
|
||||
if (zlibError != Z_OK) {
|
||||
if (zlibError == Z_STREAM_END) {
|
||||
if (fStream.avail_in != 0)
|
||||
return B_BAD_DATA;
|
||||
} else
|
||||
return _TranslateZlibError(zlibError);
|
||||
}
|
||||
|
||||
bytesConsumed = inputSize - (size_t)fStream.avail_in;
|
||||
bytesProduced = outputSize - (size_t)fStream.avail_out;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
z_stream fStream;
|
||||
bool fStreamInitialized;
|
||||
};
|
||||
|
||||
|
||||
// #pragma mark - BZlibCompressionAlgorithm
|
||||
|
||||
|
||||
BZlibCompressionAlgorithm::BZlibCompressionAlgorithm()
|
||||
:
|
||||
BCompressionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BZlibCompressionAlgorithm::~BZlibCompressionAlgorithm()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::CreateCompressingInputStream(BDataIO* input,
|
||||
const BCompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
#ifdef B_ZLIB_COMPRESSION_SUPPORT
|
||||
return Stream<BAbstractInputStream, CompressionStrategy>::Create(
|
||||
input, parameters, _stream);
|
||||
#else
|
||||
return B_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::CreateCompressingOutputStream(BDataIO* output,
|
||||
const BCompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
#ifdef B_ZLIB_COMPRESSION_SUPPORT
|
||||
return Stream<BAbstractOutputStream, CompressionStrategy>::Create(
|
||||
output, parameters, _stream);
|
||||
#else
|
||||
return B_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::CreateDecompressingInputStream(BDataIO* input,
|
||||
const BDecompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return Stream<BAbstractInputStream, DecompressionStrategy>::Create(
|
||||
input, parameters, _stream);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::CreateDecompressingOutputStream(BDataIO* output,
|
||||
const BDecompressionParameters* parameters, BDataIO*& _stream)
|
||||
{
|
||||
return Stream<BAbstractOutputStream, DecompressionStrategy>::Create(
|
||||
output, parameters, _stream);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::CompressBuffer(const void* input,
|
||||
size_t inputSize, void* output, size_t outputSize, size_t& _compressedSize,
|
||||
const BCompressionParameters* parameters)
|
||||
{
|
||||
#ifdef B_ZLIB_COMPRESSION_SUPPORT
|
||||
const BZlibCompressionParameters* zlibParameters
|
||||
= dynamic_cast<const BZlibCompressionParameters*>(parameters);
|
||||
int compressionLevel = zlibParameters != NULL
|
||||
? zlibParameters->CompressionLevel()
|
||||
: B_ZLIB_COMPRESSION_DEFAULT;
|
||||
|
||||
uLongf bytesUsed = outputSize;
|
||||
int zlibError = compress2((Bytef*)output, &bytesUsed, (const Bytef*)input,
|
||||
(uLong)inputSize, compressionLevel);
|
||||
if (zlibError != Z_OK)
|
||||
return _TranslateZlibError(zlibError);
|
||||
|
||||
_compressedSize = (size_t)bytesUsed;
|
||||
return B_OK;
|
||||
#else
|
||||
return B_NOT_SUPPORTED;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BZlibCompressionAlgorithm::DecompressBuffer(const void* input,
|
||||
size_t inputSize, void* output, size_t outputSize,
|
||||
size_t& _uncompressedSize, const BDecompressionParameters* parameters)
|
||||
{
|
||||
uLongf bytesUsed = outputSize;
|
||||
int zlibError = uncompress((Bytef*)output, &bytesUsed, (const Bytef*)input,
|
||||
(uLong)inputSize);
|
||||
if (zlibError != Z_OK)
|
||||
return _TranslateZlibError(zlibError);
|
||||
|
||||
_uncompressedSize = (size_t)bytesUsed;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/*static*/ status_t
|
||||
BZlibCompressionAlgorithm::_TranslateZlibError(int error)
|
||||
{
|
||||
switch (error) {
|
||||
case Z_OK:
|
||||
return B_OK;
|
||||
case Z_STREAM_END:
|
||||
case Z_NEED_DICT:
|
||||
// a special event (no error), but the caller doesn't seem to handle
|
||||
// it
|
||||
return B_ERROR;
|
||||
case Z_ERRNO:
|
||||
return errno;
|
||||
case Z_STREAM_ERROR:
|
||||
return B_BAD_VALUE;
|
||||
case Z_DATA_ERROR:
|
||||
return B_BAD_DATA;
|
||||
case Z_MEM_ERROR:
|
||||
return B_NO_MEMORY;
|
||||
case Z_BUF_ERROR:
|
||||
return B_BUFFER_OVERFLOW;
|
||||
case Z_VERSION_ERROR:
|
||||
return B_BAD_VALUE;
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user