| 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
|
|
|