缩略muduo库(7):Buffer 缓冲区

2021-10-09 15:33:42 浏览数 (1)

代码语言: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;
}

0 人点赞