Boost.ipcの有効利用(?)

というレベルではないですが Boost.Property_treeで暗号化したiniファイルを読んでみる - 名古屋313の日記 で暗号化を行うのに一度バッファを作って取るのが面倒だなあ、と思ったのでこれはBoost.ipcのメモリマップドファイルの出番ではないかと思いちょっとやってみました。ipcからはfile_mapping, mapped_region, ibufferstreamを利用しています。多分わざわざBoost.ipcを使う必要はなくて、普通にifstreamとかofstreamとか使った方が良いです。

#include <boost/interprocess/file_mapping.hpp>
#include <boost/interprocess/mapped_region.hpp>
#include <boost/interprocess/streams/bufferstream.hpp>
#include <boost/range/algorithm/transform.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/iostreams/filtering_stream.hpp>
#include <boost/iostreams/copy.hpp>
#include <fstream>
#include <iterator>

// ものすごく適当な暗号化/復号キー
static const int Key = 0x1E;

// ipc.mapped_regionからイテレータのペアを作る
template<class T>
boost::iterator_range<T*> make_mapped_range( boost::interprocess::mapped_region const& view )
{
	auto beg = reinterpret_cast<T*>(view.get_address());
	auto end = reinterpret_cast<T*>(view.get_address()) + view.get_size();
	return boost::iterator_range<T*>(beg,end);
}

// 復号用
struct filter : public boost::iostreams::input_filter
{
	template<class Source>
	int get( Source& src )
	{
		const int c = boost::iostreams::get(src);
		if( c == EOF )
			return c;
		else
			return c ^ Key;
	}
};

int main()
{
	namespace ipc = boost::interprocess;
	namespace io  = boost::iostreams;

	{
		ipc::file_mapping map("graph.png",ipc::read_only);
		ipc::mapped_region view(map,ipc::read_only);
		std::ofstream ofs("encrypt_copy.png",std::ios::out | std::ios::binary);

		// 超適当な暗号化
		boost::transform(make_mapped_range<char const>(view)
			, std::ostream_iterator<char>(ofs),[]( const char x ){ return x ^ Key; } );
	}
	{
		ipc::file_mapping map("encrypt_copy.png",ipc::read_only);
		ipc::mapped_region view(map,ipc::read_only);
		// ipc.ibufferstreamを使って暗号化したファイルのビューをストリームで読み取れるようにする
		ipc::ibufferstream bis(reinterpret_cast<char*>(view.get_address())
			,view.get_size(),std::ios::in | std::ios::binary);

		std::ofstream ofs("copy.png",std::ios::out | std::ios::binary);

		// 暗号を解除しながらコピー
		io::filtering_istream fi;
		fi.push(filter());
		fi.push(bis);
		io::copy(fi,ofs);
	}
}