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