はじめに
base64 を作りたいと思って調べたら boost::serialization の Dataflow Iterators が便利そう。
Serialization - Dataflow Iterators
実際に書いてみた
#include <iostream> #include <boost/pfto.hpp> #include <boost/archive/iterators/base64_from_binary.hpp> #include <boost/archive/iterators/transform_width.hpp> int main() { using namespace std; using namespace boost::archive::iterators; typedef base64_from_binary<transform_width<istream_iterator<char>, 6, 8 > > base64_iterator; copy( base64_iterator(BOOST_MAKE_PFTO_WRAPPER(istream_iterator<char>(cin))), base64_iterator(BOOST_MAKE_PFTO_WRAPPER(istream_iterator<char>())), ostream_iterator<char>(cout) ); }
ちょっと解説
transform_width
transform_width
以下のような感じ
#include <iostream> #include <boost/pfto.hpp> #include <boost/archive/iterators/transform_width.hpp> int main() { using namespace std; using namespace boost::archive::iterators; unsigned char buf[] = { 0xff, 0xff, 0x00 }; transform_width<unsigned char *, 6, 8 > it(BOOST_PFTO_WRAPPER(buf)); // input 11111111 11111111 00000000 // output 111111 111111 111100 000000 cout << static_cast<int>(*it) << endl; // => 63 (00111111) ++it; cout << static_cast<int>(*it) << endl; // => 63 (00111111) ++it; cout << static_cast<int>(*it) << endl; // => 60 (00111100) ++it; cout << static_cast<int>(*it) << endl; // => 0 (00000000) }
BOOST_PFTO_WRAPPER
これは、
template<class T> void f(T a) { ... } //(どんな型でも OK) template<class T> void f(T* a) { ... } //(ポインタだけ )
のような関数テンプレートがあって f(&obj) とやったときにどっちのテンプレートを使っていいか分からないコンパイラのためにあるマクロ。
定義側を
template<class T> void f(BOOST_PFTO_WRAPPER(T) a) { ... } //(PFTO_WRAPPER なやつだけ OK) template<class T> void f(T* a) { ... } //(ポインタだけ )
としておくと f(&obj) とやればポインタのほうだとわかるし、上のほうを呼びたければ f(BOOST_MAKE_PFTO_WRAPPER(obj)) と明示的にやってやればいい。