3 #include "CompareOptions.h"
\r
5 #include "../Externals/xdiff/xinclude.h"
\r
8 static bool read_mmfile(int fd, mmfile_t& mmfile)
\r
11 if (cio::fstat(fd, &st) == -1)
\r
13 if (st.st_size < 0 || st.st_size > INT32_MAX)
\r
15 size_t sz = static_cast<size_t>(st.st_size);
\r
16 mmfile.ptr = static_cast<char *>(malloc(sz ? sz : 1));
\r
17 if (sz && cio::read(fd, mmfile.ptr, sz) == -1) {
\r
20 mmfile.size = static_cast<long>(sz);
\r
24 unsigned long make_xdl_flags(const DiffutilsOptions& options)
\r
26 unsigned long xdl_flags = 0;
\r
27 switch (options.m_diffAlgorithm)
\r
29 case DIFF_ALGORITHM_MINIMAL:
\r
30 xdl_flags |= XDF_NEED_MINIMAL;
\r
32 case DIFF_ALGORITHM_PATIENCE:
\r
33 xdl_flags |= XDF_PATIENCE_DIFF;
\r
35 case DIFF_ALGORITHM_HISTOGRAM:
\r
36 xdl_flags |= XDF_HISTOGRAM_DIFF;
\r
38 case DIFF_ALGORITHM_NONE:
\r
39 xdl_flags |= XDF_NONE_DIFF;
\r
44 if (options.m_bIgnoreCase)
\r
45 xdl_flags |= XDF_IGNORE_CASE;
\r
46 if (options.m_bIgnoreNumbers)
\r
47 xdl_flags |= XDF_IGNORE_NUMBERS;
\r
48 if (options.m_bIgnoreBlankLines)
\r
49 xdl_flags |= XDF_IGNORE_BLANK_LINES;
\r
50 if (options.m_bIgnoreEOLDifference)
\r
51 xdl_flags |= XDF_IGNORE_CR_AT_EOL;
\r
52 switch (options.m_ignoreWhitespace)
\r
54 case WHITESPACE_IGNORE_CHANGE:
\r
55 xdl_flags |= XDF_IGNORE_WHITESPACE_CHANGE;
\r
57 case WHITESPACE_IGNORE_ALL:
\r
58 xdl_flags |= XDF_IGNORE_WHITESPACE;
\r
63 if (options.m_bIndentHeuristic)
\r
64 xdl_flags |= XDF_INDENT_HEURISTIC;
\r
68 static int hunk_func(long start_a, long count_a, long start_b, long count_b, void *cb_data)
\r
73 static void append_equivs(const xdfile_t& xdf, struct file_data& filevec, std::vector<xrecord_t *>& equivs, unsigned xdl_flags)
\r
75 std::unordered_map<unsigned long, std::vector<int>> equivs_map;
\r
76 for (int i = 0; i < static_cast<int>(equivs.size()); ++i)
\r
78 unsigned long ha = equivs[i]->ha;
\r
79 if (equivs_map.find(ha) != equivs_map.end())
\r
80 equivs_map[ha].push_back(i);
\r
82 equivs_map.emplace(ha, std::vector<int>{i});
\r
85 for (int i = 0; i < xdf.nrec; ++i)
\r
87 unsigned long ha = xdf.recs[i]->ha;
\r
88 if (equivs_map.find(ha) != equivs_map.end())
\r
91 for (auto j: equivs_map[ha])
\r
93 if (xdl_recmatch(equivs[j]->ptr, equivs[j]->size, xdf.recs[i]->ptr, xdf.recs[i]->size, xdl_flags))
\r
96 filevec.equivs[i] = j;
\r
97 equivs_map.emplace(ha, std::vector<int>{j});
\r
103 filevec.equivs[i] = static_cast<int>(equivs.size());
\r
104 equivs_map[ha].push_back(filevec.equivs[i]);
\r
105 equivs.push_back(xdf.recs[i]);
\r
110 filevec.equivs[i] = static_cast<int>(equivs.size());
\r
111 equivs_map.emplace(ha, std::vector<int>{filevec.equivs[i]});
\r
112 equivs.push_back(xdf.recs[i]);
\r
117 static int is_missing_newline(const mmfile_t& mmfile)
\r
119 if (mmfile.size == 0 || mmfile.ptr[mmfile.size - 1] == '\r' || mmfile.ptr[mmfile.size - 1] == '\n')
\r
124 struct change * diff_2_files_xdiff (struct file_data filevec[], int bMoved_blocks_flag, unsigned xdl_flags)
\r
126 mmfile_t mmfile1 = { 0 }, mmfile2 = { 0 };
\r
127 change *script = nullptr;
\r
130 xpparam_t xpp = { 0 };
\r
131 xdemitconf_t xecfg = { 0 };
\r
132 xdemitcb_t ecb = { 0 };
\r
134 if (!read_mmfile(filevec[0].desc, mmfile1))
\r
136 if (!read_mmfile(filevec[1].desc, mmfile2))
\r
139 xpp.flags = xdl_flags;
\r
140 xecfg.hunk_func = hunk_func;
\r
141 if (xdl_diff_modified(&mmfile1, &mmfile2, &xpp, &xecfg, &ecb, &xe, &xscr) == 0)
\r
143 filevec[0].buffer = mmfile1.ptr;
\r
144 filevec[1].buffer = mmfile2.ptr;
\r
145 filevec[0].bufsize = mmfile1.size;
\r
146 filevec[1].bufsize = mmfile2.size;
\r
147 filevec[0].buffered_chars = mmfile1.size;
\r
148 filevec[1].buffered_chars = mmfile2.size;
\r
149 filevec[0].linbuf_base = 0;
\r
150 filevec[1].linbuf_base = 0;
\r
151 filevec[0].valid_lines = xe.xdf1.nrec;
\r
152 filevec[1].valid_lines = xe.xdf2.nrec;
\r
153 filevec[0].linbuf = static_cast<const char **>(malloc(sizeof(char *) * (xe.xdf1.nrec + 1)));
\r
154 if (!filevec[0].linbuf)
\r
156 filevec[1].linbuf = static_cast<const char **>(malloc(sizeof(char *) * (xe.xdf2.nrec + 1)));
\r
157 if (!filevec[1].linbuf)
\r
159 filevec[0].equivs = static_cast<int *>(malloc(sizeof(int) * xe.xdf1.nrec));
\r
160 if (!filevec[0].equivs)
\r
162 filevec[1].equivs = static_cast<int *>(malloc(sizeof(int) * xe.xdf2.nrec));
\r
163 if (!filevec[1].equivs)
\r
165 for (int i = 0; i < xe.xdf1.nrec; ++i)
\r
167 filevec[0].linbuf[i] = xe.xdf1.recs[i]->ptr;
\r
168 filevec[0].equivs[i] = -1;
\r
170 if (xe.xdf1.nrec > 0)
\r
171 filevec[0].linbuf[xe.xdf1.nrec] = xe.xdf1.recs[xe.xdf1.nrec - 1]->ptr + xe.xdf1.recs[xe.xdf1.nrec - 1]->size;
\r
172 for (int i = 0; i < xe.xdf2.nrec; ++i)
\r
174 filevec[1].linbuf[i] = xe.xdf2.recs[i]->ptr;
\r
175 filevec[1].equivs[i] = -1;
\r
177 if (xe.xdf2.nrec > 0)
\r
178 filevec[1].linbuf[xe.xdf2.nrec] = xe.xdf2.recs[xe.xdf2.nrec - 1]->ptr + xe.xdf2.recs[xe.xdf2.nrec - 1]->size;
\r
179 filevec[0].missing_newline = is_missing_newline(mmfile1);
\r
180 filevec[1].missing_newline = is_missing_newline(mmfile2);
\r
182 change *prev = nullptr;
\r
183 for (xdchange_t* xcur = xscr; xcur; xcur = xcur->next)
\r
185 change* e = static_cast<change*>(malloc(sizeof(change)));
\r
190 e->line0 = xcur->i1;
\r
191 e->line1 = xcur->i2;
\r
192 e->deleted = xcur->chg1;
\r
193 e->inserted = xcur->chg2;
\r
196 e->trivial = static_cast<char>(xcur->ignore);
\r
204 if (bMoved_blocks_flag)
\r
206 std::vector<xrecord_t *> equivs;
\r
207 append_equivs(xe.xdf1, filevec[0], equivs, xdl_flags);
\r
208 append_equivs(xe.xdf2, filevec[1], equivs, xdl_flags);
\r
209 moved_block_analysis(&script, filevec);
\r
212 xdl_free_script(xscr);
\r