* 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:
parent
5e5a7d535c
commit
689605bf2a
44
src/bin/package/DataOutput.cpp
Normal file
44
src/bin/package/DataOutput.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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;
|
||||
}
|
35
src/bin/package/DataOutput.h
Normal file
35
src/bin/package/DataOutput.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||
* 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_extract.cpp
|
||||
command_list.cpp
|
||||
DataOutput.cpp
|
||||
DataReader.cpp
|
||||
package.cpp
|
||||
PackageData.cpp
|
||||
|
@ -236,8 +236,9 @@ private:
|
||||
return error;
|
||||
|
||||
size_t actuallyUncompressedSize;
|
||||
error = ZlibDecompressor().Decompress(fReadBuffer, compressedSize,
|
||||
fUncompressBuffer, uncompressedSize, actuallyUncompressedSize);
|
||||
error = ZlibDecompressor::DecompressSingleBuffer(fReadBuffer,
|
||||
compressedSize, fUncompressBuffer, uncompressedSize,
|
||||
actuallyUncompressedSize);
|
||||
if (error == B_OK && actuallyUncompressedSize != uncompressedSize)
|
||||
error = B_BAD_DATA;
|
||||
}
|
||||
|
@ -14,20 +14,25 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <new>
|
||||
|
||||
#include <ByteOrder.h>
|
||||
|
||||
#include <haiku_package.h>
|
||||
|
||||
#include "DataOutput.h"
|
||||
#include "PackageData.h"
|
||||
#include "PackageEntry.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 kScratchBufferSize = 64 * 1024;
|
||||
|
||||
|
||||
enum {
|
||||
ATTRIBUTE_INDEX_DIRECTORY_ENTRY = 0,
|
||||
@ -604,7 +609,9 @@ PackageReader::PackageReader()
|
||||
fFD(-1),
|
||||
fTOCSection(NULL),
|
||||
fAttributeTypes(NULL),
|
||||
fStrings(NULL)
|
||||
fStrings(NULL),
|
||||
fScratchBuffer(NULL),
|
||||
fScratchBufferSize(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -614,6 +621,7 @@ PackageReader::~PackageReader()
|
||||
if (fFD >= 0)
|
||||
close(fFD);
|
||||
|
||||
delete[] fScratchBuffer;
|
||||
delete[] fStrings;
|
||||
delete[] fAttributeTypes;
|
||||
delete[] fTOCSection;
|
||||
@ -641,7 +649,7 @@ PackageReader::Init(const char* fileName)
|
||||
|
||||
// read the header
|
||||
hpkg_header header;
|
||||
status_t error = _ReadBuffer(&header, sizeof(header), 0);
|
||||
status_t error = _ReadBuffer(0, &header, sizeof(header));
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -751,6 +759,14 @@ PackageReader::Init(const char* fileName)
|
||||
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
|
||||
fTOCSection = new(std::nothrow) uint8[fTOCUncompressedLength];
|
||||
if (fTOCSection == NULL) {
|
||||
@ -758,7 +774,8 @@ PackageReader::Init(const char* fileName)
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
error = _ReadBuffer(fTOCSection, fTOCUncompressedLength, fTOCSectionOffset);
|
||||
error = _ReadCompressedBuffer(fTOCSectionOffset, fTOCSection,
|
||||
fTOCCompressedLength, fTOCUncompressedLength, fTOCCompression);
|
||||
if (error != B_OK)
|
||||
return error;
|
||||
|
||||
@ -1249,7 +1266,7 @@ PackageReader::_ReadTOCBuffer(void* buffer, size_t size)
|
||||
|
||||
|
||||
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);
|
||||
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
|
||||
PackageReader::_GetStandardIndex(const AttributeType* type)
|
||||
{
|
||||
|
@ -104,8 +104,12 @@ private:
|
||||
const void*& _buffer);
|
||||
status_t _ReadTOCBuffer(void* buffer, size_t size);
|
||||
|
||||
status_t _ReadBuffer(void* buffer, size_t size,
|
||||
off_t offset);
|
||||
status_t _ReadBuffer(off_t offset, void* buffer,
|
||||
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);
|
||||
|
||||
@ -141,6 +145,9 @@ private:
|
||||
char** fStrings;
|
||||
|
||||
AttributeHandlerList* fAttributeHandlerStack;
|
||||
|
||||
uint8* fScratchBuffer;
|
||||
size_t fScratchBufferSize;
|
||||
};
|
||||
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include <haiku_package.h>
|
||||
|
||||
#include "DataOutput.h"
|
||||
#include "DataReader.h"
|
||||
#include "FDCloser.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>
|
||||
@ -386,12 +529,16 @@ PackageWriter::_AddAttribute(const char* attributeName, Type value)
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PackageWriter
|
||||
|
||||
|
||||
PackageWriter::PackageWriter()
|
||||
:
|
||||
fFileName(NULL),
|
||||
fFD(-1),
|
||||
fFinished(false),
|
||||
fDataBuffer(NULL),
|
||||
fDataWriter(NULL),
|
||||
fRootEntry(NULL),
|
||||
fRootAttribute(NULL),
|
||||
fTopAttribute(NULL),
|
||||
@ -529,26 +676,11 @@ PackageWriter::_Finish()
|
||||
printf("header size: %lu\n", sizeof(hpkg_header));
|
||||
printf("heap size: %lld\n", fHeapEnd - sizeof(hpkg_header));
|
||||
|
||||
// write the attribute type abbreviations
|
||||
off_t attributeTypesOffset = fHeapEnd;
|
||||
_WriteAttributeTypes();
|
||||
printf("attributes types size: %lld\n", fHeapEnd - attributeTypesOffset);
|
||||
hpkg_header header;
|
||||
|
||||
// write the cached strings
|
||||
off_t cachedStringsOffset = fHeapEnd;
|
||||
int32 cachedStringsWritten = _WriteCachedStrings();
|
||||
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);
|
||||
// write the TOC and package attributes
|
||||
_WriteTOC(header);
|
||||
_WritePackageAttributes(header);
|
||||
|
||||
off_t totalSize = fHeapEnd;
|
||||
printf("total size: %lld\n", totalSize);
|
||||
@ -556,38 +688,12 @@ printf("total size: %lld\n", totalSize);
|
||||
// prepare the header
|
||||
|
||||
// general
|
||||
hpkg_header header;
|
||||
header.magic = B_HOST_TO_BENDIAN_INT32(B_HPKG_MAGIC);
|
||||
header.header_size = B_HOST_TO_BENDIAN_INT16(
|
||||
(uint16)sizeof(hpkg_header));
|
||||
header.version = B_HOST_TO_BENDIAN_INT16(B_HPKG_VERSION);
|
||||
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
|
||||
_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
|
||||
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
|
||||
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)
|
||||
_WriteUnsignedLEB128(value.data.offset);
|
||||
else
|
||||
_WriteBuffer(value.data.raw, value.data.size);
|
||||
fDataWriter->WriteDataThrows(value.data.raw, value.data.size);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -838,7 +1045,7 @@ PackageWriter::_WriteUnsignedLEB128(uint64 value)
|
||||
bytes[count++] = byte | (value != 0 ? 0x80 : 0);
|
||||
} while (value != 0);
|
||||
|
||||
_WriteBuffer(bytes, count);
|
||||
fDataWriter->WriteDataThrows(bytes, count);
|
||||
}
|
||||
|
||||
|
||||
@ -1237,10 +1444,9 @@ PackageWriter::_WriteZlibCompressedData(DataReader& dataReader, off_t size,
|
||||
}
|
||||
|
||||
// compress
|
||||
ZlibCompressor compressor;
|
||||
size_t compressedSize;
|
||||
error = compressor.Compress(inputBuffer, toCopy, outputBuffer,
|
||||
toCopy, compressedSize);
|
||||
error = ZlibCompressor::CompressSingleBuffer(inputBuffer, toCopy,
|
||||
outputBuffer, toCopy, compressedSize);
|
||||
|
||||
const void* writeBuffer;
|
||||
size_t bytesToWrite;
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
|
||||
class DataReader;
|
||||
struct hpkg_header;
|
||||
|
||||
|
||||
class PackageWriter {
|
||||
@ -32,6 +33,10 @@ private:
|
||||
struct Attribute;
|
||||
struct AttributeTypeUsageGreater;
|
||||
struct Entry;
|
||||
struct DataWriter;
|
||||
struct DummyDataWriter;
|
||||
struct FDDataWriter;
|
||||
struct ZlibDataWriter;
|
||||
|
||||
typedef BOpenHashTable<AttributeTypeHashDefinition>
|
||||
AttributeTypeTable;
|
||||
@ -46,10 +51,15 @@ private:
|
||||
const char* name, size_t nameLength,
|
||||
bool isImplicit);
|
||||
|
||||
void _WriteTOC(hpkg_header& header);
|
||||
int32 _WriteTOCSections(uint64& _attributeTypesSize,
|
||||
uint64& _stringsSize, uint64& _mainSize);
|
||||
void _WriteAttributeTypes();
|
||||
int32 _WriteCachedStrings();
|
||||
void _WriteAttributeChildren(Attribute* attribute);
|
||||
|
||||
void _WritePackageAttributes(hpkg_header& header);
|
||||
|
||||
void _WriteAttributeValue(
|
||||
const AttributeValue& value,
|
||||
uint8 encoding);
|
||||
@ -61,7 +71,6 @@ private:
|
||||
|
||||
void _WriteBuffer(const void* buffer, size_t size,
|
||||
off_t offset);
|
||||
inline void _WriteBuffer(const void* buffer, size_t size);
|
||||
|
||||
void _AddEntry(int dirFD, Entry* entry,
|
||||
const char* fileName);
|
||||
@ -100,6 +109,8 @@ private:
|
||||
void* fDataBuffer;
|
||||
size_t fDataBufferSize;
|
||||
|
||||
DataWriter* fDataWriter;
|
||||
|
||||
Entry* fRootEntry;
|
||||
|
||||
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
|
||||
|
@ -7,23 +7,121 @@
|
||||
#include "ZlibCompressor.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()
|
||||
{
|
||||
if (fStreamInitialized)
|
||||
deflateEnd(&fStream);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ZlibCompressor::Compress(const void* input, size_t inputSize, void* output,
|
||||
size_t outputSize, size_t& _compressedSize)
|
||||
ZlibCompressor::Init()
|
||||
{
|
||||
// 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)
|
||||
return B_BAD_VALUE;
|
||||
|
@ -6,17 +6,32 @@
|
||||
#define ZLIB_COMPRESSOR_H
|
||||
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "ZlibCompressionBase.h"
|
||||
|
||||
|
||||
class DataOutput;
|
||||
|
||||
|
||||
class ZlibCompressor : public ZlibCompressionBase {
|
||||
public:
|
||||
ZlibCompressor();
|
||||
ZlibCompressor(DataOutput* output);
|
||||
~ZlibCompressor();
|
||||
|
||||
status_t Compress(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize,
|
||||
size_t& _compressedSize);
|
||||
status_t Init();
|
||||
status_t CompressNext(const void* input,
|
||||
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 <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()
|
||||
{
|
||||
if (fStreamInitialized)
|
||||
inflateEnd(&fStream);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ZlibDecompressor::Decompress(const void* input, size_t inputSize, void* output,
|
||||
size_t outputSize, size_t& _uncompressedSize)
|
||||
ZlibDecompressor::Init()
|
||||
{
|
||||
// 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)
|
||||
return B_BAD_VALUE;
|
||||
@ -51,7 +155,7 @@ ZlibDecompressor::Decompress(const void* input, size_t inputSize, void* output,
|
||||
return TranslateZlibError(zlibError);
|
||||
|
||||
|
||||
// deflate
|
||||
// inflate
|
||||
status_t error = B_OK;
|
||||
zlibError = inflate(&zStream, Z_FINISH);
|
||||
if (zlibError != Z_STREAM_END) {
|
||||
|
@ -6,17 +6,34 @@
|
||||
#define ZLIB_DECOMPRESSOR_H
|
||||
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "ZlibCompressionBase.h"
|
||||
|
||||
|
||||
class DataOutput;
|
||||
|
||||
|
||||
class ZlibDecompressor : public ZlibCompressionBase {
|
||||
public:
|
||||
ZlibDecompressor();
|
||||
ZlibDecompressor(DataOutput* output);
|
||||
~ZlibDecompressor();
|
||||
|
||||
status_t Decompress(const void* input, size_t inputSize,
|
||||
void* output, size_t outputSize,
|
||||
status_t Init();
|
||||
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);
|
||||
|
||||
private:
|
||||
z_stream fStream;
|
||||
DataOutput* fOutput;
|
||||
bool fStreamInitialized;
|
||||
bool fFinished;
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user