1354280cfSShuo Chen// excerpts from http://code.google.com/p/muduo/ 2354280cfSShuo Chen// 3354280cfSShuo Chen// Use of this source code is governed by a BSD-style license 4354280cfSShuo Chen// that can be found in the License file. 5354280cfSShuo Chen// 6354280cfSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7354280cfSShuo Chen 8354280cfSShuo Chen#ifndef MUDUO_NET_BUFFER_H 9354280cfSShuo Chen#define MUDUO_NET_BUFFER_H 10354280cfSShuo Chen 11354280cfSShuo Chen#include "datetime/copyable.h" 12354280cfSShuo Chen 13354280cfSShuo Chen#include <algorithm> 14354280cfSShuo Chen#include <string> 15354280cfSShuo Chen#include <vector> 16354280cfSShuo Chen 17354280cfSShuo Chen#include <assert.h> 18354280cfSShuo Chen//#include <unistd.h> // ssize_t 19354280cfSShuo Chen 20354280cfSShuo Chennamespace muduo 21354280cfSShuo Chen{ 22354280cfSShuo Chen 23354280cfSShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 24354280cfSShuo Chen/// 25354280cfSShuo Chen/// @code 26354280cfSShuo Chen/// +-------------------+------------------+------------------+ 27354280cfSShuo Chen/// | prependable bytes | readable bytes | writable bytes | 28354280cfSShuo Chen/// | | (CONTENT) | | 29354280cfSShuo Chen/// +-------------------+------------------+------------------+ 30354280cfSShuo Chen/// | | | | 31354280cfSShuo Chen/// 0 <= readerIndex <= writerIndex <= size 32354280cfSShuo Chen/// @endcode 33354280cfSShuo Chenclass Buffer : public muduo::copyable 34354280cfSShuo Chen{ 35354280cfSShuo Chen public: 36354280cfSShuo Chen static const size_t kCheapPrepend = 8; 37354280cfSShuo Chen static const size_t kInitialSize = 1024; 38354280cfSShuo Chen 39354280cfSShuo Chen Buffer() 40354280cfSShuo Chen : buffer_(kCheapPrepend + kInitialSize), 41354280cfSShuo Chen readerIndex_(kCheapPrepend), 42354280cfSShuo Chen writerIndex_(kCheapPrepend) 43354280cfSShuo Chen { 44354280cfSShuo Chen assert(readableBytes() == 0); 45354280cfSShuo Chen assert(writableBytes() == kInitialSize); 46354280cfSShuo Chen assert(prependableBytes() == kCheapPrepend); 47354280cfSShuo Chen } 48354280cfSShuo Chen 49354280cfSShuo Chen // default copy-ctor, dtor and assignment are fine 50354280cfSShuo Chen 51354280cfSShuo Chen void swap(Buffer& rhs) 52354280cfSShuo Chen { 53354280cfSShuo Chen buffer_.swap(rhs.buffer_); 54354280cfSShuo Chen std::swap(readerIndex_, rhs.readerIndex_); 55354280cfSShuo Chen std::swap(writerIndex_, rhs.writerIndex_); 56354280cfSShuo Chen } 57354280cfSShuo Chen 58354280cfSShuo Chen size_t readableBytes() const 59354280cfSShuo Chen { return writerIndex_ - readerIndex_; } 60354280cfSShuo Chen 61354280cfSShuo Chen size_t writableBytes() const 62354280cfSShuo Chen { return buffer_.size() - writerIndex_; } 63354280cfSShuo Chen 64354280cfSShuo Chen size_t prependableBytes() const 65354280cfSShuo Chen { return readerIndex_; } 66354280cfSShuo Chen 67354280cfSShuo Chen const char* peek() const 68354280cfSShuo Chen { return begin() + readerIndex_; } 69354280cfSShuo Chen 70354280cfSShuo Chen // retrieve returns void, to prevent 71354280cfSShuo Chen // string str(retrieve(readableBytes()), readableBytes()); 72354280cfSShuo Chen // the evaluation of two functions are unspecified 73354280cfSShuo Chen void retrieve(size_t len) 74354280cfSShuo Chen { 75354280cfSShuo Chen assert(len <= readableBytes()); 76354280cfSShuo Chen readerIndex_ += len; 77354280cfSShuo Chen } 78354280cfSShuo Chen 79354280cfSShuo Chen void retrieveUntil(const char* end) 80354280cfSShuo Chen { 81354280cfSShuo Chen assert(peek() <= end); 82354280cfSShuo Chen assert(end <= beginWrite()); 83354280cfSShuo Chen retrieve(end - peek()); 84354280cfSShuo Chen } 85354280cfSShuo Chen 86354280cfSShuo Chen void retrieveAll() 87354280cfSShuo Chen { 88354280cfSShuo Chen readerIndex_ = kCheapPrepend; 89354280cfSShuo Chen writerIndex_ = kCheapPrepend; 90354280cfSShuo Chen } 91354280cfSShuo Chen 92354280cfSShuo Chen std::string retrieveAsString() 93354280cfSShuo Chen { 94354280cfSShuo Chen std::string str(peek(), readableBytes()); 95354280cfSShuo Chen retrieveAll(); 96354280cfSShuo Chen return str; 97354280cfSShuo Chen } 98354280cfSShuo Chen 99354280cfSShuo Chen void append(const std::string& str) 100354280cfSShuo Chen { 101354280cfSShuo Chen append(str.data(), str.length()); 102354280cfSShuo Chen } 103354280cfSShuo Chen 104354280cfSShuo Chen void append(const char* /*restrict*/ data, size_t len) 105354280cfSShuo Chen { 106354280cfSShuo Chen ensureWritableBytes(len); 107354280cfSShuo Chen std::copy(data, data+len, beginWrite()); 108354280cfSShuo Chen hasWritten(len); 109354280cfSShuo Chen } 110354280cfSShuo Chen 111354280cfSShuo Chen void append(const void* /*restrict*/ data, size_t len) 112354280cfSShuo Chen { 113354280cfSShuo Chen append(static_cast<const char*>(data), len); 114354280cfSShuo Chen } 115354280cfSShuo Chen 116354280cfSShuo Chen void ensureWritableBytes(size_t len) 117354280cfSShuo Chen { 118354280cfSShuo Chen if (writableBytes() < len) 119354280cfSShuo Chen { 120354280cfSShuo Chen makeSpace(len); 121354280cfSShuo Chen } 122354280cfSShuo Chen assert(writableBytes() >= len); 123354280cfSShuo Chen } 124354280cfSShuo Chen 125354280cfSShuo Chen char* beginWrite() 126354280cfSShuo Chen { return begin() + writerIndex_; } 127354280cfSShuo Chen 128354280cfSShuo Chen const char* beginWrite() const 129354280cfSShuo Chen { return begin() + writerIndex_; } 130354280cfSShuo Chen 131354280cfSShuo Chen void hasWritten(size_t len) 132354280cfSShuo Chen { writerIndex_ += len; } 133354280cfSShuo Chen 134354280cfSShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 135354280cfSShuo Chen { 136354280cfSShuo Chen assert(len <= prependableBytes()); 137354280cfSShuo Chen readerIndex_ -= len; 138354280cfSShuo Chen const char* d = static_cast<const char*>(data); 139354280cfSShuo Chen std::copy(d, d+len, begin()+readerIndex_); 140354280cfSShuo Chen } 141354280cfSShuo Chen 142354280cfSShuo Chen void shrink(size_t reserve) 143354280cfSShuo Chen { 144354280cfSShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 145354280cfSShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 146354280cfSShuo Chen buf.swap(buffer_); 147354280cfSShuo Chen } 148354280cfSShuo Chen 149354280cfSShuo Chen /// Read data directly into buffer. 150354280cfSShuo Chen /// 151354280cfSShuo Chen /// It may implement with readv(2) 152354280cfSShuo Chen /// @return result of read(2), @c errno is saved 153354280cfSShuo Chen ssize_t readFd(int fd, int* savedErrno); 154354280cfSShuo Chen 155354280cfSShuo Chen private: 156354280cfSShuo Chen 157354280cfSShuo Chen char* begin() 158354280cfSShuo Chen { return &*buffer_.begin(); } 159354280cfSShuo Chen 160354280cfSShuo Chen const char* begin() const 161354280cfSShuo Chen { return &*buffer_.begin(); } 162354280cfSShuo Chen 163354280cfSShuo Chen void makeSpace(size_t len) 164354280cfSShuo Chen { 165354280cfSShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 166354280cfSShuo Chen { 167354280cfSShuo Chen buffer_.resize(writerIndex_+len); 168354280cfSShuo Chen } 169354280cfSShuo Chen else 170354280cfSShuo Chen { 171354280cfSShuo Chen // move readable data to the front, make space inside buffer 172354280cfSShuo Chen assert(kCheapPrepend < readerIndex_); 173354280cfSShuo Chen size_t readable = readableBytes(); 174354280cfSShuo Chen std::copy(begin()+readerIndex_, 175354280cfSShuo Chen begin()+writerIndex_, 176354280cfSShuo Chen begin()+kCheapPrepend); 177354280cfSShuo Chen readerIndex_ = kCheapPrepend; 178354280cfSShuo Chen writerIndex_ = readerIndex_ + readable; 179354280cfSShuo Chen assert(readable == readableBytes()); 180354280cfSShuo Chen } 181354280cfSShuo Chen } 182354280cfSShuo Chen 183354280cfSShuo Chen private: 184354280cfSShuo Chen std::vector<char> buffer_; 185354280cfSShuo Chen size_t readerIndex_; 186354280cfSShuo Chen size_t writerIndex_; 187354280cfSShuo Chen}; 188354280cfSShuo Chen 189354280cfSShuo Chen} 190354280cfSShuo Chen 191354280cfSShuo Chen#endif // MUDUO_NET_BUFFER_H 192