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