代码语言:javascript复制
#pragma once
/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
///
/// @code
/// ------------------- ------------------ ------------------
/// | prependable bytes | readable bytes | writable bytes |
/// | | (CONTENT) | |
/// ------------------- ------------------ ------------------
/// | | | |
/// 0 <= readerIndex <= writerIndex <= size
/// @endcode
#include <vector>
#include <string>
class Buffer{
public:
~Buffer();
static const size_t kCheapPrepend = 8;
static const size_t kInittialSize = 8;
explicit Buffer(size_t initialSzie = kInittialSize)
:buffer_(kCheapPrepend = initialSzie),
readerIndex_(kCheapPrepend),
writerIndex_(kCheapPrepend),
{
}
size_t readablebuffer() const{
return writerIndex_ - readerIndex_;
}
size_t writeablebuffer() const{
return buffer_.size() - readerIndex_;
}
size_t prependablebuffer() const {
return readerIndex_;
}
const char* peek(){
retrn begin() readerIndex_;
}
//buffer类型转为string类型
void retrieve(size_t len){
if(len<readablebuffer()){
readerIndex_ = len;
}
else{
retrieve_all();
}
}
void retrieve_all(){
readerIndex_ = writerIndex_ = kCheapPrepend;
}
std::string retrieve_all_asString(){
return retrieve_asString(readableBytes()); //应用读取数据长度
}
std::string retrieve_asString(size_t len){
std::string result(peek(),len); //读取出可读取数据
retrieve(len); //对缓冲区进行复位操作
return result;
}
void ensurewriteablebytes(size_t len){
if(writerIndex_ < len){
makespace();
}
}
void append(const char* data,size_t len){
ensurewriteablebytes(len);
std::copy(data,data len,beginwrite());
writeIndex_ = len;
}
char* beginwrite(){
return begin() writeIndex_;
}
ssize_t readFD(int fd,int* saveerrno);
private:
char* begin(){
return &*buffer_.begin(); //vector底层首元素地址
}
const char* begin()const{
return &*buffer_.begin();
}
void makespace(){
if(writeablebuffer() prependablebuffer() < len kCheapPrepend){
buffer_.resize(writeIndex_ len);
}
else{
size_t readable = readableBytes();
std::copy(begin() readerIndex_,
begin() writerIndex_,
begin() kCheapPrepend);
readerIndex_ = kCheapPrepend;
writerIndex_ = readerIndex_ readable;
}
}
std::vector<char> buffer_;
size_t readerIndex_;
size_t writerIndex_;
};
代码语言:javascript复制#include "buffer.hpp"
#include <errno.h>
#include <sys/uio.h>
/*
从fd上读取数据
buffer有大小,但是流数据不知道大小
*/
ssize_t Buffer::readFD(int fd,int* saveerrno){
char exreabuf[65536] = {0}; //栈上的空间
struct iovec vec[2];
const size_t writable = writableBytes();
// 先往上面这个写
vec[0].iov_base = begin() writerIndex_;
vec[0].iov_len = writable;
//上面那个写完了再用这里的
vec[1].iov_base = extrabuf;
vec[1].iov_len = sizeof extrabuf;
const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;
const ssize_t n = sockets::readv(fd, vec, iovcnt);
if (n < 0){
*savedErrno = errno;
}
else if (n <= writable){
writerIndex_ = n;
}
else{
writerIndex_ = buffer_.size();
append(extrabuf, n - writable);
}
return n;
}