Buffer.h revision 714cd85f
1714cd85fSShuo Chen// excerpts from http://code.google.com/p/muduo/
2714cd85fSShuo Chen//
3714cd85fSShuo Chen// Use of this source code is governed by a BSD-style license
4714cd85fSShuo Chen// that can be found in the License file.
5714cd85fSShuo Chen//
6714cd85fSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7714cd85fSShuo Chen
8714cd85fSShuo Chen#ifndef MUDUO_NET_BUFFER_H
9714cd85fSShuo Chen#define MUDUO_NET_BUFFER_H
10714cd85fSShuo Chen
11714cd85fSShuo Chen#include "datetime/copyable.h"
12714cd85fSShuo Chen
13714cd85fSShuo Chen#include <algorithm>
14714cd85fSShuo Chen#include <string>
15714cd85fSShuo Chen#include <vector>
16714cd85fSShuo Chen
17714cd85fSShuo Chen#include <assert.h>
18714cd85fSShuo Chen//#include <unistd.h>  // ssize_t
19714cd85fSShuo Chen
20714cd85fSShuo Chennamespace muduo
21714cd85fSShuo Chen{
22714cd85fSShuo Chen
23714cd85fSShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
24714cd85fSShuo Chen///
25714cd85fSShuo Chen/// @code
26714cd85fSShuo Chen/// +-------------------+------------------+------------------+
27714cd85fSShuo Chen/// | prependable bytes |  readable bytes  |  writable bytes  |
28714cd85fSShuo Chen/// |                   |     (CONTENT)    |                  |
29714cd85fSShuo Chen/// +-------------------+------------------+------------------+
30714cd85fSShuo Chen/// |                   |                  |                  |
31714cd85fSShuo Chen/// 0      <=      readerIndex   <=   writerIndex    <=     size
32714cd85fSShuo Chen/// @endcode
33714cd85fSShuo Chenclass Buffer : public muduo::copyable
34714cd85fSShuo Chen{
35714cd85fSShuo Chen public:
36714cd85fSShuo Chen  static const size_t kCheapPrepend = 8;
37714cd85fSShuo Chen  static const size_t kInitialSize = 1024;
38714cd85fSShuo Chen
39714cd85fSShuo Chen  Buffer()
40714cd85fSShuo Chen    : buffer_(kCheapPrepend + kInitialSize),
41714cd85fSShuo Chen      readerIndex_(kCheapPrepend),
42714cd85fSShuo Chen      writerIndex_(kCheapPrepend)
43714cd85fSShuo Chen  {
44714cd85fSShuo Chen    assert(readableBytes() == 0);
45714cd85fSShuo Chen    assert(writableBytes() == kInitialSize);
46714cd85fSShuo Chen    assert(prependableBytes() == kCheapPrepend);
47714cd85fSShuo Chen  }
48714cd85fSShuo Chen
49714cd85fSShuo Chen  // default copy-ctor, dtor and assignment are fine
50714cd85fSShuo Chen
51714cd85fSShuo Chen  void swap(Buffer& rhs)
52714cd85fSShuo Chen  {
53714cd85fSShuo Chen    buffer_.swap(rhs.buffer_);
54714cd85fSShuo Chen    std::swap(readerIndex_, rhs.readerIndex_);
55714cd85fSShuo Chen    std::swap(writerIndex_, rhs.writerIndex_);
56714cd85fSShuo Chen  }
57714cd85fSShuo Chen
58714cd85fSShuo Chen  size_t readableBytes() const
59714cd85fSShuo Chen  { return writerIndex_ - readerIndex_; }
60714cd85fSShuo Chen
61714cd85fSShuo Chen  size_t writableBytes() const
62714cd85fSShuo Chen  { return buffer_.size() - writerIndex_; }
63714cd85fSShuo Chen
64714cd85fSShuo Chen  size_t prependableBytes() const
65714cd85fSShuo Chen  { return readerIndex_; }
66714cd85fSShuo Chen
67714cd85fSShuo Chen  const char* peek() const
68714cd85fSShuo Chen  { return begin() + readerIndex_; }
69714cd85fSShuo Chen
70714cd85fSShuo Chen  // retrieve returns void, to prevent
71714cd85fSShuo Chen  // string str(retrieve(readableBytes()), readableBytes());
72714cd85fSShuo Chen  // the evaluation of two functions are unspecified
73714cd85fSShuo Chen  void retrieve(size_t len)
74714cd85fSShuo Chen  {
75714cd85fSShuo Chen    assert(len <= readableBytes());
76714cd85fSShuo Chen    readerIndex_ += len;
77714cd85fSShuo Chen  }
78714cd85fSShuo Chen
79714cd85fSShuo Chen  void retrieveUntil(const char* end)
80714cd85fSShuo Chen  {
81714cd85fSShuo Chen    assert(peek() <= end);
82714cd85fSShuo Chen    assert(end <= beginWrite());
83714cd85fSShuo Chen    retrieve(end - peek());
84714cd85fSShuo Chen  }
85714cd85fSShuo Chen
86714cd85fSShuo Chen  void retrieveAll()
87714cd85fSShuo Chen  {
88714cd85fSShuo Chen    readerIndex_ = kCheapPrepend;
89714cd85fSShuo Chen    writerIndex_ = kCheapPrepend;
90714cd85fSShuo Chen  }
91714cd85fSShuo Chen
92714cd85fSShuo Chen  std::string retrieveAsString()
93714cd85fSShuo Chen  {
94714cd85fSShuo Chen    std::string str(peek(), readableBytes());
95714cd85fSShuo Chen    readerIndex_ = kCheapPrepend;
96714cd85fSShuo Chen    writerIndex_ = kCheapPrepend;
97714cd85fSShuo Chen    return str;
98714cd85fSShuo Chen  }
99714cd85fSShuo Chen
100714cd85fSShuo Chen  void append(const std::string& str)
101714cd85fSShuo Chen  {
102714cd85fSShuo Chen    append(str.data(), str.length());
103714cd85fSShuo Chen  }
104714cd85fSShuo Chen
105714cd85fSShuo Chen  void append(const char* /*restrict*/ data, size_t len)
106714cd85fSShuo Chen  {
107714cd85fSShuo Chen    ensureWritableBytes(len);
108714cd85fSShuo Chen    std::copy(data, data+len, beginWrite());
109714cd85fSShuo Chen    hasWritten(len);
110714cd85fSShuo Chen  }
111714cd85fSShuo Chen
112714cd85fSShuo Chen  void append(const void* /*restrict*/ data, size_t len)
113714cd85fSShuo Chen  {
114714cd85fSShuo Chen    append(static_cast<const char*>(data), len);
115714cd85fSShuo Chen  }
116714cd85fSShuo Chen
117714cd85fSShuo Chen  void ensureWritableBytes(size_t len)
118714cd85fSShuo Chen  {
119714cd85fSShuo Chen    if (writableBytes() < len)
120714cd85fSShuo Chen    {
121714cd85fSShuo Chen      makeSpace(len);
122714cd85fSShuo Chen    }
123714cd85fSShuo Chen    assert(writableBytes() >= len);
124714cd85fSShuo Chen  }
125714cd85fSShuo Chen
126714cd85fSShuo Chen  char* beginWrite()
127714cd85fSShuo Chen  { return begin() + writerIndex_; }
128714cd85fSShuo Chen
129714cd85fSShuo Chen  const char* beginWrite() const
130714cd85fSShuo Chen  { return begin() + writerIndex_; }
131714cd85fSShuo Chen
132714cd85fSShuo Chen  void hasWritten(size_t len)
133714cd85fSShuo Chen  { writerIndex_ += len; }
134714cd85fSShuo Chen
135714cd85fSShuo Chen  void prepend(const void* /*restrict*/ data, size_t len)
136714cd85fSShuo Chen  {
137714cd85fSShuo Chen    assert(len <= prependableBytes());
138714cd85fSShuo Chen    readerIndex_ -= len;
139714cd85fSShuo Chen    const char* d = static_cast<const char*>(data);
140714cd85fSShuo Chen    std::copy(d, d+len, begin()+readerIndex_);
141714cd85fSShuo Chen  }
142714cd85fSShuo Chen
143714cd85fSShuo Chen  void shrink(size_t reserve)
144714cd85fSShuo Chen  {
145714cd85fSShuo Chen   std::vector<char> buf(kCheapPrepend+readableBytes()+reserve);
146714cd85fSShuo Chen   std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend);
147714cd85fSShuo Chen   buf.swap(buffer_);
148714cd85fSShuo Chen  }
149714cd85fSShuo Chen
150714cd85fSShuo Chen  /// Read data directly into buffer.
151714cd85fSShuo Chen  ///
152714cd85fSShuo Chen  /// It may implement with readv(2)
153714cd85fSShuo Chen  /// @return result of read(2), @c errno is saved
154714cd85fSShuo Chen  ssize_t readFd(int fd, int* savedErrno);
155714cd85fSShuo Chen
156714cd85fSShuo Chen private:
157714cd85fSShuo Chen
158714cd85fSShuo Chen  char* begin()
159714cd85fSShuo Chen  { return &*buffer_.begin(); }
160714cd85fSShuo Chen
161714cd85fSShuo Chen  const char* begin() const
162714cd85fSShuo Chen  { return &*buffer_.begin(); }
163714cd85fSShuo Chen
164714cd85fSShuo Chen  void makeSpace(size_t len)
165714cd85fSShuo Chen  {
166714cd85fSShuo Chen    if (writableBytes() + prependableBytes() < len + kCheapPrepend)
167714cd85fSShuo Chen    {
168714cd85fSShuo Chen      buffer_.resize(writerIndex_+len);
169714cd85fSShuo Chen    }
170714cd85fSShuo Chen    else
171714cd85fSShuo Chen    {
172714cd85fSShuo Chen      // move readable data to the front, make space inside buffer
173714cd85fSShuo Chen      assert(kCheapPrepend < readerIndex_);
174714cd85fSShuo Chen      size_t readable = readableBytes();
175714cd85fSShuo Chen      std::copy(begin()+readerIndex_,
176714cd85fSShuo Chen                begin()+writerIndex_,
177714cd85fSShuo Chen                begin()+kCheapPrepend);
178714cd85fSShuo Chen      readerIndex_ = kCheapPrepend;
179714cd85fSShuo Chen      writerIndex_ = readerIndex_ + readable;
180714cd85fSShuo Chen      assert(readable == readableBytes());
181714cd85fSShuo Chen    }
182714cd85fSShuo Chen  }
183714cd85fSShuo Chen
184714cd85fSShuo Chen private:
185714cd85fSShuo Chen  std::vector<char> buffer_;
186714cd85fSShuo Chen  size_t readerIndex_;
187714cd85fSShuo Chen  size_t writerIndex_;
188714cd85fSShuo Chen};
189714cd85fSShuo Chen
190714cd85fSShuo Chen}
191714cd85fSShuo Chen
192714cd85fSShuo Chen#endif  // MUDUO_NET_BUFFER_H
193