制限された入力サイズのチャンネルを通して成長バッファを部分的に送るコンプレッサーの設計に成功しました。私はここで、同じ問題に取り組んでいる人に答えを出しました。 ThxからMark Adlerへ、 へ私を正しい道に導くためのMSalters。
class zStreamManager {
public:
zStreamManager();
~zStreamManager();
void endStream();
void addToStream(const void *inData, size_t inDataSize);
private:
// Size of base64 encoded is about 4*originalSize/3 + (3 to 6)
// so with maximum output size of 4096, 3050 max zipped out
// buffer will be fine
const size_t CHUNK_IN = 1024, CHUNK_OUT = 3050;
const std::string base64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"/";
bool deallocated = true;
z_stream stream;
std::vector<uint8_t> outBuffer;
std::string base64Encode(std::vector<uint8_t> &str);
};
zStreamManager::~zStreamManager() {
endStream();
}
void zStreamManager::endStream() {
if(!deallocated) {
deallocated = true;
uint8_t tempBuffer[CHUNK_IN];
int response = Z_OK;
unsigned int have;
while(response == Z_OK) {
if (stream.avail_out == 0) {
outBuffer.insert(outBuffer.end(), tempBuffer, tempBuffer + CHUNK_IN);
stream.next_out = tempBuffer;
stream.avail_out = CHUNK_IN;
}
response = deflate(&stream, Z_FINISH);
}
have = CHUNK_IN - stream.avail_out;
if(have)
outBuffer.insert(outBuffer.end(), tempBuffer, tempBuffer + have);
deflateEnd(&stream);
if(outBuffer.size())
SEND << outBuffer << "$";
}
}
void zStreamManager::addToStream(const void *inData, size_t inDataSize) {
if(deallocated) {
deallocated = false;
stream.zalloc = 0;
stream.zfree = 0;
stream.opaque = 0;
deflateInit(&stream, 9);
}
std::vector<uint8_t> tempBuffer(inDataSize);
unsigned int have;
stream.next_in = reinterpret_cast<uint8_t *>(const_cast<void*>(inData));
stream.avail_in = inDataSize;
stream.next_out = &tempBuffer[0];
stream.avail_out = inDataSize;
while (stream.avail_in != 0) {
deflate(&stream, Z_SYNC_FLUSH);
if (stream.avail_out == 0) {
outBuffer.insert(outBuffer.end(), tempBuffer.begin(), tempBuffer.begin() + inDataSize);
stream.next_out = &tempBuffer[0];
stream.avail_out = inDataSize;
}
}
have = inDataSize - stream.avail_out;
if(have)
outBuffer.insert(outBuffer.end(), tempBuffer.begin(), tempBuffer.begin() + have);
while(outBuffer.size() >= CHUNK_OUT) {
std::vector<uint8_t> zipped;
zipped.insert(zipped.end(), outBuffer.begin(), outBuffer.begin() + CHUNK_OUT);
outBuffer.erase(outBuffer.begin(), outBuffer.begin() + CHUNK_OUT);
if(zipped.size())
SEND << zipped << "|";
}
}
std::string zStreamManager::base64Encode(std::vector<uint8_t> &str) {
/* ALTERED VERSION OF René Nyffenegger BASE64 CODE
Copyright (C) 2004-2008 René Nyffenegger
This source code is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this source code must not be misrepresented; you must not
claim that you wrote the original source code. If you use this source code
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original source code.
3. This notice may not be removed or altered from any source distribution.
René Nyffenegger [email protected]
*/
unsigned char const* bytes_to_encode = &str[0];
unsigned int in_len = str.size();
std::string ret;
int i = 0, j = 0;
unsigned char char_array_3[3], char_array_4[4];
while(in_len--) {
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(i = 0; (i <4) ; i++)
ret += base64Chars[char_array_4[i]];
i = 0;
}
}
if(i) {
for(j = i; j < 3; j++)
char_array_3[j] = '\0';
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
char_array_4[3] = char_array_3[2] & 0x3f;
for(j = 0; (j < i + 1); j++)
ret += base64Chars[char_array_4[j]];
while((i++ < 3))
ret += '=';
}
return ret;
}
ユースケース:RECEIVE
とSEND
、バッファを受信し、チャネルを介して送信するために使用される方法で
zStreamManager zm;
string growingBuffer = "";
bool somethingToSend = true;
while(somethingToSend) {
RECEIVE(&growingBuffer);
if(growingBuffer.size()) {
zm.addToStream(growingBuffer.c_str(), growingBuffer.size());
growingBuffer.clear();
} else {
somethingToSend = false;
}
}
zm.endStream();
。圧縮解除のために、各部分は '|'バッファ全体の終わりは '$'で区切られています。各パートは、base64でデコードされ、次に連結されなければなりません。最後に、他の圧縮データのようにzlibで圧縮解除することができます。
本当にzlibについてのアイデアはありませんが、あなたの状況を処理できるLZMAを見てください。 http://7-zip.org/sdk.html – antipattern