rippled
ZeroCopyStream.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef RIPPLE_OVERLAY_ZEROCOPYSTREAM_H_INCLUDED
21 #define RIPPLE_OVERLAY_ZEROCOPYSTREAM_H_INCLUDED
22 
23 #include <boost/asio/buffer.hpp>
24 #include <cstdint>
25 #include <google/protobuf/io/zero_copy_stream.h>
26 
27 namespace ripple {
28 
34 template <class Buffers>
35 class ZeroCopyInputStream : public ::google::protobuf::io::ZeroCopyInputStream
36 {
37 private:
38  using iterator = typename Buffers::const_iterator;
39  using const_buffer = boost::asio::const_buffer;
40 
41  google::protobuf::int64 count_ = 0;
43  iterator first_; // Where pos_ comes from
44  const_buffer pos_; // What Next() will return
45 
46 public:
47  explicit ZeroCopyInputStream(Buffers const& buffers);
48 
49  bool
50  Next(const void** data, int* size) override;
51 
52  void
53  BackUp(int count) override;
54 
55  bool
56  Skip(int count) override;
57 
58  google::protobuf::int64
59  ByteCount() const override
60  {
61  return count_;
62  }
63 };
64 
65 //------------------------------------------------------------------------------
66 
67 template <class Buffers>
69  : last_(buffers.end())
70  , first_(buffers.begin())
71  , pos_((first_ != last_) ? *first_ : const_buffer(nullptr, 0))
72 {
73 }
74 
75 template <class Buffers>
76 bool
77 ZeroCopyInputStream<Buffers>::Next(const void** data, int* size)
78 {
79  *data = boost::asio::buffer_cast<void const*>(pos_);
80  *size = boost::asio::buffer_size(pos_);
81  if (first_ == last_)
82  return false;
83  count_ += *size;
84  pos_ = (++first_ != last_) ? *first_ : const_buffer(nullptr, 0);
85  return true;
86 }
87 
88 template <class Buffers>
89 void
91 {
92  --first_;
93  pos_ = *first_ + (boost::asio::buffer_size(*first_) - count);
94  count_ -= count;
95 }
96 
97 template <class Buffers>
98 bool
100 {
101  if (first_ == last_)
102  return false;
103  while (count > 0)
104  {
105  auto const size = boost::asio::buffer_size(pos_);
106  if (count < size)
107  {
108  pos_ = pos_ + count;
109  count_ += count;
110  return true;
111  }
112  count_ += size;
113  if (++first_ == last_)
114  return false;
115  count -= size;
116  pos_ = *first_;
117  }
118  return true;
119 }
120 
121 //------------------------------------------------------------------------------
122 
127 template <class Streambuf>
128 class ZeroCopyOutputStream : public ::google::protobuf::io::ZeroCopyOutputStream
129 {
130 private:
131  using buffers_type = typename Streambuf::mutable_buffers_type;
132  using iterator = typename buffers_type::const_iterator;
133  using mutable_buffer = boost::asio::mutable_buffer;
134 
135  Streambuf& streambuf_;
137  google::protobuf::int64 count_ = 0;
141 
142 public:
143  explicit ZeroCopyOutputStream(Streambuf& streambuf, std::size_t blockSize);
144 
146 
147  bool
148  Next(void** data, int* size) override;
149 
150  void
151  BackUp(int count) override;
152 
153  google::protobuf::int64
154  ByteCount() const override
155  {
156  return count_;
157  }
158 };
159 
160 //------------------------------------------------------------------------------
161 
162 template <class Streambuf>
164  Streambuf& streambuf,
165  std::size_t blockSize)
166  : streambuf_(streambuf)
167  , blockSize_(blockSize)
168  , buffers_(streambuf_.prepare(blockSize_))
169  , pos_(buffers_.begin())
170 {
171 }
172 
173 template <class Streambuf>
175 {
176  if (commit_ != 0)
177  streambuf_.commit(commit_);
178 }
179 
180 template <class Streambuf>
181 bool
183 {
184  if (commit_ != 0)
185  {
186  streambuf_.commit(commit_);
187  count_ += commit_;
188  }
189 
190  if (pos_ == buffers_.end())
191  {
192  buffers_ = streambuf_.prepare(blockSize_);
193  pos_ = buffers_.begin();
194  }
195 
196  *data = boost::asio::buffer_cast<void*>(*pos_);
197  *size = boost::asio::buffer_size(*pos_);
198  commit_ = *size;
199  ++pos_;
200  return true;
201 }
202 
203 template <class Streambuf>
204 void
206 {
207  assert(count <= commit_);
208  auto const n = commit_ - count;
209  streambuf_.commit(n);
210  count_ += n;
211  commit_ = 0;
212 }
213 
214 } // namespace ripple
215 
216 #endif
ripple::ZeroCopyOutputStream
Implements ZeroCopyOutputStream around a Streambuf.
Definition: ZeroCopyStream.h:128
ripple::ZeroCopyOutputStream::ByteCount
google::protobuf::int64 ByteCount() const override
Definition: ZeroCopyStream.h:154
ripple::ZeroCopyOutputStream::~ZeroCopyOutputStream
~ZeroCopyOutputStream()
Definition: ZeroCopyStream.h:174
ripple::ZeroCopyInputStream::count_
google::protobuf::int64 count_
Definition: ZeroCopyStream.h:41
ripple::ZeroCopyInputStream::last_
iterator last_
Definition: ZeroCopyStream.h:42
ripple::ZeroCopyInputStream::BackUp
void BackUp(int count) override
Definition: ZeroCopyStream.h:90
ripple::ZeroCopyInputStream::ByteCount
google::protobuf::int64 ByteCount() const override
Definition: ZeroCopyStream.h:59
ripple::ZeroCopyInputStream
Implements ZeroCopyInputStream around a buffer sequence.
Definition: ZeroCopyStream.h:35
ripple::ZeroCopyOutputStream::streambuf_
Streambuf & streambuf_
Definition: ZeroCopyStream.h:135
ripple::ZeroCopyOutputStream::Next
bool Next(void **data, int *size) override
Definition: ZeroCopyStream.h:182
ripple::ZeroCopyOutputStream::iterator
typename buffers_type::const_iterator iterator
Definition: ZeroCopyStream.h:132
ripple::ZeroCopyOutputStream::commit_
std::size_t commit_
Definition: ZeroCopyStream.h:138
ripple::ZeroCopyOutputStream::blockSize_
std::size_t blockSize_
Definition: ZeroCopyStream.h:136
ripple::ZeroCopyInputStream::const_buffer
boost::asio::const_buffer const_buffer
Definition: ZeroCopyStream.h:39
ripple::ZeroCopyOutputStream::count_
google::protobuf::int64 count_
Definition: ZeroCopyStream.h:137
ripple::ZeroCopyInputStream::iterator
typename Buffers::const_iterator iterator
Definition: ZeroCopyStream.h:38
cstdint
ripple::ZeroCopyOutputStream::mutable_buffer
boost::asio::mutable_buffer mutable_buffer
Definition: ZeroCopyStream.h:133
ripple::ZeroCopyInputStream::Skip
bool Skip(int count) override
Definition: ZeroCopyStream.h:99
ripple::ZeroCopyInputStream::pos_
const_buffer pos_
Definition: ZeroCopyStream.h:44
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::ZeroCopyOutputStream::buffers_type
typename Streambuf::mutable_buffers_type buffers_type
Definition: ZeroCopyStream.h:131
ripple::ZeroCopyInputStream::Next
bool Next(const void **data, int *size) override
Definition: ZeroCopyStream.h:77
std::size_t
ripple::ZeroCopyOutputStream::buffers_
buffers_type buffers_
Definition: ZeroCopyStream.h:139
ripple::ZeroCopyOutputStream::BackUp
void BackUp(int count) override
Definition: ZeroCopyStream.h:205
ripple::ZeroCopyOutputStream::pos_
iterator pos_
Definition: ZeroCopyStream.h:140
ripple::ZeroCopyInputStream::first_
iterator first_
Definition: ZeroCopyStream.h:43
ripple::ZeroCopyOutputStream::ZeroCopyOutputStream
ZeroCopyOutputStream(Streambuf &streambuf, std::size_t blockSize)
Definition: ZeroCopyStream.h:163
ripple::ZeroCopyInputStream::ZeroCopyInputStream
ZeroCopyInputStream(Buffers const &buffers)
Definition: ZeroCopyStream.h:68