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