* Added support for iterative operation to ZlibCompressor/ZlibDecompressor.
* Added support for compressing/decompressing the TOC section of the package to PackageWriter/PackageReader. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34063 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "DataOutput.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - DataOutput
|
||||||
|
|
||||||
|
|
||||||
|
DataOutput::~DataOutput()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - BufferDataOutput
|
||||||
|
|
||||||
|
|
||||||
|
BufferDataOutput::BufferDataOutput(void* buffer, size_t size)
|
||||||
|
:
|
||||||
|
fBuffer(buffer),
|
||||||
|
fSize(size),
|
||||||
|
fBytesWritten(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
BufferDataOutput::WriteData(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return B_OK;
|
||||||
|
if (size > fSize - fBytesWritten)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
memcpy((uint8*)fBuffer + fBytesWritten, buffer, size);
|
||||||
|
fBytesWritten += size;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef DATA_OUTPUT_H
|
||||||
|
#define DATA_OUTPUT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
class DataOutput {
|
||||||
|
public:
|
||||||
|
virtual ~DataOutput();
|
||||||
|
|
||||||
|
virtual status_t WriteData(const void* buffer, size_t size) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class BufferDataOutput : public DataOutput {
|
||||||
|
public:
|
||||||
|
BufferDataOutput(void* buffer, size_t size);
|
||||||
|
|
||||||
|
size_t BytesWritten() const { return fBytesWritten; }
|
||||||
|
|
||||||
|
virtual status_t WriteData(const void* buffer, size_t size);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void* fBuffer;
|
||||||
|
size_t fSize;
|
||||||
|
size_t fBytesWritten;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // DATA_OUTPUT_H
|
||||||
@@ -14,6 +14,7 @@ BinCommand package :
|
|||||||
command_dump.cpp
|
command_dump.cpp
|
||||||
command_extract.cpp
|
command_extract.cpp
|
||||||
command_list.cpp
|
command_list.cpp
|
||||||
|
DataOutput.cpp
|
||||||
DataReader.cpp
|
DataReader.cpp
|
||||||
package.cpp
|
package.cpp
|
||||||
PackageData.cpp
|
PackageData.cpp
|
||||||
|
|||||||
@@ -236,8 +236,9 @@ private:
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
size_t actuallyUncompressedSize;
|
size_t actuallyUncompressedSize;
|
||||||
error = ZlibDecompressor().Decompress(fReadBuffer, compressedSize,
|
error = ZlibDecompressor::DecompressSingleBuffer(fReadBuffer,
|
||||||
fUncompressBuffer, uncompressedSize, actuallyUncompressedSize);
|
compressedSize, fUncompressBuffer, uncompressedSize,
|
||||||
|
actuallyUncompressedSize);
|
||||||
if (error == B_OK && actuallyUncompressedSize != uncompressedSize)
|
if (error == B_OK && actuallyUncompressedSize != uncompressedSize)
|
||||||
error = B_BAD_DATA;
|
error = B_BAD_DATA;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,20 +14,25 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <new>
|
#include <new>
|
||||||
|
|
||||||
#include <ByteOrder.h>
|
#include <ByteOrder.h>
|
||||||
|
|
||||||
#include <haiku_package.h>
|
#include <haiku_package.h>
|
||||||
|
|
||||||
|
#include "DataOutput.h"
|
||||||
#include "PackageData.h"
|
#include "PackageData.h"
|
||||||
#include "PackageEntry.h"
|
#include "PackageEntry.h"
|
||||||
#include "PackageEntryAttribute.h"
|
#include "PackageEntryAttribute.h"
|
||||||
|
#include "ZlibDecompressor.h"
|
||||||
|
|
||||||
|
|
||||||
// maximum TOC size, we support reading
|
// maximum TOC size we support reading
|
||||||
static const size_t kMaxTOCSize = 64 * 1024 * 1024;
|
static const size_t kMaxTOCSize = 64 * 1024 * 1024;
|
||||||
|
|
||||||
|
static const size_t kScratchBufferSize = 64 * 1024;
|
||||||
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ATTRIBUTE_INDEX_DIRECTORY_ENTRY = 0,
|
ATTRIBUTE_INDEX_DIRECTORY_ENTRY = 0,
|
||||||
@@ -604,7 +609,9 @@ PackageReader::PackageReader()
|
|||||||
fFD(-1),
|
fFD(-1),
|
||||||
fTOCSection(NULL),
|
fTOCSection(NULL),
|
||||||
fAttributeTypes(NULL),
|
fAttributeTypes(NULL),
|
||||||
fStrings(NULL)
|
fStrings(NULL),
|
||||||
|
fScratchBuffer(NULL),
|
||||||
|
fScratchBufferSize(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -614,6 +621,7 @@ PackageReader::~PackageReader()
|
|||||||
if (fFD >= 0)
|
if (fFD >= 0)
|
||||||
close(fFD);
|
close(fFD);
|
||||||
|
|
||||||
|
delete[] fScratchBuffer;
|
||||||
delete[] fStrings;
|
delete[] fStrings;
|
||||||
delete[] fAttributeTypes;
|
delete[] fAttributeTypes;
|
||||||
delete[] fTOCSection;
|
delete[] fTOCSection;
|
||||||
@@ -641,7 +649,7 @@ PackageReader::Init(const char* fileName)
|
|||||||
|
|
||||||
// read the header
|
// read the header
|
||||||
hpkg_header header;
|
hpkg_header header;
|
||||||
status_t error = _ReadBuffer(&header, sizeof(header), 0);
|
status_t error = _ReadBuffer(0, &header, sizeof(header));
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -751,6 +759,14 @@ PackageReader::Init(const char* fileName)
|
|||||||
return B_UNSUPPORTED;
|
return B_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allocate a scratch buffer
|
||||||
|
fScratchBuffer = new(std::nothrow) uint8[kScratchBufferSize];
|
||||||
|
if (fScratchBuffer == NULL) {
|
||||||
|
fprintf(stderr, "Error: Out of memory!\n");
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
fScratchBufferSize = kScratchBufferSize;
|
||||||
|
|
||||||
// read in the complete TOC
|
// read in the complete TOC
|
||||||
fTOCSection = new(std::nothrow) uint8[fTOCUncompressedLength];
|
fTOCSection = new(std::nothrow) uint8[fTOCUncompressedLength];
|
||||||
if (fTOCSection == NULL) {
|
if (fTOCSection == NULL) {
|
||||||
@@ -758,7 +774,8 @@ PackageReader::Init(const char* fileName)
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = _ReadBuffer(fTOCSection, fTOCUncompressedLength, fTOCSectionOffset);
|
error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection,
|
||||||
|
fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
@@ -1249,7 +1266,7 @@ PackageReader::_ReadTOCBuffer(void* buffer, size_t size)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
PackageReader::_ReadBuffer(void* buffer, size_t size, off_t offset)
|
PackageReader::_ReadBuffer(off_t offset, void* buffer, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t bytesRead = pread(fFD, buffer, size, offset);
|
ssize_t bytesRead = pread(fFD, buffer, size, offset);
|
||||||
if (bytesRead < 0) {
|
if (bytesRead < 0) {
|
||||||
@@ -1267,6 +1284,59 @@ PackageReader::_ReadBuffer(void* buffer, size_t size, off_t offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
PackageReader::_ReadCompressedBuffer(off_t offset, void* buffer,
|
||||||
|
size_t compressedSize, size_t uncompressedSize, uint32 compression)
|
||||||
|
{
|
||||||
|
switch (compression) {
|
||||||
|
case B_HPKG_COMPRESSION_NONE:
|
||||||
|
return _ReadBuffer(offset, buffer, compressedSize);
|
||||||
|
|
||||||
|
case B_HPKG_COMPRESSION_ZLIB:
|
||||||
|
{
|
||||||
|
// init the decompressor
|
||||||
|
BufferDataOutput bufferOutput(buffer, uncompressedSize);
|
||||||
|
ZlibDecompressor decompressor(&bufferOutput);
|
||||||
|
status_t error = decompressor.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
while (compressedSize > 0) {
|
||||||
|
// read compressed buffer
|
||||||
|
size_t toRead = std::min(compressedSize, fScratchBufferSize);
|
||||||
|
error = _ReadBuffer(offset, fScratchBuffer, toRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// uncompress
|
||||||
|
error = decompressor.DecompressNext(fScratchBuffer, toRead);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
compressedSize -= toRead;
|
||||||
|
offset += toRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = decompressor.Finish();
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// verify that all data have been read
|
||||||
|
if (bufferOutput.BytesWritten() != uncompressedSize) {
|
||||||
|
fprintf(stderr, "Error: Missing bytes in uncompressed "
|
||||||
|
"buffer!\n");
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return B_BAD_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*static*/ int8
|
/*static*/ int8
|
||||||
PackageReader::_GetStandardIndex(const AttributeType* type)
|
PackageReader::_GetStandardIndex(const AttributeType* type)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -104,8 +104,12 @@ private:
|
|||||||
const void*& _buffer);
|
const void*& _buffer);
|
||||||
status_t _ReadTOCBuffer(void* buffer, size_t size);
|
status_t _ReadTOCBuffer(void* buffer, size_t size);
|
||||||
|
|
||||||
status_t _ReadBuffer(void* buffer, size_t size,
|
status_t _ReadBuffer(off_t offset, void* buffer,
|
||||||
off_t offset);
|
size_t size);
|
||||||
|
status_t _ReadCompressedBuffer(off_t offset,
|
||||||
|
void* buffer, size_t compressedSize,
|
||||||
|
size_t uncompressedSize,
|
||||||
|
uint32 compression);
|
||||||
|
|
||||||
static int8 _GetStandardIndex(const AttributeType* type);
|
static int8 _GetStandardIndex(const AttributeType* type);
|
||||||
|
|
||||||
@@ -141,6 +145,9 @@ private:
|
|||||||
char** fStrings;
|
char** fStrings;
|
||||||
|
|
||||||
AttributeHandlerList* fAttributeHandlerStack;
|
AttributeHandlerList* fAttributeHandlerStack;
|
||||||
|
|
||||||
|
uint8* fScratchBuffer;
|
||||||
|
size_t fScratchBufferSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <haiku_package.h>
|
#include <haiku_package.h>
|
||||||
|
|
||||||
|
#include "DataOutput.h"
|
||||||
#include "DataReader.h"
|
#include "DataReader.h"
|
||||||
#include "FDCloser.h"
|
#include "FDCloser.h"
|
||||||
#include "Stacker.h"
|
#include "Stacker.h"
|
||||||
@@ -373,7 +374,149 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - PackageWriter
|
// #pragma mark - DataWriter
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageWriter::DataWriter {
|
||||||
|
DataWriter()
|
||||||
|
:
|
||||||
|
fBytesWritten(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~DataWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 BytesWritten() const
|
||||||
|
{
|
||||||
|
return fBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t WriteDataNoThrow(const void* buffer, size_t size) = 0;
|
||||||
|
|
||||||
|
inline void WriteDataThrows(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
status_t error = WriteDataNoThrow(buffer, size);
|
||||||
|
if (error != B_OK)
|
||||||
|
throw status_t(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint64 fBytesWritten;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageWriter::DummyDataWriter : DataWriter {
|
||||||
|
DummyDataWriter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t WriteDataNoThrow(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
fBytesWritten += size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageWriter::FDDataWriter : DataWriter {
|
||||||
|
FDDataWriter(int fd, off_t offset)
|
||||||
|
:
|
||||||
|
fFD(fd),
|
||||||
|
fOffset(offset)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t WriteDataNoThrow(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
ssize_t bytesWritten = pwrite(fFD, buffer, size, fOffset);
|
||||||
|
if (bytesWritten < 0) {
|
||||||
|
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write data: %s\n",
|
||||||
|
buffer, size, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
if ((size_t)bytesWritten != size) {
|
||||||
|
fprintf(stderr, "_WriteBuffer(%p, %lu) failed to write all data\n",
|
||||||
|
buffer, size);
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
fOffset += size;
|
||||||
|
fBytesWritten += size;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t Offset() const
|
||||||
|
{
|
||||||
|
return fOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int fFD;
|
||||||
|
off_t fOffset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PackageWriter::ZlibDataWriter : DataWriter, private DataOutput {
|
||||||
|
ZlibDataWriter(DataWriter* dataWriter)
|
||||||
|
:
|
||||||
|
fDataWriter(dataWriter),
|
||||||
|
fCompressor(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
status_t error = fCompressor.Init();
|
||||||
|
if (error != B_OK)
|
||||||
|
throw status_t(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Finish()
|
||||||
|
{
|
||||||
|
status_t error = fCompressor.Finish();
|
||||||
|
if (error != B_OK)
|
||||||
|
throw status_t(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t WriteDataNoThrow(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
status_t error = fCompressor.CompressNext(buffer, size);
|
||||||
|
if (error == B_OK)
|
||||||
|
fBytesWritten += size;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// DataOutput
|
||||||
|
virtual status_t WriteData(const void* buffer, size_t size)
|
||||||
|
{
|
||||||
|
return fDataWriter->WriteDataNoThrow(buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DataWriter* fDataWriter;
|
||||||
|
ZlibCompressor fCompressor;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageWriter (Inline Methods)
|
||||||
|
|
||||||
|
|
||||||
|
template<typename Type>
|
||||||
|
inline void
|
||||||
|
PackageWriter::_Write(const Type& value)
|
||||||
|
{
|
||||||
|
fDataWriter->WriteDataThrows(&value, sizeof(Type));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
PackageWriter::_WriteString(const char* string)
|
||||||
|
{
|
||||||
|
fDataWriter->WriteDataThrows(string, strlen(string) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
@@ -386,12 +529,16 @@ PackageWriter::_AddAttribute(const char* attributeName, Type value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - PackageWriter
|
||||||
|
|
||||||
|
|
||||||
PackageWriter::PackageWriter()
|
PackageWriter::PackageWriter()
|
||||||
:
|
:
|
||||||
fFileName(NULL),
|
fFileName(NULL),
|
||||||
fFD(-1),
|
fFD(-1),
|
||||||
fFinished(false),
|
fFinished(false),
|
||||||
fDataBuffer(NULL),
|
fDataBuffer(NULL),
|
||||||
|
fDataWriter(NULL),
|
||||||
fRootEntry(NULL),
|
fRootEntry(NULL),
|
||||||
fRootAttribute(NULL),
|
fRootAttribute(NULL),
|
||||||
fTopAttribute(NULL),
|
fTopAttribute(NULL),
|
||||||
@@ -529,26 +676,11 @@ PackageWriter::_Finish()
|
|||||||
printf("header size: %lu\n", sizeof(hpkg_header));
|
printf("header size: %lu\n", sizeof(hpkg_header));
|
||||||
printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
|
printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
|
||||||
|
|
||||||
// write the attribute type abbreviations
|
hpkg_header header;
|
||||||
off_t attributeTypesOffset = fHeapEnd;
|
|
||||||
_WriteAttributeTypes();
|
|
||||||
printf("attributes types size: %lld\n", fHeapEnd - attributeTypesOffset);
|
|
||||||
|
|
||||||
// write the cached strings
|
// write the TOC and package attributes
|
||||||
off_t cachedStringsOffset = fHeapEnd;
|
_WriteTOC(header);
|
||||||
int32 cachedStringsWritten = _WriteCachedStrings();
|
_WritePackageAttributes(header);
|
||||||
printf("cached strings size: %lld\n", fHeapEnd - cachedStringsOffset);
|
|
||||||
|
|
||||||
// write the TOC
|
|
||||||
off_t tocOffset = fHeapEnd;
|
|
||||||
_WriteAttributeChildren(fRootAttribute);
|
|
||||||
printf("toc size: %lld\n", fHeapEnd - tocOffset);
|
|
||||||
|
|
||||||
// write the package attributes
|
|
||||||
off_t packageAttributesOffset = fHeapEnd;
|
|
||||||
_Write<uint8>(0);
|
|
||||||
// TODO: Write them for real!
|
|
||||||
printf("package attributes size: %lld\n", fHeapEnd - packageAttributesOffset);
|
|
||||||
|
|
||||||
off_t totalSize = fHeapEnd;
|
off_t totalSize = fHeapEnd;
|
||||||
printf("total size: %lld\n", totalSize);
|
printf("total size: %lld\n", totalSize);
|
||||||
@@ -556,38 +688,12 @@ printf("total size: %lld\n", totalSize);
|
|||||||
// prepare the header
|
// prepare the header
|
||||||
|
|
||||||
// general
|
// general
|
||||||
hpkg_header header;
|
|
||||||
header.magic = B_HOST_TO_BENDIAN_INT32(B_HPKG_MAGIC);
|
header.magic = B_HOST_TO_BENDIAN_INT32(B_HPKG_MAGIC);
|
||||||
header.header_size = B_HOST_TO_BENDIAN_INT16(
|
header.header_size = B_HOST_TO_BENDIAN_INT16(
|
||||||
(uint16)sizeof(hpkg_header));
|
(uint16)sizeof(hpkg_header));
|
||||||
header.version = B_HOST_TO_BENDIAN_INT16(B_HPKG_VERSION);
|
header.version = B_HOST_TO_BENDIAN_INT16(B_HPKG_VERSION);
|
||||||
header.total_size = B_HOST_TO_BENDIAN_INT64(totalSize);
|
header.total_size = B_HOST_TO_BENDIAN_INT64(totalSize);
|
||||||
|
|
||||||
// package attributes
|
|
||||||
header.attributes_compression = B_HOST_TO_BENDIAN_INT32(
|
|
||||||
B_HPKG_COMPRESSION_NONE);
|
|
||||||
header.attributes_length_compressed
|
|
||||||
= B_HOST_TO_BENDIAN_INT32(fHeapEnd - packageAttributesOffset);
|
|
||||||
header.attributes_length_uncompressed
|
|
||||||
= header.attributes_length_compressed;
|
|
||||||
// TODO: Support compression!
|
|
||||||
|
|
||||||
// TOC
|
|
||||||
header.toc_compression = B_HOST_TO_BENDIAN_INT32(B_HPKG_COMPRESSION_NONE);
|
|
||||||
header.toc_length_compressed = B_HOST_TO_BENDIAN_INT64(
|
|
||||||
packageAttributesOffset - attributeTypesOffset);
|
|
||||||
header.toc_length_uncompressed = header.toc_length_compressed;
|
|
||||||
// TODO: Support compression!
|
|
||||||
|
|
||||||
// TOC subsections
|
|
||||||
header.toc_attribute_types_length = B_HOST_TO_BENDIAN_INT64(
|
|
||||||
cachedStringsOffset - attributeTypesOffset);
|
|
||||||
header.toc_attribute_types_count = B_HOST_TO_BENDIAN_INT64(
|
|
||||||
fAttributeTypes->CountElements());
|
|
||||||
header.toc_strings_length = B_HOST_TO_BENDIAN_INT64(
|
|
||||||
tocOffset - cachedStringsOffset);
|
|
||||||
header.toc_strings_count = B_HOST_TO_BENDIAN_INT64(cachedStringsWritten);
|
|
||||||
|
|
||||||
// write the header
|
// write the header
|
||||||
_WriteBuffer(&header, sizeof(hpkg_header), 0);
|
_WriteBuffer(&header, sizeof(hpkg_header), 0);
|
||||||
|
|
||||||
@@ -666,6 +772,79 @@ PackageWriter::_RegisterEntry(Entry* parent, const char* name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageWriter::_WriteTOC(hpkg_header& header)
|
||||||
|
{
|
||||||
|
// prepare the writer (zlib writer on top of a file writer)
|
||||||
|
off_t startOffset = fHeapEnd;
|
||||||
|
FDDataWriter realWriter(fFD, startOffset);
|
||||||
|
ZlibDataWriter zlibWriter(&realWriter);
|
||||||
|
fDataWriter = &zlibWriter;
|
||||||
|
zlibWriter.Init();
|
||||||
|
|
||||||
|
// write the sections
|
||||||
|
uint64 uncompressedAttributeTypesSize;
|
||||||
|
uint64 uncompressedStringsSize;
|
||||||
|
uint64 uncompressedMainSize;
|
||||||
|
int32 cachedStringsWritten = _WriteTOCSections(
|
||||||
|
uncompressedAttributeTypesSize, uncompressedStringsSize,
|
||||||
|
uncompressedMainSize);
|
||||||
|
|
||||||
|
// finish the writer
|
||||||
|
zlibWriter.Finish();
|
||||||
|
fHeapEnd = realWriter.Offset();
|
||||||
|
fDataWriter = NULL;
|
||||||
|
|
||||||
|
printf("attributes types size: %llu\n", uncompressedAttributeTypesSize);
|
||||||
|
printf("cached strings size: %llu\n", uncompressedStringsSize);
|
||||||
|
printf("TOC main size: %llu\n", uncompressedMainSize);
|
||||||
|
off_t endOffset = fHeapEnd;
|
||||||
|
printf("total TOC size: %llu (%llu)\n", endOffset - startOffset, zlibWriter.BytesWritten());
|
||||||
|
|
||||||
|
// update the header
|
||||||
|
|
||||||
|
// TOC
|
||||||
|
header.toc_compression = B_HOST_TO_BENDIAN_INT32(B_HPKG_COMPRESSION_ZLIB);
|
||||||
|
header.toc_length_compressed = B_HOST_TO_BENDIAN_INT64(
|
||||||
|
endOffset - startOffset);
|
||||||
|
header.toc_length_uncompressed = B_HOST_TO_BENDIAN_INT64(
|
||||||
|
zlibWriter.BytesWritten());
|
||||||
|
|
||||||
|
// TOC subsections
|
||||||
|
header.toc_attribute_types_length = B_HOST_TO_BENDIAN_INT64(
|
||||||
|
uncompressedAttributeTypesSize);
|
||||||
|
header.toc_attribute_types_count = B_HOST_TO_BENDIAN_INT64(
|
||||||
|
fAttributeTypes->CountElements());
|
||||||
|
header.toc_strings_length = B_HOST_TO_BENDIAN_INT64(
|
||||||
|
uncompressedStringsSize);
|
||||||
|
header.toc_strings_count = B_HOST_TO_BENDIAN_INT64(cachedStringsWritten);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
PackageWriter::_WriteTOCSections(uint64& _attributeTypesSize,
|
||||||
|
uint64& _stringsSize, uint64& _mainSize)
|
||||||
|
{
|
||||||
|
// write the attribute type abbreviations
|
||||||
|
uint64 attributeTypesOffset = fDataWriter->BytesWritten();
|
||||||
|
_WriteAttributeTypes();
|
||||||
|
|
||||||
|
// write the cached strings
|
||||||
|
uint64 cachedStringsOffset = fDataWriter->BytesWritten();
|
||||||
|
int32 cachedStringsWritten = _WriteCachedStrings();
|
||||||
|
|
||||||
|
// write the main TOC section
|
||||||
|
uint64 mainOffset = fDataWriter->BytesWritten();
|
||||||
|
_WriteAttributeChildren(fRootAttribute);
|
||||||
|
|
||||||
|
_attributeTypesSize = cachedStringsOffset - attributeTypesOffset;
|
||||||
|
_stringsSize = mainOffset - cachedStringsOffset;
|
||||||
|
_mainSize = fDataWriter->BytesWritten() - mainOffset;
|
||||||
|
|
||||||
|
return cachedStringsWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageWriter::_WriteAttributeTypes()
|
PackageWriter::_WriteAttributeTypes()
|
||||||
{
|
{
|
||||||
@@ -762,6 +941,34 @@ PackageWriter::_WriteAttributeChildren(Attribute* attribute)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
PackageWriter::_WritePackageAttributes(hpkg_header& header)
|
||||||
|
{
|
||||||
|
// write the package attributes
|
||||||
|
off_t startOffset = fHeapEnd;
|
||||||
|
FDDataWriter realWriter(fFD, startOffset);
|
||||||
|
fDataWriter = &realWriter;
|
||||||
|
|
||||||
|
_Write<uint8>(0);
|
||||||
|
// TODO: Write them for real!
|
||||||
|
fHeapEnd = realWriter.Offset();
|
||||||
|
fDataWriter = NULL;
|
||||||
|
|
||||||
|
off_t endOffset = fHeapEnd;
|
||||||
|
|
||||||
|
printf("package attributes size: %lld\n", endOffset - startOffset);
|
||||||
|
|
||||||
|
// update the header
|
||||||
|
header.attributes_compression = B_HOST_TO_BENDIAN_INT32(
|
||||||
|
B_HPKG_COMPRESSION_NONE);
|
||||||
|
header.attributes_length_compressed
|
||||||
|
= B_HOST_TO_BENDIAN_INT32(endOffset - startOffset);
|
||||||
|
header.attributes_length_uncompressed
|
||||||
|
= header.attributes_length_compressed;
|
||||||
|
// TODO: Support compression!
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
PackageWriter::_WriteAttributeValue(const AttributeValue& value, uint8 encoding)
|
PackageWriter::_WriteAttributeValue(const AttributeValue& value, uint8 encoding)
|
||||||
{
|
{
|
||||||
@@ -815,7 +1022,7 @@ PackageWriter::_WriteAttributeValue(const AttributeValue& value, uint8 encoding)
|
|||||||
if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP)
|
if (encoding == B_HPKG_ATTRIBUTE_ENCODING_RAW_HEAP)
|
||||||
_WriteUnsignedLEB128(value.data.offset);
|
_WriteUnsignedLEB128(value.data.offset);
|
||||||
else
|
else
|
||||||
_WriteBuffer(value.data.raw, value.data.size);
|
fDataWriter->WriteDataThrows(value.data.raw, value.data.size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -838,7 +1045,7 @@ PackageWriter::_WriteUnsignedLEB128(uint64 value)
|
|||||||
bytes[count++] = byte | (value != 0 ? 0x80 : 0);
|
bytes[count++] = byte | (value != 0 ? 0x80 : 0);
|
||||||
} while (value != 0);
|
} while (value != 0);
|
||||||
|
|
||||||
_WriteBuffer(bytes, count);
|
fDataWriter->WriteDataThrows(bytes, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1237,10 +1444,9 @@ PackageWriter::_WriteZlibCompressedData(DataReader& dataReader, off_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
ZlibCompressor compressor;
|
|
||||||
size_t compressedSize;
|
size_t compressedSize;
|
||||||
error = compressor.Compress(inputBuffer, toCopy, outputBuffer,
|
error = ZlibCompressor::CompressSingleBuffer(inputBuffer, toCopy,
|
||||||
toCopy, compressedSize);
|
outputBuffer, toCopy, compressedSize);
|
||||||
|
|
||||||
const void* writeBuffer;
|
const void* writeBuffer;
|
||||||
size_t bytesToWrite;
|
size_t bytesToWrite;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
class DataReader;
|
class DataReader;
|
||||||
|
struct hpkg_header;
|
||||||
|
|
||||||
|
|
||||||
class PackageWriter {
|
class PackageWriter {
|
||||||
@@ -32,6 +33,10 @@ private:
|
|||||||
struct Attribute;
|
struct Attribute;
|
||||||
struct AttributeTypeUsageGreater;
|
struct AttributeTypeUsageGreater;
|
||||||
struct Entry;
|
struct Entry;
|
||||||
|
struct DataWriter;
|
||||||
|
struct DummyDataWriter;
|
||||||
|
struct FDDataWriter;
|
||||||
|
struct ZlibDataWriter;
|
||||||
|
|
||||||
typedef BOpenHashTable<AttributeTypeHashDefinition>
|
typedef BOpenHashTable<AttributeTypeHashDefinition>
|
||||||
AttributeTypeTable;
|
AttributeTypeTable;
|
||||||
@@ -46,10 +51,15 @@ private:
|
|||||||
const char* name, size_t nameLength,
|
const char* name, size_t nameLength,
|
||||||
bool isImplicit);
|
bool isImplicit);
|
||||||
|
|
||||||
|
void _WriteTOC(hpkg_header& header);
|
||||||
|
int32 _WriteTOCSections(uint64& _attributeTypesSize,
|
||||||
|
uint64& _stringsSize, uint64& _mainSize);
|
||||||
void _WriteAttributeTypes();
|
void _WriteAttributeTypes();
|
||||||
int32 _WriteCachedStrings();
|
int32 _WriteCachedStrings();
|
||||||
void _WriteAttributeChildren(Attribute* attribute);
|
void _WriteAttributeChildren(Attribute* attribute);
|
||||||
|
|
||||||
|
void _WritePackageAttributes(hpkg_header& header);
|
||||||
|
|
||||||
void _WriteAttributeValue(
|
void _WriteAttributeValue(
|
||||||
const AttributeValue& value,
|
const AttributeValue& value,
|
||||||
uint8 encoding);
|
uint8 encoding);
|
||||||
@@ -61,7 +71,6 @@ private:
|
|||||||
|
|
||||||
void _WriteBuffer(const void* buffer, size_t size,
|
void _WriteBuffer(const void* buffer, size_t size,
|
||||||
off_t offset);
|
off_t offset);
|
||||||
inline void _WriteBuffer(const void* buffer, size_t size);
|
|
||||||
|
|
||||||
void _AddEntry(int dirFD, Entry* entry,
|
void _AddEntry(int dirFD, Entry* entry,
|
||||||
const char* fileName);
|
const char* fileName);
|
||||||
@@ -100,6 +109,8 @@ private:
|
|||||||
void* fDataBuffer;
|
void* fDataBuffer;
|
||||||
size_t fDataBufferSize;
|
size_t fDataBufferSize;
|
||||||
|
|
||||||
|
DataWriter* fDataWriter;
|
||||||
|
|
||||||
Entry* fRootEntry;
|
Entry* fRootEntry;
|
||||||
|
|
||||||
Attribute* fRootAttribute;
|
Attribute* fRootAttribute;
|
||||||
@@ -110,27 +121,4 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename Type>
|
|
||||||
inline void
|
|
||||||
PackageWriter::_Write(const Type& value)
|
|
||||||
{
|
|
||||||
_WriteBuffer(&value, sizeof(Type));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void
|
|
||||||
PackageWriter::_WriteString(const char* string)
|
|
||||||
{
|
|
||||||
_WriteBuffer(string, strlen(string) + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void
|
|
||||||
PackageWriter::_WriteBuffer(const void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
_WriteBuffer(buffer, size, fHeapEnd);
|
|
||||||
fHeapEnd += size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // PACKAGE_WRITER_H
|
#endif // PACKAGE_WRITER_H
|
||||||
|
|||||||
@@ -7,23 +7,121 @@
|
|||||||
#include "ZlibCompressor.h"
|
#include "ZlibCompressor.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include "DataOutput.h"
|
||||||
|
|
||||||
|
|
||||||
ZlibCompressor::ZlibCompressor()
|
static const size_t kOutputBufferSize = 1024;
|
||||||
|
|
||||||
|
|
||||||
|
ZlibCompressor::ZlibCompressor(DataOutput* output)
|
||||||
|
:
|
||||||
|
fOutput(output),
|
||||||
|
fStreamInitialized(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZlibCompressor::~ZlibCompressor()
|
ZlibCompressor::~ZlibCompressor()
|
||||||
{
|
{
|
||||||
|
if (fStreamInitialized)
|
||||||
|
deflateEnd(&fStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ZlibCompressor::Compress(const void* input, size_t inputSize, void* output,
|
ZlibCompressor::Init()
|
||||||
size_t outputSize, size_t& _compressedSize)
|
{
|
||||||
|
// initialize the stream
|
||||||
|
fStream.next_in = NULL;
|
||||||
|
fStream.avail_in = 0;
|
||||||
|
fStream.total_in = 0;
|
||||||
|
fStream.next_out = NULL;
|
||||||
|
fStream.avail_out = 0;
|
||||||
|
fStream.total_out = 0;
|
||||||
|
fStream.msg = 0;
|
||||||
|
fStream.state = 0;
|
||||||
|
fStream.zalloc = Z_NULL;
|
||||||
|
fStream.zfree = Z_NULL;
|
||||||
|
fStream.opaque = Z_NULL;
|
||||||
|
fStream.data_type = 0;
|
||||||
|
fStream.adler = 0;
|
||||||
|
fStream.reserved = 0;
|
||||||
|
|
||||||
|
int zlibError = deflateInit(&fStream, Z_BEST_COMPRESSION);
|
||||||
|
if (zlibError != Z_OK)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
fStreamInitialized = true;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ZlibCompressor::CompressNext(const void* input, size_t inputSize)
|
||||||
|
{
|
||||||
|
fStream.next_in = (Bytef*)input;
|
||||||
|
fStream.avail_in = inputSize;
|
||||||
|
|
||||||
|
while (fStream.avail_in > 0) {
|
||||||
|
uint8 outputBuffer[kOutputBufferSize];
|
||||||
|
fStream.next_out = (Bytef*)outputBuffer;
|
||||||
|
fStream.avail_out = sizeof(outputBuffer);
|
||||||
|
|
||||||
|
int zlibError = deflate(&fStream, 0);
|
||||||
|
if (zlibError != Z_OK)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
if (fStream.avail_out < sizeof(outputBuffer)) {
|
||||||
|
status_t error = fOutput->WriteData(outputBuffer,
|
||||||
|
sizeof(outputBuffer) - fStream.avail_out);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ZlibCompressor::Finish()
|
||||||
|
{
|
||||||
|
fStream.next_in = (Bytef*)NULL;
|
||||||
|
fStream.avail_in = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
uint8 outputBuffer[kOutputBufferSize];
|
||||||
|
fStream.next_out = (Bytef*)outputBuffer;
|
||||||
|
fStream.avail_out = sizeof(outputBuffer);
|
||||||
|
|
||||||
|
int zlibError = deflate(&fStream, Z_FINISH);
|
||||||
|
if (zlibError != Z_OK && zlibError != Z_STREAM_END)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
if (fStream.avail_out < sizeof(outputBuffer)) {
|
||||||
|
status_t error = fOutput->WriteData(outputBuffer,
|
||||||
|
sizeof(outputBuffer) - fStream.avail_out);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (zlibError == Z_STREAM_END)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
deflateEnd(&fStream);
|
||||||
|
fStreamInitialized = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
ZlibCompressor::CompressSingleBuffer(const void* input, size_t inputSize,
|
||||||
|
void* output, size_t outputSize, size_t& _compressedSize)
|
||||||
{
|
{
|
||||||
if (inputSize == 0 || outputSize == 0)
|
if (inputSize == 0 || outputSize == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|||||||
@@ -6,17 +6,32 @@
|
|||||||
#define ZLIB_COMPRESSOR_H
|
#define ZLIB_COMPRESSOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "ZlibCompressionBase.h"
|
#include "ZlibCompressionBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DataOutput;
|
||||||
|
|
||||||
|
|
||||||
class ZlibCompressor : public ZlibCompressionBase {
|
class ZlibCompressor : public ZlibCompressionBase {
|
||||||
public:
|
public:
|
||||||
ZlibCompressor();
|
ZlibCompressor(DataOutput* output);
|
||||||
~ZlibCompressor();
|
~ZlibCompressor();
|
||||||
|
|
||||||
status_t Compress(const void* input, size_t inputSize,
|
status_t Init();
|
||||||
void* output, size_t outputSize,
|
status_t CompressNext(const void* input,
|
||||||
size_t& _compressedSize);
|
size_t inputSize);
|
||||||
|
status_t Finish();
|
||||||
|
|
||||||
|
static status_t CompressSingleBuffer(const void* input,
|
||||||
|
size_t inputSize, void* output,
|
||||||
|
size_t outputSize, size_t& _compressedSize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
z_stream fStream;
|
||||||
|
DataOutput* fOutput;
|
||||||
|
bool fStreamInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,23 +7,127 @@
|
|||||||
#include "ZlibDecompressor.h"
|
#include "ZlibDecompressor.h"
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <zlib.h>
|
#include "DataOutput.h"
|
||||||
|
|
||||||
|
|
||||||
ZlibDecompressor::ZlibDecompressor()
|
// TODO: For the kernel the buffer shouldn't be allocated on the stack.
|
||||||
|
static const size_t kOutputBufferSize = 1024;
|
||||||
|
|
||||||
|
|
||||||
|
ZlibDecompressor::ZlibDecompressor(DataOutput* output)
|
||||||
|
:
|
||||||
|
fOutput(output),
|
||||||
|
fStreamInitialized(false),
|
||||||
|
fFinished(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZlibDecompressor::~ZlibDecompressor()
|
ZlibDecompressor::~ZlibDecompressor()
|
||||||
{
|
{
|
||||||
|
if (fStreamInitialized)
|
||||||
|
inflateEnd(&fStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ZlibDecompressor::Decompress(const void* input, size_t inputSize, void* output,
|
ZlibDecompressor::Init()
|
||||||
size_t outputSize, size_t& _uncompressedSize)
|
{
|
||||||
|
// initialize the stream
|
||||||
|
fStream.next_in = NULL;
|
||||||
|
fStream.avail_in = 0;
|
||||||
|
fStream.total_in = 0;
|
||||||
|
fStream.next_out = NULL;
|
||||||
|
fStream.avail_out = 0;
|
||||||
|
fStream.total_out = 0;
|
||||||
|
fStream.msg = 0;
|
||||||
|
fStream.state = 0;
|
||||||
|
fStream.zalloc = Z_NULL;
|
||||||
|
fStream.zfree = Z_NULL;
|
||||||
|
fStream.opaque = Z_NULL;
|
||||||
|
fStream.data_type = 0;
|
||||||
|
fStream.adler = 0;
|
||||||
|
fStream.reserved = 0;
|
||||||
|
|
||||||
|
int zlibError = inflateInit(&fStream);
|
||||||
|
if (zlibError != Z_OK)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
fStreamInitialized = true;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ZlibDecompressor::DecompressNext(const void* input, size_t inputSize)
|
||||||
|
{
|
||||||
|
fStream.next_in = (Bytef*)input;
|
||||||
|
fStream.avail_in = inputSize;
|
||||||
|
|
||||||
|
while (fStream.avail_in > 0) {
|
||||||
|
if (fFinished)
|
||||||
|
return B_BAD_DATA;
|
||||||
|
|
||||||
|
uint8 outputBuffer[kOutputBufferSize];
|
||||||
|
fStream.next_out = (Bytef*)outputBuffer;
|
||||||
|
fStream.avail_out = sizeof(outputBuffer);
|
||||||
|
|
||||||
|
int zlibError = inflate(&fStream, 0);
|
||||||
|
if (zlibError == Z_STREAM_END)
|
||||||
|
fFinished = true;
|
||||||
|
else if (zlibError != Z_OK)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
if (fStream.avail_out < sizeof(outputBuffer)) {
|
||||||
|
status_t error = fOutput->WriteData(outputBuffer,
|
||||||
|
sizeof(outputBuffer) - fStream.avail_out);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ZlibDecompressor::Finish()
|
||||||
|
{
|
||||||
|
fStream.next_in = (Bytef*)NULL;
|
||||||
|
fStream.avail_in = 0;
|
||||||
|
|
||||||
|
while (!fFinished) {
|
||||||
|
uint8 outputBuffer[kOutputBufferSize];
|
||||||
|
fStream.next_out = (Bytef*)outputBuffer;
|
||||||
|
fStream.avail_out = sizeof(outputBuffer);
|
||||||
|
|
||||||
|
int zlibError = inflate(&fStream, Z_FINISH);
|
||||||
|
if (zlibError == Z_STREAM_END)
|
||||||
|
fFinished = true;
|
||||||
|
else if (zlibError != Z_OK)
|
||||||
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
if (fStream.avail_out < sizeof(outputBuffer)) {
|
||||||
|
status_t error = fOutput->WriteData(outputBuffer,
|
||||||
|
sizeof(outputBuffer) - fStream.avail_out);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inflateEnd(&fStream);
|
||||||
|
fStreamInitialized = false;
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*static*/ status_t
|
||||||
|
ZlibDecompressor::DecompressSingleBuffer(const void* input, size_t inputSize,
|
||||||
|
void* output, size_t outputSize, size_t& _uncompressedSize)
|
||||||
{
|
{
|
||||||
if (inputSize == 0 || outputSize == 0)
|
if (inputSize == 0 || outputSize == 0)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
@@ -51,7 +155,7 @@ ZlibDecompressor::Decompress(const void* input, size_t inputSize, void* output,
|
|||||||
return TranslateZlibError(zlibError);
|
return TranslateZlibError(zlibError);
|
||||||
|
|
||||||
|
|
||||||
// deflate
|
// inflate
|
||||||
status_t error = B_OK;
|
status_t error = B_OK;
|
||||||
zlibError = inflate(&zStream, Z_FINISH);
|
zlibError = inflate(&zStream, Z_FINISH);
|
||||||
if (zlibError != Z_STREAM_END) {
|
if (zlibError != Z_STREAM_END) {
|
||||||
|
|||||||
@@ -6,17 +6,34 @@
|
|||||||
#define ZLIB_DECOMPRESSOR_H
|
#define ZLIB_DECOMPRESSOR_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "ZlibCompressionBase.h"
|
#include "ZlibCompressionBase.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DataOutput;
|
||||||
|
|
||||||
|
|
||||||
class ZlibDecompressor : public ZlibCompressionBase {
|
class ZlibDecompressor : public ZlibCompressionBase {
|
||||||
public:
|
public:
|
||||||
ZlibDecompressor();
|
ZlibDecompressor(DataOutput* output);
|
||||||
~ZlibDecompressor();
|
~ZlibDecompressor();
|
||||||
|
|
||||||
status_t Decompress(const void* input, size_t inputSize,
|
status_t Init();
|
||||||
void* output, size_t outputSize,
|
status_t DecompressNext(const void* input,
|
||||||
|
size_t inputSize);
|
||||||
|
status_t Finish();
|
||||||
|
|
||||||
|
static status_t DecompressSingleBuffer(const void* input,
|
||||||
|
size_t inputSize, void* output,
|
||||||
|
size_t outputSize,
|
||||||
size_t& _uncompressedSize);
|
size_t& _uncompressedSize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
z_stream fStream;
|
||||||
|
DataOutput* fOutput;
|
||||||
|
bool fStreamInitialized;
|
||||||
|
bool fFinished;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user