これは単純で、私の指の先ではありませんが、これらの線に沿った何かがうまくいくと思います:
template <unsigned BUF_SIZE>
struct Buffer {
char buf_[BUF_SIZE];
int len_;
Buffer () : buf_(), len_(0) {}
int read (int fd) {
int r = read(fd, buf_ + len_, BUF_SIZE - len_);
if (r > 0) len_ += r;
return r;
}
int capacity () const { return BUF_SIZE - len_; }
}
template <unsigned BUF_SIZE>
struct BufferStream {
typedef std::unique_ptr< Buffer<BUF_SIZE> > BufferPtr;
std::vector<BufferPtr> stream_;
BufferStream () : stream_(1, BufferPtr(new Buffer<BUF_SIZE>)) {}
int read (int fd) {
if ((*stream_.rbegin())->capacity() == 0)
stream_.push_back(BufferPtr(new Buffer<BUF_SIZE>));
return (*stream_.rbegin())->read(fd);
}
};
コメントで、大きなcharバッファの作成を避けたいとおっしゃいました。システムコールを使用する場合、read
一般に、多数の小さな読み取りよりも、いくつかの大きな読み取りを実行する方が効率的です。したがって、ほとんどの実装では、その効率を上げるために大きな入力バッファを選択します。次のようなものを実装できます。
std::vector<char> input;
char in;
int r;
while ((r = read(fd, &in, 1)) == 1) input.push_back(in);
ただし、これにはシステムコールが含まれ、入力のバイトごとに少なくとも1バイトがコピーされます。対照的に、私が提示したコードは、余分なデータコピーを回避します。
私が出したコードがあなたが採用する解決策になるとは本当に期待していません。かなりスペースと時間の効率が良い自己拡張オブジェクトを作成する方法の図を提供したかっただけです。目的に応じて、拡張することも、独自に作成することもできます。頭から離れて、いくつかの改善点は次のとおりです。
std::list
代わりに、ベクトルのサイズ変更を避けるために使用してください
- APIに、読み取るバイト数を指定するパラメーターを許可します
readv
一度に少なくともBUF_SIZE
バイト(またはバイト以上BUF_SIZE
)の読み取りを常に許可するために使用します