+ emit readyRead();
+ return;
+ }
+
+ // We let zlib directly append to the readBuffer, which means we pre-allocate extra space for ioBufferSize.
+ // Afterwards, we'll shrink the buffer appropriately. Since shrinking should not reallocate, the readBuffer's
+ // capacity should over time adapt to the largest message sizes we encounter. However, this is not a bad thing
+ // considering that otherwise (using an intermediate buffer) we'd copy around data for every single message.
+ // TODO: Benchmark if it would still make sense to squeeze the buffer from time to time (e.g. after initial sync)!
+
+ while (_socket->bytesAvailable() && _readBuffer.size() + ioBufferSize < maxBufferSize && _inputBuffer.size() < ioBufferSize) {
+ _readBuffer.resize(_readBuffer.size() + ioBufferSize);
+ _inputBuffer.append(_socket->read(ioBufferSize - _inputBuffer.size()));
+
+ _inflater->next_in = reinterpret_cast<unsigned char *>(_inputBuffer.data());
+ _inflater->avail_in = _inputBuffer.size();
+ _inflater->next_out = reinterpret_cast<unsigned char *>(_readBuffer.data() + _readBuffer.size() - ioBufferSize);
+ _inflater->avail_out = ioBufferSize;
+
+ const unsigned char *orig_out = _inflater->next_out; // so we see if we have actually produced any output
+
+ int status = inflate(_inflater, Z_SYNC_FLUSH); // get as much data as possible
+
+ // adjust input and output buffers
+ _readBuffer.resize(_inflater->next_out - reinterpret_cast<unsigned char *>(_readBuffer.data()));
+ if (_inflater->avail_in > 0)
+ memmove(_inputBuffer.data(), _inflater->next_in, _inflater->avail_in);
+ _inputBuffer.resize(_inflater->avail_in);