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