129345531d776962073312d423917406fc59b09f6Jaesung Chung// Copyright 2015 Google Inc. 229345531d776962073312d423917406fc59b09f6Jaesung Chung// 329345531d776962073312d423917406fc59b09f6Jaesung Chung// Licensed under the Apache License, Version 2.0 (the "License"); 429345531d776962073312d423917406fc59b09f6Jaesung Chung// you may not use this file except in compliance with the License. 529345531d776962073312d423917406fc59b09f6Jaesung Chung// You may obtain a copy of the License at 629345531d776962073312d423917406fc59b09f6Jaesung Chung// 729345531d776962073312d423917406fc59b09f6Jaesung Chung// http://www.apache.org/licenses/LICENSE-2.0 829345531d776962073312d423917406fc59b09f6Jaesung Chung// 929345531d776962073312d423917406fc59b09f6Jaesung Chung// Unless required by applicable law or agreed to in writing, software 1029345531d776962073312d423917406fc59b09f6Jaesung Chung// distributed under the License is distributed on an "AS IS" BASIS, 1129345531d776962073312d423917406fc59b09f6Jaesung Chung// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1229345531d776962073312d423917406fc59b09f6Jaesung Chung// See the License for the specific language governing permissions and 1329345531d776962073312d423917406fc59b09f6Jaesung Chung// limitations under the License. 1429345531d776962073312d423917406fc59b09f6Jaesung Chung// 1529345531d776962073312d423917406fc59b09f6Jaesung Chung//////////////////////////////////////////////////////////////////////////////// 1629345531d776962073312d423917406fc59b09f6Jaesung Chung 1729345531d776962073312d423917406fc59b09f6Jaesung Chung#include "src/binary_parse/range_checked_byte_ptr.h" 1829345531d776962073312d423917406fc59b09f6Jaesung Chung 1929345531d776962073312d423917406fc59b09f6Jaesung Chung#include <assert.h> 2029345531d776962073312d423917406fc59b09f6Jaesung Chung#include <cstddef> 2129345531d776962073312d423917406fc59b09f6Jaesung Chung#include <cstring> 2229345531d776962073312d423917406fc59b09f6Jaesung Chung 2329345531d776962073312d423917406fc59b09f6Jaesung Chungnamespace piex { 2429345531d776962073312d423917406fc59b09f6Jaesung Chungnamespace binary_parse { 2529345531d776962073312d423917406fc59b09f6Jaesung Chung 2629345531d776962073312d423917406fc59b09f6Jaesung Chung#ifdef BREAK_IF_DEBUGGING_AND_OUT_OF_RANGE 2729345531d776962073312d423917406fc59b09f6Jaesung Chung#define BREAK_IF_DEBUGGING() assert(false) 2829345531d776962073312d423917406fc59b09f6Jaesung Chung#else 2929345531d776962073312d423917406fc59b09f6Jaesung Chung#define BREAK_IF_DEBUGGING() assert(true) 3029345531d776962073312d423917406fc59b09f6Jaesung Chung#endif 3129345531d776962073312d423917406fc59b09f6Jaesung Chung 3229345531d776962073312d423917406fc59b09f6Jaesung Chungnamespace { 3329345531d776962073312d423917406fc59b09f6Jaesung Chungclass MemoryPagedByteArray : public PagedByteArray { 3429345531d776962073312d423917406fc59b09f6Jaesung Chung public: 3529345531d776962073312d423917406fc59b09f6Jaesung Chung MemoryPagedByteArray(const unsigned char *buffer, const size_t len); 3629345531d776962073312d423917406fc59b09f6Jaesung Chung 3729345531d776962073312d423917406fc59b09f6Jaesung Chung virtual size_t length() const; 3829345531d776962073312d423917406fc59b09f6Jaesung Chung virtual size_t pageSize() const; 3929345531d776962073312d423917406fc59b09f6Jaesung Chung virtual void getPage(size_t page_index, const unsigned char **begin, 4029345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char **end, PagePtr *page) const; 4129345531d776962073312d423917406fc59b09f6Jaesung Chung 4229345531d776962073312d423917406fc59b09f6Jaesung Chung private: 4329345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char *buffer_; 4429345531d776962073312d423917406fc59b09f6Jaesung Chung const size_t len_; 4529345531d776962073312d423917406fc59b09f6Jaesung Chung}; 4629345531d776962073312d423917406fc59b09f6Jaesung Chung 4729345531d776962073312d423917406fc59b09f6Jaesung ChungMemoryPagedByteArray::MemoryPagedByteArray(const unsigned char *buffer, 4829345531d776962073312d423917406fc59b09f6Jaesung Chung const size_t len) 4929345531d776962073312d423917406fc59b09f6Jaesung Chung : buffer_(buffer), len_(len) {} 5029345531d776962073312d423917406fc59b09f6Jaesung Chung 5129345531d776962073312d423917406fc59b09f6Jaesung Chungsize_t MemoryPagedByteArray::length() const { return len_; } 5229345531d776962073312d423917406fc59b09f6Jaesung Chung 5329345531d776962073312d423917406fc59b09f6Jaesung Chungsize_t MemoryPagedByteArray::pageSize() const { return len_; } 5429345531d776962073312d423917406fc59b09f6Jaesung Chung 55b415ce2eec78846ec705c983f98a74c9526f3faaEik Brauervoid MemoryPagedByteArray::getPage(size_t /* page_index */, 5629345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char **begin, 5729345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char **end, 5829345531d776962073312d423917406fc59b09f6Jaesung Chung PagePtr *page) const { 5929345531d776962073312d423917406fc59b09f6Jaesung Chung *begin = buffer_; 6029345531d776962073312d423917406fc59b09f6Jaesung Chung *end = buffer_ + len_; 6129345531d776962073312d423917406fc59b09f6Jaesung Chung *page = PagePtr(); 6229345531d776962073312d423917406fc59b09f6Jaesung Chung} 6329345531d776962073312d423917406fc59b09f6Jaesung Chung 6429345531d776962073312d423917406fc59b09f6Jaesung Chung// A functor that does nothing. This is used as a no-op shared pointer 6529345531d776962073312d423917406fc59b09f6Jaesung Chung// deallocator below. 6629345531d776962073312d423917406fc59b09f6Jaesung Chungclass NullFunctor { 6729345531d776962073312d423917406fc59b09f6Jaesung Chung public: 6829345531d776962073312d423917406fc59b09f6Jaesung Chung void operator()() {} 69b415ce2eec78846ec705c983f98a74c9526f3faaEik Brauer void operator()(PagedByteArray * /* p */) const {} 7029345531d776962073312d423917406fc59b09f6Jaesung Chung}; 7129345531d776962073312d423917406fc59b09f6Jaesung Chung} // namespace 7229345531d776962073312d423917406fc59b09f6Jaesung Chung 7329345531d776962073312d423917406fc59b09f6Jaesung ChungPagedByteArray::~PagedByteArray() {} 7429345531d776962073312d423917406fc59b09f6Jaesung Chung 7529345531d776962073312d423917406fc59b09f6Jaesung ChungRangeCheckedBytePtr::RangeCheckedBytePtr() 7629345531d776962073312d423917406fc59b09f6Jaesung Chung : array_(), 7729345531d776962073312d423917406fc59b09f6Jaesung Chung page_data_(NULL), 7829345531d776962073312d423917406fc59b09f6Jaesung Chung current_pos_(0), 7929345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_begin_(0), 8029345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_end_(0), 8129345531d776962073312d423917406fc59b09f6Jaesung Chung page_begin_offset_(0), 8229345531d776962073312d423917406fc59b09f6Jaesung Chung current_page_len_(0), 8329345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_(RANGE_CHECKED_BYTE_ERROR) {} 8429345531d776962073312d423917406fc59b09f6Jaesung Chung 8529345531d776962073312d423917406fc59b09f6Jaesung ChungRangeCheckedBytePtr::RangeCheckedBytePtr(const unsigned char *array, 8629345531d776962073312d423917406fc59b09f6Jaesung Chung const size_t len) 8729345531d776962073312d423917406fc59b09f6Jaesung Chung : array_(new MemoryPagedByteArray(array, len)), 8829345531d776962073312d423917406fc59b09f6Jaesung Chung page_data_(NULL), 8929345531d776962073312d423917406fc59b09f6Jaesung Chung current_pos_(0), 9029345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_begin_(0), 9129345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_end_(len), 9229345531d776962073312d423917406fc59b09f6Jaesung Chung page_begin_offset_(0), 9329345531d776962073312d423917406fc59b09f6Jaesung Chung current_page_len_(0), 9429345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_(RANGE_CHECKED_BYTE_SUCCESS) { 9529345531d776962073312d423917406fc59b09f6Jaesung Chung assert(array); 9629345531d776962073312d423917406fc59b09f6Jaesung Chung if (array == NULL) { 9729345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_ = RANGE_CHECKED_BYTE_ERROR; 9829345531d776962073312d423917406fc59b09f6Jaesung Chung } 9929345531d776962073312d423917406fc59b09f6Jaesung Chung} 10029345531d776962073312d423917406fc59b09f6Jaesung Chung 10129345531d776962073312d423917406fc59b09f6Jaesung ChungRangeCheckedBytePtr::RangeCheckedBytePtr(PagedByteArray *array) 10229345531d776962073312d423917406fc59b09f6Jaesung Chung : array_(array, NullFunctor()), 10329345531d776962073312d423917406fc59b09f6Jaesung Chung page_data_(NULL), 10429345531d776962073312d423917406fc59b09f6Jaesung Chung current_pos_(0), 10529345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_begin_(0), 10629345531d776962073312d423917406fc59b09f6Jaesung Chung sub_array_end_(array->length()), 10729345531d776962073312d423917406fc59b09f6Jaesung Chung page_begin_offset_(0), 10829345531d776962073312d423917406fc59b09f6Jaesung Chung current_page_len_(0), 10929345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_(RANGE_CHECKED_BYTE_SUCCESS) {} 11029345531d776962073312d423917406fc59b09f6Jaesung Chung 11129345531d776962073312d423917406fc59b09f6Jaesung ChungRangeCheckedBytePtr RangeCheckedBytePtr::invalidPointer() { 11229345531d776962073312d423917406fc59b09f6Jaesung Chung return RangeCheckedBytePtr(); 11329345531d776962073312d423917406fc59b09f6Jaesung Chung} 11429345531d776962073312d423917406fc59b09f6Jaesung Chung 11529345531d776962073312d423917406fc59b09f6Jaesung ChungRangeCheckedBytePtr RangeCheckedBytePtr::pointerToSubArray( 11629345531d776962073312d423917406fc59b09f6Jaesung Chung size_t pos, size_t length) const { 11729345531d776962073312d423917406fc59b09f6Jaesung Chung RangeCheckedBytePtr sub_result = (*this) + pos; 11829345531d776962073312d423917406fc59b09f6Jaesung Chung if (!sub_result.errorOccurred() && length <= sub_result.remainingLength()) { 11929345531d776962073312d423917406fc59b09f6Jaesung Chung sub_result.sub_array_begin_ = sub_result.current_pos_; 12029345531d776962073312d423917406fc59b09f6Jaesung Chung sub_result.sub_array_end_ = sub_result.sub_array_begin_ + length; 12129345531d776962073312d423917406fc59b09f6Jaesung Chung 12229345531d776962073312d423917406fc59b09f6Jaesung Chung // Restrict the boundaries of the current page to the newly set sub-array. 12329345531d776962073312d423917406fc59b09f6Jaesung Chung sub_result.restrictPageToSubArray(); 12429345531d776962073312d423917406fc59b09f6Jaesung Chung 12529345531d776962073312d423917406fc59b09f6Jaesung Chung return sub_result; 12629345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 12729345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_ = RANGE_CHECKED_BYTE_ERROR; 12829345531d776962073312d423917406fc59b09f6Jaesung Chung return invalidPointer(); 12929345531d776962073312d423917406fc59b09f6Jaesung Chung } 13029345531d776962073312d423917406fc59b09f6Jaesung Chung} 13129345531d776962073312d423917406fc59b09f6Jaesung Chung 13229345531d776962073312d423917406fc59b09f6Jaesung Chungsize_t RangeCheckedBytePtr::offsetInArray() const { 13329345531d776962073312d423917406fc59b09f6Jaesung Chung // sub_array_begin_ <= current_pos_ is a class invariant, but protect 13429345531d776962073312d423917406fc59b09f6Jaesung Chung // against violations of this invariant. 13529345531d776962073312d423917406fc59b09f6Jaesung Chung if (sub_array_begin_ <= current_pos_) { 13629345531d776962073312d423917406fc59b09f6Jaesung Chung return current_pos_ - sub_array_begin_; 13729345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 13829345531d776962073312d423917406fc59b09f6Jaesung Chung assert(false); 13929345531d776962073312d423917406fc59b09f6Jaesung Chung return 0; 14029345531d776962073312d423917406fc59b09f6Jaesung Chung } 14129345531d776962073312d423917406fc59b09f6Jaesung Chung} 14229345531d776962073312d423917406fc59b09f6Jaesung Chung 14329345531d776962073312d423917406fc59b09f6Jaesung Chungstd::string RangeCheckedBytePtr::substr(size_t pos, size_t length) const { 14429345531d776962073312d423917406fc59b09f6Jaesung Chung std::vector<unsigned char> bytes = extractBytes(pos, length); 14529345531d776962073312d423917406fc59b09f6Jaesung Chung std::string result; 14629345531d776962073312d423917406fc59b09f6Jaesung Chung result.reserve(bytes.size()); 14729345531d776962073312d423917406fc59b09f6Jaesung Chung for (size_t i = 0; i < bytes.size(); ++i) { 14829345531d776962073312d423917406fc59b09f6Jaesung Chung result.push_back(static_cast<char>(bytes[i])); 14929345531d776962073312d423917406fc59b09f6Jaesung Chung } 15029345531d776962073312d423917406fc59b09f6Jaesung Chung return result; 15129345531d776962073312d423917406fc59b09f6Jaesung Chung} 15229345531d776962073312d423917406fc59b09f6Jaesung Chung 15329345531d776962073312d423917406fc59b09f6Jaesung Chungstd::vector<unsigned char> RangeCheckedBytePtr::extractBytes( 15429345531d776962073312d423917406fc59b09f6Jaesung Chung size_t pos, size_t length) const { 15529345531d776962073312d423917406fc59b09f6Jaesung Chung std::vector<unsigned char> result; 15629345531d776962073312d423917406fc59b09f6Jaesung Chung if (pos + length < pos /* overflow */ || remainingLength() < pos + length) { 15729345531d776962073312d423917406fc59b09f6Jaesung Chung BREAK_IF_DEBUGGING(); 15829345531d776962073312d423917406fc59b09f6Jaesung Chung error_flag_ = RANGE_CHECKED_BYTE_ERROR_OVERFLOW; 15929345531d776962073312d423917406fc59b09f6Jaesung Chung return result; 16029345531d776962073312d423917406fc59b09f6Jaesung Chung } 16129345531d776962073312d423917406fc59b09f6Jaesung Chung result.reserve(length); 16229345531d776962073312d423917406fc59b09f6Jaesung Chung for (size_t i = 0; i < length; ++i) { 16329345531d776962073312d423917406fc59b09f6Jaesung Chung result.push_back((*this)[pos + i]); 16429345531d776962073312d423917406fc59b09f6Jaesung Chung } 16529345531d776962073312d423917406fc59b09f6Jaesung Chung return result; 16629345531d776962073312d423917406fc59b09f6Jaesung Chung} 16729345531d776962073312d423917406fc59b09f6Jaesung Chung 16829345531d776962073312d423917406fc59b09f6Jaesung Chungbool operator==(const RangeCheckedBytePtr &x, const RangeCheckedBytePtr &y) { 16929345531d776962073312d423917406fc59b09f6Jaesung Chung if (x.array_ != y.array_) { 17029345531d776962073312d423917406fc59b09f6Jaesung Chung assert(false); 17129345531d776962073312d423917406fc59b09f6Jaesung Chung return false; 17229345531d776962073312d423917406fc59b09f6Jaesung Chung } 17329345531d776962073312d423917406fc59b09f6Jaesung Chung 17429345531d776962073312d423917406fc59b09f6Jaesung Chung return x.current_pos_ == y.current_pos_; 17529345531d776962073312d423917406fc59b09f6Jaesung Chung} 17629345531d776962073312d423917406fc59b09f6Jaesung Chung 17729345531d776962073312d423917406fc59b09f6Jaesung Chungbool operator!=(const RangeCheckedBytePtr &x, const RangeCheckedBytePtr &y) { 17829345531d776962073312d423917406fc59b09f6Jaesung Chung return !(x == y); 17929345531d776962073312d423917406fc59b09f6Jaesung Chung} 18029345531d776962073312d423917406fc59b09f6Jaesung Chung 18129345531d776962073312d423917406fc59b09f6Jaesung Chungvoid RangeCheckedBytePtr::loadPageForOffset(size_t offset) const { 18229345531d776962073312d423917406fc59b09f6Jaesung Chung // The offset should always lie within the bounds of the sub-array (this 18329345531d776962073312d423917406fc59b09f6Jaesung Chung // condition is enforced at the callsite). However, even if the offset lies 18429345531d776962073312d423917406fc59b09f6Jaesung Chung // outside the sub-array, the restrictPageToSubArray() call at the end 18529345531d776962073312d423917406fc59b09f6Jaesung Chung // ensures that the object is left in a consistent state that maintains the 18629345531d776962073312d423917406fc59b09f6Jaesung Chung // class invariants. 18729345531d776962073312d423917406fc59b09f6Jaesung Chung assert(offset >= sub_array_begin_ && offset < sub_array_end_); 18829345531d776962073312d423917406fc59b09f6Jaesung Chung 18929345531d776962073312d423917406fc59b09f6Jaesung Chung // Ensure that offset lies within the array. 19029345531d776962073312d423917406fc59b09f6Jaesung Chung if (offset >= array_->length()) { 19129345531d776962073312d423917406fc59b09f6Jaesung Chung assert(false); 19229345531d776962073312d423917406fc59b09f6Jaesung Chung return; 19329345531d776962073312d423917406fc59b09f6Jaesung Chung } 19429345531d776962073312d423917406fc59b09f6Jaesung Chung 19529345531d776962073312d423917406fc59b09f6Jaesung Chung // Determine the index of the page to request. 19629345531d776962073312d423917406fc59b09f6Jaesung Chung size_t page_index = offset / array_->pageSize(); 19729345531d776962073312d423917406fc59b09f6Jaesung Chung 19829345531d776962073312d423917406fc59b09f6Jaesung Chung // Get the page. 19929345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char *page_begin; 20029345531d776962073312d423917406fc59b09f6Jaesung Chung const unsigned char *page_end; 20129345531d776962073312d423917406fc59b09f6Jaesung Chung array_->getPage(page_index, &page_begin, &page_end, &page_); 20229345531d776962073312d423917406fc59b09f6Jaesung Chung 20329345531d776962073312d423917406fc59b09f6Jaesung Chung // Ensure that the page has the expected length (as specified in the 20429345531d776962073312d423917406fc59b09f6Jaesung Chung // PagedByteArray interface). 20529345531d776962073312d423917406fc59b09f6Jaesung Chung size_t expected_page_size = array_->pageSize(); 20629345531d776962073312d423917406fc59b09f6Jaesung Chung if (page_index == (array_->length() - 1) / array_->pageSize()) { 20729345531d776962073312d423917406fc59b09f6Jaesung Chung expected_page_size = array_->length() - array_->pageSize() * page_index; 20829345531d776962073312d423917406fc59b09f6Jaesung Chung } 20929345531d776962073312d423917406fc59b09f6Jaesung Chung if ((page_end < page_begin) || 21029345531d776962073312d423917406fc59b09f6Jaesung Chung (static_cast<size_t>(page_end - page_begin) != expected_page_size)) { 21129345531d776962073312d423917406fc59b09f6Jaesung Chung assert(false); 21229345531d776962073312d423917406fc59b09f6Jaesung Chung return; 21329345531d776962073312d423917406fc59b09f6Jaesung Chung } 21429345531d776962073312d423917406fc59b09f6Jaesung Chung 21529345531d776962073312d423917406fc59b09f6Jaesung Chung // Remember information about page. 21629345531d776962073312d423917406fc59b09f6Jaesung Chung page_data_ = page_begin; 21729345531d776962073312d423917406fc59b09f6Jaesung Chung page_begin_offset_ = page_index * array_->pageSize(); 218a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer current_page_len_ = static_cast<size_t>(page_end - page_begin); 21929345531d776962073312d423917406fc59b09f6Jaesung Chung 22029345531d776962073312d423917406fc59b09f6Jaesung Chung // Restrict the boundaries of the page to lie within the sub-array. 22129345531d776962073312d423917406fc59b09f6Jaesung Chung restrictPageToSubArray(); 22229345531d776962073312d423917406fc59b09f6Jaesung Chung} 22329345531d776962073312d423917406fc59b09f6Jaesung Chung 22429345531d776962073312d423917406fc59b09f6Jaesung Chungvoid RangeCheckedBytePtr::restrictPageToSubArray() const { 22529345531d776962073312d423917406fc59b09f6Jaesung Chung // Restrict the current page's boundaries so that it is always contained 22629345531d776962073312d423917406fc59b09f6Jaesung Chung // completely within the extent of the sub-array. 22729345531d776962073312d423917406fc59b09f6Jaesung Chung // This function is purposely designed to work correctly in the following 22829345531d776962073312d423917406fc59b09f6Jaesung Chung // two special cases: 22929345531d776962073312d423917406fc59b09f6Jaesung Chung // a) The current page lies entirely outside the sub-array. In this case, 23029345531d776962073312d423917406fc59b09f6Jaesung Chung // current_page_len_ will be set to zero. page_data_ may either remain 23129345531d776962073312d423917406fc59b09f6Jaesung Chung // unchanged or may be changed to point one element beyond the end of the 23229345531d776962073312d423917406fc59b09f6Jaesung Chung // page, depending on whether the current page lies before or after the 23329345531d776962073312d423917406fc59b09f6Jaesung Chung // sub-array. 23429345531d776962073312d423917406fc59b09f6Jaesung Chung // b) The current page is in the state as initialized by the constructor 23529345531d776962073312d423917406fc59b09f6Jaesung Chung // (i.e. page_data_ is NULL and current_page_len_ is zero). In this case, 23629345531d776962073312d423917406fc59b09f6Jaesung Chung // page_data_ and current_page_len_ will remain unchanged. 23729345531d776962073312d423917406fc59b09f6Jaesung Chung 23829345531d776962073312d423917406fc59b09f6Jaesung Chung // Does the beginning of the page lie before the beginning of the sub-array? 23929345531d776962073312d423917406fc59b09f6Jaesung Chung if (page_begin_offset_ < sub_array_begin_) { 24029345531d776962073312d423917406fc59b09f6Jaesung Chung // Compute amount by which to shorten page. 24129345531d776962073312d423917406fc59b09f6Jaesung Chung size_t amount_to_shorten = sub_array_begin_ - page_begin_offset_; 24229345531d776962073312d423917406fc59b09f6Jaesung Chung if (amount_to_shorten > current_page_len_) { 24329345531d776962073312d423917406fc59b09f6Jaesung Chung amount_to_shorten = current_page_len_; 24429345531d776962073312d423917406fc59b09f6Jaesung Chung } 24529345531d776962073312d423917406fc59b09f6Jaesung Chung 24629345531d776962073312d423917406fc59b09f6Jaesung Chung // Adjust beginning of page accordingly. 24729345531d776962073312d423917406fc59b09f6Jaesung Chung page_begin_offset_ += amount_to_shorten; 24829345531d776962073312d423917406fc59b09f6Jaesung Chung page_data_ += amount_to_shorten; 24929345531d776962073312d423917406fc59b09f6Jaesung Chung current_page_len_ -= amount_to_shorten; 25029345531d776962073312d423917406fc59b09f6Jaesung Chung } 25129345531d776962073312d423917406fc59b09f6Jaesung Chung 25229345531d776962073312d423917406fc59b09f6Jaesung Chung // Does the end of the page lie beyond the end of the sub-array? 25329345531d776962073312d423917406fc59b09f6Jaesung Chung if (page_begin_offset_ + current_page_len_ > sub_array_end_) { 25429345531d776962073312d423917406fc59b09f6Jaesung Chung // Reduce length of page accordingly. 25529345531d776962073312d423917406fc59b09f6Jaesung Chung size_t new_len = sub_array_end_ - page_begin_offset_; 25629345531d776962073312d423917406fc59b09f6Jaesung Chung if (new_len > current_page_len_) { 25729345531d776962073312d423917406fc59b09f6Jaesung Chung new_len = current_page_len_; 25829345531d776962073312d423917406fc59b09f6Jaesung Chung } 25929345531d776962073312d423917406fc59b09f6Jaesung Chung current_page_len_ = new_len; 26029345531d776962073312d423917406fc59b09f6Jaesung Chung } 26129345531d776962073312d423917406fc59b09f6Jaesung Chung} 26229345531d776962073312d423917406fc59b09f6Jaesung Chung 26329345531d776962073312d423917406fc59b09f6Jaesung Chungint memcmp(const RangeCheckedBytePtr &x, const RangeCheckedBytePtr &y, 26429345531d776962073312d423917406fc59b09f6Jaesung Chung size_t num) { 26529345531d776962073312d423917406fc59b09f6Jaesung Chung std::vector<unsigned char> x_vec = x.extractBytes(0, num); 26629345531d776962073312d423917406fc59b09f6Jaesung Chung std::vector<unsigned char> y_vec = y.extractBytes(0, num); 26729345531d776962073312d423917406fc59b09f6Jaesung Chung 26829345531d776962073312d423917406fc59b09f6Jaesung Chung if (!x.errorOccurred() && !y.errorOccurred()) { 26929345531d776962073312d423917406fc59b09f6Jaesung Chung return ::memcmp(&x_vec[0], &y_vec[0], num); 27029345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 27129345531d776962073312d423917406fc59b09f6Jaesung Chung // return an arbitrary value 27229345531d776962073312d423917406fc59b09f6Jaesung Chung return -1; 27329345531d776962073312d423917406fc59b09f6Jaesung Chung } 27429345531d776962073312d423917406fc59b09f6Jaesung Chung} 27529345531d776962073312d423917406fc59b09f6Jaesung Chung 27629345531d776962073312d423917406fc59b09f6Jaesung Chungint strcmp(const RangeCheckedBytePtr &x, const std::string &y) { 27729345531d776962073312d423917406fc59b09f6Jaesung Chung std::vector<unsigned char> x_vec = x.extractBytes(0, y.length()); 27829345531d776962073312d423917406fc59b09f6Jaesung Chung 27929345531d776962073312d423917406fc59b09f6Jaesung Chung if (!x.errorOccurred()) { 28029345531d776962073312d423917406fc59b09f6Jaesung Chung return ::memcmp(&x_vec[0], y.c_str(), y.length()); 28129345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 28229345531d776962073312d423917406fc59b09f6Jaesung Chung // return an arbitrary value 28329345531d776962073312d423917406fc59b09f6Jaesung Chung return -1; 28429345531d776962073312d423917406fc59b09f6Jaesung Chung } 28529345531d776962073312d423917406fc59b09f6Jaesung Chung} 28629345531d776962073312d423917406fc59b09f6Jaesung Chung 28729345531d776962073312d423917406fc59b09f6Jaesung Chungsize_t strlen(const RangeCheckedBytePtr &src) { 28829345531d776962073312d423917406fc59b09f6Jaesung Chung size_t len = 0; 28929345531d776962073312d423917406fc59b09f6Jaesung Chung RangeCheckedBytePtr str = src; 29029345531d776962073312d423917406fc59b09f6Jaesung Chung while (!str.errorOccurred() && (str[0] != '\0')) { 29129345531d776962073312d423917406fc59b09f6Jaesung Chung str++; 29229345531d776962073312d423917406fc59b09f6Jaesung Chung len++; 29329345531d776962073312d423917406fc59b09f6Jaesung Chung } 29429345531d776962073312d423917406fc59b09f6Jaesung Chung return len; 29529345531d776962073312d423917406fc59b09f6Jaesung Chung} 29629345531d776962073312d423917406fc59b09f6Jaesung Chung 29729345531d776962073312d423917406fc59b09f6Jaesung Chungint16 Get16s(const RangeCheckedBytePtr &input, const bool big_endian, 29829345531d776962073312d423917406fc59b09f6Jaesung Chung MemoryStatus *status) { 29929345531d776962073312d423917406fc59b09f6Jaesung Chung const uint16 unsigned_value = Get16u(input, big_endian, status); 30029345531d776962073312d423917406fc59b09f6Jaesung Chung if (*status != RANGE_CHECKED_BYTE_SUCCESS) { 30129345531d776962073312d423917406fc59b09f6Jaesung Chung // Return an arbitrary value. 30229345531d776962073312d423917406fc59b09f6Jaesung Chung return 0; 30329345531d776962073312d423917406fc59b09f6Jaesung Chung } 30429345531d776962073312d423917406fc59b09f6Jaesung Chung 30529345531d776962073312d423917406fc59b09f6Jaesung Chung // Convert the two's-complement signed integer encoded in 'unsigned_value' 30629345531d776962073312d423917406fc59b09f6Jaesung Chung // into a signed representation in the implementation's native representation 30729345531d776962073312d423917406fc59b09f6Jaesung Chung // for signed integers. An optimized Blaze build (x64) compiles all of the 30829345531d776962073312d423917406fc59b09f6Jaesung Chung // following code to a no-op (as of this writing). 30929345531d776962073312d423917406fc59b09f6Jaesung Chung // For further details, see the corresponding comment in Get32s(). 31029345531d776962073312d423917406fc59b09f6Jaesung Chung if (unsigned_value == 0x8000u) { 31129345531d776962073312d423917406fc59b09f6Jaesung Chung return static_cast<int16>(-0x8000); 31229345531d776962073312d423917406fc59b09f6Jaesung Chung } else if (unsigned_value > 0x8000u) { 31329345531d776962073312d423917406fc59b09f6Jaesung Chung return -static_cast<int16>(0x10000u - unsigned_value); 31429345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 31529345531d776962073312d423917406fc59b09f6Jaesung Chung return static_cast<int16>(unsigned_value); 31629345531d776962073312d423917406fc59b09f6Jaesung Chung } 31729345531d776962073312d423917406fc59b09f6Jaesung Chung} 31829345531d776962073312d423917406fc59b09f6Jaesung Chung 31929345531d776962073312d423917406fc59b09f6Jaesung Chunguint16 Get16u(const RangeCheckedBytePtr &input, const bool big_endian, 32029345531d776962073312d423917406fc59b09f6Jaesung Chung MemoryStatus *status) { 32129345531d776962073312d423917406fc59b09f6Jaesung Chung if (input.remainingLength() < 2) { 32229345531d776962073312d423917406fc59b09f6Jaesung Chung if (status && *status == RANGE_CHECKED_BYTE_SUCCESS) { 32329345531d776962073312d423917406fc59b09f6Jaesung Chung *status = RANGE_CHECKED_BYTE_ERROR; 32429345531d776962073312d423917406fc59b09f6Jaesung Chung } 32529345531d776962073312d423917406fc59b09f6Jaesung Chung // Return an arbitrary value. 32629345531d776962073312d423917406fc59b09f6Jaesung Chung return 0; 32729345531d776962073312d423917406fc59b09f6Jaesung Chung } 32829345531d776962073312d423917406fc59b09f6Jaesung Chung if (big_endian) { 329a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer return (static_cast<uint16>(input[0]) << 8) | static_cast<uint16>(input[1]); 33029345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 331a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer return (static_cast<uint16>(input[1]) << 8) | static_cast<uint16>(input[0]); 33229345531d776962073312d423917406fc59b09f6Jaesung Chung } 33329345531d776962073312d423917406fc59b09f6Jaesung Chung} 33429345531d776962073312d423917406fc59b09f6Jaesung Chung 33529345531d776962073312d423917406fc59b09f6Jaesung Chungint32 Get32s(const RangeCheckedBytePtr &input, const bool big_endian, 33629345531d776962073312d423917406fc59b09f6Jaesung Chung MemoryStatus *status) { 33729345531d776962073312d423917406fc59b09f6Jaesung Chung const uint32 unsigned_value = Get32u(input, big_endian, status); 33829345531d776962073312d423917406fc59b09f6Jaesung Chung if (*status != RANGE_CHECKED_BYTE_SUCCESS) { 33929345531d776962073312d423917406fc59b09f6Jaesung Chung // Return an arbitrary value. 34029345531d776962073312d423917406fc59b09f6Jaesung Chung return 0; 34129345531d776962073312d423917406fc59b09f6Jaesung Chung } 34229345531d776962073312d423917406fc59b09f6Jaesung Chung 34329345531d776962073312d423917406fc59b09f6Jaesung Chung // Convert the two's-complement signed integer encoded in 'unsigned_value' 34429345531d776962073312d423917406fc59b09f6Jaesung Chung // into a signed representation in the implementation's native representation 34529345531d776962073312d423917406fc59b09f6Jaesung Chung // for signed integers. 34629345531d776962073312d423917406fc59b09f6Jaesung Chung // For all practical purposes, the same result could be obtained simply by 34729345531d776962073312d423917406fc59b09f6Jaesung Chung // casting unsigned_value to int32; the result of this is 34829345531d776962073312d423917406fc59b09f6Jaesung Chung // implementation-defined, but on all of the platforms we care about, it does 34929345531d776962073312d423917406fc59b09f6Jaesung Chung // what we want. 35029345531d776962073312d423917406fc59b09f6Jaesung Chung // The code below, however, arguably has the aesthetic advantage of being 35129345531d776962073312d423917406fc59b09f6Jaesung Chung // independent of the representation for signed integers chosen by the 35229345531d776962073312d423917406fc59b09f6Jaesung Chung // implementation, as long as 'int' and 'unsigned' have the required range to 35329345531d776962073312d423917406fc59b09f6Jaesung Chung // represent all of the required values. 35429345531d776962073312d423917406fc59b09f6Jaesung Chung // An optimized Blaze build (x64) compiles all of the following code to a 35529345531d776962073312d423917406fc59b09f6Jaesung Chung // no-op (as of this writing); i.e. the value that Get32u() returned in %eax 35629345531d776962073312d423917406fc59b09f6Jaesung Chung // is left unchanged. 35729345531d776962073312d423917406fc59b09f6Jaesung Chung if (unsigned_value == 0x80000000u) { 35829345531d776962073312d423917406fc59b09f6Jaesung Chung // Read here on why the constant expression is written this way: 35929345531d776962073312d423917406fc59b09f6Jaesung Chung // http://stackoverflow.com/questions/14695118 36029345531d776962073312d423917406fc59b09f6Jaesung Chung return -0x7fffffff - 1; 36129345531d776962073312d423917406fc59b09f6Jaesung Chung } else if (unsigned_value > 0x80000000u) { 36229345531d776962073312d423917406fc59b09f6Jaesung Chung // The expression 36329345531d776962073312d423917406fc59b09f6Jaesung Chung // 0xffffffffu - unsigned_value + 1 36429345531d776962073312d423917406fc59b09f6Jaesung Chung // is a portable way of flipping the sign of a twos-complement signed 36529345531d776962073312d423917406fc59b09f6Jaesung Chung // integer whose binary representation is stored in an unsigned integer. 36629345531d776962073312d423917406fc59b09f6Jaesung Chung // '0xffffffffu + 1' is used in preference to simply '0' because it makes 36729345531d776962073312d423917406fc59b09f6Jaesung Chung // it clearer that the correct result will be obtained even if an int is 36829345531d776962073312d423917406fc59b09f6Jaesung Chung // greater than 32 bits. The '0xffffffffu + 1' is "spread out" around 36929345531d776962073312d423917406fc59b09f6Jaesung Chung // 'unsigned_value' to prevent the compiler from warning about an 37029345531d776962073312d423917406fc59b09f6Jaesung Chung // integral constant overflow. ('0' would produce the correct result in 37129345531d776962073312d423917406fc59b09f6Jaesung Chung // this case too but would rely in a more subtle way on the rules for 37229345531d776962073312d423917406fc59b09f6Jaesung Chung // unsigned wraparound.) 37329345531d776962073312d423917406fc59b09f6Jaesung Chung return -static_cast<int32>(0xffffffffu - unsigned_value + 1); 37429345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 37529345531d776962073312d423917406fc59b09f6Jaesung Chung return static_cast<int32>(unsigned_value); 37629345531d776962073312d423917406fc59b09f6Jaesung Chung } 37729345531d776962073312d423917406fc59b09f6Jaesung Chung} 37829345531d776962073312d423917406fc59b09f6Jaesung Chung 37929345531d776962073312d423917406fc59b09f6Jaesung Chunguint32 Get32u(const RangeCheckedBytePtr &input, const bool big_endian, 38029345531d776962073312d423917406fc59b09f6Jaesung Chung MemoryStatus *status) { 38129345531d776962073312d423917406fc59b09f6Jaesung Chung if (input.remainingLength() < 4) { 38229345531d776962073312d423917406fc59b09f6Jaesung Chung if (status && *status == RANGE_CHECKED_BYTE_SUCCESS) { 38329345531d776962073312d423917406fc59b09f6Jaesung Chung *status = RANGE_CHECKED_BYTE_ERROR; 38429345531d776962073312d423917406fc59b09f6Jaesung Chung } 38529345531d776962073312d423917406fc59b09f6Jaesung Chung // Return an arbitrary value. 38629345531d776962073312d423917406fc59b09f6Jaesung Chung return 0; 38729345531d776962073312d423917406fc59b09f6Jaesung Chung } 38829345531d776962073312d423917406fc59b09f6Jaesung Chung if (big_endian) { 389a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer return (static_cast<uint32>(input[0]) << 24) | 390a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[1]) << 16) | 391a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[2]) << 8) | 392a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[3]) << 0); 39329345531d776962073312d423917406fc59b09f6Jaesung Chung } else { 394a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer return (static_cast<uint32>(input[3]) << 24) | 395a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[2]) << 16) | 396a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[1]) << 8) | 397a9540117cdd785b0dd75f8c4c28b278f86eb485cEik Brauer (static_cast<uint32>(input[0]) << 0); 39829345531d776962073312d423917406fc59b09f6Jaesung Chung } 39929345531d776962073312d423917406fc59b09f6Jaesung Chung} 40029345531d776962073312d423917406fc59b09f6Jaesung Chung 40129345531d776962073312d423917406fc59b09f6Jaesung Chung} // namespace binary_parse 40229345531d776962073312d423917406fc59b09f6Jaesung Chung} // namespace piex 403