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

Unified Diff: pdf/chunk_stream.cc

Issue 2558573002: Revert "reland of Improve linearized pdf load/show time." (Closed)
Patch Set: Changes to make tests pass ... Created 4 years 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 | « pdf/chunk_stream.h ('k') | pdf/chunk_stream_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pdf/chunk_stream.cc
diff --git a/pdf/chunk_stream.cc b/pdf/chunk_stream.cc
new file mode 100644
index 0000000000000000000000000000000000000000..adb3cb6edaf5c90a8015930f2378f291791ff94c
--- /dev/null
+++ b/pdf/chunk_stream.cc
@@ -0,0 +1,175 @@
+// 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 "pdf/chunk_stream.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#define __STDC_LIMIT_MACROS
+#ifdef _WIN32
+#include <limits.h>
+#else
+#include <stdint.h>
+#endif
+
+#include <algorithm>
+
+namespace chrome_pdf {
+
+ChunkStream::ChunkStream() : stream_size_(0) {
+}
+
+ChunkStream::~ChunkStream() {
+}
+
+void ChunkStream::Clear() {
+ chunks_.clear();
+ data_.clear();
+ stream_size_ = 0;
+}
+
+void ChunkStream::Preallocate(size_t stream_size) {
+ data_.reserve(stream_size);
+ stream_size_ = stream_size;
+}
+
+size_t ChunkStream::GetSize() const {
+ return data_.size();
+}
+
+bool ChunkStream::WriteData(size_t offset, void* buffer, size_t size) {
+ if (SIZE_MAX - size < offset)
+ return false;
+
+ if (data_.size() < offset + size)
+ data_.resize(offset + size);
+
+ memcpy(&data_[offset], buffer, size);
+
+ if (chunks_.empty()) {
+ chunks_[offset] = size;
+ return true;
+ }
+
+ std::map<size_t, size_t>::iterator start = chunks_.upper_bound(offset);
+ if (start != chunks_.begin())
+ --start; // start now points to the key equal or lower than offset.
+ if (start->first + start->second < offset)
+ ++start; // start element is entirely before current chunk, skip it.
+
+ std::map<size_t, size_t>::iterator end = chunks_.upper_bound(offset + size);
+ if (start == end) { // No chunks to merge.
+ chunks_[offset] = size;
+ return true;
+ }
+
+ --end;
+
+ size_t new_offset = std::min<size_t>(start->first, offset);
+ size_t new_size =
+ std::max<size_t>(end->first + end->second, offset + size) - new_offset;
+
+ chunks_.erase(start, ++end);
+
+ chunks_[new_offset] = new_size;
+
+ return true;
+}
+
+bool ChunkStream::ReadData(size_t offset, size_t size, void* buffer) const {
+ if (!IsRangeAvailable(offset, size))
+ return false;
+
+ memcpy(buffer, &data_[offset], size);
+ return true;
+}
+
+bool ChunkStream::GetMissedRanges(
+ size_t offset, size_t size,
+ std::vector<std::pair<size_t, size_t> >* ranges) const {
+ if (IsRangeAvailable(offset, size))
+ return false;
+
+ ranges->clear();
+ if (chunks_.empty()) {
+ ranges->push_back(std::pair<size_t, size_t>(offset, size));
+ return true;
+ }
+
+ std::map<size_t, size_t>::const_iterator start = chunks_.upper_bound(offset);
+ if (start != chunks_.begin())
+ --start; // start now points to the key equal or lower than offset.
+ if (start->first + start->second < offset)
+ ++start; // start element is entirely before current chunk, skip it.
+
+ std::map<size_t, size_t>::const_iterator end =
+ chunks_.upper_bound(offset + size);
+ if (start == end) { // No data in the current range available.
+ ranges->push_back(std::pair<size_t, size_t>(offset, size));
+ return true;
+ }
+
+ size_t cur_offset = offset;
+ std::map<size_t, size_t>::const_iterator it;
+ for (it = start; it != end; ++it) {
+ if (cur_offset < it->first) {
+ size_t new_size = it->first - cur_offset;
+ ranges->push_back(std::pair<size_t, size_t>(cur_offset, new_size));
+ cur_offset = it->first + it->second;
+ } else if (cur_offset < it->first + it->second) {
+ cur_offset = it->first + it->second;
+ }
+ }
+
+ // Add last chunk.
+ if (cur_offset < offset + size)
+ ranges->push_back(std::pair<size_t, size_t>(cur_offset,
+ offset + size - cur_offset));
+
+ return true;
+}
+
+bool ChunkStream::IsRangeAvailable(size_t offset, size_t size) const {
+ if (chunks_.empty())
+ return false;
+
+ if (SIZE_MAX - size < offset)
+ return false;
+
+ std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
+ if (it == chunks_.begin())
+ return false; // No chunks includes offset byte.
+
+ --it; // Now it starts equal or before offset.
+ return (it->first + it->second) >= (offset + size);
+}
+
+size_t ChunkStream::GetFirstMissingByte() const {
+ if (chunks_.empty())
+ return 0;
+ std::map<size_t, size_t>::const_iterator begin = chunks_.begin();
+ return begin->first > 0 ? 0 : begin->second;
+}
+
+size_t ChunkStream::GetFirstMissingByteInInterval(size_t offset) const {
+ if (chunks_.empty())
+ return 0;
+ std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
+ if (it == chunks_.begin())
+ return 0;
+ --it;
+ return it->first + it->second;
+}
+
+size_t ChunkStream::GetLastMissingByteInInterval(size_t offset) const {
+ if (chunks_.empty())
+ return stream_size_ - 1;
+ std::map<size_t, size_t>::const_iterator it = chunks_.upper_bound(offset);
+ if (it == chunks_.end())
+ return stream_size_ - 1;
+ return it->first - 1;
+}
+
+} // namespace chrome_pdf
« no previous file with comments | « pdf/chunk_stream.h ('k') | pdf/chunk_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698