Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Last active August 29, 2015 14:27
Show Gist options
  • Save ynkdir/82624093bd2274de86a3 to your computer and use it in GitHub Desktop.
Save ynkdir/82624093bd2274de86a3 to your computer and use it in GitHub Desktop.
abcdiff(仮)
// cl /Idtl abcdiff.cpp
// https://github.com/cubicdaiya/dtl
#include <dtl/dtl.hpp>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <time.h>
#include <sys/stat.h>
using namespace std;
using dtl::Diff;
using dtl::elemInfo;
using dtl::uniHunk;
struct normalHunk {
int oldstart;
int oldcount;
int newstart;
int newcount;
};
static bool isFileExist(string& fs);
static void showStats (string fp1, string fp2);
static void unifiedDiff (string fp1, string fp2);
static void normalDiff (string fp1, string fp2);
static bool isFileExist(string& fs)
{
FILE *fp;
if ((fp = fopen(fs.c_str(), "r")) == NULL) {
return false;
}
fclose(fp);
return true;
}
static void showStats (string fp1, string fp2)
{
const int MAX_LENGTH = 255;
char time_format[] = "%Y-%m-%d %H:%M:%S %z";
time_t rawtime[2];
struct tm *timeinfo[2];
struct stat st[2];
if (stat(fp1.c_str(), &st[0]) == -1) {
cerr << "argv1 is invalid." << endl;
exit(-1);
}
if (stat(fp2.c_str(), &st[1]) == -1) {
cerr << "argv2 is invalid" << endl;
exit(-1);
}
char buf[2][MAX_LENGTH + 1];
rawtime[0] = st[0].st_mtime;
timeinfo[0] = localtime(&rawtime[0]);
strftime(buf[0], MAX_LENGTH, time_format, timeinfo[0]);
cout << "--- " << fp1 << '\t' << buf[0] << endl;
rawtime[1] = st[1].st_mtime;
timeinfo[1] = localtime(&rawtime[1]);
strftime(buf[1], MAX_LENGTH, time_format, timeinfo[1]);
cout << "+++ " << fp2 << '\t' << buf[1] << endl;
}
static void unifiedDiff (string fp1, string fp2)
{
typedef string elem;
typedef vector< elem > sequence;
typedef pair< elem, elemInfo > sesElem;
ifstream Aifs(fp1.c_str());
ifstream Bifs(fp2.c_str());
elem buf;
sequence ALines, BLines;
while(getline(Aifs, buf)){
ALines.push_back(buf);
}
while(getline(Bifs, buf)){
BLines.push_back(buf);
}
Diff< elem > diff(ALines, BLines);
diff.onHuge();
//diff.onUnserious();
diff.compose();
// type unihunk definition test
uniHunk< sesElem > hunk;
if (diff.getEditDistance() > 0) {
showStats(fp1, fp2); // show file info
}
diff.composeUnifiedHunks();
diff.printUnifiedFormat();
}
static void normalDiff (string fp1, string fp2)
{
typedef string elem;
typedef vector< elem > sequence;
typedef pair< elem, elemInfo > sesElem;
ifstream Aifs(fp1.c_str());
ifstream Bifs(fp2.c_str());
elem buf;
sequence ALines, BLines;
while(getline(Aifs, buf)){
ALines.push_back(buf);
}
while(getline(Bifs, buf)){
BLines.push_back(buf);
}
Diff< elem > diff(ALines, BLines);
diff.onHuge();
//diff.onUnserious();
diff.compose();
vector<normalHunk> hunks;
// composeNormalHunks
{
int i = 0;
int a = 0;
int b = 0;
normalHunk h;
auto seq = diff.getSes().getSequence();
while (i < seq.size()) {
switch (seq[i].second.type) {
case dtl::SES_COMMON:
++i;
++a;
++b;
break;
case dtl::SES_ADD:
h.oldstart = a;
h.oldcount = 0;
h.newstart = b;
h.newcount = 0;
while (i < seq.size() && seq[i].second.type == dtl::SES_ADD) {
++b;
++h.newcount;
++i;
}
while (i < seq.size() && seq[i].second.type == dtl::SES_DELETE) {
++a;
++h.oldcount;
++i;
}
hunks.push_back(h);
break;
case dtl::SES_DELETE:
h.oldstart = a;
h.oldcount = 0;
h.newstart = b;
h.newcount = 0;
while (i < seq.size() && seq[i].second.type == dtl::SES_DELETE) {
++a;
++h.oldcount;
++i;
}
while (i < seq.size() && seq[i].second.type == dtl::SES_ADD) {
++b;
++h.newcount;
++i;
}
hunks.push_back(h);
break;
}
}
}
// printNormalFormat
{
int base = 1;
stringstream ss;
string oldrange;
string newrange;
for (auto h : hunks) {
ss.str("");
if (h.oldcount == 0) {
ss << h.oldstart;
} else if (h.oldcount == 1) {
ss << (h.oldstart + base);
} else {
ss << (h.oldstart + base) << "," << (h.oldstart + base + h.oldcount - 1);
}
oldrange = ss.str();
ss.str("");
if (h.newcount == 0) {
ss << h.newstart;
} else if (h.newcount == 1) {
ss << (h.newstart + base);
} else {
ss << (h.newstart + base) << "," << (h.newstart + base + h.newcount - 1);
}
newrange = ss.str();
if (h.oldcount == 0) {
cout << oldrange << "a" << newrange << endl;
for (int i = 0; i < h.newcount; ++i) {
cout << "> " << BLines[h.newstart + i] << endl;
}
} else if (h.newcount == 0) {
cout << oldrange << "d" << newrange << endl;
for (int i = 0; i < h.oldcount; ++i) {
cout << "< " << ALines[h.oldstart + i] << endl;
}
} else {
cout << oldrange << "c" << newrange << endl;
for (int i = 0; i < h.oldcount; ++i) {
cout << "< " << ALines[h.oldstart + i] << endl;
}
cout << "---" << endl;
for (int i = 0; i < h.newcount; ++i) {
cout << "> " << BLines[h.newstart + i] << endl;
}
}
}
}
}
int main(int argc, char *argv[])
{
if (argc < 3) {
cerr << "Too few arguments." << endl;
return -1;
}
string s1(argv[1]);
string s2(argv[2]);
bool fileExist = true;
if (!isFileExist(s1)) {
cerr << s1 << " is invalid." << endl;
fileExist = false;
}
if (!isFileExist(s2)) {
cerr << s2 << " is invalid." << endl;
fileExist = false;
}
if (!fileExist) {
return -1;
}
normalDiff(s1, s2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment