rippled
Loading...
Searching...
No Matches
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 <xrpl/beast/utility/instrumentation.h>
24
25#include <boost/asio/buffer.hpp>
26#include <google/protobuf/io/zero_copy_stream.h>
27
28namespace ripple {
29
35template <class Buffers>
36class ZeroCopyInputStream : public ::google::protobuf::io::ZeroCopyInputStream
37{
38private:
39 using iterator = typename Buffers::const_iterator;
40 using const_buffer = boost::asio::const_buffer;
41
42 google::protobuf::int64 count_ = 0;
44 iterator first_; // Where pos_ comes from
45 const_buffer pos_; // What Next() will return
46
47public:
48 explicit ZeroCopyInputStream(Buffers const& buffers);
49
50 bool
51 Next(const void** data, int* size) override;
52
53 void
54 BackUp(int count) override;
55
56 bool
57 Skip(int count) override;
58
59 google::protobuf::int64
60 ByteCount() const override
61 {
62 return count_;
63 }
64};
65
66//------------------------------------------------------------------------------
67
68template <class Buffers>
70 : last_(buffers.end())
71 , first_(buffers.begin())
72 , pos_((first_ != last_) ? *first_ : const_buffer(nullptr, 0))
73{
74}
75
76template <class Buffers>
77bool
78ZeroCopyInputStream<Buffers>::Next(const void** data, int* size)
79{
80 *data = boost::asio::buffer_cast<void const*>(pos_);
81 *size = boost::asio::buffer_size(pos_);
82 if (first_ == last_)
83 return false;
84 count_ += *size;
85 pos_ = (++first_ != last_) ? *first_ : const_buffer(nullptr, 0);
86 return true;
87}
88
89template <class Buffers>
90void
92{
93 --first_;
94 pos_ = *first_ + (boost::asio::buffer_size(*first_) - count);
95 count_ -= count;
96}
97
98template <class Buffers>
99bool
101{
102 if (first_ == last_)
103 return false;
104 while (count > 0)
105 {
106 auto const size = boost::asio::buffer_size(pos_);
107 if (count < size)
108 {
109 pos_ = pos_ + count;
110 count_ += count;
111 return true;
112 }
113 count_ += size;
114 if (++first_ == last_)
115 return false;
116 count -= size;
117 pos_ = *first_;
118 }
119 return true;
120}
121
122//------------------------------------------------------------------------------
123
128template <class Streambuf>
129class ZeroCopyOutputStream : public ::google::protobuf::io::ZeroCopyOutputStream
130{
131private:
132 using buffers_type = typename Streambuf::mutable_buffers_type;
133 using iterator = typename buffers_type::const_iterator;
134 using mutable_buffer = boost::asio::mutable_buffer;
135
136 Streambuf& streambuf_;
138 google::protobuf::int64 count_ = 0;
142
143public:
144 explicit ZeroCopyOutputStream(Streambuf& streambuf, std::size_t blockSize);
145
147
148 bool
149 Next(void** data, int* size) override;
150
151 void
152 BackUp(int count) override;
153
154 google::protobuf::int64
155 ByteCount() const override
156 {
157 return count_;
158 }
159};
160
161//------------------------------------------------------------------------------
162
163template <class Streambuf>
165 Streambuf& streambuf,
166 std::size_t blockSize)
167 : streambuf_(streambuf)
168 , blockSize_(blockSize)
169 , buffers_(streambuf_.prepare(blockSize_))
170 , pos_(buffers_.begin())
171{
172}
173
174template <class Streambuf>
176{
177 if (commit_ != 0)
178 streambuf_.commit(commit_);
179}
180
181template <class Streambuf>
182bool
184{
185 if (commit_ != 0)
186 {
187 streambuf_.commit(commit_);
188 count_ += commit_;
189 }
190
191 if (pos_ == buffers_.end())
192 {
193 buffers_ = streambuf_.prepare(blockSize_);
194 pos_ = buffers_.begin();
195 }
196
197 *data = boost::asio::buffer_cast<void*>(*pos_);
198 *size = boost::asio::buffer_size(*pos_);
199 commit_ = *size;
200 ++pos_;
201 return true;
202}
203
204template <class Streambuf>
205void
207{
208 XRPL_ASSERT(
209 count <= commit_, "ripple::ZeroCopyOutputStream::BackUp : valid input");
210 auto const n = commit_ - count;
211 streambuf_.commit(n);
212 count_ += n;
213 commit_ = 0;
214}
215
216} // namespace ripple
217
218#endif
Implements ZeroCopyInputStream around a buffer sequence.
google::protobuf::int64 count_
bool Next(const void **data, int *size) override
ZeroCopyInputStream(Buffers const &buffers)
void BackUp(int count) override
boost::asio::const_buffer const_buffer
google::protobuf::int64 ByteCount() const override
bool Skip(int count) override
typename Buffers::const_iterator iterator
Implements ZeroCopyOutputStream around a Streambuf.
google::protobuf::int64 ByteCount() const override
google::protobuf::int64 count_
typename Streambuf::mutable_buffers_type buffers_type
void BackUp(int count) override
ZeroCopyOutputStream(Streambuf &streambuf, std::size_t blockSize)
typename buffers_type::const_iterator iterator
boost::asio::mutable_buffer mutable_buffer
bool Next(void **data, int *size) override
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26