OSDN Git Service

refactor
[winmerge-jp/winmerge-jp.git] / Src / xdiff_gnudiff_compat.cpp
1 #include "pch.h"\r
2 #include "cio.h"\r
3 #include "CompareOptions.h"\r
4 extern "C" {\r
5 #include "../Externals/xdiff/xinclude.h"\r
6 }\r
7 \r
8 unsigned long make_xdl_flags(const DiffutilsOptions& options)\r
9 {\r
10         unsigned long xdl_flags = 0;\r
11         switch (options.m_diffAlgorithm)\r
12         {\r
13         case DIFF_ALGORITHM_MINIMAL:\r
14                 xdl_flags |= XDF_NEED_MINIMAL;\r
15                 break;\r
16         case DIFF_ALGORITHM_PATIENCE:\r
17                 xdl_flags |= XDF_PATIENCE_DIFF;\r
18                 break;\r
19         case DIFF_ALGORITHM_HISTOGRAM:\r
20                 xdl_flags |= XDF_HISTOGRAM_DIFF;\r
21                 break;\r
22         case DIFF_ALGORITHM_NONE:\r
23                 xdl_flags |= XDF_NONE_DIFF;\r
24                 break;\r
25         default:\r
26                 break;\r
27         }\r
28         if (options.m_bIgnoreCase)\r
29                 xdl_flags |= XDF_IGNORE_CASE;\r
30         if (options.m_bIgnoreNumbers)\r
31                 xdl_flags |= XDF_IGNORE_NUMBERS;\r
32         if (options.m_bIgnoreBlankLines)\r
33                 xdl_flags |= XDF_IGNORE_BLANK_LINES;\r
34         if (options.m_bIgnoreEOLDifference)\r
35                 xdl_flags |= XDF_IGNORE_CR_AT_EOL;\r
36         switch (options.m_ignoreWhitespace)\r
37         {\r
38         case WHITESPACE_IGNORE_CHANGE:\r
39                 xdl_flags |= XDF_IGNORE_WHITESPACE_CHANGE;\r
40                 break;\r
41         case WHITESPACE_IGNORE_ALL:\r
42                 xdl_flags |= XDF_IGNORE_WHITESPACE;\r
43                 break;\r
44         default:\r
45                 break;\r
46         }\r
47         if (options.m_bIndentHeuristic)\r
48                 xdl_flags |= XDF_INDENT_HEURISTIC;\r
49         return xdl_flags;\r
50 }\r
51 \r
52 static int hunk_func(long start_a, long count_a, long start_b, long count_b, void *cb_data)\r
53 {\r
54         return 0;\r
55 }\r
56 \r
57 struct change* diff_2_buffers_xdiff(const char* ptr1, size_t size1, const char* ptr2, size_t size2, unsigned xdl_flags)\r
58 {\r
59         change *script = nullptr;\r
60         xdfenv_t xe;\r
61         xdchange_t *xscr;\r
62         xpparam_t xpp = { 0 };\r
63         xdemitconf_t xecfg = { 0 };\r
64         xdemitcb_t ecb = { 0 };\r
65         mmfile_t mmfile1 = { const_cast<char*>(ptr1), static_cast<long>(size1) };\r
66         mmfile_t mmfile2 = { const_cast<char*>(ptr2), static_cast<long>(size2) };\r
67 \r
68         xpp.flags = xdl_flags;\r
69         xecfg.hunk_func = hunk_func;\r
70 \r
71         if (xdl_diff_modified(&mmfile1, &mmfile2, &xpp, &xecfg, &ecb, &xe, &xscr) == 0)\r
72         {\r
73                 change *prev = nullptr;\r
74                 for (xdchange_t* xcur = xscr; xcur; xcur = xcur->next)\r
75                 {\r
76                         change* e = static_cast<change*>(malloc(sizeof(change)));\r
77                         if (!e)\r
78                                 goto abort;\r
79                         if (!script)\r
80                                 script = e;\r
81                         e->line0 = xcur->i1;\r
82                         e->line1 = xcur->i2;\r
83                         e->deleted = xcur->chg1;\r
84                         e->inserted = xcur->chg2;\r
85                         e->match0 = -1;\r
86                         e->match1 = -1;\r
87                         e->trivial = static_cast<char>(xcur->ignore);\r
88                         e->link = nullptr;\r
89                         e->ignore = 0;\r
90                         if (prev)\r
91                                 prev->link = e;\r
92                         prev = e;\r
93                 }\r
94 \r
95                 xdl_free_script(xscr);\r
96                 xdl_free_env(&xe);\r
97         }\r
98 \r
99         return script;\r
100 \r
101 abort:\r
102         return nullptr;\r
103 }\r
104 \r
105 struct change * diff_2_files_xdiff (struct file_data filevec[], int* bin_status, int bMoved_blocks_flag, int* bin_file, unsigned xdl_flags)\r
106 {\r
107         change *script = nullptr;\r
108 \r
109         if (read_files(filevec, no_details_flag & ~ignore_some_changes, bin_file))\r
110         {\r
111                 int i;\r
112                 int changes;\r
113                 // copy from analyze.c\r
114                 //  We can now safely assume to have a pair of Binary files.\r
115 \r
116                 // Are both files Open and Regular (no Pipes, Directories, Devices (e.g. NUL))\r
117                 if (filevec[0].desc < 0 || filevec[1].desc < 0 ||\r
118                         !(S_ISREG (filevec[0].stat.st_mode)) || !(S_ISREG (filevec[1].stat.st_mode))   )\r
119                         changes = 1;\r
120                 else\r
121                 //  Files with different lengths must be different.  \r
122                 if (filevec[0].stat.st_size != filevec[1].stat.st_size)\r
123                         changes = 1;\r
124                 else\r
125                 //  Identical descriptor implies identical files\r
126                 if (filevec[0].desc == filevec[1].desc)\r
127                         changes = 0;\r
128                 //  Scan both files, a buffer at a time, looking for a difference.  \r
129                 else\r
130                 {\r
131                         //  Same-sized buffers for both files were allocated in read_files().  \r
132                         size_t buffer_size = filevec[0].bufsize;\r
133                         \r
134                         for (;;)\r
135                         {\r
136                                 //  Read a buffer's worth from both files.  \r
137                                 for (i = 0; i < 2; i++)\r
138                                         while (filevec[i].buffered_chars < buffer_size)\r
139                                           {\r
140                                                 cio::ssize_t r = cio::read (filevec[i].desc,\r
141                                                                            filevec[i].buffer    + filevec[i].buffered_chars,\r
142                                                                            buffer_size - filevec[i].buffered_chars);\r
143                                                 if (r == 0)\r
144                                                         break;\r
145                                                 if (r < 0)\r
146                                                         pfatal_with_name (filevec[i].name);\r
147                                                 filevec[i].buffered_chars += r;\r
148                                           }\r
149                                                 \r
150                                 //  If the buffers have different number of chars, the files differ.  \r
151                                 if (filevec[0].buffered_chars != filevec[1].buffered_chars)\r
152                                 {\r
153                                         changes = 1;\r
154                                         break;\r
155                                 }\r
156 \r
157                                 //  If we reach end-of-file, the files are the same.  \r
158                                 if (filevec[0].buffered_chars==0) // therefore: filevec[1].buffered_chars==0\r
159                                 {\r
160                                         changes = 0;\r
161                                         break;\r
162                                 }       \r
163 \r
164                                 //      If buffers have different contents, the files are different.\r
165                                 if (memcmp (filevec[0].buffer,\r
166                                                         filevec[1].buffer,\r
167                                                         filevec[0].buffered_chars) != 0)\r
168                                 {\r
169                                         changes = 1;\r
170                                         break;\r
171                                 }\r
172 \r
173                                 //      Files appear identical so far...\r
174                                 //      Prepare to loop again for the next pair of buffers.\r
175                                 filevec[0].buffered_chars = filevec[1].buffered_chars = 0;\r
176                         }\r
177                 }\r
178                 if (bin_status != NULL)\r
179                         *bin_status = (changes != 0 ? -1 : 1);\r
180         }\r
181         else\r
182         {\r
183                 script = diff_2_buffers_xdiff(\r
184                         filevec[0].prefix_end,\r
185                         filevec[0].suffix_begin - filevec[0].prefix_end,\r
186                         filevec[1].prefix_end,\r
187                         filevec[1].suffix_begin - filevec[1].prefix_end,\r
188                         xdl_flags);\r
189                 if (bMoved_blocks_flag)\r
190                         moved_block_analysis(&script, filevec);\r
191         }\r
192 \r
193         return script;\r
194 }\r