Buffer.h revision 354280cf
1354280cfSShuo Chen// excerpts from http://code.google.com/p/muduo/
2354280cfSShuo Chen//
3354280cfSShuo Chen// Use of this source code is governed by a BSD-style license
4354280cfSShuo Chen// that can be found in the License file.
5354280cfSShuo Chen//
6354280cfSShuo Chen// Author: Shuo Chen (chenshuo at chenshuo dot com)
7354280cfSShuo Chen
8354280cfSShuo Chen#ifndef MUDUO_NET_BUFFER_H
9354280cfSShuo Chen#define MUDUO_NET_BUFFER_H
10354280cfSShuo Chen
11354280cfSShuo Chen#include "datetime/copyable.h"
12354280cfSShuo Chen
13354280cfSShuo Chen#include <algorithm>
14354280cfSShuo Chen#include <string>
15354280cfSShuo Chen#include <vector>
16354280cfSShuo Chen
17354280cfSShuo Chen#include <assert.h>
18354280cfSShuo Chen//#include <unistd.h>  // ssize_t
19354280cfSShuo Chen
20354280cfSShuo Chennamespace muduo
21354280cfSShuo Chen{
22354280cfSShuo Chen
23354280cfSShuo Chen/// A buffer class modeled after org.jboss.netty.buffer.ChannelBuffer
24354280cfSShuo Chen///
25354280cfSShuo Chen/// @code
26354280cfSShuo Chen/// +-------------------+------------------+------------------+
27354280cfSShuo Chen/// | prependable bytes |  readable bytes  |  writable bytes  |
28354280cfSShuo Chen/// |                   |     (CONTENT)    |                  |
29354280cfSShuo Chen/// +-------------------+------------------+------------------+
30354280cfSShuo Chen/// |                   |                  |                  |
31354280cfSShuo Chen/// 0      <=      readerIndex   <=   writerIndex    <=     size
32354280cfSShuo Chen/// @endcode
33354280cfSShuo Chenclass Buffer : public muduo::copyable
34354280cfSShuo Chen{
35354280cfSShuo Chen public:
36354280cfSShuo Chen  static const size_t kCheapPrepend = 8;
37354280cfSShuo Chen  static const size_t kInitialSize = 1024;
38354280cfSShuo Chen
39354280cfSShuo Chen  Buffer()
40354280cfSShuo Chen    : buffer_(kCheapPrepend + kInitialSize),
41354280cfSShuo Chen      readerIndex_(kCheapPrepend),
42354280cfSShuo Chen      writerIndex_(kCheapPrepend)
43354280cfSShuo Chen  {
44354280cfSShuo Chen    assert(readableBytes() == 0);
45354280cfSShuo Chen    assert(writableBytes() == kInitialSize);
46354280cfSShuo Chen    assert(prependableBytes() == kCheapPrepend);
47354280cfSShuo Chen  }
48354280cfSShuo Chen
49354280cfSShuo Chen  // default copy-ctor, dtor and assignment are fine
50354280cfSShuo Chen
51354280cfSShuo Chen  void swap(Buffer& rhs)
52354280cfSShuo Chen  {
53354280cfSShuo Chen    buffer_.swap(rhs.buffer_);
54354280cfSShuo Chen    std::swap(readerIndex_, rhs.readerIndex_);
55354280cfSShuo Chen    std::swap(writerIndex_, rhs.writerIndex_);
56354280cfSShuo Chen  }
57354280cfSShuo Chen
58354280cfSShuo Chen  size_t readableBytes() const
59354280cfSShuo Chen  { return writerIndex_ - readerIndex_; }
60354280cfSShuo Chen
61354280cfSShuo Chen  size_t writableBytes() const
62354280cfSShuo Chen  { return buffer_.size() - writerIndex_; }
63354280cfSShuo Chen
64354280cfSShuo Chen  size_t prependableBytes() const
65354280cfSShuo Chen  { return readerIndex_; }
66354280cfSShuo Chen
67354280cfSShuo Chen  const char* peek() const
68354280cfSShuo Chen  { return begin() + readerIndex_; }
69354280cfSShuo Chen
70354280cfSShuo Chen  // retrieve returns void, to prevent
71354280cfSShuo Chen  // string str(retrieve(readableBytes()), readableBytes());
72354280cfSShuo Chen  // the evaluation of two functions are unspecified
73354280cfSShuo Chen  void retrieve(size_t len)
74354280cfSShuo Chen  {
75354280cfSShuo Chen    assert(len <= readableBytes());
76354280cfSShuo Chen    readerIndex_ += len;
77354280cfSShuo Chen  }
78354280cfSShuo Chen
79354280cfSShuo Chen  void retrieveUntil(const char* end)
80354280cfSShuo Chen  {
81354280cfSShuo Chen    assert(peek() <= end);
82354280cfSShuo Chen    assert(end <= beginWrite());
83354280cfSShuo Chen    retrieve(end - peek());
84354280cfSShuo Chen  }
85354280cfSShuo Chen
86354280cfSShuo Chen  void retrieveAll()
87354280cfSShuo Chen  {
88354280cfSShuo Chen    readerIndex_ = kCheapPrepend;
89354280cfSShuo Chen    writerIndex_ = kCheapPrepend;
90354280cfSShuo Chen  }
91354280cfSShuo Chen
92354280cfSShuo Chen  std::string retrieveAsString()
93354280cfSShuo Chen  {
94354280cfSShuo Chen    std::string str(peek(), readableBytes());
95354280cfSShuo Chen    retrieveAll();
96354280cfSShuo Chen    return str;
97354280cfSShuo Chen  }
98354280cfSShuo Chen
99354280cfSShuo Chen  void append(const std::string& str)
100354280cfSShuo Chen  {
101354280cfSShuo Chen    append(str.data(), str.length());
102354280cfSShuo Chen  }
103354280cfSShuo Chen
104354280cfSShuo Chen  void append(const char* /*restrict*/ data, size_t len)
105354280cfSShuo Chen  {
106354280cfSShuo Chen    ensureWritableBytes(len);
107354280cfSShuo Chen    std::copy(data, data+len, beginWrite());
108354280cfSShuo Chen    hasWritten(len);
109354280cfSShuo Chen  }
110354280cfSShuo Chen
111354280cfSShuo Chen  void append(const void* /*restrict*/ data, size_t len)
112354280cfSShuo Chen  {
113354280cfSShuo Chen    append(static_cast<const char*>(data), len);
114354280cfSShuo Chen  }
115354280cfSShuo Chen
116354280cfSShuo Chen  void ensureWritableBytes(size_t len)
117354280cfSShuo Chen  {
118354280cfSShuo Chen    if (writableBytes() < len)
119354280cfSShuo Chen    {
120354280cfSShuo Chen      makeSpace(len);
121354280cfSShuo Chen    }
122354280cfSShuo Chen    assert(writableBytes() >= len);
123354280cfSShuo Chen  }
124354280cfSShuo Chen
125354280cfSShuo Chen  char* beginWrite()
126354280cfSShuo Chen  { return begin() + writerIndex_; }
127354280cfSShuo Chen
128354280cfSShuo Chen  const char* beginWrite() const
129354280cfSShuo Chen  { return begin() + writerIndex_; }
130354280cfSShuo Chen
131354280cfSShuo Chen  void hasWritten(size_t len)
132354280cfSShuo Chen  { writerIndex_ += len; }
133354280cfSShuo Chen
134354280cfSShuo Chen  void prepend(const void* /*restrict*/ data, size_t len)
135354280cfSShuo Chen  {
136354280cfSShuo Chen    assert(len <= prependableBytes());
137354280cfSShuo Chen    readerIndex_ -= len;
138354280cfSShuo Chen    const char* d = static_cast<const char*>(data);
139354280cfSShuo Chen    std::copy(d, d+len, begin()+readerIndex_);
140354280cfSShuo Chen  }
141354280cfSShuo Chen
142354280cfSShuo Chen  void shrink(size_t reserve)
143354280cfSShuo Chen  {
144354280cfSShuo Chen   std::vector<char> buf(kCheapPrepend+readableBytes()+reserve);
145354280cfSShuo Chen   std::copy(peek(), peek()+readableBytes(), buf.begin()+kCheapPrepend);
146354280cfSShuo Chen   buf.swap(buffer_);
147354280cfSShuo Chen  }
148354280cfSShuo Chen
149354280cfSShuo Chen  /// Read data directly into buffer.
150354280cfSShuo Chen  ///
151354280cfSShuo Chen  /// It may implement with readv(2)
152354280cfSShuo Chen  /// @return result of read(2), @c errno is saved
153354280cfSShuo Chen  ssize_t readFd(int fd, int* savedErrno);
154354280cfSShuo Chen
155354280cfSShuo Chen private:
156354280cfSShuo Chen
157354280cfSShuo Chen  char* begin()
158354280cfSShuo Chen  { return &*buffer_.begin(); }
159354280cfSShuo Chen
160354280cfSShuo Chen  const char* begin() const
161354280cfSShuo Chen  { return &*buffer_.begin(); }
162354280cfSShuo Chen
163354280cfSShuo Chen  void makeSpace(size_t len)
164354280cfSShuo Chen  {
165354280cfSShuo Chen    if (writableBytes() + prependableBytes() < len + kCheapPrepend)
166354280cfSShuo Chen    {
167354280cfSShuo Chen      buffer_.resize(writerIndex_+len);
168354280cfSShuo Chen    }
169354280cfSShuo Chen    else
170354280cfSShuo Chen    {
171354280cfSShuo Chen      // move readable data to the front, make space inside buffer
172354280cfSShuo Chen      assert(kCheapPrepend < readerIndex_);
173354280cfSShuo Chen      size_t readable = readableBytes();
174354280cfSShuo Chen      std::copy(begin()+readerIndex_,
175354280cfSShuo Chen                begin()+writerIndex_,
176354280cfSShuo Chen                begin()+kCheapPrepend);
177354280cfSShuo Chen      readerIndex_ = kCheapPrepend;
178354280cfSShuo Chen      writerIndex_ = readerIndex_ + readable;
179354280cfSShuo Chen      assert(readable == readableBytes());
180354280cfSShuo Chen    }
181354280cfSShuo Chen  }
182354280cfSShuo Chen
183354280cfSShuo Chen private:
184354280cfSShuo Chen  std::vector<char> buffer_;
185354280cfSShuo Chen  size_t readerIndex_;
186354280cfSShuo Chen  size_t writerIndex_;
187354280cfSShuo Chen};
188354280cfSShuo Chen
189354280cfSShuo Chen}
190354280cfSShuo Chen
191354280cfSShuo Chen#endif  // MUDUO_NET_BUFFER_H
192