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