buffer类的设计

来源:互联网 发布:人工智能就业 知乎 编辑:程序博客网 时间:2024/06/13 18:26

这个Buffer类被作为muduo的TcpConnection的buffer。
WSABUF和WSARecv 可以实现 iovec和readv一样的功能

#pragma once#include<vector>#include<string>#include<algorithm>#include<assert.h>class Buffer{public:    static const size_t kPrependSize = 8;    static const size_t kInitialSize = 1024;private:    static const char CRLF[];    std::vector<char> buffer_;    size_t readIndex_;    size_t writeIndex_;public:    Buffer(size_t initial_size = kInitialSize);    ~Buffer();    void swap(Buffer & buf);    size_t prependableBytes() const { return readIndex_; }    size_t readableBytes() const { return writeIndex_ - readIndex_; }    size_t writeableBytes() const { return buffer_.size() - writeIndex_; }    const char* peek() const { return begin() + readIndex_; }    char* beginWrite() { return begin() + writeIndex_; }    const char* beginWrite()const { return begin() + writeIndex_; }    //write    void ensureWriteable(size_t len)    {        if (writeableBytes() < len)        {            makeSpace(len);        }        assert(writeableBytes() > len);    }    void hasWritten(size_t len)    {        writeIndex_ += len;    }    void append(const std::string& str)    {        append(str.c_str(), str.size());    }    void append(const char* data, size_t len)// this function is internal impl    {        ensureWriteable(len);        std::copy(data, data + len, beginWrite());        hasWritten(len);    }    void append(const void* data, size_t len)    {        append(static_cast<const char*>(data), len);    }    void prepend(const void* data, size_t len)    {        assert(len < prependableBytes());        readIndex_ -= len;        const char* d = static_cast<const char*>(data);        std::copy(d, d + len, begin() + readIndex_);    }    //read    void retrieve(size_t len)// this function is internal impl    {        assert(len <= readableBytes());        if (len < readableBytes())            readIndex_ += len;        else            retrieveAll();    }    void retrieveUntil(const char* end)    {        size_t len = end - peek();        retrieve(len);    }    void retrieveAll()    {        readIndex_ = kPrependSize;        writeIndex_ = kPrependSize;    }    std::string retrieveAllAsString()    {        printf("retrieveAllAsString() of Buffer size=%d\n", readableBytes());        return retrieveAsString(readableBytes());    }    std::string retrieveAsString(size_t len)    {        assert(len <= readableBytes());        std::string ret(peek(), len);        printf("retrieveAllAsString string=%s\n", ret.c_str());        retrieve(len);        return ret;    }    //find    const char* findCRLF() const    {        const char *ret = std::search(peek(), beginWrite(), CRLF, CRLF + 2);        return ret == beginWrite() ? NULL : ret;    }    const char* findCRLF(const char* start) const    {        assert(peek() < start);        assert(start < beginWrite());        const char *ret = std::search(start, beginWrite(), CRLF, CRLF + 2);        return ret == beginWrite() ? NULL : ret;    }    const char* findEOL() const    {        const void *ret = memchr(peek(), '\n', readableBytes());        return static_cast<const char*>(ret);    }    const char* findEOL(const char* start) const    {        assert(peek() < start);        assert(start < beginWrite());        const void *ret = memchr(peek(), '\n', beginWrite() - start);        return static_cast<const char*>(ret);    }    //other    void shrink()    {        buffer_.shrink_to_fit();    }    intptr_t readFd(int fd, int* savedErrno);private:    char* begin() { return &*buffer_.begin(); }    const char* begin() const { return &*buffer_.begin(); }    void makeSpace(size_t len)    {        if (len + kPrependSize > writeableBytes() + prependableBytes())//确实需要扩充        {            buffer_.resize(len + kPrependSize);        }        else//prepend有足够空间        {            assert(readIndex_ > kPrependSize);            size_t read_able = readableBytes();            std::copy(begin() + readIndex_, begin() + writeIndex_, begin() + kPrependSize);            readIndex_ = kPrependSize;            writeIndex_ = readIndex_ + read_able;            assert(read_able == readableBytes());        }    }};
#include<WinSock2.h>#include <muduo_five\net\Buffer.h>#include<iostream>using std::cout; using std::cin; using std::endl;const char Buffer::CRLF[] = "\r\n";Buffer::Buffer(size_t initial_size) :    buffer_(kPrependSize + initial_size), readIndex_(kPrependSize), writeIndex_(kPrependSize){    assert(prependableBytes() == kPrependSize);    assert(readableBytes() == 0);    assert(writeableBytes() == kInitialSize);}Buffer::~Buffer(){}void Buffer::swap(Buffer & buf){    buffer_.swap(buf.buffer_);    std::swap(readIndex_, buf.readIndex_);    std::swap(writeIndex_, buf.writeIndex_);}//WSABUF like linux iovec, WSARecv like readv.intptr_t Buffer::readFd(int fd, int* savedErrno){    cout << "readFd() of Buffer  " << endl;    char extrabuf[65536];    WSABUF vec[2];    const size_t writable = writeableBytes();    vec[0].buf = begin() + writeIndex_;    vec[0].len = writable;    vec[1].buf = extrabuf;    vec[1].len = sizeof extrabuf;    // when there is enough space in this buffer, don't read into extrabuf.    // when extrabuf is used, we read 128k-1 bytes at most.    const int iovcnt = (writable < sizeof extrabuf) ? 2 : 1;    DWORD  n = 0;//count of received    DWORD flag = 0;    WSARecv(fd, vec, iovcnt, &n, &flag, NULL, NULL);    if (n < 0)    {        *savedErrno = errno;    }    else if (n <= DWORD(writable))    {        writeIndex_ += n;    }    else    {        writeIndex_ = buffer_.size();        append(extrabuf, n - writable);    }    return n;}
原创粉丝点击