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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/base/compound_buffer.h ('k') | remoting/base/compound_buffer_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/base/compound_buffer.cc
diff --git a/remoting/base/compound_buffer.cc b/remoting/base/compound_buffer.cc
new file mode 100644
index 0000000000000000000000000000000000000000..9e8b8c32a2ae77d957ebe33cd68976786dc53f24
--- /dev/null
+++ b/remoting/base/compound_buffer.cc
@@ -0,0 +1,232 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <functional>
+
+#include "base/logging.h"
+#include "net/base/io_buffer.h"
+#include "remoting/base/compound_buffer.h"
+
+namespace remoting {
+
+CompoundBuffer::DataChunk::DataChunk(
+ net::IOBuffer* buffer_value, const char* start_value, int size_value)
+ : buffer(buffer_value),
+ start(start_value),
+ size(size_value) {
+}
+
+CompoundBuffer::CompoundBuffer()
+ : total_bytes_(0),
+ locked_(false) {
+}
+
+CompoundBuffer::~CompoundBuffer() {
+}
+
+void CompoundBuffer::Clear() {
+ CHECK(!locked_);
+ chunks_.clear();
+ total_bytes_ = 0;
+}
+
+void CompoundBuffer::Append(net::IOBuffer* buffer,
+ const char* start, int size) {
+ // A weak check that the |start| is within |buffer|.
+ DCHECK_GE(start, buffer->data());
+ DCHECK_GT(size, 0);
+
+ CHECK(!locked_);
+
+ chunks_.push_back(DataChunk(buffer, start, size));
+ total_bytes_ += size;
+}
+
+void CompoundBuffer::Append(net::IOBuffer* buffer, int size) {
+ Append(buffer, buffer->data(), size);
+}
+
+void CompoundBuffer::Append(const CompoundBuffer& buffer) {
+ for (DataChunkList::const_iterator it = buffer.chunks_.begin();
+ it != buffer.chunks_.end(); ++it) {
+ Append(it->buffer, it->start, it->size);
+ }
+}
+
+void CompoundBuffer::Prepend(net::IOBuffer* buffer,
+ const char* start, int size) {
+ // A weak check that the |start| is within |buffer|.
+ DCHECK_GE(start, buffer->data());
+ DCHECK_GT(size, 0);
+
+ CHECK(!locked_);
+
+ chunks_.push_front(DataChunk(buffer, start, size));
+ total_bytes_ += size;
+}
+
+void CompoundBuffer::Prepend(net::IOBuffer* buffer, int size) {
+ Prepend(buffer, buffer->data(), size);
+}
+
+void CompoundBuffer::Prepend(const CompoundBuffer& buffer) {
+ for (DataChunkList::const_iterator it = buffer.chunks_.begin();
+ it != buffer.chunks_.end(); ++it) {
+ Prepend(it->buffer, it->start, it->size);
+ }
+}
+void CompoundBuffer::AppendCopyOf(const char* data, int size) {
+ net::IOBuffer* buffer = new net::IOBuffer(size);
+ memcpy(buffer->data(), data, size);
+ Append(buffer, size);
+}
+
+void CompoundBuffer::PrependCopyOf(const char* data, int size) {
+ net::IOBuffer* buffer = new net::IOBuffer(size);
+ memcpy(buffer->data(), data, size);
+ Prepend(buffer, size);
+}
+
+void CompoundBuffer::Lock() {
+ locked_ = true;
+}
+
+net::IOBufferWithSize* CompoundBuffer::ToIOBufferWithSize() const {
+ net::IOBufferWithSize* result = new net::IOBufferWithSize(total_bytes_);
+ CopyTo(result->data(), total_bytes_);
+ return result;
+}
+
+void CompoundBuffer::CopyTo(char* data, int size) const {
+ char* pos = data;
+ for (DataChunkList::const_iterator it = chunks_.begin();
+ it != chunks_.end(); ++it) {
+ CHECK_LE(pos + it->size, data + size);
+ memcpy(pos, it->start, it->size);
+ pos += it->size;
+ }
+}
+
+void CompoundBuffer::CopyFrom(const CompoundBuffer& source,
+ int start, int end) {
+ // Check that 0 <= |start| <= |end| <= |total_bytes_|.
+ DCHECK_LE(0, start);
+ DCHECK_LE(start, end);
+ DCHECK_LE(end, source.total_bytes());
+
+ Clear();
+
+ if (end == start) {
+ return;
+ }
+
+ // Iterate over chunks in the |source| and add those that we need.
+ int pos = 0;
+ for (DataChunkList::const_iterator it = source.chunks_.begin();
+ it != source.chunks_.end(); ++it) {
+
+ // Add data from the current chunk only if it is in the specified interval.
+ if (pos + it->size > start && pos < end) {
+ int relative_start = std::max(0, start - pos);
+ int relative_end = std::min(it->size, end - pos);
+ DCHECK_LE(0, relative_start);
+ DCHECK_LT(relative_start, relative_end);
+ DCHECK_LE(relative_end, it->size);
+ Append(it->buffer.get(), it->start + relative_start,
+ relative_end - relative_start);
+ }
+
+ pos += it->size;
+ if (pos >= end) {
+ // We've got all the data we need.
+ break;
+ }
+ }
+
+ DCHECK_EQ(total_bytes_, end - start);
+}
+
+CompoundBufferInputStream::CompoundBufferInputStream(
+ const CompoundBuffer* buffer)
+ : buffer_(buffer),
+ current_chunk_(0),
+ current_chunk_position_(0),
+ position_(0),
+ last_returned_size_(0) {
+ DCHECK(buffer_->locked());
+}
+
+CompoundBufferInputStream::~CompoundBufferInputStream() {
+}
+
+bool CompoundBufferInputStream::Next(const void** data, int* size) {
+ if (current_chunk_ < buffer_->chunks_.size()) {
+ // Reply with the number of bytes remaining in the current buffer.
+ const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
+ int read_size = chunk.size - current_chunk_position_;
+ *data = chunk.start + current_chunk_position_;
+ *size = read_size;
+
+ // Adjust position.
+ ++current_chunk_;
+ current_chunk_position_ = 0;
+ position_ += read_size;
+
+ last_returned_size_ = read_size;
+ return true;
+ }
+
+ DCHECK_EQ(position_, buffer_->total_bytes());
+
+ // We've reached the end of the stream. So reset |last_returned_size_|
+ // to zero to prevent any backup request.
+ // This is the same as in ArrayInputStream.
+ // See google/protobuf/io/zero_copy_stream_impl_lite.cc.
+ last_returned_size_ = 0;
+ return false;
+}
+
+void CompoundBufferInputStream::BackUp(int count) {
+ DCHECK_LE(count, last_returned_size_);
+ DCHECK_GT(current_chunk_, 0u);
+
+ // Rewind one buffer and rewind data offset by |count| bytes.
+ --current_chunk_;
+ const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
+ current_chunk_position_ = chunk.size - count;
+ position_ -= count;
+ DCHECK_GE(position_, 0);
+
+ // Prevent additional backups.
+ last_returned_size_ = 0;
+}
+
+bool CompoundBufferInputStream::Skip(int count) {
+ DCHECK_GE(count, 0);
+ last_returned_size_ = 0;
+
+ while (count > 0 && current_chunk_ < buffer_->chunks_.size()) {
+ const CompoundBuffer::DataChunk& chunk = buffer_->chunks_[current_chunk_];
+ int read = std::min(count, chunk.size - current_chunk_position_);
+
+ // Advance the current buffer offset and position.
+ current_chunk_position_ += read;
+ position_ += read;
+ count -= read;
+
+ // If the current buffer is fully read, then advance to the next buffer.
+ if (current_chunk_position_ == chunk.size) {
+ ++current_chunk_;
+ current_chunk_position_ = 0;
+ }
+ }
+
+ return count == 0;
+}
+
+int64 CompoundBufferInputStream::ByteCount() const {
+ return position_;
+}
+
+} // namespace remoting
« 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