OSDN Git Service

Reduce compilation time (2)
[winmerge-jp/winmerge-jp.git] / Src / DiffFileData.cpp
1 /** 
2  * @file DiffFileData.cpp
3  *
4  * @brief Code for DiffFileData class
5  *
6  * @date  Created: 2003-08-22
7  */
8
9 #include "pch.h"
10 #include "DiffFileData.h"
11 #include <io.h>
12 #include <memory>
13 #include "DiffItem.h"
14 #include "FileLocation.h"
15 #include "diff.h"
16 #include "TFile.h"
17 #include "FileTransform.h"
18 #include "unicoder.h"
19 #include "DebugNew.h"
20
21 /**
22  * @brief Simple initialization of DiffFileData
23  * @note Diffcounts are initialized to invalid values, not zeros.
24  */
25 DiffFileData::DiffFileData()
26 : m_inf(new file_data[2])
27 {
28         int i = 0;
29         for (i = 0; i < 2; ++i)
30                 memset(&m_inf[i], 0, sizeof(m_inf[i]));
31         m_used = false;
32         Reset();
33 }
34
35 /** @brief deallocate member data */
36 DiffFileData::~DiffFileData()
37 {
38         Reset();
39         delete [] m_inf;
40 }
41
42 /** @brief Open file descriptors in the inf structure (return false if failure) */
43 bool DiffFileData::OpenFiles(const String& szFilepath1, const String& szFilepath2)
44 {
45         m_FileLocation[0].setPath(szFilepath1);
46         m_FileLocation[1].setPath(szFilepath2);
47         bool b = DoOpenFiles();
48         if (!b)
49                 Reset();
50         return b;
51 }
52
53 /** @brief stash away true names for display, before opening files */
54 void DiffFileData::SetDisplayFilepaths(const String& szTrueFilepath1, const String& szTrueFilepath2)
55 {
56         m_sDisplayFilepath[0] = szTrueFilepath1;
57         m_sDisplayFilepath[1] = szTrueFilepath2;
58 }
59
60
61 /** @brief Open file descriptors in the inf structure (return false if failure) */
62 bool DiffFileData::DoOpenFiles()
63 {
64         Reset();
65
66         for (int i = 0; i < 2; ++i)
67         {
68                 // Fill in 8-bit versions of names for diffutils (WinMerge doesn't use these)
69                 // Actual paths are m_FileLocation[i].filepath
70                 // but these are often temporary files
71                 // Displayable (original) paths are m_sDisplayFilepath[i]
72                 m_inf[i].name = _strdup(ucr::toSystemCP(m_sDisplayFilepath[i]).c_str());
73                 if (m_inf[i].name == nullptr)
74                         return false;
75
76                 // Open up file descriptors
77                 // Always use O_BINARY mode, to avoid terminating file read on ctrl-Z (DOS EOF)
78                 // Also, WinMerge-modified diffutils handles all three major eol styles
79                 if (m_inf[i].desc == 0)
80                 {
81                         _tsopen_s(&m_inf[i].desc, TFile(m_FileLocation[i].filepath).wpath().c_str(),
82                                         O_RDONLY | O_BINARY, _SH_DENYWR, _S_IREAD);
83                 }
84                 if (m_inf[i].desc < 0)
85                         return false;
86
87                 // Get file stats (diffutils uses these)
88                 if (myfstat(m_inf[i].desc, &m_inf[i].stat) != 0)
89                 {
90                         return false;
91                 }
92                 
93                 if (strutils::compare_nocase(m_FileLocation[0].filepath,
94                                 m_FileLocation[1].filepath) == 0)
95                 {
96                         m_inf[1].desc = m_inf[0].desc;
97                 }
98         }
99
100         m_used = true;
101         return true;
102 }
103
104 /** @brief Clear inf structure to pristine */
105 void DiffFileData::Reset()
106 {
107         assert(m_inf != nullptr);
108         // If diffutils put data in, have it cleanup
109         if (m_used)
110         {
111                 cleanup_file_buffers(m_inf);
112                 m_used = false;
113         }
114         // clean up any open file handles, and zero stuff out
115         // open file handles might be leftover from a failure in DiffFileData::OpenFiles
116         for (int i = 0; i < 2; ++i)
117         {
118                 if (m_inf[1].desc == m_inf[0].desc)
119                 {
120                         m_inf[1].desc = 0;
121                 }
122                 free((void *)m_inf[i].name);
123                 m_inf[i].name = nullptr;
124
125                 if (m_inf[i].desc > 0)
126                 {
127                         _close(m_inf[i].desc);
128                 }
129                 m_inf[i].desc = 0;
130                 memset(&m_inf[i], 0, sizeof(m_inf[i]));
131         }
132 }
133
134 /**
135  * @brief Invoke appropriate plugins for prediffing
136  * return false if anything fails
137  * caller has to DeleteFile filepathTransformed, if it differs from filepath
138  */
139 bool DiffFileData::Filepath_Transform(bool bForceUTF8,
140         const FileTextEncoding & encoding, const String & filepath, String & filepathTransformed,
141         const String& filteredFilenames, PrediffingInfo * infoPrediffer)
142 {
143         // third step : prediff (plugins)
144         bool bMayOverwrite =  // temp variable set each time it is used
145                 (filepathTransformed != filepath); // may overwrite if we've already copied to temp file
146
147         // FileTransform_Prediffing tries each prediffer for the pointed out filteredFilenames
148         // if a prediffer fails, we consider it is not the good one, that's all
149         // FileTransform_Prediffing returns `false` only if the prediffer works, 
150         // but the data can not be saved to disk (no more place ??)
151         if (!FileTransform::Prediffing(infoPrediffer, filepathTransformed, filteredFilenames, bMayOverwrite))
152                 return false;
153
154         if ((encoding.m_unicoding && encoding.m_unicoding != ucr::UTF8) || bForceUTF8)
155         {
156                 // fourth step : prepare for diffing
157                 // may overwrite if we've already copied to temp file
158                 bool bMayOverwrite1 = 0 != strutils::compare_nocase(filepathTransformed, filepath);
159                 if (!FileTransform::AnyCodepageToUTF8(encoding.m_codepage, filepathTransformed, bMayOverwrite1))
160                         return false;
161         }
162         return true;
163 }