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

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: - 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
« no previous file with comments | « remoting/base/compound_buffer.h ('k') | remoting/base/compound_buffer_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_value, const char* start_value, int size_value)
15 : buffer(buffer_value),
16 start(start_value),
17 size(size_value) {
18 }
19
20 CompoundBuffer::CompoundBuffer()
21 : total_bytes_(0),
22 locked_(false) {
23 }
24
25 CompoundBuffer::~CompoundBuffer() {
26 }
27
28 void CompoundBuffer::Clear() {
29 CHECK(!locked_);
30 chunks_.clear();
31 total_bytes_ = 0;
32 }
33
34 void CompoundBuffer::Append(net::IOBuffer* buffer,
35 const char* start, int size) {
36 // A weak check that the |start| is within |buffer|.
37 DCHECK_GE(start, buffer->data());
38 DCHECK_GT(size, 0);
39
40 CHECK(!locked_);
41
42 chunks_.push_back(DataChunk(buffer, start, size));
43 total_bytes_ += size;
44 }
45
46 void CompoundBuffer::Append(net::IOBuffer* buffer, int size) {
47 Append(buffer, buffer->data(), size);
48 }
49
50 void CompoundBuffer::Append(const CompoundBuffer& buffer) {
51 for (DataChunkList::const_iterator it = buffer.chunks_.begin();
52 it != buffer.chunks_.end(); ++it) {
53 Append(it->buffer, it->start, it->size);
54 }
55 }
56
57 void CompoundBuffer::Prepend(net::IOBuffer* buffer,
58 const char* start, int size) {
59 // A weak check that the |start| is within |buffer|.
60 DCHECK_GE(start, buffer->data());
61 DCHECK_GT(size, 0);
62
63 CHECK(!locked_);
64
65 chunks_.push_front(DataChunk(buffer, start, size));
66 total_bytes_ += size;
67 }
68
69 void CompoundBuffer::Prepend(net::IOBuffer* buffer, int size) {
70 Prepend(buffer, buffer->data(), size);
71 }
72
73 void CompoundBuffer::Prepend(const CompoundBuffer& buffer) {
74 for (DataChunkList::const_iterator it = buffer.chunks_.begin();
75 it != buffer.chunks_.end(); ++it) {
76 Prepend(it->buffer, it->start, it->size);
77 }
78 }
79 void CompoundBuffer::AppendCopyOf(const char* data, int size) {
80 net::IOBuffer* buffer = new net::IOBuffer(size);
81 memcpy(buffer->data(), data, size);
82 Append(buffer, size);
83 }
84
85 void CompoundBuffer::PrependCopyOf(const char* data, int size) {
86 net::IOBuffer* buffer = new net::IOBuffer(size);
87 memcpy(buffer->data(), data, size);
88 Prepend(buffer, size);
89 }
90
91 void CompoundBuffer::Lock() {
92 locked_ = true;
93 }
94
95 net::IOBufferWithSize* CompoundBuffer::ToIOBufferWithSize() const {
96 net::IOBufferWithSize* result = new net::IOBufferWithSize(total_bytes_);
97 CopyTo(result->data(), total_bytes_);
98 return result;
99 }
100
101 void CompoundBuffer::CopyTo(char* data, int size) const {
102 char* pos = data;
103 for (DataChunkList::const_iterator it = chunks_.begin();
104 it != chunks_.end(); ++it) {
105 CHECK_LE(pos + it->size, data + size);
106 memcpy(pos, it->start, it->size);
107 pos += it->size;
108 }
109 }
110
111 void CompoundBuffer::CopyFrom(const CompoundBuffer& source,
112 int start, int end) {
113 // Check that 0 <= |start| <= |end| <= |total_bytes_|.
114 DCHECK_LE(0, start);
115 DCHECK_LE(start, end);
116 DCHECK_LE(end, source.total_bytes());
117
118 Clear();
119
120 if (end == start) {
121 return;
122 }
123
124 // Iterate over chunks in the |source| and add those that we need.
125 int pos = 0;
126 for (DataChunkList::const_iterator it = source.chunks_.begin();
127 it != source.chunks_.end(); ++it) {
128
129 // Add data from the current chunk only if it is in the specified interval.
130 if (pos + it->size > start && pos < end) {
131 int relative_start = std::max(0, start - pos);
132 int relative_end = std::min(it->size, end - pos);
133 DCHECK_LE(0, relative_start);
134 DCHECK_LT(relative_start, relative_end);
135 DCHECK_LE(relative_end, it->size);
136 Append(it->buffer.get(), it->start + relative_start,
137 relative_end - relative_start);
138 }
139
140 pos += it->size;
141 if (pos >= end) {
142 // We've got all the data we need.
143 break;
144 }
145 }
146
147 DCHECK_EQ(total_bytes_, end - start);
148 }
149
150 CompoundBufferInputStream::CompoundBufferInputStream(
151 const CompoundBuffer* buffer)
152 : buffer_(buffer),
153 current_chunk_(0),
154 current_chunk_position_(0),
155 position_(0),
156 last_returned_size_(0) {
157 DCHECK(buffer_->locked());
158 }
159
160 CompoundBufferInputStream::~CompoundBufferInputStream() {
161 }
162
163 bool CompoundBufferInputStream::Next(const void** data, int* size) {
164 if (current_chunk_ < buffer_->chunks_.size()) {
165 // Reply with the number of bytes remaining in the current buffer.
166 const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
167 int read_size = chunk.size - current_chunk_position_;
168 *data = chunk.start + current_chunk_position_;
169 *size = read_size;
170
171 // Adjust position.
172 ++current_chunk_;
173 current_chunk_position_ = 0;
174 position_ += read_size;
175
176 last_returned_size_ = read_size;
177 return true;
178 }
179
180 DCHECK_EQ(position_, buffer_->total_bytes());
181
182 // We've reached the end of the stream. So reset |last_returned_size_|
183 // to zero to prevent any backup request.
184 // This is the same as in ArrayInputStream.
185 // See google/protobuf/io/zero_copy_stream_impl_lite.cc.
186 last_returned_size_ = 0;
187 return false;
188 }
189
190 void CompoundBufferInputStream::BackUp(int count) {
191 DCHECK_LE(count, last_returned_size_);
192 DCHECK_GT(current_chunk_, 0u);
193
194 // Rewind one buffer and rewind data offset by |count| bytes.
195 --current_chunk_;
196 const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
197 current_chunk_position_ = chunk.size - count;
198 position_ -= count;
199 DCHECK_GE(position_, 0);
200
201 // Prevent additional backups.
202 last_returned_size_ = 0;
203 }
204
205 bool CompoundBufferInputStream::Skip(int count) {
206 DCHECK_GE(count, 0);
207 last_returned_size_ = 0;
208
209 while (count > 0 && current_chunk_ < buffer_->chunks_.size()) {
210 const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
211 int read = std::min(count, chunk.size - current_chunk_position_);
212
213 // Advance the current buffer offset and position.
214 current_chunk_position_ += read;
215 position_ += read;
216 count -= read;
217
218 // If the current buffer is fully read, then advance to the next buffer.
219 if (current_chunk_position_ == chunk.size) {
220 ++current_chunk_;
221 current_chunk_position_ = 0;
222 }
223 }
224
225 return count == 0;
226 }
227
228 int64 CompoundBufferInputStream::ByteCount() const {
229 return position_;
230 }
231
232 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/base/compound_buffer.h ('k') | remoting/base/compound_buffer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698