Author: bonefish Date: 2009-11-15 22:29:53 +0100 (Sun, 15 Nov 2009) New Revision: 34063 Changeset: http://dev.haiku-os.org/changeset/34063/haiku Added: haiku/trunk/src/bin/package/DataOutput.cpp haiku/trunk/src/bin/package/DataOutput.h Modified: haiku/trunk/src/bin/package/Jamfile haiku/trunk/src/bin/package/PackageDataReader.cpp haiku/trunk/src/bin/package/PackageReader.cpp haiku/trunk/src/bin/package/PackageReader.h haiku/trunk/src/bin/package/PackageWriter.cpp haiku/trunk/src/bin/package/PackageWriter.h haiku/trunk/src/bin/package/compression/ZlibCompressor.cpp haiku/trunk/src/bin/package/compression/ZlibCompressor.h haiku/trunk/src/bin/package/compression/ZlibDecompressor.cpp haiku/trunk/src/bin/package/compression/ZlibDecompressor.h Log: * Added support for iterative operation to ZlibCompressor/ZlibDecompressor. * Added support for compressing/decompressing the TOC section of the package to PackageWriter/PackageReader. Added: haiku/trunk/src/bin/package/DataOutput.cpp =================================================================== --- haiku/trunk/src/bin/package/DataOutput.cpp (rev 0) +++ haiku/trunk/src/bin/package/DataOutput.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -0,0 +1,44 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * 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; +} Added: haiku/trunk/src/bin/package/DataOutput.h =================================================================== --- haiku/trunk/src/bin/package/DataOutput.h (rev 0) +++ haiku/trunk/src/bin/package/DataOutput.h 2009-11-15 21:29:53 UTC (rev 34063) @@ -0,0 +1,35 @@ +/* + * Copyright 2009, Ingo Weinhold, ingo_weinhold@xxxxxxx + * 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 Modified: haiku/trunk/src/bin/package/Jamfile =================================================================== --- haiku/trunk/src/bin/package/Jamfile 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/Jamfile 2009-11-15 21:29:53 UTC (rev 34063) @@ -14,6 +14,7 @@ command_dump.cpp command_extract.cpp command_list.cpp + DataOutput.cpp DataReader.cpp package.cpp PackageData.cpp Modified: haiku/trunk/src/bin/package/PackageDataReader.cpp =================================================================== --- haiku/trunk/src/bin/package/PackageDataReader.cpp 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/PackageDataReader.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -236,8 +236,9 @@ 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; } Modified: haiku/trunk/src/bin/package/PackageReader.cpp =================================================================== --- haiku/trunk/src/bin/package/PackageReader.cpp 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/PackageReader.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -14,21 +14,26 @@ #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, ATTRIBUTE_INDEX_FILE_TYPE, @@ -604,7 +609,9 @@ fFD(-1), fTOCSection(NULL), fAttributeTypes(NULL), - fStrings(NULL) + fStrings(NULL), + fScratchBuffer(NULL), + fScratchBufferSize(0) { } @@ -614,6 +621,7 @@ if (fFD >= 0) close(fFD); + delete[] fScratchBuffer; delete[] fStrings; delete[] fAttributeTypes; delete[] fTOCSection; @@ -641,7 +649,7 @@ // 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 @@ 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 @@ 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 @@ 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 @@ } +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) { Modified: haiku/trunk/src/bin/package/PackageReader.h =================================================================== --- haiku/trunk/src/bin/package/PackageReader.h 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/PackageReader.h 2009-11-15 21:29:53 UTC (rev 34063) @@ -104,8 +104,12 @@ 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 @@ char** fStrings; AttributeHandlerList* fAttributeHandlerStack; + + uint8* fScratchBuffer; + size_t fScratchBufferSize; }; Modified: haiku/trunk/src/bin/package/PackageWriter.cpp =================================================================== --- haiku/trunk/src/bin/package/PackageWriter.cpp 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/PackageWriter.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -25,6 +25,7 @@ #include <haiku_package.h> +#include "DataOutput.h" #include "DataReader.h" #include "FDCloser.h" #include "Stacker.h" @@ -373,10 +374,152 @@ }; -// #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> inline PackageWriter::Attribute* PackageWriter::_AddAttribute(const char* attributeName, Type value) { @@ -386,12 +529,16 @@ } +// #pragma mark - PackageWriter + + PackageWriter::PackageWriter() : fFileName(NULL), fFD(-1), fFinished(false), fDataBuffer(NULL), + fDataWriter(NULL), fRootEntry(NULL), fRootAttribute(NULL), fTopAttribute(NULL), @@ -529,65 +676,24 @@ 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 and package attributes + _WriteTOC(header); + _WritePackageAttributes(header); - // 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; 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); @@ -667,6 +773,79 @@ 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() { // create an array of the attribute types @@ -763,6 +942,34 @@ 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) { switch (value.type) { @@ -815,7 +1022,7 @@ 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 @@ bytes[count++] = byte | (value != 0 ? 0x80 : 0); } while (value != 0); - _WriteBuffer(bytes, count); + fDataWriter->WriteDataThrows(bytes, count); } @@ -1237,10 +1444,9 @@ } // 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; Modified: haiku/trunk/src/bin/package/PackageWriter.h =================================================================== --- haiku/trunk/src/bin/package/PackageWriter.h 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/PackageWriter.h 2009-11-15 21:29:53 UTC (rev 34063) @@ -13,6 +13,7 @@ class DataReader; +struct hpkg_header; class PackageWriter { @@ -32,6 +33,10 @@ struct Attribute; struct AttributeTypeUsageGreater; struct Entry; + struct DataWriter; + struct DummyDataWriter; + struct FDDataWriter; + struct ZlibDataWriter; typedef BOpenHashTable<AttributeTypeHashDefinition> AttributeTypeTable; @@ -46,10 +51,15 @@ 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 @@ 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 @@ void* fDataBuffer; size_t fDataBufferSize; + DataWriter* fDataWriter; + Entry* fRootEntry; Attribute* fRootAttribute; @@ -110,27 +121,4 @@ }; -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 Modified: haiku/trunk/src/bin/package/compression/ZlibCompressor.cpp =================================================================== --- haiku/trunk/src/bin/package/compression/ZlibCompressor.cpp 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/compression/ZlibCompressor.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -7,24 +7,122 @@ #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; Modified: haiku/trunk/src/bin/package/compression/ZlibCompressor.h =================================================================== --- haiku/trunk/src/bin/package/compression/ZlibCompressor.h 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/compression/ZlibCompressor.h 2009-11-15 21:29:53 UTC (rev 34063) @@ -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; }; Modified: haiku/trunk/src/bin/package/compression/ZlibDecompressor.cpp =================================================================== --- haiku/trunk/src/bin/package/compression/ZlibDecompressor.cpp 2009-11-15 18:11:58 UTC (rev 34062) +++ haiku/trunk/src/bin/package/compression/ZlibDecompressor.cpp 2009-11-15 21:29:53 UTC (rev 34063) @@ -7,24 +7,128 @@ #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); } [... truncated: 155 lines follow ...]