1/* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <package/hpkg/ZlibCompressor.h> 8 9#include <errno.h> 10#include <stdio.h> 11 12#include <package/hpkg/DataOutput.h> 13 14 15namespace BPackageKit { 16 17namespace BHPKG { 18 19namespace BPrivate { 20 21 22static const size_t kOutputBufferSize = 1024; 23 24 25ZlibCompressor::ZlibCompressor(BDataOutput* output) 26 : 27 fOutput(output), 28 fStreamInitialized(false) 29{ 30} 31 32 33ZlibCompressor::~ZlibCompressor() 34{ 35 if (fStreamInitialized) 36 deflateEnd(&fStream); 37} 38 39 40status_t 41ZlibCompressor::Init() 42{ 43 // initialize the stream 44 fStream.next_in = NULL; 45 fStream.avail_in = 0; 46 fStream.total_in = 0; 47 fStream.next_out = NULL; 48 fStream.avail_out = 0; 49 fStream.total_out = 0; 50 fStream.msg = 0; 51 fStream.state = 0; 52 fStream.zalloc = Z_NULL; 53 fStream.zfree = Z_NULL; 54 fStream.opaque = Z_NULL; 55 fStream.data_type = 0; 56 fStream.adler = 0; 57 fStream.reserved = 0; 58 59 int zlibError = deflateInit(&fStream, Z_BEST_COMPRESSION); 60 if (zlibError != Z_OK) 61 return TranslateZlibError(zlibError); 62 63 fStreamInitialized = true; 64 65 return B_OK; 66} 67 68 69status_t 70ZlibCompressor::CompressNext(const void* input, size_t inputSize) 71{ 72 fStream.next_in = (Bytef*)input; 73 fStream.avail_in = inputSize; 74 75 while (fStream.avail_in > 0) { 76 uint8 outputBuffer[kOutputBufferSize]; 77 fStream.next_out = (Bytef*)outputBuffer; 78 fStream.avail_out = sizeof(outputBuffer); 79 80 int zlibError = deflate(&fStream, 0); 81 if (zlibError != Z_OK) 82 return TranslateZlibError(zlibError); 83 84 if (fStream.avail_out < sizeof(outputBuffer)) { 85 status_t error = fOutput->WriteData(outputBuffer, 86 sizeof(outputBuffer) - fStream.avail_out); 87 if (error != B_OK) 88 return error; 89 } 90 } 91 92 return B_OK; 93} 94 95 96status_t 97ZlibCompressor::Finish() 98{ 99 fStream.next_in = (Bytef*)NULL; 100 fStream.avail_in = 0; 101 102 while (true) { 103 uint8 outputBuffer[kOutputBufferSize]; 104 fStream.next_out = (Bytef*)outputBuffer; 105 fStream.avail_out = sizeof(outputBuffer); 106 107 int zlibError = deflate(&fStream, Z_FINISH); 108 if (zlibError != Z_OK && zlibError != Z_STREAM_END) 109 return TranslateZlibError(zlibError); 110 111 if (fStream.avail_out < sizeof(outputBuffer)) { 112 status_t error = fOutput->WriteData(outputBuffer, 113 sizeof(outputBuffer) - fStream.avail_out); 114 if (error != B_OK) 115 return error; 116 } 117 118 if (zlibError == Z_STREAM_END) 119 break; 120 } 121 122 deflateEnd(&fStream); 123 fStreamInitialized = false; 124 125 return B_OK; 126} 127 128 129/*static*/ status_t 130ZlibCompressor::CompressSingleBuffer(const void* input, size_t inputSize, 131 void* output, size_t outputSize, size_t& _compressedSize) 132{ 133 if (inputSize == 0 || outputSize == 0) 134 return B_BAD_VALUE; 135 136 // prepare stream 137 z_stream zStream = { 138 (Bytef*)input, // next_in 139 inputSize, // avail_in 140 0, // total_in 141 (Bytef*)output, // next_out 142 outputSize, // avail_out 143 0, // total_out 144 0, // msg 145 0, // state; 146 Z_NULL, // zalloc 147 Z_NULL, // zfree 148 Z_NULL, // opaque 149 0, // data_type 150 0, // adler 151 0 // reserved 152 }; 153 154 int zlibError = deflateInit(&zStream, Z_BEST_COMPRESSION); 155 if (zlibError != Z_OK) 156 return TranslateZlibError(zlibError); 157 158 // deflate 159 status_t error = B_OK; 160 zlibError = deflate(&zStream, Z_FINISH); 161 if (zlibError != Z_STREAM_END) { 162 if (zlibError == Z_OK) 163 error = B_BUFFER_OVERFLOW; 164 else 165 error = TranslateZlibError(zlibError); 166 } 167 168 // clean up 169 zlibError = deflateEnd(&zStream); 170 if (zlibError != Z_OK && error == B_OK) 171 error = TranslateZlibError(zlibError); 172 173 if (error != B_OK) 174 return error; 175 176 _compressedSize = zStream.total_out; 177 return B_OK; 178} 179 180 181} // namespace BPrivate 182 183} // namespace BHPKG 184 185} // namespace BPackageKit 186