Buffer.h revision 40161064
140161064SShuo Chen// excerpts from http://code.google.com/p/muduo/ 240161064SShuo Chen// 340161064SShuo Chen// Use of this source code is governed by a BSD-style license 440161064SShuo Chen// that can be found in the License file. 540161064SShuo Chen// 640161064SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 740161064SShuo Chen 840161064SShuo Chen#ifndef MUDUO_NET_BUFFER_H 940161064SShuo Chen#define MUDUO_NET_BUFFER_H 1040161064SShuo Chen 1140161064SShuo Chen#include "datetime/copyable.h" 1240161064SShuo Chen 1340161064SShuo Chen#include <algorithm> 1440161064SShuo Chen#include <string> 1540161064SShuo Chen#include <vector> 1640161064SShuo Chen 1740161064SShuo Chen#include <assert.h> 1840161064SShuo Chen//#include <unistd.h> // ssize_t 1940161064SShuo Chen 2040161064SShuo Chennamespace muduo 2140161064SShuo Chen{ 2240161064SShuo Chen 2340161064SShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 2440161064SShuo Chen/// 2540161064SShuo Chen/// @code 2640161064SShuo Chen/// +-------------------+------------------+------------------+ 2740161064SShuo Chen/// | prependable bytes | readable bytes | writable bytes | 2840161064SShuo Chen/// | | (CONTENT) | | 2940161064SShuo Chen/// +-------------------+------------------+------------------+ 3040161064SShuo Chen/// | | | | 3140161064SShuo Chen/// 0 <= readerIndex <= writerIndex <= size 3240161064SShuo Chen/// @endcode 3340161064SShuo Chenclass Buffer : public muduo::copyable 3440161064SShuo Chen{ 3540161064SShuo Chen public: 3640161064SShuo Chen static const size_t kCheapPrepend = 8; 3740161064SShuo Chen static const size_t kInitialSize = 1024; 3840161064SShuo Chen 3940161064SShuo Chen Buffer() 4040161064SShuo Chen : buffer_(kCheapPrepend + kInitialSize), 4140161064SShuo Chen readerIndex_(kCheapPrepend), 4240161064SShuo Chen writerIndex_(kCheapPrepend) 4340161064SShuo Chen { 4440161064SShuo Chen assert(readableBytes() == 0); 4540161064SShuo Chen assert(writableBytes() == kInitialSize); 4640161064SShuo Chen assert(prependableBytes() == kCheapPrepend); 4740161064SShuo Chen } 4840161064SShuo Chen 4940161064SShuo Chen // default copy-ctor, dtor and assignment are fine 5040161064SShuo Chen 5140161064SShuo Chen void swap(Buffer& rhs) 5240161064SShuo Chen { 5340161064SShuo Chen buffer_.swap(rhs.buffer_); 5440161064SShuo Chen std::swap(readerIndex_, rhs.readerIndex_); 5540161064SShuo Chen std::swap(writerIndex_, rhs.writerIndex_); 5640161064SShuo Chen } 5740161064SShuo Chen 5840161064SShuo Chen size_t readableBytes() const 5940161064SShuo Chen { return writerIndex_ - readerIndex_; } 6040161064SShuo Chen 6140161064SShuo Chen size_t writableBytes() const 6240161064SShuo Chen { return buffer_.size() - writerIndex_; } 6340161064SShuo Chen 6440161064SShuo Chen size_t prependableBytes() const 6540161064SShuo Chen { return readerIndex_; } 6640161064SShuo Chen 6740161064SShuo Chen const char* peek() const 6840161064SShuo Chen { return begin() + readerIndex_; } 6940161064SShuo Chen 7040161064SShuo Chen // retrieve returns void, to prevent 7140161064SShuo Chen // string str(retrieve(readableBytes()), readableBytes()); 7240161064SShuo Chen // the evaluation of two functions are unspecified 7340161064SShuo Chen void retrieve(size_t len) 7440161064SShuo Chen { 7540161064SShuo Chen assert(len <= readableBytes()); 7640161064SShuo Chen readerIndex_ += len; 7740161064SShuo Chen } 7840161064SShuo Chen 7940161064SShuo Chen void retrieveUntil(const char* end) 8040161064SShuo Chen { 8140161064SShuo Chen assert(peek() <= end); 8240161064SShuo Chen assert(end <= beginWrite()); 8340161064SShuo Chen retrieve(end - peek()); 8440161064SShuo Chen } 8540161064SShuo Chen 8640161064SShuo Chen void retrieveAll() 8740161064SShuo Chen { 8840161064SShuo Chen readerIndex_ = kCheapPrepend; 8940161064SShuo Chen writerIndex_ = kCheapPrepend; 9040161064SShuo Chen } 9140161064SShuo Chen 9240161064SShuo Chen std::string retrieveAsString() 9340161064SShuo Chen { 9440161064SShuo Chen std::string str(peek(), readableBytes()); 9540161064SShuo Chen retrieveAll(); 9640161064SShuo Chen return str; 9740161064SShuo Chen } 9840161064SShuo Chen 9940161064SShuo Chen void append(const std::string& str) 10040161064SShuo Chen { 10140161064SShuo Chen append(str.data(), str.length()); 10240161064SShuo Chen } 10340161064SShuo Chen 10440161064SShuo Chen void append(const char* /*restrict*/ data, size_t len) 10540161064SShuo Chen { 10640161064SShuo Chen ensureWritableBytes(len); 10740161064SShuo Chen std::copy(data, data+len, beginWrite()); 10840161064SShuo Chen hasWritten(len); 10940161064SShuo Chen } 11040161064SShuo Chen 11140161064SShuo Chen void append(const void* /*restrict*/ data, size_t len) 11240161064SShuo Chen { 11340161064SShuo Chen append(static_cast<const char*>(data), len); 11440161064SShuo Chen } 11540161064SShuo Chen 11640161064SShuo Chen void ensureWritableBytes(size_t len) 11740161064SShuo Chen { 11840161064SShuo Chen if (writableBytes() < len) 11940161064SShuo Chen { 12040161064SShuo Chen makeSpace(len); 12140161064SShuo Chen } 12240161064SShuo Chen assert(writableBytes() >= len); 12340161064SShuo Chen } 12440161064SShuo Chen 12540161064SShuo Chen char* beginWrite() 12640161064SShuo Chen { return begin() + writerIndex_; } 12740161064SShuo Chen 12840161064SShuo Chen const char* beginWrite() const 12940161064SShuo Chen { return begin() + writerIndex_; } 13040161064SShuo Chen 13140161064SShuo Chen void hasWritten(size_t len) 13240161064SShuo Chen { writerIndex_ += len; } 13340161064SShuo Chen 13440161064SShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 13540161064SShuo Chen { 13640161064SShuo Chen assert(len <= prependableBytes()); 13740161064SShuo Chen readerIndex_ -= len; 13840161064SShuo Chen const char* d = static_cast<const char*>(data); 13940161064SShuo Chen std::copy(d, d+len, begin()+readerIndex_); 14040161064SShuo Chen } 14140161064SShuo Chen 14240161064SShuo Chen void shrink(size_t reserve) 14340161064SShuo Chen { 14440161064SShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 14540161064SShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 14640161064SShuo Chen buf.swap(buffer_); 14740161064SShuo Chen } 14840161064SShuo Chen 14940161064SShuo Chen /// Read data directly into buffer. 15040161064SShuo Chen /// 15140161064SShuo Chen /// It may implement with readv(2) 15240161064SShuo Chen /// @return result of read(2), @c errno is saved 15340161064SShuo Chen ssize_t readFd(int fd, int* savedErrno); 15440161064SShuo Chen 15540161064SShuo Chen private: 15640161064SShuo Chen 15740161064SShuo Chen char* begin() 15840161064SShuo Chen { return &*buffer_.begin(); } 15940161064SShuo Chen 16040161064SShuo Chen const char* begin() const 16140161064SShuo Chen { return &*buffer_.begin(); } 16240161064SShuo Chen 16340161064SShuo Chen void makeSpace(size_t len) 16440161064SShuo Chen { 16540161064SShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 16640161064SShuo Chen { 16740161064SShuo Chen buffer_.resize(writerIndex_+len); 16840161064SShuo Chen } 16940161064SShuo Chen else 17040161064SShuo Chen { 17140161064SShuo Chen // move readable data to the front, make space inside buffer 17240161064SShuo Chen assert(kCheapPrepend < readerIndex_); 17340161064SShuo Chen size_t readable = readableBytes(); 17440161064SShuo Chen std::copy(begin()+readerIndex_, 17540161064SShuo Chen begin()+writerIndex_, 17640161064SShuo Chen begin()+kCheapPrepend); 17740161064SShuo Chen readerIndex_ = kCheapPrepend; 17840161064SShuo Chen writerIndex_ = readerIndex_ + readable; 17940161064SShuo Chen assert(readable == readableBytes()); 18040161064SShuo Chen } 18140161064SShuo Chen } 18240161064SShuo Chen 18340161064SShuo Chen private: 18440161064SShuo Chen std::vector<char> buffer_; 18540161064SShuo Chen size_t readerIndex_; 18640161064SShuo Chen size_t writerIndex_; 18740161064SShuo Chen}; 18840161064SShuo Chen 18940161064SShuo Chen} 19040161064SShuo Chen 19140161064SShuo Chen#endif // MUDUO_NET_BUFFER_H 192