1b37003a7SShuo Chen// excerpts from http://code.google.com/p/muduo/ 2b37003a7SShuo Chen// 3b37003a7SShuo Chen// Use of this source code is governed by a BSD-style license 4b37003a7SShuo Chen// that can be found in the License file. 5b37003a7SShuo Chen// 6b37003a7SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 7b37003a7SShuo Chen 8b37003a7SShuo Chen#ifndef MUDUO_NET_BUFFER_H 9b37003a7SShuo Chen#define MUDUO_NET_BUFFER_H 10b37003a7SShuo Chen 11b37003a7SShuo Chen#include "datetime/copyable.h" 12b37003a7SShuo Chen 13b37003a7SShuo Chen#include <algorithm> 14b37003a7SShuo Chen#include <string> 15b37003a7SShuo Chen#include <vector> 16b37003a7SShuo Chen 17b37003a7SShuo Chen#include <assert.h> 18b37003a7SShuo Chen//#include <unistd.h> // ssize_t 19b37003a7SShuo Chen 20b37003a7SShuo Chennamespace muduo 21b37003a7SShuo Chen{ 22b37003a7SShuo Chen 23b37003a7SShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 24b37003a7SShuo Chen/// 25b37003a7SShuo Chen/// @code 26b37003a7SShuo Chen/// +-------------------+------------------+------------------+ 27b37003a7SShuo Chen/// | prependable bytes | readable bytes | writable bytes | 28b37003a7SShuo Chen/// | | (CONTENT) | | 29b37003a7SShuo Chen/// +-------------------+------------------+------------------+ 30b37003a7SShuo Chen/// | | | | 31b37003a7SShuo Chen/// 0 <= readerIndex <= writerIndex <= size 32b37003a7SShuo Chen/// @endcode 33b37003a7SShuo Chenclass Buffer : public muduo::copyable 34b37003a7SShuo Chen{ 35b37003a7SShuo Chen public: 36b37003a7SShuo Chen static const size_t kCheapPrepend = 8; 37b37003a7SShuo Chen static const size_t kInitialSize = 1024; 38b37003a7SShuo Chen 39b37003a7SShuo Chen Buffer() 40b37003a7SShuo Chen : buffer_(kCheapPrepend + kInitialSize), 41b37003a7SShuo Chen readerIndex_(kCheapPrepend), 42b37003a7SShuo Chen writerIndex_(kCheapPrepend) 43b37003a7SShuo Chen { 44b37003a7SShuo Chen assert(readableBytes() == 0); 45b37003a7SShuo Chen assert(writableBytes() == kInitialSize); 46b37003a7SShuo Chen assert(prependableBytes() == kCheapPrepend); 47b37003a7SShuo Chen } 48b37003a7SShuo Chen 49b37003a7SShuo Chen // default copy-ctor, dtor and assignment are fine 50b37003a7SShuo Chen 51b37003a7SShuo Chen void swap(Buffer& rhs) 52b37003a7SShuo Chen { 53b37003a7SShuo Chen buffer_.swap(rhs.buffer_); 54b37003a7SShuo Chen std::swap(readerIndex_, rhs.readerIndex_); 55b37003a7SShuo Chen std::swap(writerIndex_, rhs.writerIndex_); 56b37003a7SShuo Chen } 57b37003a7SShuo Chen 58b37003a7SShuo Chen size_t readableBytes() const 59b37003a7SShuo Chen { return writerIndex_ - readerIndex_; } 60b37003a7SShuo Chen 61b37003a7SShuo Chen size_t writableBytes() const 62b37003a7SShuo Chen { return buffer_.size() - writerIndex_; } 63b37003a7SShuo Chen 64b37003a7SShuo Chen size_t prependableBytes() const 65b37003a7SShuo Chen { return readerIndex_; } 66b37003a7SShuo Chen 67b37003a7SShuo Chen const char* peek() const 68b37003a7SShuo Chen { return begin() + readerIndex_; } 69b37003a7SShuo Chen 70b37003a7SShuo Chen // retrieve returns void, to prevent 71b37003a7SShuo Chen // string str(retrieve(readableBytes()), readableBytes()); 72b37003a7SShuo Chen // the evaluation of two functions are unspecified 73b37003a7SShuo Chen void retrieve(size_t len) 74b37003a7SShuo Chen { 75b37003a7SShuo Chen assert(len <= readableBytes()); 76b37003a7SShuo Chen readerIndex_ += len; 77b37003a7SShuo Chen } 78b37003a7SShuo Chen 79b37003a7SShuo Chen void retrieveUntil(const char* end) 80b37003a7SShuo Chen { 81b37003a7SShuo Chen assert(peek() <= end); 82b37003a7SShuo Chen assert(end <= beginWrite()); 83b37003a7SShuo Chen retrieve(end - peek()); 84b37003a7SShuo Chen } 85b37003a7SShuo Chen 86b37003a7SShuo Chen void retrieveAll() 87b37003a7SShuo Chen { 88b37003a7SShuo Chen readerIndex_ = kCheapPrepend; 89b37003a7SShuo Chen writerIndex_ = kCheapPrepend; 90b37003a7SShuo Chen } 91b37003a7SShuo Chen 92b37003a7SShuo Chen std::string retrieveAsString() 93b37003a7SShuo Chen { 94b37003a7SShuo Chen std::string str(peek(), readableBytes()); 95ffbff871SShuo Chen retrieveAll(); 96b37003a7SShuo Chen return str; 97b37003a7SShuo Chen } 98b37003a7SShuo Chen 99b37003a7SShuo Chen void append(const std::string& str) 100b37003a7SShuo Chen { 101b37003a7SShuo Chen append(str.data(), str.length()); 102b37003a7SShuo Chen } 103b37003a7SShuo Chen 104b37003a7SShuo Chen void append(const char* /*restrict*/ data, size_t len) 105b37003a7SShuo Chen { 106b37003a7SShuo Chen ensureWritableBytes(len); 107b37003a7SShuo Chen std::copy(data, data+len, beginWrite()); 108b37003a7SShuo Chen hasWritten(len); 109b37003a7SShuo Chen } 110b37003a7SShuo Chen 111b37003a7SShuo Chen void append(const void* /*restrict*/ data, size_t len) 112b37003a7SShuo Chen { 113b37003a7SShuo Chen append(static_cast<const char*>(data), len); 114b37003a7SShuo Chen } 115b37003a7SShuo Chen 116b37003a7SShuo Chen void ensureWritableBytes(size_t len) 117b37003a7SShuo Chen { 118b37003a7SShuo Chen if (writableBytes() < len) 119b37003a7SShuo Chen { 120b37003a7SShuo Chen makeSpace(len); 121b37003a7SShuo Chen } 122b37003a7SShuo Chen assert(writableBytes() >= len); 123b37003a7SShuo Chen } 124b37003a7SShuo Chen 125b37003a7SShuo Chen char* beginWrite() 126b37003a7SShuo Chen { return begin() + writerIndex_; } 127b37003a7SShuo Chen 128b37003a7SShuo Chen const char* beginWrite() const 129b37003a7SShuo Chen { return begin() + writerIndex_; } 130b37003a7SShuo Chen 131b37003a7SShuo Chen void hasWritten(size_t len) 132b37003a7SShuo Chen { writerIndex_ += len; } 133b37003a7SShuo Chen 134b37003a7SShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 135b37003a7SShuo Chen { 136b37003a7SShuo Chen assert(len <= prependableBytes()); 137b37003a7SShuo Chen readerIndex_ -= len; 138b37003a7SShuo Chen const char* d = static_cast<const char*>(data); 139b37003a7SShuo Chen std::copy(d, d+len, begin()+readerIndex_); 140b37003a7SShuo Chen } 141b37003a7SShuo Chen 142b37003a7SShuo Chen void shrink(size_t reserve) 143b37003a7SShuo Chen { 144b37003a7SShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 145b37003a7SShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 146b37003a7SShuo Chen buf.swap(buffer_); 147b37003a7SShuo Chen } 148b37003a7SShuo Chen 149b37003a7SShuo Chen /// Read data directly into buffer. 150b37003a7SShuo Chen /// 151b37003a7SShuo Chen /// It may implement with readv(2) 152b37003a7SShuo Chen /// @return result of read(2), @c errno is saved 153b37003a7SShuo Chen ssize_t readFd(int fd, int* savedErrno); 154b37003a7SShuo Chen 155b37003a7SShuo Chen private: 156b37003a7SShuo Chen 157b37003a7SShuo Chen char* begin() 158b37003a7SShuo Chen { return &*buffer_.begin(); } 159b37003a7SShuo Chen 160b37003a7SShuo Chen const char* begin() const 161b37003a7SShuo Chen { return &*buffer_.begin(); } 162b37003a7SShuo Chen 163b37003a7SShuo Chen void makeSpace(size_t len) 164b37003a7SShuo Chen { 165b37003a7SShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 166b37003a7SShuo Chen { 167b37003a7SShuo Chen buffer_.resize(writerIndex_+len); 168b37003a7SShuo Chen } 169b37003a7SShuo Chen else 170b37003a7SShuo Chen { 171b37003a7SShuo Chen // move readable data to the front, make space inside buffer 172b37003a7SShuo Chen assert(kCheapPrepend < readerIndex_); 173b37003a7SShuo Chen size_t readable = readableBytes(); 174b37003a7SShuo Chen std::copy(begin()+readerIndex_, 175b37003a7SShuo Chen begin()+writerIndex_, 176b37003a7SShuo Chen begin()+kCheapPrepend); 177b37003a7SShuo Chen readerIndex_ = kCheapPrepend; 178b37003a7SShuo Chen writerIndex_ = readerIndex_ + readable; 179b37003a7SShuo Chen assert(readable == readableBytes()); 180b37003a7SShuo Chen } 181b37003a7SShuo Chen } 182b37003a7SShuo Chen 183b37003a7SShuo Chen private: 184b37003a7SShuo Chen std::vector<char> buffer_; 185b37003a7SShuo Chen size_t readerIndex_; 186b37003a7SShuo Chen size_t writerIndex_; 187b37003a7SShuo Chen}; 188b37003a7SShuo Chen 189b37003a7SShuo Chen} 190b37003a7SShuo Chen 191b37003a7SShuo Chen#endif // MUDUO_NET_BUFFER_H 192