缩略muduo库:Buffer 缓冲区

Posted 看,未来

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了缩略muduo库:Buffer 缓冲区相关的知识,希望对你有一定的参考价值。

#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_;
};
#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;
}

以上是关于缩略muduo库:Buffer 缓冲区的主要内容,如果未能解决你的问题,请参考以下文章

缩略muduo网络库周边小代码

缩略muduo网络库周边小代码

缩略muduo库:TcpServer

缩略muduo库:事件循环 EventLoop

缩略muduo库:事件循环 EventLoop

缩略muduo库:ThreadEventThreadEventThreadPool