#pragma once #include namespace DB { class CompressedReadBuffer : public CompressedReadBufferBase, public BufferWithOwnMemory { private: size_t size_compressed = 0; bool nextImpl() { size_t size_decompressed; size_compressed = readCompressedData(size_decompressed); if (!size_compressed) return false; memory.resize(size_decompressed); working_buffer = Buffer(&memory[0], &memory[size_decompressed]); decompress(working_buffer.begin(), size_decompressed); return true; } public: CompressedReadBuffer(ReadBuffer & in_) : CompressedReadBufferBase(&in_), BufferWithOwnMemory(0) { } size_t readBig(char * to, size_t n) { size_t bytes_read = 0; /// Если в буфере есть непрочитанные байты, то скопируем сколько надо в to. if (pos < working_buffer.end()) bytes_read += read(to, std::min(static_cast(working_buffer.end() - pos), n)); /// Если надо ещё прочитать - будем, по возможности, разжимать сразу в to. while (bytes_read < n) { size_t size_decompressed; if (!readCompressedData(size_decompressed)) return bytes_read; /// Если разжатый блок помещается целиком туда, куда его надо скопировать. if (size_decompressed <= n - bytes_read) { decompress(to + bytes_read, size_decompressed); bytes_read += size_decompressed; bytes += size_decompressed; } else { bytes += offset(); memory.resize(size_decompressed); working_buffer = Buffer(&memory[0], &memory[size_decompressed]); pos = working_buffer.begin(); decompress(working_buffer.begin(), size_decompressed); bytes_read += read(to + bytes_read, n - bytes_read); break; } } return bytes_read; } /// Сжатый размер текущего блока. size_t getSizeCompressed() const { return size_compressed; } }; }