📄 vbindiff.cpp
字号:
//--------------------------------------------------------------------// $Id: vbindiff.cpp 4759 2008-07-26 03:19:24Z cjm $//--------------------------------------------------------------------//// Visual Binary Diff// Copyright 1995-2008 by Christopher J. Madsen//// Visual display of differences in binary files//// This program is free software; you can redistribute it and/or// modify it under the terms of the GNU General Public License as// published by the Free Software Foundation; either version 2 of// the License, or (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program. If not, see <http://www.gnu.org/licenses/>.//--------------------------------------------------------------------#include "config.h"#include <ctype.h>#include <limits.h>#include <stdlib.h>#include <string.h>#include <algorithm>#include <iostream>#include <sstream>#include <map>#include <string>#include <vector>using namespace std;#include "GetOpt/GetOpt.hpp"#include "ConWin.hpp"#include "FileIO.hpp"const char titleString[] = "\nVBinDiff " PACKAGE_VERSION "\nCopyright 1995-2008 Christopher J. Madsen";void exitMsg(int status, const char* message);void usage(bool showHelp=true, int exitStatus=0);//====================================================================// Type definitions:typedef unsigned char Byte;typedef unsigned short Word;typedef Byte Command;enum LockState { lockNeither = 0, lockTop, lockBottom };//--------------------------------------------------------------------// Strings:typedef string String;typedef String::size_type StrIdx;typedef String::iterator StrItr;typedef String::const_iterator StrConstItr;//--------------------------------------------------------------------// Vectors:typedef vector<String> StrVec;typedef StrVec::iterator SVItr;typedef StrVec::const_iterator SVConstItr;typedef StrVec::size_type VecSize;//--------------------------------------------------------------------// Map:typedef map<VecSize, String> StrMap;typedef StrMap::value_type SMVal;typedef StrMap::iterator SMItr;typedef StrMap::const_iterator SMConstItr;//====================================================================// Constants:const Command cmmMove = 0x80;const Command cmmMoveSize = 0x03;const Command cmmMoveForward = 0x04;const Command cmmMoveTop = 0x08;const Command cmmMoveBottom = 0x10;const Command cmmMoveByte = 0x00; // Move 1 byteconst Command cmmMoveLine = 0x01; // Move 1 lineconst Command cmmMovePage = 0x02; // Move 1 pageconst Command cmmMoveAll = 0x03; // Move to beginning or endconst Command cmmMoveBoth = cmmMoveTop|cmmMoveBottom;const Command cmgGoto = 0x04; // Commands 4-7const Command cmgGotoTop = 0x01;const Command cmgGotoBottom = 0x02;const Command cmgGotoBoth = cmgGotoTop|cmgGotoBottom;const Command cmgGotoMask = ~cmgGotoBoth;const Command cmNothing = 0;const Command cmNextDiff = 1;const Command cmQuit = 2;const Command cmEditTop = 8;const Command cmEditBottom = 9;const Command cmUseTop = 10;const Command cmUseBottom = 11;const Command cmToggleASCII = 12;const Command cmFind = 16; // Commands 16-19const short leftMar = 11; // Starting column of hex displayconst short leftMar2 = 61; // Starting column of ASCII displayconst int lineWidth = 16; // Number of bytes displayed per lineconst int promptHeight = 4; // Height of prompt windowconst int inWidth = 10; // Width of input window (excluding border)const int screenWidth = 80;const int maxPath = 260;const VecSize maxHistory = 2000;const char hexDigits[] = "0123456789ABCDEF";#include "tables.h" // ASCII and EBCDIC tables//====================================================================// Class Declarations:void showEditPrompt();void showPrompt();class Difference;union FileBuffer{ Byte line[1][lineWidth]; Byte buffer[lineWidth];}; // end FileBufferclass FileDisplay{ friend class Difference; protected: int bufContents; FileBuffer* data; const Difference* diffs; File file; char fileName[maxPath]; FPos offset; ConWindow win; bool writable; int yPos; public: FileDisplay(); ~FileDisplay(); void init(int y, const Difference* aDiff=NULL, const char* aFileName=NULL); void resize(); void shutDown(); void display(); bool edit(const FileDisplay* other); const Byte* getBuffer() const { return data->buffer; }; void move(int step) { moveTo(offset + step); }; void moveTo(FPos newOffset); bool moveTo(const Byte* searchFor, int searchLen); void moveToEnd(FileDisplay* other); bool setFile(const char* aFileName); protected: void setByte(short x, short y, Byte b);}; // end FileDisplayclass Difference{ friend void FileDisplay::display(); protected: FileBuffer* data; const FileDisplay* file1; const FileDisplay* file2; int numDiffs; public: Difference(const FileDisplay* aFile1, const FileDisplay* aFile2); ~Difference(); int compute(); int getNumDiffs() const { return numDiffs; }; void resize();}; // end Differenceclass InputManager{ private: char* buf; // The editing buffer const char* restrict; // If non-NULL, only allow these chars StrVec& history; // The history vector to use StrMap historyOverlay; // Overlay of modified history entries VecSize historyPos; // The current offset into history[] int maxLen; // The size of buf (not including NUL) int len; // The current length of the string int i; // The current cursor position bool upcase; // Force all characters to uppercase? bool splitHex; // Entering space-separated hex bytes? bool insert; // False for overstrike mode public: InputManager(char* aBuf, int aMaxLen, StrVec& aHistory); bool run(); void setCharacters(const char* aRestriction) { restrict = aRestriction; }; void setSplitHex(bool val) { splitHex = val; }; void setUpcase(bool val) { upcase = val; }; private: bool normalize(int pos); void useHistory(int delta);}; // end InputManager//====================================================================// Global Variables:String lastSearch;StrVec hexSearchHistory, textSearchHistory, positionHistory;ConWindow promptWin,inWin;FileDisplay file1, file2;Difference diffs(&file1, &file2);const char* displayTable = asciiDisplayTable;const char* program_name; // Name under which this program was invokedLockState lockState = lockNeither;bool singleFile = false;int numLines = 9; // Number of lines of each file to displayint bufSize = numLines * lineWidth;int linesBetween = 1; // Number of lines of padding between files// The number of bytes to move for each possible step size:// See cmmMoveByte, cmmMoveLine, cmmMovePageint steps[4] = {1, lineWidth, bufSize-lineWidth, 0};//====================================================================// Miscellaneous Functions://--------------------------------------------------------------------// Beep the speaker:#ifdef WIN32_CONSOLE // beep() is defined by ncursesvoid beep(){ MessageBeep(-1);} // end beep#endif // WIN32_CONSOLE//--------------------------------------------------------------------// Convert a character to uppercase://// The standard toupper(c) isn't guaranteed for arbitrary integers.int safeUC(int c){ return (c >= 0 && c <= UCHAR_MAX) ? toupper(c) : c;} // end safeUC//====================================================================// Class Difference://// Member Variables:// file1, file2:// The FileDisplay objects being compared// numDiffs:// The number of differences between the two FileDisplay buffers// line/table:// An array of bools for each byte in the FileDisplay buffers// True marks differences////--------------------------------------------------------------------// Constructor://// Input:// aFile1, aFile2:// Pointers to the FileDisplay objects to compareDifference::Difference(const FileDisplay* aFile1, const FileDisplay* aFile2): data(NULL), file1(aFile1), file2(aFile2){} // end Difference::Difference//--------------------------------------------------------------------Difference::~Difference(){ delete [] reinterpret_cast<Byte*>(data);} // end Difference::~Difference//--------------------------------------------------------------------// Compute differences://// Input Variables:// file1, file2: The files to compare//// Returns:// The number of differences between the buffers// -1 if both buffers are empty//// Output Variables:// numDiffs: The number of differences between the buffersint Difference::compute(){ if (singleFile) // We return 1 so that cmNextDiff won't keep searching: return (file1->bufContents ? 1 : -1); memset(data->buffer, 0, bufSize); // Clear the difference table int different = 0; const Byte* buf1 = file1->data->buffer; const Byte* buf2 = file2->data->buffer; int size = min(file1->bufContents, file2->bufContents); int i; for (i = 0; i < size; i++) if (*(buf1++) != *(buf2++)) { data->buffer[i] = true; ++different; } size = max(file1->bufContents, file2->bufContents); if (i < size) { // One buffer has more data than the other: different += size - i; for (; i < size; i++) data->buffer[i] = true; // These bytes are only in 1 buffer } else if (!size) return -1; // Both buffers are empty numDiffs = different; return different;} // end Difference::compute//--------------------------------------------------------------------void Difference::resize(){ if (singleFile) return; if (data) delete [] reinterpret_cast<Byte*>(data); data = reinterpret_cast<FileBuffer*>(new Byte[bufSize]);} // end Difference::resize//====================================================================// Class FileDisplay://// Member Variables:// bufContents:// The number of bytes in the file buffer// diffs:// A pointer to the Difference object related to this file// file:// The file being displayed// fileName:// The relative pathname of the file being displayed// offset:// The position in the file of the first byte in the buffer// win:// The handle of the window used for display// yPos:// The vertical position of the display window// buffer/line:// The currently displayed portion of the file////--------------------------------------------------------------------// Constructor:FileDisplay::FileDisplay(): bufContents(0), data(NULL), diffs(NULL), offset(0), writable(false), yPos(0){ fileName[0] = '\0';} // end FileDisplay::FileDisplay//--------------------------------------------------------------------// Initialize://// Creates the display window and opens the file.//// Input:// y: The vertical position of the display window// aDiff: The Difference object related to this buffer// aFileName: The name of the file to displayvoid FileDisplay::init(int y, const Difference* aDiff, const char* aFileName){ diffs = aDiff; yPos = y; win.init(0,y, screenWidth, (numLines + 1 + ((y==0) ? linesBetween : 0)), cFileWin); resize(); if (aFileName) setFile(aFileName);} // end FileDisplay::init//--------------------------------------------------------------------// Destructor:FileDisplay::~FileDisplay(){ shutDown(); CloseFile(file); delete [] reinterpret_cast<Byte*>(data);} // end FileDisplay::~FileDisplay//--------------------------------------------------------------------void FileDisplay::resize(){ if (data) delete [] reinterpret_cast<Byte*>(data); data = reinterpret_cast<FileBuffer*>(new Byte[bufSize]); // FIXME resize window} // end FileDisplay::resize//--------------------------------------------------------------------// Shut down the file display://// Deletes the display window.void FileDisplay::shutDown(){ win.close();} // end FileDisplay::shutDown//--------------------------------------------------------------------// Display the file contents:void FileDisplay::display(){ if (!fileName[0]) return; FPos lineOffset = offset; short i,j,index,lineLength; char buf[lineWidth + lineWidth/8 + 1]; buf[sizeof(buf)-1] = '\0'; char buf2[screenWidth+1]; buf2[screenWidth] = '\0'; memset(buf, ' ', sizeof(buf)-1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -