为C++istream定制流缓冲区
Customized streambuffer for C++ istream
本文关键字:缓冲区 C++istream 更新时间:2023-10-16
基本上,我为istream
操作实现了一个传统的基于文件描述符的流缓冲区。该实现覆盖sync
和underflow
函数,而在sync
中,缓冲区将在必要时自动放大(就像vector
一样)。
class InputStreamBuffer : public std::basic_streambuf<char> {
private:
// small stack buffer optimization
constexpr static size_t _STACK_BUFSZ = 128;
static_assert(_STACK_BUFSZ >= 1, "Stack buffer size should be at least 1");
char_type _stk [_STACK_BUFSZ];
char_type* _buf {_stk};
size_t _size {_STACK_BUFSZ};
const int _fd {-1};
public:
InputStreamBuffer(const int);
~InputStreamBuffer();
protected:
int sync() override;
int_type underflow() override;
};
InputStreamBuffer::InputStreamBuffer(const int fd) :
_fd {fd} {
setg(_buf, _buf, _buf);
}
InputStreamBuffer::~InputStreamBuffer() {
if(_buf != _stk) {
std::free(_buf);
}
}
int InputStreamBuffer::sync() {
auto success = int {0};
while(1) {
size_t empty = gptr() - eback();
size_t avail = egptr() - gptr();
// Before we issue the read, make sure we have enough space.
if(egptr() == eback() + _size) {
// Reuse the empty region.
if(empty > _size / 2) {
std::memmove(eback(), gptr(), avail);
}
// Double the array size.
else {
_size = _size * 2;
auto chunk = static_cast<char_type*>(std::malloc(_size*sizeof(char_type)));
std::memcpy(chunk, gptr(), avail);
if(_buf != _stk) std::free(_buf);
_buf = chunk;
}
setg(_buf, _buf, _buf + avail);
}
// Read the data.
issue_read:
auto ret = ::read(_fd, egptr(), _size - avail);
if(ret == -1) {
if(errno == EINTR) {
goto issue_read;
}
if(errno != EAGAIN && errno != EWOULDBLOCK) {
success = -1;
}
break;
}
else if(ret == 0) {
break;
}
setg(eback(), gptr(), egptr() + ret);
}
return success;
}
InputStreamBuffer::int_type InputStreamBuffer::underflow() {
int success = sync();
if(success == -1 || gptr() == egptr()) return traits_type::eof();
return *(gptr());
}
这里的想法是将这个流缓冲区与非阻塞io一起使用。io多路复用器将自主调用sync
,并调用用户注册的回调来执行istream
风格的操作。简单地说,以下是我的一些问题:
输入流缓冲区具有称为"putback"的特定类型的操作。使用
putback
的潜在好处是什么?当到达
EOF
时,::read
将返回0
,这是一个非常有用的指示基于套接字的IO连接状态的信号。在sync
中处理此问题的最佳实践是什么?我当前的实现只是跳过了这个。任何可以改进实施的意见都将不胜感激!
根据Edd先生对自定义流缓冲区实现的非常有用的介绍,
为与istream一起使用而编写的输入流缓冲区往往比为ostream编写的输出缓冲区复杂一点。这是因为我们应该努力允许用户在合理的程度上将字符放回流中,这是通过
std::istream
的putback()
成员函数完成的。这意味着我们需要在数组的开头保留一个部分,用于放置回空间。通常,预计会有一个字符的放回空间,尽管一般来说,我们没有理由不能提供更多。
另请参阅https://stackoverflow.com/a/39078167/1399272.
相关文章:
- C++字符*缓冲区的大小
- 为什么msgrcv()将垃圾字符馈送到缓冲区
- 为什么istream不支持右值提取
- 将无符号char*转换为std::istream*C++
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- ostream过载时的缓冲区冲洗
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- Xaudio2在更改缓冲区或循环时弹出声音
- 为什么我在leetcode上收到AddressSanitizer:地址0x602000000058上的堆缓冲区溢出错误
- 需要从 istream 和 ostream 派生 iostream
- 如何将图像传输到c++(dll)中的缓冲区,然后在c#的缓冲区中读/写
- 如何在cpp.中使用协议缓冲区存储大缓冲区/数组(char/int)
- 多线程双缓冲区
- istream std::cin如何修改自定义istream缓冲区
- 将缓冲区转换为在现有程序中工作的iStream
- IStream COM 读取到缓冲区,然后通过 winsock 发送
- 为C++istream定制流缓冲区
- 字符缓冲区的istream
- 如何在c++中读取标准istream缓冲区
- 从IStream读取到缓冲区(音频)