[haiku-commits] r34063 - in haiku/trunk/src/bin/package: . compression

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Sun, 15 Nov 2009 22:29:54 +0100 (CET)

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 ...]

Other related posts:

  • » [haiku-commits] r34063 - in haiku/trunk/src/bin/package: . compression - ingo_weinhold