arbitrary_positional_facade
位置復元可能ストリームを元に任意位置ストリームを生成するヘルパクラスを作成しました。
namespace hamigaki { namespace iostreams { template<class Derived, class CharT, std::streamsize MaxBlockSize> class arbitrary_positional_facade; // iterator_core_accessと同じ役割 class core_access { #if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) public: #else template<class Derived, class CharT, std::streamsize MaxBlockSize> friend class arbitrary_positional_facade; #endif template<class RepositionalSource, class CharT> static std::streamsize read_blocks( RepositionalSource& src, CharT* s, std::streamsize n) { return src.read_blocks(s, n); } template<class RepositionalSink, class CharT> static std::streamsize write_blocks( RepositionalSink& sink, const CharT* s, std::streamsize n) { return sink.write_blocks(s, n); } }; template<class Derived, class CharT, std::streamsize MaxBlockSize> class arbitrary_positional_facade { private: typedef CharT char_type; Derived& derived() { return *static_cast<Derived*>(this); } protected: // 派生クラスからアクセスしやすいように typedef arbitrary_positional_facade< Derived,CharT,MaxBlockSize> arbitrary_positional_facade_; public: explicit arbitrary_positional_facade(std::streamsize block_size) : block_size_(block_size), count_(0) { } std::streamsize read(char_type* s, std::streamsize n) { if ((count_ == 0) && ((n % block_size_) == 0)) return core_access::read_blocks(derived(), s, n/block_size_); else { // 略 } } std::streamsize write(const char_type* s, std::streamsize n); private: char_type buffer_[MaxBlockSize]; std::streamsize block_size_; std::streamsize count_; // バッファに格納されている文字数 }; } } // End namespaces iostreams, hamigaki.
これを使って、
class my_sink : public hamigaki::iostreams::arbitrary_positional_facade<my_sink, char, 4> { // write_blocks()にアクセスできるようにする friend class hamigaki::iostreams::core_access; public: explicit my_sink(const pcm_format& f) : arbitrary_positional_facade(f.block_size()) { } private: // 直接呼ばれるとバッファリングが狂うのでprivateにする std::streamsize write_blocks(const char* s, std::streamsize n) { // nブロック書き出す }
とすると、write_blocks()からバッファリング付きのwrite()が導出されます。
以下、TODO。
- seek()のサポート
- Seekableのように入力と出力でヘッドを共有している場合は、read()とwrite()で同期を取る
- Bidirectionalの場合はバッファを2つ用意する
modeによって場合分けが発生するのがBoost.Iostreamsの面倒なところです。