Buffer.h revision 714cd85f
1714cd85fSShuo Chen// excerpts from http://code.google.com/p/muduo/ 2714cd85fSShuo Chen// 3714cd85fSShuo Chen// Use of this source code is governed by a BSD-style license 4714cd85fSShuo Chen// that can be found in the License file. 5714cd85fSShuo Chen// 6714cd85fSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7714cd85fSShuo Chen 8714cd85fSShuo Chen#ifndef MUDUO_NET_BUFFER_H 9714cd85fSShuo Chen#define MUDUO_NET_BUFFER_H 10714cd85fSShuo Chen 11714cd85fSShuo Chen#include "datetime/copyable.h" 12714cd85fSShuo Chen 13714cd85fSShuo Chen#include <algorithm> 14714cd85fSShuo Chen#include <string> 15714cd85fSShuo Chen#include <vector> 16714cd85fSShuo Chen 17714cd85fSShuo Chen#include <assert.h> 18714cd85fSShuo Chen//#include <unistd.h> // ssize_t 19714cd85fSShuo Chen 20714cd85fSShuo Chennamespace muduo 21714cd85fSShuo Chen{ 22714cd85fSShuo Chen 23714cd85fSShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 24714cd85fSShuo Chen/// 25714cd85fSShuo Chen/// @code 26714cd85fSShuo Chen/// +-------------------+------------------+------------------+ 27714cd85fSShuo Chen/// | prependable bytes | readable bytes | writable bytes | 28714cd85fSShuo Chen/// | | (CONTENT) | | 29714cd85fSShuo Chen/// +-------------------+------------------+------------------+ 30714cd85fSShuo Chen/// | | | | 31714cd85fSShuo Chen/// 0 <= readerIndex <= writerIndex <= size 32714cd85fSShuo Chen/// @endcode 33714cd85fSShuo Chenclass Buffer : public muduo::copyable 34714cd85fSShuo Chen{ 35714cd85fSShuo Chen public: 36714cd85fSShuo Chen static const size_t kCheapPrepend = 8; 37714cd85fSShuo Chen static const size_t kInitialSize = 1024; 38714cd85fSShuo Chen 39714cd85fSShuo Chen Buffer() 40714cd85fSShuo Chen : buffer_(kCheapPrepend + kInitialSize), 41714cd85fSShuo Chen readerIndex_(kCheapPrepend), 42714cd85fSShuo Chen writerIndex_(kCheapPrepend) 43714cd85fSShuo Chen { 44714cd85fSShuo Chen assert(readableBytes() == 0); 45714cd85fSShuo Chen assert(writableBytes() == kInitialSize); 46714cd85fSShuo Chen assert(prependableBytes() == kCheapPrepend); 47714cd85fSShuo Chen } 48714cd85fSShuo Chen 49714cd85fSShuo Chen // default copy-ctor, dtor and assignment are fine 50714cd85fSShuo Chen 51714cd85fSShuo Chen void swap(Buffer& rhs) 52714cd85fSShuo Chen { 53714cd85fSShuo Chen buffer_.swap(rhs.buffer_); 54714cd85fSShuo Chen std::swap(readerIndex_, rhs.readerIndex_); 55714cd85fSShuo Chen std::swap(writerIndex_, rhs.writerIndex_); 56714cd85fSShuo Chen } 57714cd85fSShuo Chen 58714cd85fSShuo Chen size_t readableBytes() const 59714cd85fSShuo Chen { return writerIndex_ - readerIndex_; } 60714cd85fSShuo Chen 61714cd85fSShuo Chen size_t writableBytes() const 62714cd85fSShuo Chen { return buffer_.size() - writerIndex_; } 63714cd85fSShuo Chen 64714cd85fSShuo Chen size_t prependableBytes() const 65714cd85fSShuo Chen { return readerIndex_; } 66714cd85fSShuo Chen 67714cd85fSShuo Chen const char* peek() const 68714cd85fSShuo Chen { return begin() + readerIndex_; } 69714cd85fSShuo Chen 70714cd85fSShuo Chen // retrieve returns void, to prevent 71714cd85fSShuo Chen // string str(retrieve(readableBytes()), readableBytes()); 72714cd85fSShuo Chen // the evaluation of two functions are unspecified 73714cd85fSShuo Chen void retrieve(size_t len) 74714cd85fSShuo Chen { 75714cd85fSShuo Chen assert(len <= readableBytes()); 76714cd85fSShuo Chen readerIndex_ += len; 77714cd85fSShuo Chen } 78714cd85fSShuo Chen 79714cd85fSShuo Chen void retrieveUntil(const char* end) 80714cd85fSShuo Chen { 81714cd85fSShuo Chen assert(peek() <= end); 82714cd85fSShuo Chen assert(end <= beginWrite()); 83714cd85fSShuo Chen retrieve(end - peek()); 84714cd85fSShuo Chen } 85714cd85fSShuo Chen 86714cd85fSShuo Chen void retrieveAll() 87714cd85fSShuo Chen { 88714cd85fSShuo Chen readerIndex_ = kCheapPrepend; 89714cd85fSShuo Chen writerIndex_ = kCheapPrepend; 90714cd85fSShuo Chen } 91714cd85fSShuo Chen 92714cd85fSShuo Chen std::string retrieveAsString() 93714cd85fSShuo Chen { 94714cd85fSShuo Chen std::string str(peek(), readableBytes()); 95714cd85fSShuo Chen readerIndex_ = kCheapPrepend; 96714cd85fSShuo Chen writerIndex_ = kCheapPrepend; 97714cd85fSShuo Chen return str; 98714cd85fSShuo Chen } 99714cd85fSShuo Chen 100714cd85fSShuo Chen void append(const std::string& str) 101714cd85fSShuo Chen { 102714cd85fSShuo Chen append(str.data(), str.length()); 103714cd85fSShuo Chen } 104714cd85fSShuo Chen 105714cd85fSShuo Chen void append(const char* /*restrict*/ data, size_t len) 106714cd85fSShuo Chen { 107714cd85fSShuo Chen ensureWritableBytes(len); 108714cd85fSShuo Chen std::copy(data, data+len, beginWrite()); 109714cd85fSShuo Chen hasWritten(len); 110714cd85fSShuo Chen } 111714cd85fSShuo Chen 112714cd85fSShuo Chen void append(const void* /*restrict*/ data, size_t len) 113714cd85fSShuo Chen { 114714cd85fSShuo Chen append(static_cast<const char*>(data), len); 115714cd85fSShuo Chen } 116714cd85fSShuo Chen 117714cd85fSShuo Chen void ensureWritableBytes(size_t len) 118714cd85fSShuo Chen { 119714cd85fSShuo Chen if (writableBytes() < len) 120714cd85fSShuo Chen { 121714cd85fSShuo Chen makeSpace(len); 122714cd85fSShuo Chen } 123714cd85fSShuo Chen assert(writableBytes() >= len); 124714cd85fSShuo Chen } 125714cd85fSShuo Chen 126714cd85fSShuo Chen char* beginWrite() 127714cd85fSShuo Chen { return begin() + writerIndex_; } 128714cd85fSShuo Chen 129714cd85fSShuo Chen const char* beginWrite() const 130714cd85fSShuo Chen { return begin() + writerIndex_; } 131714cd85fSShuo Chen 132714cd85fSShuo Chen void hasWritten(size_t len) 133714cd85fSShuo Chen { writerIndex_ += len; } 134714cd85fSShuo Chen 135714cd85fSShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 136714cd85fSShuo Chen { 137714cd85fSShuo Chen assert(len <= prependableBytes()); 138714cd85fSShuo Chen readerIndex_ -= len; 139714cd85fSShuo Chen const char* d = static_cast<const char*>(data); 140714cd85fSShuo Chen std::copy(d, d+len, begin()+readerIndex_); 141714cd85fSShuo Chen } 142714cd85fSShuo Chen 143714cd85fSShuo Chen void shrink(size_t reserve) 144714cd85fSShuo Chen { 145714cd85fSShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 146714cd85fSShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 147714cd85fSShuo Chen buf.swap(buffer_); 148714cd85fSShuo Chen } 149714cd85fSShuo Chen 150714cd85fSShuo Chen /// Read data directly into buffer. 151714cd85fSShuo Chen /// 152714cd85fSShuo Chen /// It may implement with readv(2) 153714cd85fSShuo Chen /// @return result of read(2), @c errno is saved 154714cd85fSShuo Chen ssize_t readFd(int fd, int* savedErrno); 155714cd85fSShuo Chen 156714cd85fSShuo Chen private: 157714cd85fSShuo Chen 158714cd85fSShuo Chen char* begin() 159714cd85fSShuo Chen { return &*buffer_.begin(); } 160714cd85fSShuo Chen 161714cd85fSShuo Chen const char* begin() const 162714cd85fSShuo Chen { return &*buffer_.begin(); } 163714cd85fSShuo Chen 164714cd85fSShuo Chen void makeSpace(size_t len) 165714cd85fSShuo Chen { 166714cd85fSShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 167714cd85fSShuo Chen { 168714cd85fSShuo Chen buffer_.resize(writerIndex_+len); 169714cd85fSShuo Chen } 170714cd85fSShuo Chen else 171714cd85fSShuo Chen { 172714cd85fSShuo Chen // move readable data to the front, make space inside buffer 173714cd85fSShuo Chen assert(kCheapPrepend < readerIndex_); 174714cd85fSShuo Chen size_t readable = readableBytes(); 175714cd85fSShuo Chen std::copy(begin()+readerIndex_, 176714cd85fSShuo Chen begin()+writerIndex_, 177714cd85fSShuo Chen begin()+kCheapPrepend); 178714cd85fSShuo Chen readerIndex_ = kCheapPrepend; 179714cd85fSShuo Chen writerIndex_ = readerIndex_ + readable; 180714cd85fSShuo Chen assert(readable == readableBytes()); 181714cd85fSShuo Chen } 182714cd85fSShuo Chen } 183714cd85fSShuo Chen 184714cd85fSShuo Chen private: 185714cd85fSShuo Chen std::vector<char> buffer_; 186714cd85fSShuo Chen size_t readerIndex_; 187714cd85fSShuo Chen size_t writerIndex_; 188714cd85fSShuo Chen}; 189714cd85fSShuo Chen 190714cd85fSShuo Chen} 191714cd85fSShuo Chen 192714cd85fSShuo Chen#endif // MUDUO_NET_BUFFER_H 193