Прозрачно манипулирующие строки, вставленные в ostream - PullRequest
2 голосов
/ 07 октября 2010

Я хотел бы предоставить std::ostream, который может или не может, с точки зрения пользователя, зашифровать его содержимое.

Представьте себе некоторую случайную функцию, которая использует std::ostream&:

void write_stuff( std::ostream& stream ) {
    os << "stuff";
}

Будет ли stuff выводиться в виде открытого текста или зашифровано, зависит от того, как был инициализирован аргумент stream.

Я думаю о наследовании от std::basic_streambuf, но яне уверен, что это лучший путь.Я думаю, что идеальный сценарий - это какой-то объект фильтра, который запускается до того, как содержимое действительно выводится.Таким образом было бы легко объединять операции, например, шифровать, а затем кодировать в шестнадцатеричном формате, что является преимуществом, так как создание собственного basic_streambuf, похоже, не дает (по крайней мере, не легко).

Любые советы?

Спасибо.

ОБНОВЛЕНИЕ : Я следовал стратегии, изложенной в принятом ответе.Мне показалось, что эта статья о написании custom streambuf, которая выполняет обфускацию XOR , чрезвычайно полезна в качестве отправной точки.

Ответы [ 3 ]

4 голосов
/ 07 октября 2010

A streambuf может быть реализовано в виде другого произвольного streambuf, который либо передается в качестве аргумента конструктору, либо устанавливается с помощью специальной функции-члена. И это позволяет вам составлять streambuf реализации, о которых вы думали.

Вы могли бы даже создать манипулятор, который использует функцию ostream s rdbuf для получения текущего streambuf, вызвать функцию на вашем streambuf, которая устанавливает «сложенный» streambuf, и затем вызвать rdbuf снова, чтобы заменить ostream streambuf на ваш собственный.

aes_ctr_streambuf encrypter(key);
zlib_streambuf compressor;
::std::cout << stack_streambuf(encrypter) << stack_streambuf(compressor);
2 голосов
/ 07 октября 2010

Трудно описать вкратце, что вам нужно сделать, чтобы создать поток ввода-вывода для нового источника или приемника.К счастью, Джонатан Турканис и CodeRage, LLC создали очень хорошие строительные блоки с исключительной документацией, которые могут помочь вам сэкономить сотни часов исследований и разработок новых потоков.Библиотека называется Boost.Iostreams .

Второй пример в документации точно показывает, как решить вашу проблему.

Также обратите внимание, что ониуже есть выходной поток со сжатием zip.Поэтому, возможно, вам даже не нужно писать ни одной строки кода.

Удачи!

0 голосов
/ 07 октября 2010

Я не уверен, что то, что я собираюсь предложить, это именно то, что вам нужно (и это слишком сложно, чтобы быть комментарием), но вы когда-нибудь слышали о потоковых манипуляторах ?

#include <iostream>
#include <iomanip>

int main(int, char**)
{
  int a = 10;
  std::cout << "a: " << a << std::endl; //outputs: "a: 10"
  std::cout << "a: " << std::hex << a << std::endl; //outputs: "a: a"
  std::cout << "a: " << std::dec << a << std::endl; //outputs: "a: 10"

  return EXIT_SUCCESS;
}

Вы действительно можете использовать подобный шаблон (это соответствует тому, что вы на самом деле называете объектом «фильтра»), чтобы каким-то образом изменить состояние вашего пользовательского объекта потока.

...