10a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Copyright 2008 Google Inc. 20a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Author: Lincoln Smith 30a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 40a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Licensed under the Apache License, Version 2.0 (the "License"); 50a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// you may not use this file except in compliance with the License. 60a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// You may obtain a copy of the License at 70a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 80a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// http://www.apache.org/licenses/LICENSE-2.0 90a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Unless required by applicable law or agreed to in writing, software 110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// distributed under the License is distributed on an "AS IS" BASIS, 120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// See the License for the specific language governing permissions and 140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// limitations under the License. 150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <config.h> 170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "headerparser.h" 180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "logging.h" 190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "varint_bigendian.h" 200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "vcdiff_defs.h" 210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathnamespace open_vcdiff { 230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Methods for ParseableChunk 250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid ParseableChunk::Advance(size_t number_of_bytes) { 270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (number_of_bytes > UnparsedSize()) { 280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: position advanced by " << number_of_bytes 290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes, current unparsed size " << UnparsedSize() 300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ = end_; 320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ += number_of_bytes; 350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid ParseableChunk::SetPosition(const char* position) { 380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (position < start_) { 390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: new data position " << position 400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " is beyond start of data " << start_ << VCD_ENDL; 410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ = start_; 420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (position > end_) { 450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: new data position " << position 460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " is beyond end of data " << end_ << VCD_ENDL; 470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ = end_; 480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ = position; 510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid ParseableChunk::FinishExcept(size_t number_of_bytes) { 540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (number_of_bytes > UnparsedSize()) { 550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: specified number of remaining bytes " 560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << number_of_bytes << " is greater than unparsed data size " 570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << UnparsedSize() << VCD_ENDL; 580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Finish(); 590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath position_ = end_ - number_of_bytes; 620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Methods for VCDiffHeaderParser 650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffHeaderParser::VCDiffHeaderParser(const char* header_start, 670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* data_end) 680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath : parseable_chunk_(header_start, data_end - header_start), 690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_(RESULT_SUCCESS), 700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_encoding_length_(0), 710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_encoding_start_(NULL) { } 720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseByte(unsigned char* value) { 740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != return_code_) { 750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (parseable_chunk_.Empty()) { 780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_END_OF_DATA; 790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *value = static_cast<unsigned char>(*parseable_chunk_.UnparsedData()); 820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk_.Advance(1); 830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseInt32(const char* variable_description, 870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t* value) { 880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != return_code_) { 890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t parsed_value = 920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VarintBE<int32_t>::Parse(parseable_chunk_.End(), 930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk_.UnparsedDataAddr()); 940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (parsed_value) { 950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Expected " << variable_description 970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "; found invalid variable-length integer" << VCD_ENDL; 980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_END_OF_DATA; 1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *value = parsed_value; 1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// When an unsigned 32-bit integer is expected, parse a signed 64-bit value 1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// instead, then check the value limit. The uint32_t type can't be parsed 1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// directly because two negative values are given special meanings (RESULT_ERROR 1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// and RESULT_END_OF_DATA) and could not be expressed in an unsigned format. 1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseUInt32(const char* variable_description, 1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath uint32_t* value) { 1150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != return_code_) { 1160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int64_t parsed_value = 1190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VarintBE<int64_t>::Parse(parseable_chunk_.End(), 1200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk_.UnparsedDataAddr()); 1210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (parsed_value) { 1220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 1230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Expected " << variable_description 1240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "; found invalid variable-length integer" << VCD_ENDL; 1250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 1260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 1280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_END_OF_DATA; 1290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 1310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (parsed_value > 0xFFFFFFFF) { 1320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Value of " << variable_description << "(" << parsed_value 1330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") is too large for unsigned 32-bit integer" << VCD_ENDL; 1340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 1350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *value = static_cast<uint32_t>(parsed_value); 1380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 1390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// A VCDChecksum represents an unsigned 32-bit value returned by adler32(), 1430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// but isn't a uint32_t. 1440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseChecksum(const char* variable_description, 1450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDChecksum* value) { 1460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath uint32_t parsed_value = 0; 1470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseUInt32(variable_description, &parsed_value)) { 1480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *value = static_cast<VCDChecksum>(parsed_value); 1510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 1520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseSize(const char* variable_description, 1550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* value) { 1560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t parsed_value = 0; 1570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseInt32(variable_description, &parsed_value)) { 1580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *value = static_cast<size_t>(parsed_value); 1610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 1620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 1630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseSourceSegmentLengthAndPosition( 1650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t from_size, 1660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* from_boundary_name, 1670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* from_name, 1680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* source_segment_length, 1690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* source_segment_position) { 1700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Verify the length and position values 1710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseSize("source segment length", source_segment_length)) { 1720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Guard against overflow by checking source length first 1750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (*source_segment_length > from_size) { 1760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Source segment length (" << *source_segment_length 1770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") is larger than " << from_name << " (" << from_size 1780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ")" << VCD_ENDL; 1790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 1800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseSize("source segment position", source_segment_position)) { 1830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((*source_segment_position >= from_size) && 1860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (*source_segment_length > 0)) { 1870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Source segment position (" << *source_segment_position 1880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") is past " << from_boundary_name 1890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " (" << from_size << ")" << VCD_ENDL; 1900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 1910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 1920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t source_segment_end = *source_segment_position + 1940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *source_segment_length; 1950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (source_segment_end > from_size) { 1960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Source segment end position (" << source_segment_end 1970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") is past " << from_boundary_name 1980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " (" << from_size << ")" << VCD_ENDL; 1990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 2000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseWinIndicatorAndSourceSegment( 2060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size, 2070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t decoded_target_size, 2080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool allow_vcd_target, 2090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char* win_indicator, 2100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* source_segment_length, 2110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* source_segment_position) { 2120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseByte(win_indicator)) { 2130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char source_target_flags = 2160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *win_indicator & (VCD_SOURCE | VCD_TARGET); 2170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (source_target_flags) { 2180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_SOURCE: 2190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return ParseSourceSegmentLengthAndPosition(dictionary_size, 2200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "end of dictionary", 2210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "dictionary", 2220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_length, 2230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_position); 2240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_TARGET: 2250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!allow_vcd_target) { 2260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Delta file contains VCD_TARGET flag, which is not " 2270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "allowed by current decoder settings" << VCD_ENDL; 2280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 2290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return ParseSourceSegmentLengthAndPosition(decoded_target_size, 2320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "current target position", 2330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "target file", 2340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_length, 2350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_position); 2360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_SOURCE | VCD_TARGET: 2370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Win_Indicator must not have both VCD_SOURCE" 2380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " and VCD_TARGET set" << VCD_ENDL; 2390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 2400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 2420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseWindowLengths(size_t* target_window_length) { 2470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (delta_encoding_start_) { 2480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: VCDiffHeaderParser::ParseWindowLengths " 2490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "was called twice for the same delta window" << VCD_ENDL; 2500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 2510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseSize("length of the delta encoding", &delta_encoding_length_)) { 2540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_encoding_start_ = UnparsedData(); 2570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseSize("size of the target window", target_window_length)) { 2580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst char* VCDiffHeaderParser::EndOfDeltaWindow() const { 2640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!delta_encoding_start_) { 2650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: VCDiffHeaderParser::GetDeltaWindowEnd " 2660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "was called before ParseWindowLengths" << VCD_ENDL; 2670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return NULL; 2680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return delta_encoding_start_ + delta_encoding_length_; 2700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseDeltaIndicator() { 2730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char delta_indicator; 2740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ParseByte(&delta_indicator)) { 2750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (delta_indicator & (VCD_DATACOMP | VCD_INSTCOMP | VCD_ADDRCOMP)) { 2780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Secondary compression of delta file sections " 2790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "is not supported" << VCD_ENDL; 2800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 2810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffHeaderParser::ParseSectionLengths( 2870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool has_checksum, 2880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* add_and_run_data_length, 2890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* instructions_and_sizes_length, 2900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t* addresses_length, 2910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDChecksum* checksum) { 2920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseSize("length of data for ADDs and RUNs", add_and_run_data_length); 2930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseSize("length of instructions section", instructions_and_sizes_length); 2940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseSize("length of addresses for COPYs", addresses_length); 2950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (has_checksum) { 2960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseChecksum("Adler32 checksum value", checksum); 2970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != return_code_) { 2990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!delta_encoding_start_) { 3020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: VCDiffHeaderParser::ParseSectionLengths " 3030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "was called before ParseWindowLengths" << VCD_ENDL; 3040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 3050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t delta_encoding_header_length = 3080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UnparsedData() - delta_encoding_start_; 3090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (delta_encoding_length_ != 3100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (delta_encoding_header_length + 3110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *add_and_run_data_length + 3120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *instructions_and_sizes_length + 3130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *addresses_length)) { 3140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "The length of the delta encoding does not match " 3150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "the size of the header plus the sizes of the data sections" 3160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 3170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return_code_ = RESULT_ERROR; 3180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} // namespace open_vcdiff 324