Повысьте Iostreams zlib_error с помощью собственного источника

Я пытаюсь использовать zlib_decompressor распаковать данные через istreambuf_iterator, Я не смог найти встроенный способ использовать итератор ввода в качестве входного потока (пожалуйста, укажите способ, если он уже существует), поэтому я написал этот источник:

template <class cha_type, class iterator_type>
class IteratorSource {
public:
typedef cha_type char_type;
typedef boost::iostreams::source_tag category;
iterator_type& i;
iterator_type eof;

IteratorSource(iterator_type& it, iterator_type end) : i(it), eof(end) {
}

std::streamsize read(char* s, std::streamsize n) {
for(int j = 0; j < n; j++) {
if(i == eof) {
std::cout << "Reached eof after " << j << " bytes\n";
return -1;
}
char next = *i++;
std::cout << "Reading " << next << "\n";
*s++ = next;
}
return n;
}
};

И использовал это так:

int main() {
std::vector<char> data_back = {'\x78', '\x9c', '\x73', '\x04', '\x00', '\x00', '\x42', '\x00', '\x42'};
auto start = data_back.begin();
IteratorSource<char, decltype(data_back)::iterator> data(start, data_back.end());

boost::iostreams::filtering_istreambuf def;
def.push(boost::iostreams::zlib_decompressor());
def.push(data);
boost::iostreams::copy(def, std::cout);
return 0;
}

Чтобы дать этот вывод:

Reading x
Reading �
Reading s
Reading
Reading
Reading
Reading B
Reading
Reading B
Reached eof after 9 bytes
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::iostreams::zlib_error> >'
what():  zlib error
Aborted (core dumped)

Я не уверен, почему это приводит к ошибке, потому что загрузка из файла работает нормально.

4

Решение

РЕДАКТИРОВАТЬ В ответ на уточненный вопрос (в комментариях ниже), вот тривиальная адаптация, которую я сделал для вашего исходного образца, что JustWorks ™ на моей коробке:

#include <boost/iostreams/copy.hpp>
#include <boost/iostreams/filter/zlib.hpp>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <iostream>
#include <sstream>

template <class cha_type, class iterator_type>
struct my_source {
typedef cha_type char_type;
typedef boost::iostreams::source_tag category;

iterator_type& it;
iterator_type end;

my_source(iterator_type& it, iterator_type end = {}) : it(it), end(end)
{ }

std::streamsize read(char* s, std::streamsize n) {
std::streamsize result = 0;
while ((it!=end) && n--) {
++result;
*s++ = *it++;
}
return result;
}
};

int main() {
std::string const rawdata {'x', '\234', '\313', 'H', '\315', '\311', '\311', 'W', '(', '\317', '/', '\312', 'I', '\341', '\002', '\0', '\036', 'r', '\004', 'g' };
std::istringstream iss(rawdata, std::ios::binary);

auto start = std::istreambuf_iterator<char>(iss);
my_source<char, decltype(start)> data(start);

boost::iostreams::filtering_istreambuf def;
def.push(boost::iostreams::zlib_decompressor());
def.push(data);

boost::iostreams::copy(def, std::cout);
}

Видеть это Жить на Колиру


Старый ответ:

Я думаю, что вы можете использовать любой поток, например stringstream:

std::istringstream iss("hello world\n");

filtering_streambuf<input> def;
def.push(zlib_compressor());
def.push(iss);
boost::iostreams::copy(def, std::cout);

или распаковать:

std::string const rawdata {'x', '\234', '\313', 'H', '\315', '\311', '\311', 'W', '(', '\317', '/', '\312', 'I', '\341', '\002', '\0', '\036', 'r', '\004', 'g' };
std::istringstream iss(rawdata, std::ios::binary);

filtering_streambuf<input> def;
def.push(zlib_decompressor());
def.push(iss);
boost::iostreams::copy(def, std::cout);

Это работает как шарм здесь. (Извините за восьмеричные побеги: это то, что дал мне Баш

printf "%q\n" "$(echo hello world | zlib-flate -compress)"

и я достаточно ленив, чтобы так держать).

Смотрите полный пример Жить на Колиру


альтернативно Boost Iostreams принимает потоковый буфер, так что вы можете эквивалентно

def.push(*iss.rdbuf());
4

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector