2

在询问有关 crypto++的问题后,我尝试使用 boost iostreams 来实现它。我生成了以下代码:

#include <iostream>
#include <cryptopp/sha.h>
#include <algorithm>
#include <boost/array.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/operations.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/device/file.hpp>

template<typename hash>
class sha_output_filter : public boost::iostreams::output_filter
{
  hash _hash;
  char _digest[hash::DIGESTSIZE];
public:
  typedef char                                 char_type;
  typedef boost::iostreams::output_filter_tag  category;

  sha_output_filter() {}
  //sha_output_filter(const sha_output_filter &) = delete;
  sha_output_filter &operator=(const sha_output_filter &) = delete;

  template<typename Sink>
  bool put (Sink &dest, int c)
  {
    std::cout << "put" << std::endl;
    char _c = c;
    _hash.Update ((const byte *)&_c, 1);
    boost::iostreams::put (dest, c);
  }

  template<typename Source>
  void close (Source &src)
  {
    std::cout << "close" << std::endl;
    _hash.Final(_digest);
  }

  boost::array<char, hash::DIGESTSIZE> digest() {
    boost::array<char, hash::DIGESTSIZE> tmp;
    std::copy(_digest, _digest + hash::DIGESTSIZE, tmp.begin() );
    return tmp;
  }
};

int main()
{
  sha_output_filter<CryptoPP::SHA1> outf;
  boost::iostreams::filtering_ostream out;
  out.set_auto_close (true);
  out.push(outf);
  out.push(boost::iostreams::file_sink("my_file.txt"));
  std::cout << "write" << std::endl;
  out.write("123\n", 4);
  out.pop ();
  out.pop ();
  boost::iostreams::file_sink hash_out("hash.txt");
  boost::array<char, CryptoPP::SHA1::DIGESTSIZE> digest = outf.digest();
  hash_out.write(digest.begin (), CryptoPP::SHA1::DIGESTSIZE);
}

问题编号 1:如果我使 sha_output_filter 不可复制,尽管文档说明“如果 T 是标准流或流缓冲区类型,则通过使用 push 的模板化重载采用非常量引用”,它不起作用。但如果我取消注释行:

In file included from /usr/include/boost/iostreams/traits.hpp:31:0,
                 from /usr/include/boost/iostreams/detail/dispatch.hpp:17,
                 from /usr/include/boost/iostreams/flush.hpp:17,
                 from /usr/include/boost/iostreams/close.hpp:18,
                 from /usr/include/boost/iostreams/operations.hpp:16,
                 from test.cpp:6:
test.cpp: In function ‘T boost::iostreams::detail::wrap(const T&, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’:
/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   instantiated from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:257:60:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:216:1:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
/usr/include/boost/iostreams/chain.hpp:496:7:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:484:1:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
test.cpp:51:16:   instantiated from here
test.cpp:20:3: error: deleted function ‘sha_output_filter<hash>::sha_output_filter(const sha_output_filter<hash>&) [with hash = CryptoPP::SHA1, sha_output_filter<hash> = sha_output_filter<CryptoPP::SHA1>]’
/usr/include/boost/iostreams/detail/wrap_unwrap.hpp:53:14: error: used here
In file included from /usr/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp:23:0,
                 from /usr/include/boost/iostreams/stream_buffer.hpp:22,
                 from /usr/include/boost/iostreams/chain.hpp:35,
                 from /usr/include/boost/iostreams/filtering_streambuf.hpp:17,
                 from /usr/include/boost/iostreams/filtering_stream.hpp:22,
                 from test.cpp:7:
test.cpp: In constructor ‘boost::iostreams::detail::concept_adapter<T>::concept_adapter(const T&) [with T = sha_output_filter<CryptoPP::SHA1>]’:
/usr/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp:187:5:   instantiated from ‘void boost::iostreams::detail::indirect_streambuf<T, Tr, Alloc, Mode>::open(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/stream_buffer.hpp:106:13:   instantiated from ‘void boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::open_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   instantiated from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:257:60:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:216:1:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
/usr/include/boost/iostreams/chain.hpp:496:7:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:484:1:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
test.cpp:51:16:   instantiated from here
test.cpp:20:3: error: deleted function ‘sha_output_filter<hash>::sha_output_filter(const sha_output_filter<hash>&) [with hash = CryptoPP::SHA1, sha_output_filter<hash> = sha_output_filter<CryptoPP::SHA1>]’
/usr/include/boost/iostreams/detail/adapter/concept_adapter.hpp:67:48: error: used here
test.cpp: In copy constructor ‘boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >::concept_adapter(const boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >&)’:
/usr/include/boost/iostreams/detail/adapter/concept_adapter.hpp:38:23:   instantiated from ‘void boost::iostreams::detail::optional<T>::reset(const T&) [with T = boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >]’
/usr/include/boost/iostreams/detail/streambuf/indirect_streambuf.hpp:187:5:   instantiated from ‘void boost::iostreams::detail::indirect_streambuf<T, Tr, Alloc, Mode>::open(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/stream_buffer.hpp:106:13:   instantiated from ‘void boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::open_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/stream_buffer.hpp:94:5:   instantiated from ‘boost::iostreams::stream_buffer<T, Tr, Alloc, Mode>::stream_buffer(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:257:60:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:216:1:   instantiated from ‘void boost::iostreams::detail::chain_base<Self, Ch, Tr, Alloc, Mode>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Self = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, Ch = char, Tr = std::char_traits<char>, Alloc = std::allocator<char>, Mode = boost::iostreams::output, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
/usr/include/boost/iostreams/chain.hpp:496:7:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push_impl(const T&, std::streamsize, std::streamsize) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int]’
/usr/include/boost/iostreams/chain.hpp:484:1:   instantiated from ‘void boost::iostreams::detail::chain_client<Chain>::push(const T&, std::streamsize, std::streamsize, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter<CryptoPP::SHA1>, Chain = boost::iostreams::chain<boost::iostreams::output, char, std::char_traits<char>, std::allocator<char> >, std::streamsize = long int, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]’
test.cpp:51:16:   instantiated from here
test.cpp:20:3: error: deleted function ‘sha_output_filter<hash>::sha_output_filter(const sha_output_filter<hash>&) [with hash = CryptoPP::SHA1, sha_output_filter<hash> = sha_output_filter<CryptoPP::SHA1>]’
/usr/include/boost/iostreams/detail/adapter/concept_adapter.hpp:38:23: error: used here
In file included from /usr/include/boost/iostreams/detail/streambuf/direct_streambuf.hpp:26:0,
                 from /usr/include/boost/iostreams/stream_buffer.hpp:21,
                 from /usr/include/boost/iostreams/chain.hpp:35,
                 from /usr/include/boost/iostreams/filtering_streambuf.hpp:17,
                 from /usr/include/boost/iostreams/filtering_stream.hpp:22,
                 from test.cpp:7:
/usr/include/boost/iostreams/detail/optional.hpp: In member function ‘void boost::iostreams::detail::optional<T>::reset(const T&) [with T = boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >]’:
/usr/include/boost/iostreams/detail/optional.hpp:100:9: note: synthesized method ‘boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >::concept_adapter(const boost::iostreams::detail::concept_adapter<sha_output_filter<CryptoPP::SHA1> >&)’ first required here

然而boost::ref作品。


问题编号 2. 如何关闭流?调试输出为:

write
put
put
put
put
4

1 回答 1

5

第一个问题是你sha_output_filter不满足使用 的非常量重载的要求push,因为它不是从std::istream,std::ostream或派生的std::streambuf,所以不属于标准流或流缓冲区类型。
这可以从编译器的第一条消息中推断出来

test.cpp: 在函数'T boost::iostreams::detail::wrap(const T&, typename boost::disable_if<boost::iostreams::is_std_io<T> >::type*) [with T = sha_output_filter< CryptoPP::SHA1>,类型名 boost::disable_if<boost::iostreams::is_std_io<T> >::type = void]':

它表明它可以成功解决boost::disable_if<...>::type,因此它不会禁用此重载。如果您查看源代码,您可能会发现enable_if对非常量重载的测试。


关于第二个问题,您的过滤器未标记为可关闭,因此 Boost 库不知道它可以调用close过滤器。

这可以通过将 typedef 替换category

struct category : boost::iostreams::output_filter_tag, boost::iostreams::closable_tag {};
于 2011-01-12T19:37:40.487 回答