1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright 2007 Google Inc.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Author: Lincoln Smith
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Licensed under the Apache License, Version 2.0 (the "License");
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// you may not use this file except in compliance with the License.
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// You may obtain a copy of the License at
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//      http://www.apache.org/licenses/LICENSE-2.0
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unless required by applicable law or agreed to in writing, software
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// distributed under the License is distributed on an "AS IS" BASIS,
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See the License for the specific language governing permissions and
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// limitations under the License.
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Classes to implement an Encoder for the format described in
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// RFC 3284 - The VCDIFF Generic Differencing and Compression Data Format.
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The RFC text can be found at http://www.faqs.org/rfcs/rfc3284.html
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott//
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The RFC describes the possibility of using a secondary compressor
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to further reduce the size of each section of the VCDIFF output.
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// That feature is not supported in this implementation of the encoder
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and decoder.
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// No secondary compressor types have been publicly registered with
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the IANA at http://www.iana.org/assignments/vcdiff-comp-ids
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// in the more than five years since the registry was created, so there
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is no standard set of compressor IDs which would be generated by other
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// encoders or accepted by other decoders.
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <config.h>
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "google/vcencoder.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "checksum.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "encodetable.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "logging.h"
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "google/output_string.h"
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "vcdiffengine.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace open_vcdiff {
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHashedDictionary::HashedDictionary(const char* dictionary_contents,
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                   size_t dictionary_size)
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : engine_(new VCDiffEngine(dictionary_contents, dictionary_size)) { }
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottHashedDictionary::~HashedDictionary() { delete engine_; }
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool HashedDictionary::Init() {
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return const_cast<VCDiffEngine*>(engine_)->Init();
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass VCDiffStreamingEncoderImpl {
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffStreamingEncoderImpl(const HashedDictionary* dictionary,
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             VCDiffFormatExtensionFlags format_extensions,
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             bool look_for_target_matches);
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These functions are identical to their counterparts
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // in VCDiffStreamingEncoder.
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool StartEncoding(OutputStringInterface* out);
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool EncodeChunk(const char* data, size_t len, OutputStringInterface* out);
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool FinishEncoding(OutputStringInterface* out);
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::vector<int>& match_counts() const {
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return coder_.match_counts();
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Write the header (as defined in section 4.1 of the RFC) to *output.
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This includes information that can be gathered
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // before the first chunk of input is available.
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void WriteHeader(OutputStringInterface* output) const;
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const VCDiffEngine* engine_;
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This implementation of the encoder uses the default
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // code table.  A VCDiffCodeTableWriter could also be constructed
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // using a custom code table.
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffCodeTableWriter coder_;
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const VCDiffFormatExtensionFlags format_extensions_;
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Determines whether to look for matches within the previously encoded
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // target data, or just within the source (dictionary) data.  Please see
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // vcencoder.h for a full explanation of this parameter.
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const bool look_for_target_matches_;
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This state variable is used to ensure that StartEncoding(), EncodeChunk(),
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // and FinishEncoding() are called in the correct order.  It will be true
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // if StartEncoding() has been called, followed by zero or more calls to
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // EncodeChunk(), but FinishEncoding() has not yet been called.  It will
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be false initially, and also after FinishEncoding() has been called.
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool encode_chunk_allowed_;
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Making these private avoids implicit copy constructor & assignment operator
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  VCDiffStreamingEncoderImpl(const VCDiffStreamingEncoderImpl&);  // NOLINT
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void operator=(const VCDiffStreamingEncoderImpl&);
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline VCDiffStreamingEncoderImpl::VCDiffStreamingEncoderImpl(
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const HashedDictionary* dictionary,
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffFormatExtensionFlags format_extensions,
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool look_for_target_matches)
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : engine_(dictionary->engine()),
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      coder_((format_extensions & VCD_FORMAT_INTERLEAVED) != 0),
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      format_extensions_(format_extensions),
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      look_for_target_matches_(look_for_target_matches),
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      encode_chunk_allowed_(false) { }
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline void VCDiffStreamingEncoderImpl::WriteHeader(
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* output) const {
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DeltaFileHeader header_data = {
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xD6,  // Header1: "V" | 0x80
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC3,  // Header2: "C" | 0x80
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0xC4,  // Header3: "D" | 0x80
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00,  // Header4: Draft standard format
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    0x00 };  // Hdr_Indicator:
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott             // No compression, no custom code table
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (format_extensions_ != VCD_STANDARD_FORMAT) {
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    header_data.header4 = 'S';  // Header4: VCDIFF/SDCH, extensions used
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  output->append(reinterpret_cast<const char*>(&header_data),
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                 sizeof(header_data));
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If custom cache table sizes or a custom code table were used
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // for encoding, here is where they would be appended to *output.
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // This implementation of the encoder does not use those features,
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // although the decoder can understand and interpret them.
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool VCDiffStreamingEncoderImpl::StartEncoding(
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* out) {
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!coder_.Init(engine_->dictionary_size())) {
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(DFATAL) << "Internal error: "
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                   "Initialization of code table writer failed" << LOG_ENDL;
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  WriteHeader(out);
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  encode_chunk_allowed_ = true;
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool VCDiffStreamingEncoderImpl::EncodeChunk(
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const char* data,
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t len,
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* out) {
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!encode_chunk_allowed_) {
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "EncodeChunk called before StartEncoding" << LOG_ENDL;
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if ((format_extensions_ & VCD_FORMAT_CHECKSUM) != 0) {
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    coder_.AddChecksum(ComputeAdler32(data, len));
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  engine_->Encode(data, len, look_for_target_matches_, out, &coder_);
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottinline bool VCDiffStreamingEncoderImpl::FinishEncoding(
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* /*out*/) {
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!encode_chunk_allowed_) {
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(ERROR) << "FinishEncoding called before StartEncoding" << LOG_ENDL;
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  encode_chunk_allowed_ = false;
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // There should not be any need to output more data
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // since EncodeChunk() encodes a complete target window
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // and there is no end-of-delta-file marker.
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffStreamingEncoder::VCDiffStreamingEncoder(
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const HashedDictionary* dictionary,
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    VCDiffFormatExtensionFlags format_extensions,
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    bool look_for_target_matches)
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : impl_(new VCDiffStreamingEncoderImpl(dictionary,
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           format_extensions,
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                           look_for_target_matches)) { }
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottVCDiffStreamingEncoder::~VCDiffStreamingEncoder() { delete impl_; }
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool VCDiffStreamingEncoder::StartEncodingToInterface(
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* out) {
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return impl_->StartEncoding(out);
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool VCDiffStreamingEncoder::EncodeChunkToInterface(
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const char* data,
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    size_t len,
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* out) {
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return impl_->EncodeChunk(data, len, out);
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool VCDiffStreamingEncoder::FinishEncodingToInterface(
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    OutputStringInterface* out) {
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return impl_->FinishEncoding(out);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid VCDiffStreamingEncoder::GetMatchCounts(
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::vector<int>* match_counts) const {
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!match_counts) {
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    LOG(DFATAL) << "GetMatchCounts() called with NULL argument" << LOG_ENDL;
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *match_counts = impl_->match_counts();
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool VCDiffEncoder::EncodeToInterface(const char* target_data,
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      size_t target_len,
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                      OutputStringInterface* out) {
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  out->clear();
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!encoder_) {
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!dictionary_.Init()) {
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      LOG(ERROR) << "Error initializing HashedDictionary" << LOG_ENDL;
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return false;
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    encoder_ = new VCDiffStreamingEncoder(&dictionary_,
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          flags_,
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          look_for_target_matches_);
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!encoder_->StartEncodingToInterface(out)) {
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!encoder_->EncodeChunkToInterface(target_data, target_len, out)) {
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return encoder_->FinishEncodingToInterface(out);
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}  // namespace open_vcdiff
230