Я написал простой фильтр для Boost iostreams, который определяет, является ли файл сжатым или простым текстом, и делегировал бы gzip_decompressor
, если это так.
Проблема в том, что я возвращаюсь в свой входной поток, чтобы снова подать данные внутри декомпрессора. Только некоторые потоки не поддерживают это и прерываются с помощью резкого исключения потока.
Вместо этого я подумал: хорошо, давайте использовать basic_array_source
для подачи двух символов, но этот источник не поддерживает вызов read
!
Так что это работает постоянно:
struct gz_decompressor {
typedef char char_type;
typedef boost::iostreams::multichar_input_filter_tag category;
boost::iostreams::gzip_decompressor m_decompressor{15, backtest::GzReader::GZIP_BUFFER_SIZE};
bool m_initialized{false};
bool m_is_compressed{false};
template<typename Source>
std::streamsize read(Source& src, char* s, std::streamsize n) {
if (!m_initialized) {
init(src, s, n);
}
if (m_is_compressed) {
return m_decompressor.read(src, s, n);
}
return boost::iostreams::read(src, s, n);
}
};
Часть, которую я не могу понять:
template<typename Source>
void init(Source& src, char* s, std::streamsize n) {
char header[2];
header[0] = boost::iostreams::get(src);
header[1] = boost::iostreams::get(src);
m_is_compressed = header[0] == static_cast<char>(0x1f) && header[2] == static_cast<char>(0x8b);
m_initialized = true;
boost::iostreams::basic_array_source<char> source(header);
if (m_is_compressed) {
m_decompressor.read(source, s, n); // Nope, is not allowed!
}
else {
boost::iostreams::read(source, s, n);
}
}
Любая подсказка о том, как сделать это правильно, то есть без поиска назад?