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// A command-line interface to the open-vcdiff library. 170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <config.h> 190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <assert.h> 200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <errno.h> 210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef WIN32 220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <fcntl.h> 230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <io.h> 240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif // WIN32 250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <stdio.h> 260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string.h> // strerror 270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <iostream> 280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <memory> 290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <string> 300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include <vector> 310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "gflags/gflags.h" 320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "google/vcdecoder.h" 330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#include "google/vcencoder.h" 340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifndef HAS_GLOBAL_STRING 360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing std::string; 370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif // !HAS_GLOBAL_STRING 380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing google::GetCommandLineFlagInfoOrDie; 390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathusing google::ShowUsageWithFlagsRestrict; 400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const size_t kDefaultMaxTargetSize = 1 << 26; // 64 MB 420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Definitions of command-line flags 440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(dictionary, "", 450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "File containing dictionary data (required)"); 460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(target, "", 470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Target file (default is stdin for encode, stdout for decode"); 480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_string(delta, "", 490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Encoded delta file (default is stdout for encode, " 500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "stdin for decode"); 510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// --buffersize is the maximum allowable size of a target window. 520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// This value may be increased if there is sufficient memory available. 530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_uint64(buffersize, 1 << 20, // 1 MB 540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Buffer size for reading input file"); 550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(allow_vcd_target, true, 560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "If false, the decoder issues an error when the VCD_TARGET flag " 570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "is encountered"); 580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(checksum, false, 590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Include an Adler32 checksum of the target data when encoding"); 600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(interleaved, false, "Use interleaved format"); 610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(json, false, "Output diff in the JSON format when encoding"); 620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(stats, false, "Report compression percentage"); 630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_bool(target_matches, false, "Find duplicate strings in target data" 640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " as well as dictionary data"); 650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_uint64(max_target_file_size, kDefaultMaxTargetSize, 660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Maximum target file size allowed by decoder"); 670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathDEFINE_uint64(max_target_window_size, kDefaultMaxTargetSize, 680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "Maximum target window size allowed by decoder"); 690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathstatic const char* const kUsageString = 710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " {encode | delta | decode | patch }[ <options> ]\n" 720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "encode or delta: create delta file from dictionary and target file\n" 730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath "decode or patch: reconstruct target file from dictionary and delta file"; 740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathnamespace open_vcdiff { 760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathclass VCDiffFileBasedCoder { 780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath public: 790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffFileBasedCoder(); 800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ~VCDiffFileBasedCoder(); 810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Once the command-line arguments have been parsed, these functions 830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will use the supplied options to carry out a file-based encode 840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // or decode operation. 850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool Encode(); 860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool Decode(); 870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool DecodeAndCompare(); // for "vcdiff test"; compare target with original 880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath private: 900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Determines the size of the file. The given file must be an input file 910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // opened for reading only, not an input stream such as stdin. The function 920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // returns true and populates file_size if successful; otherwise, it returns 930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // false. 940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static bool FileSize(FILE* file, size_t* file_size); 950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Opens a file for incremental reading. file_name is the name of the file 970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to be opened. file_type should be a descriptive name (like "target") for 980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // use in log messages. If successful, returns true and sets *file to a 990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // valid input file, *buffer to a region of memory allocated using malloc() 1000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // (so the caller must release it using free()), and buffer_size to the size 1010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // of the buffer, which will not be larger than the size of the file, and 1020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // will not be smaller than the --buffersize option. If the function fails, 1030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // it outputs a log message and returns false. 1040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool OpenFileForReading(const string& file_name, 1050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* file_type, 1060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FILE** file, 1070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::vector<char>* buffer); 1080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Opens the dictionary file and reads it into a newly allocated buffer. 1100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If successful, returns true and populates dictionary_ with the dictionary 1110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // contents; otherwise, returns false. 1120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool OpenDictionary(); 1130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Opens the input file (the delta or target file) for reading. 1150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Allocates space for the input buffer. If successful, 1160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // input_file_ will be valid and input_buffer_ will be allocated. 1170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool OpenInputFile() { 1180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return OpenFileForReading(input_file_name_, 1190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_type_, 1200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &input_file_, 1210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &input_buffer_); 1220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Opens the output file (the target or delta file) for writing. 1250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If successful, output_file_ will be valid. 1260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool OpenOutputFile(); 1270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Opens the output file (the target file) for comparison against the decoded 1290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // output when using "vcdiff test". 1300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool OpenOutputFileForCompare() { 1310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return OpenFileForReading(output_file_name_, 1320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_type_, 1330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &output_file_, 1340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath &compare_buffer_); 1350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 1360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reads as much input data as possible from the input file 1380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // into input_buffer_. If successful, returns true and sets *bytes_read 1390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to the number of bytes read into input_buffer_. If an error occurs, 1400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // writes an error log message and returns false. 1410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool ReadInput(size_t* bytes_read); 1420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Writes the contents of output to output_file_. If successful, returns 1440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // true. If an error occurs, writes an error log message and returns false. 1450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool WriteOutput(const string& output); 1460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Reads a number of bytes from output_file_ equal to the size of output, 1480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and compares to make sure they match the contents of output. If the bytes 1490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // do not match, or if end of file is reached before the expected number of 1500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // bytes have been read, or a read error occurs, the function returns false; 1510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // otherwise, returns true. 1520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath bool CompareOutput(const string& output); 1530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Dictionary contents. The entire dictionary file will be read into memory. 1550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::vector<char> dictionary_; 1560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::auto_ptr<open_vcdiff::HashedDictionary> hashed_dictionary_; 1580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // These should be set to either "delta" or "target". They are only 1600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // used in log messages such as "Error opening delta file..." 1610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* input_file_type_; 1620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* output_file_type_; 1630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The filenames used for input and output. Will be empty if stdin 1650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // or stdout is being used. 1660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string input_file_name_; 1670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string output_file_name_; 1680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // stdio-style file handles for the input and output files and the dictionary. 1700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // When encoding, input_file_ is the target file and output_file_ is the delta 1710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // file; when decoding, the reverse is true. The dictionary is always read 1720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // from a file rather than from standard input. 1730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FILE* input_file_; 1740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FILE* output_file_; 1750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // A memory buffer used to load the input file into memory. If the input 1770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // comes from stdin because no input file was specified, then the size of 1780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // input_buffer_ will be the value specified by the --buffersize option. 1790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // If the input comes from a file, then the buffer will be allocated to match 1800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the file size, if possible. However, the buffer will not exceed 1810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // --buffersize bytes in length. 1820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::vector<char> input_buffer_; 1830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // A memory buffer used to load the output file into memory for comparison 1850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if "vcdiff test" is specified. 1860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::vector<char> compare_buffer_; 1870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Making these private avoids implicit copy constructor & assignment operator 1890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffFileBasedCoder(const VCDiffFileBasedCoder&); // NOLINT 1900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath void operator=(const VCDiffFileBasedCoder&); 1910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath}; 1920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathinline VCDiffFileBasedCoder::VCDiffFileBasedCoder() 1940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath : input_file_type_(""), 1950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_type_(""), 1960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_(NULL), 1970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_(NULL) { } 1980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan KamathVCDiffFileBasedCoder::~VCDiffFileBasedCoder() { 2000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (input_file_ && (input_file_ != stdin)) { 2010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fclose(input_file_); 2020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_ = NULL; 2030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (output_file_ && (output_file_ != stdout)) { 2050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fclose(output_file_); 2060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_ = NULL; 2070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::FileSize(FILE* file, size_t* file_size) { 2110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath long initial_position = ftell(file); 2120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (fseek(file, 0, SEEK_END) != 0) { 2130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *file_size = static_cast<size_t>(ftell(file)); 2160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (fseek(file, initial_position, SEEK_SET) != 0) { 2170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::OpenDictionary() { 2230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath assert(dictionary_.empty()); 2240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath assert(!FLAGS_dictionary.empty()); 2250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FILE* dictionary_file = fopen(FLAGS_dictionary.c_str(), "rb"); 2260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!dictionary_file) { 2270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error opening dictionary file '" << FLAGS_dictionary 2280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 2290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t dictionary_size = 0U; 2320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!FileSize(dictionary_file, &dictionary_size)) { 2330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error finding size of dictionary file '" << FLAGS_dictionary 2340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 2350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_.resize(dictionary_size); 2380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (dictionary_size > 0) { 2390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (fread(&dictionary_[0], 1, dictionary_size, dictionary_file) 2400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath != dictionary_size) { 2410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Unable to read dictionary file '" << FLAGS_dictionary 2420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 2430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fclose(dictionary_file); 2440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_.clear(); 2450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fclose(dictionary_file); 2490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::OpenFileForReading(const string& file_name, 2530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* file_type, 2540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FILE** file, 2550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::vector<char>* buffer) { 2560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath assert(buffer->empty()); 2570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t buffer_size = 0U; 2580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!*file && file_name.empty()) { 2590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef WIN32 2600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath _setmode(_fileno(stdin), _O_BINARY); 2610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif 2620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *file = stdin; 2630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath buffer_size = static_cast<size_t>(FLAGS_buffersize); 2640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 2650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!*file) { 2660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *file = fopen(file_name.c_str(), "rb"); 2670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!*file) { 2680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error opening " << file_type << " file '" 2690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << file_name << "': " << strerror(errno) << std::endl; 2700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t file_size = 0U; 2740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!FileSize(*file, &file_size)) { 2750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error finding size of " << file_type << " file '" 2760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << file_name << "': " << strerror(errno) << std::endl; 2770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 2780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath buffer_size = static_cast<size_t>(FLAGS_buffersize); 2800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (file_size < buffer_size) { 2810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Allocate just enough memory to store the entire file 2820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath buffer_size = file_size; 2830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 2850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath buffer->resize(buffer_size); 2860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 2870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 2880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 2890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// Opens the output file for streamed read operations using the 2900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// standard C I/O library, i.e., fopen(), fwrite(), fclose(). 2910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// No output buffer is allocated because the encoded/decoded output 2920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// is constructed progressively using a std::string object 2930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath// whose buffer is resized as needed. 2940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::OpenOutputFile() { 2950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (output_file_name_.empty()) { 2960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#ifdef WIN32 2970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath _setmode(_fileno(stdout), _O_BINARY); 2980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath#endif 2990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_ = stdout; 3000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 3010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_ = fopen(output_file_name_.c_str(), "wb"); 3020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!output_file_) { 3030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error opening " << output_file_type_ << " file '" 3040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << output_file_name_ 3050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 3060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::ReadInput(size_t* bytes_read) { 3130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Read from file or stdin 3140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath *bytes_read = fread(&input_buffer_[0], 1, input_buffer_.size(), input_file_); 3150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (ferror(input_file_)) { 3160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error reading from " << input_file_type_ << " file '" 3170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << input_file_name_ 3180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 3190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::WriteOutput(const string& output) { 3250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!output.empty()) { 3260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Some new output has been generated and is ready to be written 3270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // to the output file or to stdout. 3280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath fwrite(output.data(), 1, output.size(), output_file_); 3290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (ferror(output_file_)) { 3300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error writing " << output.size() << " bytes to " 3310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << output_file_type_ << " file '" << output_file_name_ 3320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "': " << strerror(errno) << std::endl; 3330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::CompareOutput(const string& output) { 3400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!output.empty()) { 3410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t output_size = output.size(); 3420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Some new output has been generated and is ready to be compared against 3430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // the output file. 3440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (output_size > compare_buffer_.size()) { 3450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath compare_buffer_.resize(output_size); 3460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t bytes_read = fread(&compare_buffer_[0], 3480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 1, 3490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size, 3500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_); 3510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (ferror(output_file_)) { 3520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error reading from " << output_file_type_ << " file '" 3530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << output_file_name_ << "': " << strerror(errno) << std::endl; 3540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (bytes_read < output_size) { 3570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decoded target is longer than original target file" 3580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 3590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (output.compare(0, output_size, &compare_buffer_[0], bytes_read) != 0) { 3620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Original target file does not match decoded target" 3630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 3640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 3680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 3690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 3700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::Encode() { 3710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_type_ = "target"; 3720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_name_ = FLAGS_target; 3730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_type_ = "delta"; 3740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_name_ = FLAGS_delta; 3750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!OpenDictionary() || !OpenInputFile() || !OpenOutputFile()) { 3760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Issue 6: Visual Studio STL produces a runtime exception 3790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if &dictionary_[0] is attempted for an empty dictionary. 3800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (dictionary_.empty()) { 3810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath hashed_dictionary_.reset(new open_vcdiff::HashedDictionary("", 0)); 3820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 3830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath hashed_dictionary_.reset( 3840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath new open_vcdiff::HashedDictionary(&dictionary_[0], 3850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath dictionary_.size())); 3860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!hashed_dictionary_->Init()) { 3880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error initializing hashed dictionary" << std::endl; 3890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 3900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath VCDiffFormatExtensionFlags format_flags = open_vcdiff::VCD_STANDARD_FORMAT; 3920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_interleaved) { 3930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath format_flags |= open_vcdiff::VCD_FORMAT_INTERLEAVED; 3940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_checksum) { 3960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath format_flags |= open_vcdiff::VCD_FORMAT_CHECKSUM; 3970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 3980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_json) { 3990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath format_flags |= open_vcdiff::VCD_FORMAT_JSON; 4000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffStreamingEncoder encoder(hashed_dictionary_.get(), 4020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath format_flags, 4030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath FLAGS_target_matches); 4040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string output; 4050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t input_size = 0; 4060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t output_size = 0; 4070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath { 4080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!encoder.StartEncoding(&output)) { 4090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error during encoder initialization" << std::endl; 4100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath do { 4140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t bytes_read = 0; 4150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!WriteOutput(output) || !ReadInput(&bytes_read)) { 4160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 4190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 4200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (bytes_read > 0) { 4210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_size += bytes_read; 4220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!encoder.EncodeChunk(&input_buffer_[0], bytes_read, &output)) { 4230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error trying to encode data chunk of length " 4240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << bytes_read << std::endl; 4250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } while (!feof(input_file_)); 4290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath encoder.FinishEncoding(&output); 4300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!WriteOutput(output)) { 4310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 4340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 4350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_stats && (input_size > 0)) { 4360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Original size: " << input_size 4370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "\tCompressed size: " << output_size << " (" 4380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ((static_cast<double>(output_size) / input_size) * 100) 4390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "% of original)" << std::endl; 4400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 4420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 4430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::Decode() { 4450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_type_ = "delta"; 4460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_name_ = FLAGS_delta; 4470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_type_ = "target"; 4480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_name_ = FLAGS_target; 4490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!OpenDictionary() || !OpenInputFile() || !OpenOutputFile()) { 4500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffStreamingDecoder decoder; 4540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetMaximumTargetFileSize( 4550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<size_t>(FLAGS_max_target_file_size)); 4560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetMaximumTargetWindowSize( 4570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<size_t>(FLAGS_max_target_window_size)); 4580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetAllowVcdTarget(FLAGS_allow_vcd_target); 4590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string output; 4600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t input_size = 0; 4610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t output_size = 0; 4620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Issue 6: Visual Studio STL produces a runtime exception 4630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if &dictionary_[0] is attempted for an empty dictionary. 4640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (dictionary_.empty()) { 4650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.StartDecoding("", 0); 4660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 4670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.StartDecoding(&dictionary_[0], dictionary_.size()); 4680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 4700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath do { 4710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t bytes_read = 0; 4720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ReadInput(&bytes_read)) { 4730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (bytes_read > 0) { 4760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_size += bytes_read; 4770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!decoder.DecodeChunk(&input_buffer_[0], bytes_read, &output)) { 4780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error trying to decode data chunk of length " 4790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << bytes_read << std::endl; 4800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!WriteOutput(output)) { 4840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 4870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 4880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } while (!feof(input_file_)); 4890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!decoder.FinishDecoding()) { 4900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decode error; '" << FLAGS_delta 4910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " may not be a valid VCDIFF delta file" << std::endl; 4920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!WriteOutput(output)) { 4950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 4960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 4970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 4980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 4990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_stats && (output_size > 0)) { 5000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decompressed size: " << output_size 5010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "\tCompressed size: " << input_size << " (" 5020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ((static_cast<double>(input_size) / output_size) * 100) 5030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "% of original)" << std::endl; 5040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 5060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 5070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathbool VCDiffFileBasedCoder::DecodeAndCompare() { 5090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_type_ = "delta"; 5100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_file_name_ = FLAGS_delta; 5110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_type_ = "target"; 5120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_file_name_ = FLAGS_target; 5130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!OpenDictionary() || !OpenInputFile() || !OpenOutputFileForCompare()) { 5140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffStreamingDecoder decoder; 5180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetMaximumTargetFileSize( 5190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<size_t>(FLAGS_max_target_file_size)); 5200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetMaximumTargetWindowSize( 5210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath static_cast<size_t>(FLAGS_max_target_window_size)); 5220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.SetAllowVcdTarget(FLAGS_allow_vcd_target); 5230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath string output; 5240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t input_size = 0; 5250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t output_size = 0; 5260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Issue 6: Visual Studio STL produces a runtime exception 5270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // if &dictionary_[0] is attempted for an empty dictionary. 5280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (dictionary_.empty()) { 5290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.StartDecoding("", 0); 5300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 5310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath decoder.StartDecoding(&dictionary_[0], dictionary_.size()); 5320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath do { 5350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath size_t bytes_read = 0; 5360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!ReadInput(&bytes_read)) { 5370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (bytes_read > 0) { 5400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath input_size += bytes_read; 5410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!decoder.DecodeChunk(&input_buffer_[0], bytes_read, &output)) { 5420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error trying to decode data chunk of length " 5430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << bytes_read << std::endl; 5440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!CompareOutput(output)) { 5480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 5510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 5520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } while (!feof(input_file_)); 5530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!decoder.FinishDecoding()) { 5540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decode error; '" << FLAGS_delta 5550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " may not be a valid VCDIFF delta file" << std::endl; 5560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5570a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5580a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!CompareOutput(output)) { 5590a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5600a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5610a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output_size += output.size(); 5620a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath output.clear(); 5630a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (fgetc(output_file_) != EOF) { 5640a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decoded target is shorter than original target file" 5650a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 5660a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5670a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5680a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (ferror(output_file_)) { 5690a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Error reading end-of-file indicator from target file" 5700a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 5710a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return false; 5720a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5730a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_stats && (output_size > 0)) { 5740a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << "Decompressed size: " << output_size 5750a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "\tCompressed size: " << input_size << " (" 5760a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ((static_cast<double>(input_size) / output_size) * 100) 5770a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << "% of original)" << std::endl; 5780a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5790a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return true; 5800a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 5810a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5820a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} // namespace open_vcdiff 5830a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath 5840a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamathint main(int argc, char** argv) { 5850a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* const command_name = argv[0]; 5860a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath google::SetUsageMessage(kUsageString); 5870a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath google::ParseCommandLineFlags(&argc, &argv, true); 5880a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (argc != 2) { 5890a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << command_name << ": Must specify exactly one command option" 5900a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 5910a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(command_name, "vcdiff"); 5920a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 5930a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 5940a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const char* const command_option = argv[1]; 5950a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_dictionary.empty()) { 5960a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << command_name << " " << command_option 5970a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << ": Must specify --dictionary <file-name>" << std::endl; 5980a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(command_name, "vcdiff"); 5990a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6000a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6010a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!GetCommandLineFlagInfoOrDie("buffersize").is_default && 6020a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (FLAGS_buffersize == 0)) { 6030a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << command_name << ": Option --buffersize cannot be 0" 6040a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << std::endl; 6050a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(command_name, "vcdiff"); 6060a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6070a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6080a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if ((strcmp(command_option, "encode") == 0) || 6090a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (strcmp(command_option, "delta") == 0)) { 6100a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffFileBasedCoder coder; 6110a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!coder.Encode()) { 6120a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6130a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6140a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // The destructor for VCDiffFileBasedCoder will clean up the open files 6150a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and allocated memory. 6160a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if ((strcmp(command_option, "decode") == 0) || 6170a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath (strcmp(command_option, "patch") == 0)) { 6180a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffFileBasedCoder coder; 6190a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!coder.Decode()) { 6200a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6210a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6220a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else if ((strcmp(command_option, "test") == 0)) { 6230a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // "vcdiff test" does not appear in the usage string, but can be 6240a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // used for debugging. It encodes, then decodes, then compares the result 6250a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // with the original target. It expects the same arguments as 6260a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // "vcdiff encode", with the additional requirement that the --target 6270a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // and --delta file arguments must be specified, rather than using stdin 6280a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // or stdout. It produces a delta file just as for "vcdiff encode". 6290a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (FLAGS_target.empty() || FLAGS_delta.empty()) { 6300a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << command_name 6310a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << " test: Must specify both --target <file-name>" 6320a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath " and --delta <file-name>" << std::endl; 6330a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6340a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6350a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath const string original_target(FLAGS_target); 6360a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath // Put coder into a separate scope. 6370a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath { 6380a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffFileBasedCoder coder; 6390a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!coder.Encode()) { 6400a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6410a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6420a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6430a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath { 6440a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath open_vcdiff::VCDiffFileBasedCoder coder; 6450a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath if (!coder.DecodeAndCompare()) { 6460a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6470a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6480a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6490a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } else { 6500a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath std::cerr << command_name << ": Unrecognized command option " 6510a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath << command_option << std::endl; 6520a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath ShowUsageWithFlagsRestrict(command_name, "vcdiff"); 6530a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 1; 6540a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath } 6550a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath return 0; 6560a58c5c2f73e5047b36f12b5f12b12d6f2a9f69dNarayan Kamath} 657