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