Buffer.h revision ffbff871
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()); 95ffbff871SShuo Chen retrieveAll(); 96714cd85fSShuo Chen return str; 97714cd85fSShuo Chen } 98714cd85fSShuo Chen 99714cd85fSShuo Chen void append(const std::string& str) 100714cd85fSShuo Chen { 101714cd85fSShuo Chen append(str.data(), str.length()); 102714cd85fSShuo Chen } 103714cd85fSShuo Chen 104714cd85fSShuo Chen void append(const char* /*restrict*/ data, size_t len) 105714cd85fSShuo Chen { 106714cd85fSShuo Chen ensureWritableBytes(len); 107714cd85fSShuo Chen std::copy(data, data+len, beginWrite()); 108714cd85fSShuo Chen hasWritten(len); 109714cd85fSShuo Chen } 110714cd85fSShuo Chen 111714cd85fSShuo Chen void append(const void* /*restrict*/ data, size_t len) 112714cd85fSShuo Chen { 113714cd85fSShuo Chen append(static_cast<const char*>(data), len); 114714cd85fSShuo Chen } 115714cd85fSShuo Chen 116714cd85fSShuo Chen void ensureWritableBytes(size_t len) 117714cd85fSShuo Chen { 118714cd85fSShuo Chen if (writableBytes() < len) 119714cd85fSShuo Chen { 120714cd85fSShuo Chen makeSpace(len); 121714cd85fSShuo Chen } 122714cd85fSShuo Chen assert(writableBytes() >= len); 123714cd85fSShuo Chen } 124714cd85fSShuo Chen 125714cd85fSShuo Chen char* beginWrite() 126714cd85fSShuo Chen { return begin() + writerIndex_; } 127714cd85fSShuo Chen 128714cd85fSShuo Chen const char* beginWrite() const 129714cd85fSShuo Chen { return begin() + writerIndex_; } 130714cd85fSShuo Chen 131714cd85fSShuo Chen void hasWritten(size_t len) 132714cd85fSShuo Chen { writerIndex_ += len; } 133714cd85fSShuo Chen 134714cd85fSShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 135714cd85fSShuo Chen { 136714cd85fSShuo Chen assert(len <= prependableBytes()); 137714cd85fSShuo Chen readerIndex_ -= len; 138714cd85fSShuo Chen const char* d = static_cast<const char*>(data); 139714cd85fSShuo Chen std::copy(d, d+len, begin()+readerIndex_); 140714cd85fSShuo Chen } 141714cd85fSShuo Chen 142714cd85fSShuo Chen void shrink(size_t reserve) 143714cd85fSShuo Chen { 144714cd85fSShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 145714cd85fSShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 146714cd85fSShuo Chen buf.swap(buffer_); 147714cd85fSShuo Chen } 148714cd85fSShuo Chen 149714cd85fSShuo Chen /// Read data directly into buffer. 150714cd85fSShuo Chen /// 151714cd85fSShuo Chen /// It may implement with readv(2) 152714cd85fSShuo Chen /// @return result of read(2), @c errno is saved 153714cd85fSShuo Chen ssize_t readFd(int fd, int* savedErrno); 154714cd85fSShuo Chen 155714cd85fSShuo Chen private: 156714cd85fSShuo Chen 157714cd85fSShuo Chen char* begin() 158714cd85fSShuo Chen { return &*buffer_.begin(); } 159714cd85fSShuo Chen 160714cd85fSShuo Chen const char* begin() const 161714cd85fSShuo Chen { return &*buffer_.begin(); } 162714cd85fSShuo Chen 163714cd85fSShuo Chen void makeSpace(size_t len) 164714cd85fSShuo Chen { 165714cd85fSShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 166714cd85fSShuo Chen { 167714cd85fSShuo Chen buffer_.resize(writerIndex_+len); 168714cd85fSShuo Chen } 169714cd85fSShuo Chen else 170714cd85fSShuo Chen { 171714cd85fSShuo Chen // move readable data to the front, make space inside buffer 172714cd85fSShuo Chen assert(kCheapPrepend < readerIndex_); 173714cd85fSShuo Chen size_t readable = readableBytes(); 174714cd85fSShuo Chen std::copy(begin()+readerIndex_, 175714cd85fSShuo Chen begin()+writerIndex_, 176714cd85fSShuo Chen begin()+kCheapPrepend); 177714cd85fSShuo Chen readerIndex_ = kCheapPrepend; 178714cd85fSShuo Chen writerIndex_ = readerIndex_ + readable; 179714cd85fSShuo Chen assert(readable == readableBytes()); 180714cd85fSShuo Chen } 181714cd85fSShuo Chen } 182714cd85fSShuo Chen 183714cd85fSShuo Chen private: 184714cd85fSShuo Chen std::vector<char> buffer_; 185714cd85fSShuo Chen size_t readerIndex_; 186714cd85fSShuo Chen size_t writerIndex_; 187714cd85fSShuo Chen}; 188714cd85fSShuo Chen 189714cd85fSShuo Chen} 190714cd85fSShuo Chen 191714cd85fSShuo Chen#endif // MUDUO_NET_BUFFER_H 192