Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: remoting/base/compound_buffer.cc

Issue 4779001: Added CompoundBuffer that will be used to store data in the encoding/decoding (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: merged CompoundBuffer with MultipleArrayInputStream Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <functional>
6
7 #include "base/logging.h"
8 #include "net/base/io_buffer.h"
9 #include "remoting/base/compound_buffer.h"
10
11 namespace remoting {
12
13 CompoundBuffer::DataChunk::DataChunk(
14 net::IOBuffer* buffer, const char* data_start, int data_size)
15 : buffer(buffer),
16 data_start(data_start),
17 data_size(data_size) {
18 }
19
20 CompoundBuffer::CompoundBuffer()
21 : total_bytes_(0),
22 current_buffer_(0),
23 current_buffer_position_(0),
24 position_(0),
25 last_returned_size_(0) {
26 }
27
28 CompoundBuffer::~CompoundBuffer() {
29 }
30
31 void CompoundBuffer::Clear() {
32 buffers_.clear();
33 total_bytes_ = 0;
34 position_ = 0;
35 last_returned_size_ = 0;
36 current_buffer_ = 0;
37 current_buffer_position_ = 0;
38 }
39
40
awong 2010/11/12 02:40:06 remove extra newline
Sergey Ulanov 2010/11/13 04:43:39 Done.
41 void CompoundBuffer::Append(net::IOBuffer* buffer,
42 const char* data, int data_size) {
43 // A weak check that the |data| is within |buffer|.
44 DCHECK_GE(data, buffer->data());
45 DCHECK_GT(data_size, 0);
46
47 DCHECK_EQ(position_, 0); // Haven't started reading.
awong 2010/11/12 02:40:06 So the API contract is that once you start reading
Sergey Ulanov 2010/11/13 04:43:39 Done.
48
49 buffers_.push_back(DataChunk(buffer, data, data_size));
50 total_bytes_ += data_size;
51 }
52
53 void CompoundBuffer::Append(net::IOBuffer* buffer, int data_size) {
54 Append(buffer, buffer->data(), data_size);
55 }
56
57 void CompoundBuffer::Prepend(net::IOBuffer* buffer,
58 const char* data, int data_size) {
59 // A weak check that the |data| is within |buffer|.
60 DCHECK_GE(data, buffer->data());
awong 2010/11/12 02:40:06 Same comments as earlier. Also, should there be a
Sergey Ulanov 2010/11/13 04:43:39 Added locked() returns true if content is locked.
61 DCHECK_GT(data_size, 0);
62
63 DCHECK_EQ(position_, 0); // Haven't started reading.
64
65 buffers_.push_front(DataChunk(buffer, data, data_size));
66 total_bytes_ += data_size;
67 }
68
69 void CompoundBuffer::Prepend(net::IOBuffer* buffer, int data_size) {
70 Prepend(buffer, buffer->data(), data_size);
71 }
72
73 void CompoundBuffer::CopyAndAppend(const char* data, int data_size) {
74 net::IOBuffer* buffer = new net::IOBuffer(data_size);
75 memcpy(buffer->data(), data, data_size);
76 Append(buffer, buffer->data(), data_size);
77 }
78
79 void CompoundBuffer::CopyAndPrepend(const char* data, int data_size) {
80 net::IOBuffer* buffer = new net::IOBuffer(data_size);
81 memcpy(buffer->data(), data, data_size);
82 Prepend(buffer, buffer->data(), data_size);
83 }
84
85 net::IOBufferWithSize* CompoundBuffer::Assemble() const {
86 net::IOBufferWithSize* result = new net::IOBufferWithSize(total_bytes_);
awong 2010/11/12 02:40:06 Are these things refcounted?
Sergey Ulanov 2010/11/13 04:43:39 Yes, but we just create it, and then the caller wi
87 Assemble(result->data(), total_bytes_);
88 return result;
89 }
90
91 void CompoundBuffer::Assemble(char* data, int data_size) const {
92 char* pos = data;
93 for (DataChunkList::const_iterator it = buffers_.begin();
94 it != buffers_.end(); ++it) {
95 CHECK_LE(pos + it->data_size, data + data_size);
96 memcpy(pos, it->data_start, it->data_size);
97 pos += it->data_size;
98 }
99 }
100
101 void CompoundBuffer::CopyFrom(const CompoundBuffer& source,
102 int start, int end) {
103 // Check that 0 <= |start| <= |end| <= |total_bytes_|.
104 DCHECK_LE(0, start);
105 DCHECK_LE(start, end);
106 DCHECK_LE(end, source.total_bytes());
107
108 Clear();
109
110 if (end == start) {
111 return;
112 }
113
114 // Iterate over chunks in the |source| and add those that we need.
115 int pos = 0;
116 for (DataChunkList::const_iterator it = source.buffers_.begin();
117 it != source.buffers_.end(); ++it) {
118
119 // Add data from the current chunk only if it is in the specified interval.
120 if (pos + it->data_size > start && pos < end) {
121 int relative_start = std::max(0, start - pos);
122 int relative_end = std::min(it->data_size, end - pos);
123 DCHECK_LE(0, relative_start);
124 DCHECK_LT(relative_start, relative_end);
125 DCHECK_LE(relative_end, it->data_size);
126 Append(it->buffer.get(), it->data_start + relative_start,
127 relative_end - relative_start);
128 }
129
130 pos += it->data_size;
131 if (pos >= end) {
132 // We've got all the data we need.
133 break;
134 }
135 }
136
137 DCHECK_EQ(total_bytes_, end - start);
138 }
139
140 bool CompoundBuffer::Next(const void** data, int* size) {
141 if (current_buffer_ < buffers_.size()) {
142 // Reply with the number of bytes remaining in the current buffer.
143 const DataChunk& buffer = buffers_[current_buffer_];
144 int read_size = buffer.data_size - current_buffer_position_;
145 *data = buffer.data_start + current_buffer_position_;
146 *size = read_size;
147
148 // Adjust position.
149 ++current_buffer_;
150 current_buffer_position_ = 0;
151 position_ += read_size;
152
153 last_returned_size_ = read_size;
154 return true;
155 }
156
157 DCHECK_EQ(position_, total_bytes_);
158
159 // We've reached the end of the stream. So reset |last_returned_size_|
160 // to zero to prevent any backup request.
161 // This is the same as in ArrayInputStream.
162 // See google/protobuf/io/zero_copy_stream_impl_lite.cc.
163 last_returned_size_ = 0;
164 return false;
165 }
166
167 void CompoundBuffer::BackUp(int count) {
168 DCHECK_LE(count, last_returned_size_);
169 DCHECK_GT(current_buffer_, 0u);
170
171 // Rewind one buffer and rewind data offset by |count| bytes.
172 --current_buffer_;
173 const DataChunk& buffer = buffers_[current_buffer_];
174 current_buffer_position_ = buffer.data_size - count;
175 position_ -= count;
176 DCHECK_GE(position_, 0);
177
178 // Prevent additional backups.
179 last_returned_size_ = 0;
180 }
181
182 bool CompoundBuffer::Skip(int count) {
183 DCHECK_GE(count, 0);
184 last_returned_size_ = 0;
185
186 while (count > 0 && current_buffer_ < buffers_.size()) {
187 const DataChunk& buffer = buffers_[current_buffer_];
188 int read = std::min(count, buffer.data_size - current_buffer_position_);
189
190 // Advance the current buffer offset and position.
191 current_buffer_position_ += read;
192 position_ += read;
193 count -= read;
194
195 // If the current buffer is fully read, then advance to the next buffer.
196 if (current_buffer_position_ == buffer.data_size) {
197 ++current_buffer_;
198 current_buffer_position_ = 0;
199 }
200 }
201
202 return count == 0;
203 }
204
205 int64 CompoundBuffer::ByteCount() const {
206 return position_;
207 }
208
209 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698