3 #include <sys/stat.h>
\r
4 #include "CompareOptions.h"
\r
6 #include "../Externals/xdiff/xinclude.h"
\r
9 static bool read_mmfile(int fd, mmfile_t& mmfile)
\r
12 if (myfstat(fd, &st) == -1)
\r
14 if (st.st_size < 0 || st.st_size > INT32_MAX)
\r
16 size_t sz = static_cast<size_t>(st.st_size);
\r
17 mmfile.ptr = static_cast<char *>(malloc(sz ? sz : 1));
\r
18 if (sz && _read(fd, mmfile.ptr, static_cast<unsigned>(sz)) == -1) {
\r
21 mmfile.size = static_cast<long>(sz);
\r
25 unsigned long make_xdl_flags(const DiffutilsOptions& options)
\r
27 unsigned long xdl_flags = 0;
\r
28 switch (options.m_diffAlgorithm)
\r
30 case DIFF_ALGORITHM_MINIMAL:
\r
31 xdl_flags |= XDF_NEED_MINIMAL;
\r
33 case DIFF_ALGORITHM_PATIENCE:
\r
34 xdl_flags |= XDF_PATIENCE_DIFF;
\r
36 case DIFF_ALGORITHM_HISTOGRAM:
\r
37 xdl_flags |= XDF_HISTOGRAM_DIFF;
\r
42 if (options.m_bIgnoreCase)
\r
43 xdl_flags |= XDF_IGNORE_CASE;
\r
44 if (options.m_bIgnoreBlankLines)
\r
45 xdl_flags |= XDF_IGNORE_BLANK_LINES;
\r
46 if (options.m_bIgnoreEOLDifference)
\r
47 xdl_flags |= XDF_IGNORE_CR_AT_EOL;
\r
48 switch (options.m_ignoreWhitespace)
\r
50 case WHITESPACE_IGNORE_CHANGE:
\r
51 xdl_flags |= XDF_IGNORE_WHITESPACE_CHANGE;
\r
53 case WHITESPACE_IGNORE_ALL:
\r
54 xdl_flags |= XDF_IGNORE_WHITESPACE;
\r
59 if (options.m_bIndentHeuristic)
\r
60 xdl_flags |= XDF_INDENT_HEURISTIC;
\r
64 static int hunk_func(long start_a, long count_a, long start_b, long count_b, void *cb_data)
\r
69 static void append_equivs(const xdfile_t& xdf, struct file_data& filevec, std::vector<xrecord_t *>& equivs, unsigned xdl_flags)
\r
71 std::unordered_map<unsigned long, std::vector<int>> equivs_map;
\r
72 for (int i = 0; i < static_cast<int>(equivs.size()); ++i)
\r
74 unsigned long ha = equivs[i]->ha;
\r
75 if (equivs_map.find(ha) != equivs_map.end())
\r
76 equivs_map[ha].push_back(i);
\r
78 equivs_map.emplace(ha, std::vector<int>{i});
\r
81 for (int i = 0; i < xdf.nrec; ++i)
\r
83 unsigned long ha = xdf.recs[i]->ha;
\r
84 if (equivs_map.find(ha) != equivs_map.end())
\r
87 for (auto j: equivs_map[ha])
\r
89 if (xdl_recmatch(equivs[j]->ptr, equivs[j]->size, xdf.recs[i]->ptr, xdf.recs[i]->size, xdl_flags))
\r
92 filevec.equivs[i] = j;
\r
93 equivs_map.emplace(ha, std::vector<int>{j});
\r
99 filevec.equivs[i] = static_cast<int>(equivs.size());
\r
100 equivs_map[ha].push_back(filevec.equivs[i]);
\r
101 equivs.push_back(xdf.recs[i]);
\r
106 filevec.equivs[i] = static_cast<int>(equivs.size());
\r
107 equivs_map.emplace(ha, std::vector<int>{filevec.equivs[i]});
\r
108 equivs.push_back(xdf.recs[i]);
\r
113 static int is_missing_newline(const mmfile_t& mmfile)
\r
115 if (mmfile.size == 0 || mmfile.ptr[mmfile.size - 1] == '\r' || mmfile.ptr[mmfile.size - 1] == '\n')
\r
120 struct change * diff_2_files_xdiff (struct file_data filevec[], int bMoved_blocks_flag, unsigned xdl_flags)
\r
122 mmfile_t mmfile1 = { 0 }, mmfile2 = { 0 };
\r
123 change *script = nullptr;
\r
126 xpparam_t xpp = { 0 };
\r
127 xdemitconf_t xecfg = { 0 };
\r
128 xdemitcb_t ecb = { 0 };
\r
130 if (!read_mmfile(filevec[0].desc, mmfile1))
\r
132 if (!read_mmfile(filevec[1].desc, mmfile2))
\r
135 xpp.flags = xdl_flags;
\r
136 xecfg.hunk_func = hunk_func;
\r
137 if (xdl_diff_modified(&mmfile1, &mmfile2, &xpp, &xecfg, &ecb, &xe, &xscr) == 0)
\r
139 filevec[0].buffer = mmfile1.ptr;
\r
140 filevec[1].buffer = mmfile2.ptr;
\r
141 filevec[0].bufsize = mmfile1.size;
\r
142 filevec[1].bufsize = mmfile2.size;
\r
143 filevec[0].buffered_chars = mmfile1.size;
\r
144 filevec[1].buffered_chars = mmfile2.size;
\r
145 filevec[0].linbuf_base = 0;
\r
146 filevec[1].linbuf_base = 0;
\r
147 filevec[0].valid_lines = xe.xdf1.nrec;
\r
148 filevec[1].valid_lines = xe.xdf2.nrec;
\r
149 filevec[0].linbuf = static_cast<const char **>(malloc(sizeof(char *) * (xe.xdf1.nrec + 1)));
\r
150 if (!filevec[0].linbuf)
\r
152 filevec[1].linbuf = static_cast<const char **>(malloc(sizeof(char *) * (xe.xdf2.nrec + 1)));
\r
153 if (!filevec[1].linbuf)
\r
155 filevec[0].equivs = static_cast<int *>(malloc(sizeof(int) * xe.xdf1.nrec));
\r
156 if (!filevec[0].equivs)
\r
158 filevec[1].equivs = static_cast<int *>(malloc(sizeof(int) * xe.xdf2.nrec));
\r
159 if (!filevec[1].equivs)
\r
161 for (int i = 0; i < xe.xdf1.nrec; ++i)
\r
163 filevec[0].linbuf[i] = xe.xdf1.recs[i]->ptr;
\r
164 filevec[0].equivs[i] = -1;
\r
166 if (xe.xdf1.nrec > 0)
\r
167 filevec[0].linbuf[xe.xdf1.nrec] = xe.xdf1.recs[xe.xdf1.nrec - 1]->ptr + xe.xdf1.recs[xe.xdf1.nrec - 1]->size;
\r
168 for (int i = 0; i < xe.xdf2.nrec; ++i)
\r
170 filevec[1].linbuf[i] = xe.xdf2.recs[i]->ptr;
\r
171 filevec[1].equivs[i] = -1;
\r
173 if (xe.xdf2.nrec > 0)
\r
174 filevec[1].linbuf[xe.xdf2.nrec] = xe.xdf2.recs[xe.xdf2.nrec - 1]->ptr + xe.xdf2.recs[xe.xdf2.nrec - 1]->size;
\r
175 filevec[0].missing_newline = is_missing_newline(mmfile1);
\r
176 filevec[1].missing_newline = is_missing_newline(mmfile2);
\r
178 change *prev = nullptr;
\r
179 for (xdchange_t* xcur = xscr; xcur; xcur = xcur->next)
\r
181 change* e = static_cast<change*>(malloc(sizeof(change)));
\r
186 e->line0 = xcur->i1;
\r
187 e->line1 = xcur->i2;
\r
188 e->deleted = xcur->chg1;
\r
189 e->inserted = xcur->chg2;
\r
192 e->trivial = static_cast<char>(xcur->ignore);
\r
200 if (bMoved_blocks_flag)
\r
202 std::vector<xrecord_t *> equivs;
\r
203 append_equivs(xe.xdf1, filevec[0], equivs, xdl_flags);
\r
204 append_equivs(xe.xdf2, filevec[1], equivs, xdl_flags);
\r
205 moved_block_analysis(&script, filevec);
\r
208 xdl_free_script(xscr);
\r