Index: sdch/open_vcdiff/depot/opensource/open-vcdiff/src/headerparser.cc |
=================================================================== |
--- sdch/open_vcdiff/depot/opensource/open-vcdiff/src/headerparser.cc (revision 2678) |
+++ sdch/open_vcdiff/depot/opensource/open-vcdiff/src/headerparser.cc (working copy) |
@@ -1,323 +0,0 @@ |
-// Copyright 2008 Google Inc. |
-// Author: Lincoln Smith |
-// |
-// Licensed under the Apache License, Version 2.0 (the "License"); |
-// you may not use this file except in compliance with the License. |
-// You may obtain a copy of the License at |
-// |
-// http://www.apache.org/licenses/LICENSE-2.0 |
-// |
-// Unless required by applicable law or agreed to in writing, software |
-// distributed under the License is distributed on an "AS IS" BASIS, |
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
-// See the License for the specific language governing permissions and |
-// limitations under the License. |
- |
-#include <config.h> |
-#include "headerparser.h" |
-#include "logging.h" |
-#include "varint_bigendian.h" |
-#include "vcdiff_defs.h" |
- |
-namespace open_vcdiff { |
- |
-// *** Methods for ParseableChunk |
- |
-void ParseableChunk::Advance(size_t number_of_bytes) { |
- if (number_of_bytes > UnparsedSize()) { |
- LOG(DFATAL) << "Internal error: position advanced by " << number_of_bytes |
- << " bytes, current unparsed size " << UnparsedSize() |
- << LOG_ENDL; |
- position_ = end_; |
- return; |
- } |
- position_ += number_of_bytes; |
-} |
- |
-void ParseableChunk::SetPosition(const char* position) { |
- if (position < start_) { |
- LOG(DFATAL) << "Internal error: new data position " << position |
- << " is beyond start of data " << start_ << LOG_ENDL; |
- position_ = start_; |
- return; |
- } |
- if (position > end_) { |
- LOG(DFATAL) << "Internal error: new data position " << position |
- << " is beyond end of data " << end_ << LOG_ENDL; |
- position_ = end_; |
- return; |
- } |
- position_ = position; |
-} |
- |
-void ParseableChunk::FinishExcept(size_t number_of_bytes) { |
- if (number_of_bytes > UnparsedSize()) { |
- LOG(DFATAL) << "Internal error: specified number of remaining bytes " |
- << number_of_bytes << " is greater than unparsed data size " |
- << UnparsedSize() << LOG_ENDL; |
- Finish(); |
- return; |
- } |
- position_ = end_ - number_of_bytes; |
-} |
- |
-// *** Methods for VCDiffHeaderParser |
- |
-VCDiffHeaderParser::VCDiffHeaderParser(const char* header_start, |
- const char* data_end) |
- : parseable_chunk_(header_start, data_end - header_start), |
- return_code_(RESULT_SUCCESS), |
- delta_encoding_length_(0), |
- delta_encoding_start_(NULL) { } |
- |
-bool VCDiffHeaderParser::ParseByte(unsigned char* value) { |
- if (RESULT_SUCCESS != return_code_) { |
- return false; |
- } |
- if (parseable_chunk_.Empty()) { |
- return_code_ = RESULT_END_OF_DATA; |
- return false; |
- } |
- *value = static_cast<unsigned char>(*parseable_chunk_.UnparsedData()); |
- parseable_chunk_.Advance(1); |
- return true; |
-} |
- |
-bool VCDiffHeaderParser::ParseInt32(const char* variable_description, |
- int32_t* value) { |
- if (RESULT_SUCCESS != return_code_) { |
- return false; |
- } |
- int32_t parsed_value = |
- VarintBE<int32_t>::Parse(parseable_chunk_.End(), |
- parseable_chunk_.UnparsedDataAddr()); |
- switch (parsed_value) { |
- case RESULT_ERROR: |
- LOG(ERROR) << "Expected " << variable_description |
- << "; found invalid variable-length integer" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- case RESULT_END_OF_DATA: |
- return_code_ = RESULT_END_OF_DATA; |
- return false; |
- default: |
- *value = parsed_value; |
- return true; |
- } |
-} |
- |
-// When an unsigned 32-bit integer is expected, parse a signed 64-bit value |
-// instead, then check the value limit. The uint32_t type can't be parsed |
-// directly because two negative values are given special meanings (RESULT_ERROR |
-// and RESULT_END_OF_DATA) and could not be expressed in an unsigned format. |
-bool VCDiffHeaderParser::ParseUInt32(const char* variable_description, |
- uint32_t* value) { |
- if (RESULT_SUCCESS != return_code_) { |
- return false; |
- } |
- int64_t parsed_value = |
- VarintBE<int64_t>::Parse(parseable_chunk_.End(), |
- parseable_chunk_.UnparsedDataAddr()); |
- switch (parsed_value) { |
- case RESULT_ERROR: |
- LOG(ERROR) << "Expected " << variable_description |
- << "; found invalid variable-length integer" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- case RESULT_END_OF_DATA: |
- return_code_ = RESULT_END_OF_DATA; |
- return false; |
- default: |
- if (parsed_value > 0xFFFFFFFF) { |
- LOG(ERROR) << "Value of " << variable_description << "(" << parsed_value |
- << ") is too large for unsigned 32-bit integer" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- *value = static_cast<uint32_t>(parsed_value); |
- return true; |
- } |
-} |
- |
-// A VCDChecksum represents an unsigned 32-bit value returned by adler32(), |
-// but isn't a uint32_t. |
-bool VCDiffHeaderParser::ParseChecksum(const char* variable_description, |
- VCDChecksum* value) { |
- uint32_t parsed_value = 0; |
- if (!ParseUInt32(variable_description, &parsed_value)) { |
- return false; |
- } |
- *value = static_cast<VCDChecksum>(parsed_value); |
- return true; |
-} |
- |
-bool VCDiffHeaderParser::ParseSize(const char* variable_description, |
- size_t* value) { |
- int32_t parsed_value = 0; |
- if (!ParseInt32(variable_description, &parsed_value)) { |
- return false; |
- } |
- *value = static_cast<size_t>(parsed_value); |
- return true; |
-} |
- |
-bool VCDiffHeaderParser::ParseSourceSegmentLengthAndPosition( |
- size_t from_size, |
- const char* from_boundary_name, |
- const char* from_name, |
- size_t* source_segment_length, |
- size_t* source_segment_position) { |
- // Verify the length and position values |
- if (!ParseSize("source segment length", source_segment_length)) { |
- return false; |
- } |
- // Guard against overflow by checking source length first |
- if (*source_segment_length > from_size) { |
- LOG(ERROR) << "Source segment length (" << *source_segment_length |
- << ") is larger than " << from_name << " (" << from_size |
- << ")" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- if (!ParseSize("source segment position", source_segment_position)) { |
- return false; |
- } |
- if ((*source_segment_position >= from_size) && |
- (*source_segment_length > 0)) { |
- LOG(ERROR) << "Source segment position (" << *source_segment_position |
- << ") is past " << from_boundary_name |
- << " (" << from_size << ")" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- const size_t source_segment_end = *source_segment_position + |
- *source_segment_length; |
- if (source_segment_end > from_size) { |
- LOG(ERROR) << "Source segment end position (" << source_segment_end |
- << ") is past " << from_boundary_name |
- << " (" << from_size << ")" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- return true; |
-} |
- |
-bool VCDiffHeaderParser::ParseWinIndicatorAndSourceSegment( |
- size_t dictionary_size, |
- size_t decoded_target_size, |
- unsigned char* win_indicator, |
- size_t* source_segment_length, |
- size_t* source_segment_position) { |
- if (!ParseByte(win_indicator)) { |
- return false; |
- } |
- unsigned char source_target_flags = |
- *win_indicator & (VCD_SOURCE | VCD_TARGET); |
- switch (source_target_flags) { |
- case VCD_SOURCE: |
- return ParseSourceSegmentLengthAndPosition(dictionary_size, |
- "end of dictionary", |
- "dictionary", |
- source_segment_length, |
- source_segment_position); |
- case VCD_TARGET: |
- return ParseSourceSegmentLengthAndPosition(decoded_target_size, |
- "current target position", |
- "target file", |
- source_segment_length, |
- source_segment_position); |
- case VCD_SOURCE | VCD_TARGET: |
- LOG(ERROR) << "Win_Indicator must not have both VCD_SOURCE" |
- " and VCD_TARGET set" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- default: |
- return true; |
- } |
-} |
- |
-bool VCDiffHeaderParser::ParseWindowLengths(size_t* target_window_length) { |
- if (delta_encoding_start_) { |
- LOG(DFATAL) << "Internal error: VCDiffHeaderParser::ParseWindowLengths " |
- "was called twice for the same delta window" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- if (!ParseSize("length of the delta encoding", &delta_encoding_length_)) { |
- return false; |
- } |
- delta_encoding_start_ = UnparsedData(); |
- if (!ParseSize("size of the target window", target_window_length)) { |
- return false; |
- } |
- if (*target_window_length > kMaxTargetWindowSize) { |
- LOG(ERROR) << "Length of target window (" << (*target_window_length) |
- << ") exceeds limit of " << kMaxTargetWindowSize << " bytes" |
- << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- return true; |
-} |
- |
-const char* VCDiffHeaderParser::EndOfDeltaWindow() const { |
- if (!delta_encoding_start_) { |
- LOG(DFATAL) << "Internal error: VCDiffHeaderParser::GetDeltaWindowEnd " |
- "was called before ParseWindowLengths" << LOG_ENDL; |
- return NULL; |
- } |
- return delta_encoding_start_ + delta_encoding_length_; |
-} |
- |
-bool VCDiffHeaderParser::ParseDeltaIndicator() { |
- unsigned char delta_indicator; |
- if (!ParseByte(&delta_indicator)) { |
- return false; |
- } |
- if (delta_indicator & (VCD_DATACOMP | VCD_INSTCOMP | VCD_ADDRCOMP)) { |
- LOG(ERROR) << "Secondary compression of delta file sections " |
- "is not supported" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- return true; |
-} |
- |
-bool VCDiffHeaderParser::ParseSectionLengths( |
- bool has_checksum, |
- size_t* add_and_run_data_length, |
- size_t* instructions_and_sizes_length, |
- size_t* addresses_length, |
- VCDChecksum* checksum) { |
- ParseSize("length of data for ADDs and RUNs", add_and_run_data_length); |
- ParseSize("length of instructions section", instructions_and_sizes_length); |
- ParseSize("length of addresses for COPYs", addresses_length); |
- if (has_checksum) { |
- ParseChecksum("Adler32 checksum value", checksum); |
- } |
- if (RESULT_SUCCESS != return_code_) { |
- return false; |
- } |
- if (!delta_encoding_start_) { |
- LOG(DFATAL) << "Internal error: VCDiffHeaderParser::ParseSectionLengths " |
- "was called before ParseWindowLengths" << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- const size_t delta_encoding_header_length = |
- UnparsedData() - delta_encoding_start_; |
- if (delta_encoding_length_ != |
- (delta_encoding_header_length + |
- *add_and_run_data_length + |
- *instructions_and_sizes_length + |
- *addresses_length)) { |
- LOG(ERROR) << "The length of the delta encoding does not match " |
- "the size of the header plus the sizes of the data sections" |
- << LOG_ENDL; |
- return_code_ = RESULT_ERROR; |
- return false; |
- } |
- return true; |
-} |
- |
-} // namespace open_vcdiff |