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