Buffer.h revision ffbff871
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());
95ffbff871SShuo Chen    retrieveAll();
96714cd85fSShuo Chen    return str;
97714cd85fSShuo Chen  }
98714cd85fSShuo Chen
99714cd85fSShuo Chen  void append(const std::string& str)
100714cd85fSShuo Chen  {
101714cd85fSShuo Chen    append(str.data(), str.length());
102714cd85fSShuo Chen  }
103714cd85fSShuo Chen
104714cd85fSShuo Chen  void append(const char* /*restrict*/ data, size_t len)
105714cd85fSShuo Chen  {
106714cd85fSShuo Chen    ensureWritableBytes(len);
107714cd85fSShuo Chen    std::copy(data, data+len, beginWrite());
108714cd85fSShuo Chen    hasWritten(len);
109714cd85fSShuo Chen  }
110714cd85fSShuo Chen
111714cd85fSShuo Chen  void append(const void* /*restrict*/ data, size_t len)
112714cd85fSShuo Chen  {
113714cd85fSShuo Chen    append(static_cast<const char*>(data), len);
114714cd85fSShuo Chen  }
115714cd85fSShuo Chen
116714cd85fSShuo Chen  void ensureWritableBytes(size_t len)
117714cd85fSShuo Chen  {
118714cd85fSShuo Chen    if (writableBytes() < len)
119714cd85fSShuo Chen    {
120714cd85fSShuo Chen      makeSpace(len);
121714cd85fSShuo Chen    }
122714cd85fSShuo Chen    assert(writableBytes() >= len);
123714cd85fSShuo Chen  }
124714cd85fSShuo Chen
125714cd85fSShuo Chen  char* beginWrite()
126714cd85fSShuo Chen  { return begin() + writerIndex_; }
127714cd85fSShuo Chen
128714cd85fSShuo Chen  const char* beginWrite() const
129714cd85fSShuo Chen  { return begin() + writerIndex_; }
130714cd85fSShuo Chen
131714cd85fSShuo Chen  void hasWritten(size_t len)
132714cd85fSShuo Chen  { writerIndex_ += len; }
133714cd85fSShuo Chen
134714cd85fSShuo Chen  void prepend(const void* /*restrict*/ data, size_t len)
135714cd85fSShuo Chen  {
136714cd85fSShuo Chen    assert(len <= prependableBytes());
137714cd85fSShuo Chen    readerIndex_ -= len;
138714cd85fSShuo Chen    const char* d = static_cast<const char*>(data);
139714cd85fSShuo Chen    std::copy(d, d+len, begin()+readerIndex_);
140714cd85fSShuo Chen  }
141714cd85fSShuo Chen
142714cd85fSShuo Chen  void shrink(size_t reserve)
143714cd85fSShuo Chen  {
144714cd85fSShuo Chen   std::vector<char> buf(kCheapPrepend+readableBytes()+reserve);
145714cd85fSShuo Chen   std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend);
146714cd85fSShuo Chen   buf.swap(buffer_);
147714cd85fSShuo Chen  }
148714cd85fSShuo Chen
149714cd85fSShuo Chen  /// Read data directly into buffer.
150714cd85fSShuo Chen  ///
151714cd85fSShuo Chen  /// It may implement with readv(2)
152714cd85fSShuo Chen  /// @return result of read(2), @c errno is saved
153714cd85fSShuo Chen  ssize_t readFd(int fd, int* savedErrno);
154714cd85fSShuo Chen
155714cd85fSShuo Chen private:
156714cd85fSShuo Chen
157714cd85fSShuo Chen  char* begin()
158714cd85fSShuo Chen  { return &*buffer_.begin(); }
159714cd85fSShuo Chen
160714cd85fSShuo Chen  const char* begin() const
161714cd85fSShuo Chen  { return &*buffer_.begin(); }
162714cd85fSShuo Chen
163714cd85fSShuo Chen  void makeSpace(size_t len)
164714cd85fSShuo Chen  {
165714cd85fSShuo Chen    if (writableBytes() + prependableBytes() < len + kCheapPrepend)
166714cd85fSShuo Chen    {
167714cd85fSShuo Chen      buffer_.resize(writerIndex_+len);
168714cd85fSShuo Chen    }
169714cd85fSShuo Chen    else
170714cd85fSShuo Chen    {
171714cd85fSShuo Chen      // move readable data to the front, make space inside buffer
172714cd85fSShuo Chen      assert(kCheapPrepend < readerIndex_);
173714cd85fSShuo Chen      size_t readable = readableBytes();
174714cd85fSShuo Chen      std::copy(begin()+readerIndex_,
175714cd85fSShuo Chen                begin()+writerIndex_,
176714cd85fSShuo Chen                begin()+kCheapPrepend);
177714cd85fSShuo Chen      readerIndex_ = kCheapPrepend;
178714cd85fSShuo Chen      writerIndex_ = readerIndex_ + readable;
179714cd85fSShuo Chen      assert(readable == readableBytes());
180714cd85fSShuo Chen    }
181714cd85fSShuo Chen  }
182714cd85fSShuo Chen
183714cd85fSShuo Chen private:
184714cd85fSShuo Chen  std::vector<char> buffer_;
185714cd85fSShuo Chen  size_t readerIndex_;
186714cd85fSShuo Chen  size_t writerIndex_;
187714cd85fSShuo Chen};
188714cd85fSShuo Chen
189714cd85fSShuo Chen}
190714cd85fSShuo Chen
191714cd85fSShuo Chen#endif  // MUDUO_NET_BUFFER_H
192