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// Implements a Decoder for the format described in 170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// RFC 3284 - The VCDIFF Generic Differencing and Compression Data Format. 180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The RFC text can be found at http://www.faqs.org/rfcs/rfc3284.html 190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The RFC describes the possibility of using a secondary compressor 210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// to further reduce the size of each section of the VCDIFF output. 220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// That feature is not supported in this implementation of the encoder 230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// and decoder. 240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// No secondary compressor types have been publicly registered with 250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// the IANA at http://www.iana.org/assignments/vcdiff-comp-ids 260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// in the more than five years since the registry was created, so there 270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// is no standard set of compressor IDs which would be generated by other 280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// encoders or accepted by other decoders. 290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <config.h> 310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "google/vcdecoder.h" 320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stddef.h> // size_t, ptrdiff_t 330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdint.h> // int32_t 340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string.h> // memcpy, memset 350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <memory> // auto_ptr 360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string> 370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "addrcache.h" 380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "checksum.h" 390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "codetable.h" 400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "decodetable.h" 410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "headerparser.h" 420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "logging.h" 430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "google/output_string.h" 440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "varint_bigendian.h" 450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "vcdiff_defs.h" 460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathnamespace open_vcdiff { 480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This class is used to parse delta file windows as described 500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// in RFC sections 4.2 and 4.3. Its methods are not thread-safe. 510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Here is the window format copied from the RFC: 530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Window1 550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Win_Indicator - byte 560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Source segment size] - integer 570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Source segment position] - integer 580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The delta encoding of the target window 590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of the delta encoding - integer 600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The delta encoding 610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Size of the target window - integer 620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Delta_Indicator - byte 630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of data for ADDs and RUNs - integer 640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of instructions and sizes - integer 650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of addresses for COPYs - integer 660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Data section for ADDs and RUNs - array of bytes 670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Instructions and sizes section - array of bytes 680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Addresses section for COPYs - array of bytes 690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Window2 700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ... 710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Sample usage: 730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// VCDiffDeltaFileWindow delta_window_; 750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// delta_window_.Init(parent); 760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// ParseableChunk parseable_chunk(input_buffer, 770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// input_size, 780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// leftover_unencoded_bytes); 790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// while (!parseable_chunk.Empty()) { 800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// switch (delta_window_.DecodeWindow(&parseable_chunk)) { 810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// case RESULT_END_OF_DATA: 820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// <Read more input and retry DecodeWindow later.> 830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// case RESULT_ERROR: 840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// <Handle error case. An error log message has already been generated.> 850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// } 860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// } 870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// DecodeWindow consumes only a single window, and needs to be placed within 890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// a loop if multiple windows are to be processed. 900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass VCDiffDeltaFileWindow { 920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public: 930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffDeltaFileWindow(); 940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ~VCDiffDeltaFileWindow(); 950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Init() should be called immediately after constructing the 970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // VCDiffDeltaFileWindow(). It must be called before DecodeWindow() can be 980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // invoked, or an error will occur. 990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void Init(VCDiffStreamingDecoderImpl* parent); 1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Resets the pointers to the data sections in the current window. 1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void Reset(); 1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool UseCodeTable(const VCDiffCodeTableData& code_table_data, 1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char max_mode) { 1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return reader_.UseCodeTable(code_table_data, max_mode); 1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Decodes a single delta window using the input data from *parseable_chunk. 1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Appends the decoded target window to parent_->decoded_target(). Returns 1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // RESULT_SUCCESS if an entire window was decoded, or RESULT_END_OF_DATA if 1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the end of input was reached before the entire window could be decoded and 1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // more input is expected (only possible if IsInterleaved() is true), or 1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // RESULT_ERROR if an error occurred during decoding. In the RESULT_ERROR 1150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // case, the value of parseable_chunk->pointer_ is undefined; otherwise, 1160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // parseable_chunk->Advance() is called to point to the input data position 1170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // just after the data that has been decoded. 1180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult DecodeWindow(ParseableChunk* parseable_chunk); 1200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool FoundWindowHeader() const { 1220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return found_header_; 1230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool MoreDataExpected() const { 1260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // When parsing an interleaved-format delta file, 1270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // every time DecodeBody() exits, interleaved_bytes_expected_ 1280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will be decremented by the number of bytes parsed. If it 1290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // reaches zero, then there is no more data expected because 1300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the size of the interleaved section (given in the window 1310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // header) has been reached. 1320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return IsInterleaved() && (interleaved_bytes_expected_ > 0); 1330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t target_window_start_pos() const { return target_window_start_pos_; } 1360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void set_target_window_start_pos(size_t new_start_pos) { 1380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_window_start_pos_ = new_start_pos; 1390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Returns the number of bytes remaining to be decoded in the target window. 1420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If not in the process of decoding a window, returns 0. 1430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t TargetBytesRemaining(); 1440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private: 1460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reads the header of the window section as described in RFC sections 4.2 and 1470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 4.3, up to and including the value "Length of addresses for COPYs". If the 1480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // entire header is found, this function sets up the DeltaWindowSections 1490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // instructions_and_sizes_, data_for_add_and_run_, and addresses_for_copy_ so 1500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // that the decoder can begin decoding the opcodes in these sections. Returns 1510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // RESULT_ERROR if an error occurred, or RESULT_END_OF_DATA if the end of 1520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // available data was reached before the entire header could be read. (The 1530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // latter may be an error condition if there is no more data available.) 1540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Otherwise, returns RESULT_SUCCESS and advances parseable_chunk past the 1550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // parsed header. 1560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult ReadHeader(ParseableChunk* parseable_chunk); 1580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // After the window header has been parsed as far as the Delta_Indicator, 1600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // this function is called to parse the following delta window header fields: 1610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Length of data for ADDs and RUNs - integer (VarintBE format) 1630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Length of instructions and sizes - integer (VarintBE format) 1640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Length of addresses for COPYs - integer (VarintBE format) 1650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If has_checksum_ is true, it also looks for the following element: 1670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Adler32 checksum - unsigned 32-bit integer (VarintBE format) 1690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // It sets up the DeltaWindowSections instructions_and_sizes_, 1710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data_for_add_and_run_, and addresses_for_copy_. If the interleaved format 1720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // is being used, all three sections will include the entire window body; if 1730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the standard format is used, three non-overlapping window sections will be 1740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // defined. Returns RESULT_ERROR if an error occurred, or RESULT_END_OF_DATA 1750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if standard format is being used and there is not enough input data to read 1760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the entire window body. Otherwise, returns RESULT_SUCCESS. 1770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult SetUpWindowSections(VCDiffHeaderParser* header_parser); 1780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Decodes the body of the window section as described in RFC sections 4.3, 1800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // including the sections "Data section for ADDs and RUNs", "Instructions 1810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and sizes section", and "Addresses section for COPYs". These sections 1820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // must already have been set up by ReadWindowHeader(). Returns a 1830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // non-negative value on success, or RESULT_END_OF_DATA if the end of input 1840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // was reached before the entire window could be decoded (only possible if 1850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // IsInterleaved() is true), or RESULT_ERROR if an error occurred during 1860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoding. Appends as much of the decoded target window as possible to 1870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // parent->decoded_target(). 1880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 1890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int DecodeBody(ParseableChunk* parseable_chunk); 1900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Returns the number of bytes already decoded into the target window. 1920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t TargetBytesDecoded(); 1930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Decodes a single ADD instruction, updating parent_->decoded_target_. 1950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult DecodeAdd(size_t size); 1960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Decodes a single RUN instruction, updating parent_->decoded_target_. 1980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult DecodeRun(size_t size); 1990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Decodes a single COPY instruction, updating parent_->decoded_target_. 2010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult DecodeCopy(size_t size, unsigned char mode); 2020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // When using the interleaved format, this function is called both on parsing 2040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the header and on resuming after a RESULT_END_OF_DATA was returned from a 2050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // previous call to DecodeBody(). It sets up all three section pointers to 2060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // reference the same interleaved stream of instructions, sizes, addresses, 2070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and data. These pointers must be reset every time that work resumes on a 2080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // delta window, because the input data string may have been changed or 2090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // resized since DecodeBody() last returned. 2100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void UpdateInterleavedSectionPointers(const char* data_pos, 2110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* data_end) { 2120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const ptrdiff_t available_data = data_end - data_pos; 2130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Don't read past the end of currently-available data 2140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (available_data > interleaved_bytes_expected_) { 2150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.Init(data_pos, interleaved_bytes_expected_); 2160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 2170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.Init(data_pos, available_data); 2180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data_for_add_and_run_.Init(&instructions_and_sizes_); 2200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_for_copy_.Init(&instructions_and_sizes_); 2210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If true, the interleaved format described in AllowInterleaved() is used 2240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // for the current delta file. Only valid after ReadWindowHeader() has been 2250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // called and returned a positive number (i.e., the whole header was parsed), 2260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // but before the window has finished decoding. 2270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 2280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool IsInterleaved() const { 2290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If the sections are interleaved, both addresses_for_copy_ and 2300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data_for_add_and_run_ should point at instructions_and_sizes_. 2310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return !addresses_for_copy_.IsOwned(); 2320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Executes a single COPY or ADD instruction, appending data to 2350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // parent_->decoded_target(). 2360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void CopyBytes(const char* data, size_t size); 2370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Executes a single RUN instruction, appending data to 2390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // parent_->decoded_target(). 2400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void RunByte(unsigned char byte, size_t size); 2410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Advance *parseable_chunk to point to the current position in the 2430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // instructions/sizes section. If interleaved format is used, then 2440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decrement the number of expected bytes in the instructions/sizes section 2450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // by the number of instruction/size bytes parsed. 2460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void UpdateInstructionPointer(ParseableChunk* parseable_chunk); 2470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The parent object which was passed to Init(). 2490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffStreamingDecoderImpl* parent_; 2500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This value will be true if VCDiffDeltaFileWindow::ReadDeltaWindowHeader() 2520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // has been called and succeeded in parsing the delta window header, but the 2530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // entire window has not yet been decoded. 2540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool found_header_; 2550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Contents and length of the current source window. source_segment_ptr_ 2570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will be non-NULL if (a) the window section header for the current window 2580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // has been read, but the window has not yet finished decoding; or 2590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // (b) the window did not specify a source segment. 2600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* source_segment_ptr_; 2610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t source_segment_length_; 2620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The delta encoding window sections as defined in RFC section 4.3. 2640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The pointer for each section will be incremented as data is consumed and 2650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoded from that section. If the interleaved format is used, 2660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data_for_add_and_run_ and addresses_for_copy_ will both point to 2670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // instructions_and_sizes_; otherwise, they will be separate data sections. 2680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 2690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath DeltaWindowSection instructions_and_sizes_; 2700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath DeltaWindowSection data_for_add_and_run_; 2710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath DeltaWindowSection addresses_for_copy_; 2720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The expected bytes left to decode in instructions_and_sizes_. Only used 2740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // for the interleaved format. 2750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int interleaved_bytes_expected_; 2760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The expected length of the target window once it has been decoded. 2780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t target_window_length_; 2790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The index in decoded_target at which the first byte of the current 2810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // target window was/will be written. 2820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t target_window_start_pos_; 2830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If has_checksum_ is true, then expected_checksum_ contains an Adler32 2850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // checksum of the target window data. This is an extension included in the 2860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // VCDIFF 'S' (SDCH) format, but is not part of the RFC 3284 draft standard. 2870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool has_checksum_; 2880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDChecksum expected_checksum_; 2890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffCodeTableReader reader_; 2910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Making these private avoids implicit copy constructor & assignment operator 2930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffDeltaFileWindow(const VCDiffDeltaFileWindow&); // NOLINT 2940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void operator=(const VCDiffDeltaFileWindow&); 2950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}; 2960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Inline methods for VCDiffDeltaFileWindow 2980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline VCDiffDeltaFileWindow::VCDiffDeltaFileWindow() : parent_(NULL) { 3000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 3010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline VCDiffDeltaFileWindow::~VCDiffDeltaFileWindow() { } 3040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline void VCDiffDeltaFileWindow::Init(VCDiffStreamingDecoderImpl* parent) { 3060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_ = parent; 3070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass VCDiffStreamingDecoderImpl { 3100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public: 3110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath typedef std::string string; 3120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The default maximum target file size (and target window size) if 3140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // SetMaximumTargetFileSize() is not called. 3150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static const size_t kDefaultMaximumTargetFileSize = 67108864U; // 64 MB 3160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The largest value that can be passed to SetMaximumTargetWindowSize(). 3180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Using a larger value will result in an error. 3190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static const size_t kTargetSizeLimit = 2147483647U; // INT32_MAX 3200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // A constant that is the default value for planned_target_file_size_, 3220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // indicating that the decoder does not have an expected length 3230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // for the target data. 3240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static const size_t kUnlimitedBytes = static_cast<size_t>(-3); 3250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffStreamingDecoderImpl(); 3270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ~VCDiffStreamingDecoderImpl(); 3280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Resets all member variables to their initial states. 3300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void Reset(); 3310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // These functions are identical to their counterparts 3330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // in VCDiffStreamingDecoder. 3340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 3350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void StartDecoding(const char* dictionary_ptr, size_t dictionary_size); 3360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool DecodeChunk(const char* data, 3380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t len, 3390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* output_string); 3400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool FinishDecoding(); 3420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If true, the version of VCDIFF used in the current delta file allows 3440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // for the interleaved format, in which instructions, addresses and data 3450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // are all sent interleaved in the instructions section of each window 3460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // rather than being sent in separate sections. This is not part of 3470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the VCDIFF draft standard, so we've defined a special version code 3480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 'S' which implies that this feature is available. Even if interleaving 3490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // is supported, it is not mandatory; interleaved format will be implied 3500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if the address and data sections are both zero-length. 3510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 3520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool AllowInterleaved() const { return vcdiff_version_code_ == 'S'; } 3530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If true, the version of VCDIFF used in the current delta file allows 3550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // each delta window to contain an Adler32 checksum of the target window data. 3560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If the bit 0x08 (VCD_CHECKSUM) is set in the Win_Indicator flags, then 3570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // this checksum will appear as a variable-length integer, just after the 3580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // "length of addresses for COPYs" value and before the window data sections. 3590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // It is possible for some windows in a delta file to use the checksum feature 3600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and for others not to use it (and leave the flag bit set to 0.) 3610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Just as with AllowInterleaved(), this extension is not part of the draft 3620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // standard and is only available when the version code 'S' is specified. 3630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 3640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool AllowChecksum() const { return vcdiff_version_code_ == 'S'; } 3650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool SetMaximumTargetFileSize(size_t new_maximum_target_file_size) { 3670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath maximum_target_file_size_ = new_maximum_target_file_size; 3680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool SetMaximumTargetWindowSize(size_t new_maximum_target_window_size) { 3720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (new_maximum_target_window_size > kTargetSizeLimit) { 3730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Specified maximum target window size " 3740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << new_maximum_target_window_size << " exceeds limit of " 3750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << kTargetSizeLimit << " bytes" << VCD_ENDL; 3760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath maximum_target_window_size_ = new_maximum_target_window_size; 3790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // See description of planned_target_file_size_, below. 3830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool HasPlannedTargetFileSize() const { 3840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return planned_target_file_size_ != kUnlimitedBytes; 3850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void SetPlannedTargetFileSize(size_t planned_target_file_size) { 3880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath planned_target_file_size_ = planned_target_file_size; 3890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void AddToTotalTargetWindowSize(size_t window_size) { 3920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath total_of_target_window_sizes_ += window_size; 3930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Checks to see whether the decoded target data has reached its planned size. 3960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool ReachedPlannedTargetFileSize() const { 3970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!HasPlannedTargetFileSize()) { 3980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The planned target file size should not have been exceeded. 4010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // TargetWindowWouldExceedSizeLimits() ensures that the advertised size of 4020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // each target window would not make the target file exceed that limit, and 4030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // DecodeBody() will return RESULT_ERROR if the actual decoded output ever 4040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // exceeds the advertised target window size. 4050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (total_of_target_window_sizes_ > planned_target_file_size_) { 4060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: Decoded data size " 4070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << total_of_target_window_sizes_ 4080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " exceeds planned target file size " 4090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << planned_target_file_size_ << VCD_ENDL; 4100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 4110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return total_of_target_window_sizes_ == planned_target_file_size_; 4130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Checks to see whether adding a new target window of the specified size 4160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // would exceed the planned target file size, the maximum target file size, 4170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // or the maximum target window size. If so, logs an error and returns true; 4180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // otherwise, returns false. 4190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool TargetWindowWouldExceedSizeLimits(size_t window_size) const; 4200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Returns the amount of input data passed to the last DecodeChunk() 4220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // that was not consumed by the decoder. This is essential if 4230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // SetPlannedTargetFileSize() is being used, in order to preserve the 4240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // remaining input data stream once the planned target file has been decoded. 4250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t GetUnconsumedDataSize() const { 4260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return unparsed_bytes_.size(); 4270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This function will return true if the decoder has parsed a complete delta 4300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // file header plus zero or more delta file windows, with no data left over. 4310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // It will also return true if no delta data at all was decoded. If these 4320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // conditions are not met, then FinishDecoding() should not be called. 4330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool IsDecodingComplete() const { 4340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!FoundFileHeader()) { 4350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // No complete delta file header has been parsed yet. DecodeChunk() 4360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // may have received some data that it hasn't yet parsed, in which case 4370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoding is incomplete. 4380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return unparsed_bytes_.empty(); 4390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (custom_code_table_decoder_.get()) { 4400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The decoder is in the middle of parsing a custom code table. 4410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (delta_window_.FoundWindowHeader()) { 4430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The decoder is in the middle of parsing an interleaved format delta 4440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // window. 4450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (ReachedPlannedTargetFileSize()) { 4470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The decoder found exactly the planned number of bytes. In this case 4480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // it is OK for unparsed_bytes_ to be non-empty; it contains the leftover 4490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data after the end of the delta file. 4500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 4510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 4520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // No complete delta file window has been parsed yet. DecodeChunk() 4530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // may have received some data that it hasn't yet parsed, in which case 4540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoding is incomplete. 4550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return unparsed_bytes_.empty(); 4560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* dictionary_ptr() const { return dictionary_ptr_; } 4600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size() const { return dictionary_size_; } 4620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffAddressCache* addr_cache() { return addr_cache_.get(); } 4640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string* decoded_target() { return &decoded_target_; } 4660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool allow_vcd_target() const { return allow_vcd_target_; } 4680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void SetAllowVcdTarget(bool allow_vcd_target) { 4700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (start_decoding_was_called_) { 4710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "SetAllowVcdTarget() called after StartDecoding()" 4720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 4730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 4740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath allow_vcd_target_ = allow_vcd_target; 4760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private: 4790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reads the VCDiff delta file header section as described in RFC section 4.1, 4800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // except the custom code table data. Returns RESULT_ERROR if an error 4810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // occurred, or RESULT_END_OF_DATA if the end of available data was reached 4820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // before the entire header could be read. (The latter may be an error 4830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // condition if there is no more data available.) Otherwise, advances 4840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data->position_ past the header and returns RESULT_SUCCESS. 4850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 4860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult ReadDeltaFileHeader(ParseableChunk* data); 4870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Indicates whether or not the header has already been read. 4890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool FoundFileHeader() const { return addr_cache_.get() != NULL; } 4900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If ReadDeltaFileHeader() finds the VCD_CODETABLE flag set within the delta 4920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // file header, this function parses the custom cache sizes and initializes 4930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // a nested VCDiffStreamingDecoderImpl object that will be used to parse the 4940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // custom code table in ReadCustomCodeTable(). Returns RESULT_ERROR if an 4950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // error occurred, or RESULT_END_OF_DATA if the end of available data was 4960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // reached before the custom cache sizes could be read. Otherwise, returns 4970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the number of bytes read. 4980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 4990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int InitCustomCodeTable(const char* data_start, const char* data_end); 5000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If a custom code table was specified in the header section that was parsed 5020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // by ReadDeltaFileHeader(), this function makes a recursive call to another 5030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // VCDiffStreamingDecoderImpl object (custom_code_table_decoder_), since the 5040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // custom code table is expected to be supplied as an embedded VCDIFF 5050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // encoding that uses the standard code table. Returns RESULT_ERROR if an 5060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // error occurs, or RESULT_END_OF_DATA if the end of available data was 5070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // reached before the entire custom code table could be read. Otherwise, 5080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // returns RESULT_SUCCESS and sets *data_ptr to the position after the encoded 5090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // custom code table. If the function returns RESULT_SUCCESS or 5100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // RESULT_END_OF_DATA, it advances data->position_ past the parsed bytes. 5110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 5120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult ReadCustomCodeTable(ParseableChunk* data); 5130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Called after the decoder exhausts all input data. This function 5150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // copies from decoded_target_ into output_string all the data that 5160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // has not yet been output. It sets decoded_target_output_position_ 5170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to mark the start of the next data that needs to be output. 5180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void AppendNewOutputText(OutputStringInterface* output_string); 5190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Appends to output_string the portion of decoded_target_ that has 5210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // not yet been output, then clears decoded_target_. This function is 5220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // called after each complete target window has been decoded if 5230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // allow_vcd_target is false. In that case, there is no need to retain 5240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // target data from any window except the current window. 5250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void FlushDecodedTarget(OutputStringInterface* output_string); 5260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Contents and length of the source (dictionary) data. 5280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* dictionary_ptr_; 5290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size_; 5300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This string will be used to store any unparsed bytes left over when 5320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // DecodeChunk() reaches the end of its input and returns RESULT_END_OF_DATA. 5330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // It will also be used to concatenate those unparsed bytes with the data 5340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // supplied to the next call to DecodeChunk(), so that they appear in 5350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // contiguous memory. 5360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string unparsed_bytes_; 5370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The portion of the target file that has been decoded so far. This will be 5390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // used to fill the output string for DecodeChunk(), and will also be used to 5400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // execute COPY instructions that reference target data. Since the source 5410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // window can come from a range of addresses in the previously decoded target 5420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // data, the entire target file needs to be available to the decoder, not just 5430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the current target window. 5440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string decoded_target_; 5450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The VCDIFF version byte (also known as "header4") from the 5470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // delta file header. 5480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char vcdiff_version_code_; 5490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffDeltaFileWindow delta_window_; 5510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::auto_ptr<VCDiffAddressCache> addr_cache_; 5530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Will be NULL unless a custom code table has been defined. 5550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::auto_ptr<VCDiffCodeTableData> custom_code_table_; 5560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Used to receive the decoded custom code table. 5580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string custom_code_table_string_; 5590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If a custom code table is specified, it will be expressed 5610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // as an embedded VCDIFF delta file which uses the default code table 5620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // as the source file (dictionary). Use a child decoder object 5630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to decode that delta file. 5640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::auto_ptr<VCDiffStreamingDecoderImpl> custom_code_table_decoder_; 5650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If set, then the decoder is expecting *exactly* this number of 5670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // target bytes to be decoded from one or more delta file windows. 5680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If this number is exceeded while decoding a window, but was not met 5690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // before starting on that window, an error will be reported. 5700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If FinishDecoding() is called before this number is met, an error 5710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will also be reported. This feature is used for decoding the 5720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // embedded code table data within a VCDIFF delta file; we want to 5730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // stop processing the embedded data once the entire code table has 5740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // been decoded, and treat the rest of the available data as part 5750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // of the enclosing delta file. 5760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t planned_target_file_size_; 5770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t maximum_target_file_size_; 5790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t maximum_target_window_size_; 5810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Contains the sum of the decoded sizes of all target windows seen so far, 5830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // including the expected total size of the current target window in progress 5840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // (even if some of the current target window has not yet been decoded.) 5850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t total_of_target_window_sizes_; 5860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Contains the byte position within decoded_target_ of the first data that 5880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // has not yet been output by AppendNewOutputText(). 5890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t decoded_target_output_position_; 5900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This value is used to ensure the correct order of calls to the interface 5920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // functions, i.e., a single call to StartDecoding(), followed by zero or 5930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // more calls to DecodeChunk(), followed by a single call to 5940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // FinishDecoding(). 5950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool start_decoding_was_called_; 5960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If this value is true then the VCD_TARGET flag can be specified to allow 5980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the source segment to be chosen from the previously-decoded target data. 5990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // (This is the default behavior.) If it is false, then specifying the 6000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // VCD_TARGET flag is considered an error, and the decoder does not need to 6010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // keep in memory any decoded target data prior to the current window. 6020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool allow_vcd_target_; 6030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Making these private avoids implicit copy constructor & assignment operator 6050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffStreamingDecoderImpl(const VCDiffStreamingDecoderImpl&); // NOLINT 6060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void operator=(const VCDiffStreamingDecoderImpl&); 6070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}; 6080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Methods for VCDiffStreamingDecoderImpl 6100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst size_t VCDiffStreamingDecoderImpl::kDefaultMaximumTargetFileSize; 6120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathconst size_t VCDiffStreamingDecoderImpl::kUnlimitedBytes; 6130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffStreamingDecoderImpl::VCDiffStreamingDecoderImpl() 6150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath : maximum_target_file_size_(kDefaultMaximumTargetFileSize), 6160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath maximum_target_window_size_(kDefaultMaximumTargetFileSize), 6170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath allow_vcd_target_(true) { 6180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_window_.Init(this); 6190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 6200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 6210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Reset() will delete the component objects without reallocating them. 6230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffStreamingDecoderImpl::~VCDiffStreamingDecoderImpl() { Reset(); } 6240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoderImpl::Reset() { 6260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath start_decoding_was_called_ = false; 6270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_ptr_ = NULL; 6280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_size_ = 0; 6290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vcdiff_version_code_ = '\0'; 6300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath planned_target_file_size_ = kUnlimitedBytes; 6310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath total_of_target_window_sizes_ = 0; 6320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addr_cache_.reset(); 6330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_.reset(); 6340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_decoder_.reset(); 6350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_window_.Reset(); 6360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_output_position_ = 0; 6370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 6380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoderImpl::StartDecoding(const char* dictionary_ptr, 6400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size) { 6410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (start_decoding_was_called_) { 6420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "StartDecoding() called twice without FinishDecoding()" 6430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 6440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return; 6450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unparsed_bytes_.clear(); 6470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.clear(); // delta_window_.Reset() depends on this 6480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 6490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_ptr_ = dictionary_ptr; 6500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_size_ = dictionary_size; 6510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath start_decoding_was_called_ = true; 6520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 6530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 6540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Reads the VCDiff delta file header section as described in RFC section 4.1: 6550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 6560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Header1 - byte = 0xD6 (ASCII 'V' | 0x80) 6570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Header2 - byte = 0xC3 (ASCII 'C' | 0x80) 6580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Header3 - byte = 0xC4 (ASCII 'D' | 0x80) 6590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Header4 - byte 6600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Hdr_Indicator - byte 6610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Secondary compressor ID] - byte 6620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Length of code table data] - integer 6630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Code table data] 6640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 6650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Initializes the code table and address cache objects. Returns RESULT_ERROR 6660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// if an error occurred, and RESULT_END_OF_DATA if the end of available data was 6670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// reached before the entire header could be read. (The latter may be an error 6680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// condition if there is no more data available.) Otherwise, returns 6690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// RESULT_SUCCESS, and removes the header bytes from the data string. 6700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 6710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// It's relatively inefficient to expect this function to parse any number of 6720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// input bytes available, down to 1 byte, but it is necessary in case the input 6730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// is not a properly formatted VCDIFF delta file. If the entire input consists 6740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// of two bytes "12", then we should recognize that it does not match the 6750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// initial VCDIFF magic number "VCD" and report an error, rather than waiting 6760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// indefinitely for more input that will never arrive. 6770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 6780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffStreamingDecoderImpl::ReadDeltaFileHeader( 6790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk* data) { 6800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FoundFileHeader()) { 6810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 6820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t data_size = data->UnparsedSize(); 6840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const DeltaFileHeader* header = 6850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reinterpret_cast<const DeltaFileHeader*>(data->UnparsedData()); 6860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool wrong_magic_number = false; 6870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (data_size) { 6880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Verify only the bytes that are available. 6890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 6900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Found header contents up to and including VCDIFF version 6910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath vcdiff_version_code_ = header->header4; 6920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((vcdiff_version_code_ != 0x00) && // Draft standard VCDIFF (RFC 3284) 6930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (vcdiff_version_code_ != 'S')) { // Enhancements for SDCH protocol 6940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Unrecognized VCDIFF format version" << VCD_ENDL; 6950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 6960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // fall through 6980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case 3: 6990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header->header3 != 0xC4) { // magic value 'D' | 0x80 7000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath wrong_magic_number = true; 7010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // fall through 7030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case 2: 7040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header->header2 != 0xC3) { // magic value 'C' | 0x80 7050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath wrong_magic_number = true; 7060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // fall through 7080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case 1: 7090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header->header1 != 0xD6) { // magic value 'V' | 0x80 7100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath wrong_magic_number = true; 7110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // fall through 7130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case 0: 7140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (wrong_magic_number) { 7150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Did not find VCDIFF header bytes; " 7160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "input is not a VCDIFF delta file" << VCD_ENDL; 7170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 7180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (data_size < sizeof(DeltaFileHeader)) return RESULT_END_OF_DATA; 7200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Secondary compressor not supported. 7220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header->hdr_indicator & VCD_DECOMPRESS) { 7230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Secondary compression is not supported" << VCD_ENDL; 7240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 7250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header->hdr_indicator & VCD_CODETABLE) { 7270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int bytes_parsed = InitCustomCodeTable( 7280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->UnparsedData() + sizeof(DeltaFileHeader), 7290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->End()); 7300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (bytes_parsed) { 7310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 7320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 7330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 7340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 7350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 7360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->Advance(sizeof(DeltaFileHeader) + bytes_parsed); 7370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 7390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addr_cache_.reset(new VCDiffAddressCache); 7400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // addr_cache_->Init() will be called 7410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // from VCDiffStreamingDecoderImpl::DecodeChunk() 7420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->Advance(sizeof(DeltaFileHeader)); 7430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 7450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 7460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 7470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathint VCDiffStreamingDecoderImpl::InitCustomCodeTable(const char* data_start, 7480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* data_end) { 7490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // A custom code table is being specified. Parse the variable-length 7500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // cache sizes and begin parsing the encoded custom code table. 7510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t near_cache_size = 0, same_cache_size = 0; 7520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffHeaderParser header_parser(data_start, data_end); 7530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!header_parser.ParseInt32("size of near cache", &near_cache_size)) { 7540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return header_parser.GetResult(); 7550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!header_parser.ParseInt32("size of same cache", &same_cache_size)) { 7570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return header_parser.GetResult(); 7580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_.reset(new struct VCDiffCodeTableData); 7600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath memset(custom_code_table_.get(), 0, sizeof(struct VCDiffCodeTableData)); 7610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_string_.clear(); 7620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addr_cache_.reset(new VCDiffAddressCache(near_cache_size, same_cache_size)); 7630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // addr_cache_->Init() will be called 7640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // from VCDiffStreamingDecoderImpl::DecodeChunk() 7650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 7660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If we reach this point (the start of the custom code table) 7670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // without encountering a RESULT_END_OF_DATA condition, then we won't call 7680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // ReadDeltaFileHeader() again for this delta file. 7690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 7700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Instantiate a recursive decoder to interpret the custom code table 7710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // as a VCDIFF encoding of the default code table. 7720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_decoder_.reset(new VCDiffStreamingDecoderImpl); 7730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_decoder_->StartDecoding( 7740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reinterpret_cast<const char*>( 7750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &VCDiffCodeTableData::kDefaultCodeTableData), 7760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath sizeof(VCDiffCodeTableData::kDefaultCodeTableData)); 7770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_decoder_->SetPlannedTargetFileSize( 7780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath sizeof(*custom_code_table_)); 7790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return static_cast<int>(header_parser.ParsedSize()); 7800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 7810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 7820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffStreamingDecoderImpl::ReadCustomCodeTable( 7830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk* data) { 7840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!custom_code_table_decoder_.get()) { 7850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 7860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!custom_code_table_.get()) { 7880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: custom_code_table_decoder_ is set," 7890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " but custom_code_table_ is NULL" << VCD_ENDL; 7900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 7910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputString<string> output_string(&custom_code_table_string_); 7930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!custom_code_table_decoder_->DecodeChunk(data->UnparsedData(), 7940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->UnparsedSize(), 7950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &output_string)) { 7960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 7970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 7980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (custom_code_table_string_.length() < sizeof(*custom_code_table_)) { 7990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Skip over the consumed data. 8000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->Finish(); 8010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 8020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!custom_code_table_decoder_->FinishDecoding()) { 8040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 8050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (custom_code_table_string_.length() != sizeof(*custom_code_table_)) { 8070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Decoded custom code table size (" 8080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << custom_code_table_string_.length() 8090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") does not match size of a code table (" 8100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << sizeof(*custom_code_table_) << ")" << VCD_ENDL; 8110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 8120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath memcpy(custom_code_table_.get(), 8140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_string_.data(), 8150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath sizeof(*custom_code_table_)); 8160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_string_.clear(); 8170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Skip over the consumed data. 8180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data->FinishExcept(custom_code_table_decoder_->GetUnconsumedDataSize()); 8190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath custom_code_table_decoder_.reset(); 8200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_window_.UseCodeTable(*custom_code_table_, addr_cache_->LastMode()); 8210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 8220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 8230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 8240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoderImpl::FlushDecodedTarget( 8250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* output_string) { 8260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_string->append( 8270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.data() + decoded_target_output_position_, 8280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.size() - decoded_target_output_position_); 8290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.clear(); 8300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath delta_window_.set_target_window_start_pos(0); 8310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_output_position_ = 0; 8320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 8330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 8340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoderImpl::AppendNewOutputText( 8350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* output_string) { 8360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t bytes_decoded_this_chunk = 8370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.size() - decoded_target_output_position_; 8380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (bytes_decoded_this_chunk > 0) { 8390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t target_bytes_remaining = delta_window_.TargetBytesRemaining(); 8400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (target_bytes_remaining > 0) { 8410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The decoder is midway through decoding a target window. Resize 8420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // output_string to match the expected length. The interface guarantees 8430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // not to resize output_string more than once per target window decoded. 8440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_string->ReserveAdditionalBytes(bytes_decoded_this_chunk 8450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath + target_bytes_remaining); 8460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_string->append( 8480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_.data() + decoded_target_output_position_, 8490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bytes_decoded_this_chunk); 8500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target_output_position_ = decoded_target_.size(); 8510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 8530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 8540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoderImpl::DecodeChunk( 8550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* data, 8560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t len, 8570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* output_string) { 8580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!start_decoding_was_called_) { 8590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "DecodeChunk() called without StartDecoding()" << VCD_ENDL; 8600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 8610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 8620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk parseable_chunk(data, len); 8640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!unparsed_bytes_.empty()) { 8650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unparsed_bytes_.append(data, len); 8660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk.SetDataBuffer(unparsed_bytes_.data(), 8670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unparsed_bytes_.size()); 8680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult result = ReadDeltaFileHeader(&parseable_chunk); 8700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS == result) { 8710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath result = ReadCustomCodeTable(&parseable_chunk); 8720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS == result) { 8740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while (!parseable_chunk.Empty()) { 8750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath result = delta_window_.DecodeWindow(&parseable_chunk); 8760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != result) { 8770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 8780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (ReachedPlannedTargetFileSize()) { 8800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Found exactly the length we expected. Stop decoding. 8810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 8820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!allow_vcd_target()) { 8840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // VCD_TARGET will never be used to reference target data before the 8850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // start of the current window, so flush and clear the contents of 8860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoded_target_. 8870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FlushDecodedTarget(output_string); 8880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_ERROR == result) { 8920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); // Don't allow further DecodeChunk calls 8930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 8940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 8950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unparsed_bytes_.assign(parseable_chunk.UnparsedData(), 8960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk.UnparsedSize()); 8970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath AppendNewOutputText(output_string); 8980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 8990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 9000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Finishes decoding after all data has been received. Returns true 9020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// if decoding of the entire stream was successful. 9030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoderImpl::FinishDecoding() { 9040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool success = true; 9050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!start_decoding_was_called_) { 9060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_WARNING << "FinishDecoding() called before StartDecoding()," 9070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " or called after DecodeChunk() returned false" 9080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 9090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath success = false; 9100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (!IsDecodingComplete()) { 9110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "FinishDecoding() called before parsing entire" 9120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " delta file window" << VCD_ENDL; 9130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath success = false; 9140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reset the object state for the next decode operation 9160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 9170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return success; 9180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 9190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoderImpl::TargetWindowWouldExceedSizeLimits( 9210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t window_size) const { 9220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (window_size > maximum_target_window_size_) { 9230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Length of target window (" << window_size 9240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ") exceeds limit of " << maximum_target_window_size_ 9250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes" << VCD_ENDL; 9260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 9270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (HasPlannedTargetFileSize()) { 9290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The logical expression to check would be: 9300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 9310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // total_of_target_window_sizes_ + window_size > planned_target_file_size_ 9320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // 9330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // but the addition might cause an integer overflow if target_bytes_to_add 9340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // is very large. So it is better to check target_bytes_to_add against 9350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the remaining planned target bytes. 9360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t remaining_planned_target_file_size = 9370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath planned_target_file_size_ - total_of_target_window_sizes_; 9380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (window_size > remaining_planned_target_file_size) { 9390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Length of target window (" << window_size 9400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes) plus previous windows (" 9410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << total_of_target_window_sizes_ 9420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes) would exceed planned size of " 9430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << planned_target_file_size_ << " bytes" << VCD_ENDL; 9440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 9450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t remaining_maximum_target_bytes = 9480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath maximum_target_file_size_ - total_of_target_window_sizes_; 9490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (window_size > remaining_maximum_target_bytes) { 9500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Length of target window (" << window_size 9510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes) plus previous windows (" 9520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << total_of_target_window_sizes_ 9530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes) would exceed maximum target file size of " 9540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << maximum_target_file_size_ << " bytes" << VCD_ENDL; 9550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 9560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 9580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 9590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Methods for VCDiffDeltaFileWindow 9610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffDeltaFileWindow::Reset() { 9630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath found_header_ = false; 9640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Mark the start of the current target window. 9660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_window_start_pos_ = parent_ ? parent_->decoded_target()->size() : 0U; 9670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_window_length_ = 0; 9680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_ptr_ = NULL; 9700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_length_ = 0; 9710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.Invalidate(); 9730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data_for_add_and_run_.Invalidate(); 9740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_for_copy_.Invalidate(); 9750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath interleaved_bytes_expected_ = 0; 9770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath has_checksum_ = false; 9790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath expected_checksum_ = 0; 9800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 9810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 9820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::SetUpWindowSections( 9830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffHeaderParser* header_parser) { 9840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t add_and_run_data_length = 0; 9850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t instructions_and_sizes_length = 0; 9860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t addresses_length = 0; 9870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!header_parser->ParseSectionLengths(has_checksum_, 9880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &add_and_run_data_length, 9890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &instructions_and_sizes_length, 9900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &addresses_length, 9910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &expected_checksum_)) { 9920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return header_parser->GetResult(); 9930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 9940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (parent_->AllowInterleaved() && 9950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (add_and_run_data_length == 0) && 9960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (addresses_length == 0)) { 9970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The interleaved format is being used. 9980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath interleaved_bytes_expected_ = 9990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<int>(instructions_and_sizes_length); 10000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UpdateInterleavedSectionPointers(header_parser->UnparsedData(), 10010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath header_parser->End()); 10020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 10030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If interleaved format is not used, then the whole window contents 10040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // must be available before decoding can begin. If only part of 10050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the current window is available, then report end of data 10060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and re-parse the whole header when DecodeChunk() is called again. 10070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (header_parser->UnparsedSize() < (add_and_run_data_length + 10080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_length + 10090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_length)) { 10100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 10110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data_for_add_and_run_.Init(header_parser->UnparsedData(), 10130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath add_and_run_data_length); 10140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.Init(data_for_add_and_run_.End(), 10150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_length); 10160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_for_copy_.Init(instructions_and_sizes_.End(), addresses_length); 10170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (addresses_for_copy_.End() != header_parser->EndOfDeltaWindow()) { 10180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "The end of the instructions section " 10190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "does not match the end of the delta window" << VCD_ENDL; 10200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 10210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reader_.Init(instructions_and_sizes_.UnparsedDataAddr(), 10240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.End()); 10250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 10260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 10270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 10280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Here are the elements of the delta window header to be parsed, 10290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// from section 4 of the RFC: 10300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 10310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Window1 10320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Win_Indicator - byte 10330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Source segment size] - integer 10340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// [Source segment position] - integer 10350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The delta encoding of the target window 10360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of the delta encoding - integer 10370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// The delta encoding 10380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Size of the target window - integer 10390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Delta_Indicator - byte 10400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of data for ADDs and RUNs - integer 10410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of instructions and sizes - integer 10420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Length of addresses for COPYs - integer 10430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Data section for ADDs and RUNs - array of bytes 10440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Instructions and sizes section - array of bytes 10450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Addresses section for COPYs - array of bytes 10460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// 10470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::ReadHeader( 10480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk* parseable_chunk) { 10490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::string* decoded_target = parent_->decoded_target(); 10500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffHeaderParser header_parser(parseable_chunk->UnparsedData(), 10510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk->End()); 10520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t source_segment_position = 0; 10530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char win_indicator = 0; 10540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!header_parser.ParseWinIndicatorAndSourceSegment( 10550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->dictionary_size(), 10560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target->size(), 10570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->allow_vcd_target(), 10580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &win_indicator, 10590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &source_segment_length_, 10600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &source_segment_position)) { 10610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return header_parser.GetResult(); 10620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath has_checksum_ = parent_->AllowChecksum() && (win_indicator & VCD_CHECKSUM); 10640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!header_parser.ParseWindowLengths(&target_window_length_)) { 10650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return header_parser.GetResult(); 10660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (parent_->TargetWindowWouldExceedSizeLimits(target_window_length_)) { 10680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // An error has been logged by TargetWindowWouldExceedSizeLimits(). 10690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 10700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath header_parser.ParseDeltaIndicator(); 10720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult setup_return_code = SetUpWindowSections(&header_parser); 10730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (RESULT_SUCCESS != setup_return_code) { 10740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return setup_return_code; 10750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reserve enough space in the output string for the current target window. 10770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t wanted_capacity = 10780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_window_start_pos_ + target_window_length_; 10790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (decoded_target->capacity() < wanted_capacity) { 10800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoded_target->reserve(wanted_capacity); 10810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Get a pointer to the start of the source segment. 10830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (win_indicator & VCD_SOURCE) { 10840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_ptr_ = parent_->dictionary_ptr() + source_segment_position; 10850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if (win_indicator & VCD_TARGET) { 10860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // This assignment must happen after the reserve(). 10870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // decoded_target should not be resized again while processing this window, 10880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // so source_segment_ptr_ should remain valid. 10890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath source_segment_ptr_ = decoded_target->data() + source_segment_position; 10900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 10910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The whole window header was found and parsed successfully. 10920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath found_header_ = true; 10930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk->Advance(header_parser.ParsedSize()); 10940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->AddToTotalTargetWindowSize(target_window_length_); 10950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 10960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 10970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 10980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffDeltaFileWindow::UpdateInstructionPointer( 10990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk* parseable_chunk) { 11000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (IsInterleaved()) { 11010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t bytes_parsed = instructions_and_sizes_.ParsedSize(); 11020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reduce expected instruction segment length by bytes parsed 11030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath interleaved_bytes_expected_ -= static_cast<int>(bytes_parsed); 11040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk->Advance(bytes_parsed); 11050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline size_t VCDiffDeltaFileWindow::TargetBytesDecoded() { 11090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return parent_->decoded_target()->size() - target_window_start_pos_; 11100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathsize_t VCDiffDeltaFileWindow::TargetBytesRemaining() { 11130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (target_window_length_ == 0) { 11140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // There is no window being decoded at present 11150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 0; 11160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 11170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return target_window_length_ - TargetBytesDecoded(); 11180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline void VCDiffDeltaFileWindow::CopyBytes(const char* data, size_t size) { 11220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->decoded_target()->append(data, size); 11230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline void VCDiffDeltaFileWindow::RunByte(unsigned char byte, size_t size) { 11260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->decoded_target()->append(size, byte); 11270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::DecodeAdd(size_t size) { 11300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (size > data_for_add_and_run_.UnparsedSize()) { 11310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 11320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Write the next "size" data bytes 11340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath CopyBytes(data_for_add_and_run_.UnparsedData(), size); 11350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data_for_add_and_run_.Advance(size); 11360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 11370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::DecodeRun(size_t size) { 11400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (data_for_add_and_run_.Empty()) { 11410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 11420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Write "size" copies of the next data byte 11440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath RunByte(*data_for_add_and_run_.UnparsedData(), size); 11450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath data_for_add_and_run_.Advance(1); 11460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 11470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 11480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 11490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::DecodeCopy(size_t size, 11500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char mode) { 11510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Keep track of the number of target bytes decoded as a local variable 11520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to avoid recalculating it each time it is needed. 11530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t target_bytes_decoded = TargetBytesDecoded(); 11540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const VCDAddress here_address = 11550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<VCDAddress>(source_segment_length_ + target_bytes_decoded); 11560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const VCDAddress decoded_address = parent_->addr_cache()->DecodeAddress( 11570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath here_address, 11580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath mode, 11590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_for_copy_.UnparsedDataAddr(), 11600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath addresses_for_copy_.End()); 11610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (decoded_address) { 11620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 11630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Unable to decode address for COPY" << VCD_ENDL; 11640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 11650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 11660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 11670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 11680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((decoded_address < 0) || (decoded_address > here_address)) { 11690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: unexpected address " << decoded_address 11700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " returned from DecodeAddress, with here_address = " 11710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << here_address << VCD_ENDL; 11720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 11730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 11750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t address = static_cast<size_t>(decoded_address); 11770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((address + size) <= source_segment_length_) { 11780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Copy all data from source segment 11790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath CopyBytes(&source_segment_ptr_[address], size); 11800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 11810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Copy some data from target window... 11830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (address < source_segment_length_) { 11840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // ... plus some data from source segment 11850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t partial_copy_size = source_segment_length_ - address; 11860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath CopyBytes(&source_segment_ptr_[address], partial_copy_size); 11870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_bytes_decoded += partial_copy_size; 11880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath address += partial_copy_size; 11890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size -= partial_copy_size; 11900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 11910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath address -= source_segment_length_; 11920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // address is now based at start of target window 11930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* const target_segment_ptr = parent_->decoded_target()->data() + 11940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_window_start_pos_; 11950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while (size > (target_bytes_decoded - address)) { 11960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Recursive copy that extends into the yet-to-be-copied target data 11970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t partial_copy_size = target_bytes_decoded - address; 11980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath CopyBytes(&target_segment_ptr[address], partial_copy_size); 11990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target_bytes_decoded += partial_copy_size; 12000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath address += partial_copy_size; 12010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size -= partial_copy_size; 12020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath CopyBytes(&target_segment_ptr[address], size); 12040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 12050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 12060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 12070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathint VCDiffDeltaFileWindow::DecodeBody(ParseableChunk* parseable_chunk) { 12080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (IsInterleaved() && (instructions_and_sizes_.UnparsedData() 12090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath != parseable_chunk->UnparsedData())) { 12100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: interleaved format is used, but the" 12110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " input pointer does not point to the instructions section" 12120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 12130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath while (TargetBytesDecoded() < target_window_length_) { 12160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath int32_t decoded_size = VCD_INSTRUCTION_ERROR; 12170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath unsigned char mode = 0; 12180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffInstructionType instruction = 12190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reader_.GetNextInstruction(&decoded_size, &mode); 12200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (instruction) { 12210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_INSTRUCTION_END_OF_DATA: 12220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UpdateInstructionPointer(parseable_chunk); 12230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 12240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_INSTRUCTION_ERROR: 12250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 12270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 12280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const size_t size = static_cast<size_t>(decoded_size); 12300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The value of "size" itself could be enormous (say, INT32_MAX) 12310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // so check it individually against the limit to protect against 12320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // overflow when adding it to something else. 12330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((size > target_window_length_) || 12340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ((size + TargetBytesDecoded()) > target_window_length_)) { 12350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << VCDiffInstructionName(instruction) 12360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " with size " << size 12370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " plus existing " << TargetBytesDecoded() 12380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes of target data exceeds length of target" 12390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " window (" << target_window_length_ << " bytes)" 12400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 12410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffResult result = RESULT_SUCCESS; 12440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (instruction) { 12450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_ADD: 12460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath result = DecodeAdd(size); 12470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 12480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_RUN: 12490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath result = DecodeRun(size); 12500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 12510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case VCD_COPY: 12520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath result = DecodeCopy(size, mode); 12530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 12540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 12550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Unexpected instruction type " << instruction 12560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "in opcode stream" << VCD_ENDL; 12570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (result) { 12600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 12610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reader_.UnGetInstruction(); 12620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UpdateInstructionPointer(parseable_chunk); 12630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 12640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 12650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_SUCCESS: 12670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; 12680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (TargetBytesDecoded() != target_window_length_) { 12710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Decoded target window size (" << TargetBytesDecoded() 12720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " bytes) does not match expected size (" 12730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << target_window_length_ << " bytes)" << VCD_ENDL; 12740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* const target_window_start = 12770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parent_->decoded_target()->data() + target_window_start_pos_; 12780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (has_checksum_ && 12790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (ComputeAdler32(target_window_start, target_window_length_) 12800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath != expected_checksum_)) { 12810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Target data does not match checksum; this could mean " 12820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "that the wrong dictionary was used" << VCD_ENDL; 12830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!instructions_and_sizes_.Empty()) { 12860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Excess instructions and sizes left over " 12870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "after decoding target window" << VCD_ENDL; 12880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!IsInterleaved()) { 12910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Standard format is being used, with three separate sections for the 12920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // instructions, data, and addresses. 12930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!data_for_add_and_run_.Empty()) { 12940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Excess ADD/RUN data left over " 12950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "after decoding target window" << VCD_ENDL; 12960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 12970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 12980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!addresses_for_copy_.Empty()) { 12990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "Excess COPY addresses left over " 13000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "after decoding target window" << VCD_ENDL; 13010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reached the end of the window. Update the ParseableChunk to point to the 13040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // end of the addresses section, which is the last section in the window. 13050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk->SetPosition(addresses_for_copy_.End()); 13060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 13070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Interleaved format is being used. 13080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UpdateInstructionPointer(parseable_chunk); 13090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 13110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffResult VCDiffDeltaFileWindow::DecodeWindow( 13140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ParseableChunk* parseable_chunk) { 13150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!parent_) { 13160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: VCDiffDeltaFileWindow::DecodeWindow() " 13170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "called before VCDiffDeltaFileWindow::Init()" << VCD_ENDL; 13180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!found_header_) { 13210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (ReadHeader(parseable_chunk)) { 13220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 13230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 13240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 13250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 13270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reset address cache between windows (RFC section 5.1) 13280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!parent_->addr_cache()->Init()) { 13290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Error initializing address cache" << VCD_ENDL; 13300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 13340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // We are resuming a window that was partially decoded before a 13350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // RESULT_END_OF_DATA was returned. This can only happen on the first 13360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // loop iteration, and only if the interleaved format is enabled and used. 13370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!IsInterleaved()) { 13380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_DFATAL << "Internal error: Resumed decoding of a delta file window" 13390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " when interleaved format is not being used" << VCD_ENDL; 13400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath UpdateInterleavedSectionPointers(parseable_chunk->UnparsedData(), 13430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath parseable_chunk->End()); 13440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath reader_.UpdatePointers(instructions_and_sizes_.UnparsedDataAddr(), 13450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath instructions_and_sizes_.End()); 13460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath switch (DecodeBody(parseable_chunk)) { 13480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_END_OF_DATA: 13490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (MoreDataExpected()) { 13500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_END_OF_DATA; 13510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 13520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCD_ERROR << "End of data reached while decoding VCDIFF delta file" 13530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << VCD_ENDL; 13540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // fall through to RESULT_ERROR case 13550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath case RESULT_ERROR: 13570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_ERROR; 13580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath default: 13590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath break; // DecodeBody succeeded 13600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 13610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Get ready to read a new delta window 13620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath Reset(); 13630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return RESULT_SUCCESS; 13640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// *** Methods for VCDiffStreamingDecoder 13670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffStreamingDecoder::VCDiffStreamingDecoder() 13690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath: impl_(new VCDiffStreamingDecoderImpl) { } 13700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffStreamingDecoder::~VCDiffStreamingDecoder() { delete impl_; } 13720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoder::StartDecoding(const char* source, size_t len) { 13740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath impl_->StartDecoding(source, len); 13750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoder::DecodeChunkToInterface( 13780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* data, 13790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t len, 13800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* output_string) { 13810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return impl_->DecodeChunk(data, len, output_string); 13820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoder::FinishDecoding() { 13850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return impl_->FinishDecoding(); 13860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoder::SetMaximumTargetFileSize( 13890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t new_maximum_target_file_size) { 13900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return impl_->SetMaximumTargetFileSize(new_maximum_target_file_size); 13910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffStreamingDecoder::SetMaximumTargetWindowSize( 13940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t new_maximum_target_window_size) { 13950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return impl_->SetMaximumTargetWindowSize(new_maximum_target_window_size); 13960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 13970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 13980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathvoid VCDiffStreamingDecoder::SetAllowVcdTarget(bool allow_vcd_target) { 13990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath impl_->SetAllowVcdTarget(allow_vcd_target); 14000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 14010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 14020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffDecoder::DecodeToInterface(const char* dictionary_ptr, 14030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size, 14040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const string& encoding, 14050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath OutputStringInterface* target) { 14060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target->clear(); 14070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder_.StartDecoding(dictionary_ptr, dictionary_size); 14080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!decoder_.DecodeChunkToInterface(encoding.data(), 14090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath encoding.size(), 14100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath target)) { 14110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 14120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 14130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return decoder_.FinishDecoding(); 14140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 14150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 14160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} // namespace open_vcdiff 1417