12a18e699SShuo Chen// excerpts from http://code.google.com/p/muduo/ 22a18e699SShuo Chen// 32a18e699SShuo Chen// Use of this source code is governed by a BSD-style license 42a18e699SShuo Chen// that can be found in the License file. 52a18e699SShuo Chen// 62a18e699SShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com) 72a18e699SShuo Chen 82a18e699SShuo Chen#ifndef MUDUO_NET_BUFFER_H 92a18e699SShuo Chen#define MUDUO_NET_BUFFER_H 102a18e699SShuo Chen 112a18e699SShuo Chen#include "datetime/copyable.h" 122a18e699SShuo Chen 132a18e699SShuo Chen#include <algorithm> 142a18e699SShuo Chen#include <string> 152a18e699SShuo Chen#include <vector> 162a18e699SShuo Chen 172a18e699SShuo Chen#include <assert.h> 182a18e699SShuo Chen//#include <unistd.h> // ssize_t 192a18e699SShuo Chen 202a18e699SShuo Chennamespace muduo 212a18e699SShuo Chen{ 222a18e699SShuo Chen 232a18e699SShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer 242a18e699SShuo Chen/// 252a18e699SShuo Chen/// @code 262a18e699SShuo Chen/// +-------------------+------------------+------------------+ 272a18e699SShuo Chen/// | prependable bytes | readable bytes | writable bytes | 282a18e699SShuo Chen/// | | (CONTENT) | | 292a18e699SShuo Chen/// +-------------------+------------------+------------------+ 302a18e699SShuo Chen/// | | | | 312a18e699SShuo Chen/// 0 <= readerIndex <= writerIndex <= size 322a18e699SShuo Chen/// @endcode 332a18e699SShuo Chenclass Buffer : public muduo::copyable 342a18e699SShuo Chen{ 352a18e699SShuo Chen public: 362a18e699SShuo Chen static const size_t kCheapPrepend = 8; 372a18e699SShuo Chen static const size_t kInitialSize = 1024; 382a18e699SShuo Chen 392a18e699SShuo Chen Buffer() 402a18e699SShuo Chen : buffer_(kCheapPrepend + kInitialSize), 412a18e699SShuo Chen readerIndex_(kCheapPrepend), 422a18e699SShuo Chen writerIndex_(kCheapPrepend) 432a18e699SShuo Chen { 442a18e699SShuo Chen assert(readableBytes() == 0); 452a18e699SShuo Chen assert(writableBytes() == kInitialSize); 462a18e699SShuo Chen assert(prependableBytes() == kCheapPrepend); 472a18e699SShuo Chen } 482a18e699SShuo Chen 492a18e699SShuo Chen // default copy-ctor, dtor and assignment are fine 502a18e699SShuo Chen 512a18e699SShuo Chen void swap(Buffer& rhs) 522a18e699SShuo Chen { 532a18e699SShuo Chen buffer_.swap(rhs.buffer_); 542a18e699SShuo Chen std::swap(readerIndex_, rhs.readerIndex_); 552a18e699SShuo Chen std::swap(writerIndex_, rhs.writerIndex_); 562a18e699SShuo Chen } 572a18e699SShuo Chen 582a18e699SShuo Chen size_t readableBytes() const 592a18e699SShuo Chen { return writerIndex_ - readerIndex_; } 602a18e699SShuo Chen 612a18e699SShuo Chen size_t writableBytes() const 622a18e699SShuo Chen { return buffer_.size() - writerIndex_; } 632a18e699SShuo Chen 642a18e699SShuo Chen size_t prependableBytes() const 652a18e699SShuo Chen { return readerIndex_; } 662a18e699SShuo Chen 672a18e699SShuo Chen const char* peek() const 682a18e699SShuo Chen { return begin() + readerIndex_; } 692a18e699SShuo Chen 702a18e699SShuo Chen // retrieve returns void, to prevent 712a18e699SShuo Chen // string str(retrieve(readableBytes()), readableBytes()); 722a18e699SShuo Chen // the evaluation of two functions are unspecified 732a18e699SShuo Chen void retrieve(size_t len) 742a18e699SShuo Chen { 752a18e699SShuo Chen assert(len <= readableBytes()); 762a18e699SShuo Chen readerIndex_ += len; 772a18e699SShuo Chen } 782a18e699SShuo Chen 792a18e699SShuo Chen void retrieveUntil(const char* end) 802a18e699SShuo Chen { 812a18e699SShuo Chen assert(peek() <= end); 822a18e699SShuo Chen assert(end <= beginWrite()); 832a18e699SShuo Chen retrieve(end - peek()); 842a18e699SShuo Chen } 852a18e699SShuo Chen 862a18e699SShuo Chen void retrieveAll() 872a18e699SShuo Chen { 882a18e699SShuo Chen readerIndex_ = kCheapPrepend; 892a18e699SShuo Chen writerIndex_ = kCheapPrepend; 902a18e699SShuo Chen } 912a18e699SShuo Chen 922a18e699SShuo Chen std::string retrieveAsString() 932a18e699SShuo Chen { 942a18e699SShuo Chen std::string str(peek(), readableBytes()); 95ffbff871SShuo Chen retrieveAll(); 962a18e699SShuo Chen return str; 972a18e699SShuo Chen } 982a18e699SShuo Chen 992a18e699SShuo Chen void append(const std::string& str) 1002a18e699SShuo Chen { 1012a18e699SShuo Chen append(str.data(), str.length()); 1022a18e699SShuo Chen } 1032a18e699SShuo Chen 1042a18e699SShuo Chen void append(const char* /*restrict*/ data, size_t len) 1052a18e699SShuo Chen { 1062a18e699SShuo Chen ensureWritableBytes(len); 1072a18e699SShuo Chen std::copy(data, data+len, beginWrite()); 1082a18e699SShuo Chen hasWritten(len); 1092a18e699SShuo Chen } 1102a18e699SShuo Chen 1112a18e699SShuo Chen void append(const void* /*restrict*/ data, size_t len) 1122a18e699SShuo Chen { 1132a18e699SShuo Chen append(static_cast<const char*>(data), len); 1142a18e699SShuo Chen } 1152a18e699SShuo Chen 1162a18e699SShuo Chen void ensureWritableBytes(size_t len) 1172a18e699SShuo Chen { 1182a18e699SShuo Chen if (writableBytes() < len) 1192a18e699SShuo Chen { 1202a18e699SShuo Chen makeSpace(len); 1212a18e699SShuo Chen } 1222a18e699SShuo Chen assert(writableBytes() >= len); 1232a18e699SShuo Chen } 1242a18e699SShuo Chen 1252a18e699SShuo Chen char* beginWrite() 1262a18e699SShuo Chen { return begin() + writerIndex_; } 1272a18e699SShuo Chen 1282a18e699SShuo Chen const char* beginWrite() const 1292a18e699SShuo Chen { return begin() + writerIndex_; } 1302a18e699SShuo Chen 1312a18e699SShuo Chen void hasWritten(size_t len) 1322a18e699SShuo Chen { writerIndex_ += len; } 1332a18e699SShuo Chen 1342a18e699SShuo Chen void prepend(const void* /*restrict*/ data, size_t len) 1352a18e699SShuo Chen { 1362a18e699SShuo Chen assert(len <= prependableBytes()); 1372a18e699SShuo Chen readerIndex_ -= len; 1382a18e699SShuo Chen const char* d = static_cast<const char*>(data); 1392a18e699SShuo Chen std::copy(d, d+len, begin()+readerIndex_); 1402a18e699SShuo Chen } 1412a18e699SShuo Chen 1422a18e699SShuo Chen void shrink(size_t reserve) 1432a18e699SShuo Chen { 1442a18e699SShuo Chen std::vector<char> buf(kCheapPrepend+readableBytes()+reserve); 1452a18e699SShuo Chen std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend); 1462a18e699SShuo Chen buf.swap(buffer_); 1472a18e699SShuo Chen } 1482a18e699SShuo Chen 1492a18e699SShuo Chen /// Read data directly into buffer. 1502a18e699SShuo Chen /// 1512a18e699SShuo Chen /// It may implement with readv(2) 1522a18e699SShuo Chen /// @return result of read(2), @c errno is saved 1532a18e699SShuo Chen ssize_t readFd(int fd, int* savedErrno); 1542a18e699SShuo Chen 1552a18e699SShuo Chen private: 1562a18e699SShuo Chen 1572a18e699SShuo Chen char* begin() 1582a18e699SShuo Chen { return &*buffer_.begin(); } 1592a18e699SShuo Chen 1602a18e699SShuo Chen const char* begin() const 1612a18e699SShuo Chen { return &*buffer_.begin(); } 1622a18e699SShuo Chen 1632a18e699SShuo Chen void makeSpace(size_t len) 1642a18e699SShuo Chen { 1652a18e699SShuo Chen if (writableBytes() + prependableBytes() < len + kCheapPrepend) 1662a18e699SShuo Chen { 1672a18e699SShuo Chen buffer_.resize(writerIndex_+len); 1682a18e699SShuo Chen } 1692a18e699SShuo Chen else 1702a18e699SShuo Chen { 1712a18e699SShuo Chen // move readable data to the front, make space inside buffer 1722a18e699SShuo Chen assert(kCheapPrepend < readerIndex_); 1732a18e699SShuo Chen size_t readable = readableBytes(); 1742a18e699SShuo Chen std::copy(begin()+readerIndex_, 1752a18e699SShuo Chen begin()+writerIndex_, 1762a18e699SShuo Chen begin()+kCheapPrepend); 1772a18e699SShuo Chen readerIndex_ = kCheapPrepend; 1782a18e699SShuo Chen writerIndex_ = readerIndex_ + readable; 1792a18e699SShuo Chen assert(readable == readableBytes()); 1802a18e699SShuo Chen } 1812a18e699SShuo Chen } 1822a18e699SShuo Chen 1832a18e699SShuo Chen private: 1842a18e699SShuo Chen std::vector<char> buffer_; 1852a18e699SShuo Chen size_t readerIndex_; 1862a18e699SShuo Chen size_t writerIndex_; 1872a18e699SShuo Chen}; 1882a18e699SShuo Chen 1892a18e699SShuo Chen} 1902a18e699SShuo Chen 1912a18e699SShuo Chen#endif // MUDUO_NET_BUFFER_H 192