OSDN Git Service

Improve plugin system (#797)
[winmerge-jp/winmerge-jp.git] / Src / Common / UniFile.h
1 /**
2  *  @file   UniFile.h
3  *  @author Perry Rapp, Creator, 2003-2006
4  *  @date   Created: 2003-10
5  *  @date   Edited:  2006-02-20 (Perry Rapp)
6  *
7  *  @brief  Declaration of Unicode file classes.
8  */
9 #pragma once
10
11 #include "unicoder.h"
12
13 namespace Poco { class SharedMemory; }
14
15 /**
16  * @brief Interface to file classes in this module
17  */
18 class UniFile
19 {
20 public:
21
22         /**
23          * @brief A struct for error message or error code.
24          */
25         struct UniError
26         {
27                 String desc; // valid if apiname empty
28
29                 UniError();
30                 bool HasError() const;
31                 void ClearError();
32                 String GetError() const;
33         };
34
35         virtual ~UniFile() { }
36         virtual bool OpenReadOnly(const String& filename) = 0;
37         virtual void Close() = 0;
38         virtual bool IsOpen() const = 0;
39
40         virtual String GetFullyQualifiedPath() const = 0;
41         virtual const UniError & GetLastUniError() const = 0;
42
43         virtual bool IsUnicode() = 0;
44         virtual bool ReadBom() = 0;
45         virtual bool HasBom() const = 0;
46         virtual void SetBom(bool bom) = 0;
47
48         virtual ucr::UNICODESET GetUnicoding() const = 0;
49         virtual void SetUnicoding(ucr::UNICODESET unicoding) = 0;
50         virtual int GetCodepage() const = 0;
51         virtual void SetCodepage(int codepage) = 0;
52
53 public:
54         virtual bool ReadString(String & line, bool * lossy) = 0;
55         virtual bool ReadString(String & line, String & eol, bool * lossy) = 0;
56         virtual bool ReadStringAll(String & line) = 0;
57         virtual int GetLineNumber() const = 0;
58         virtual int64_t GetPosition() const = 0;
59         virtual bool WriteString(const String & line) = 0;
60
61         struct txtstats
62         {
63                 int ncrs;
64                 int nlfs;
65                 int ncrlfs;
66                 int nzeros;
67                 int nlosses;
68                 txtstats() { clear(); }
69                 void clear() { ncrs = nlfs = ncrlfs = nzeros = nlosses = 0; }
70         };
71         virtual const txtstats & GetTxtStats() const = 0;
72 };
73
74 /**
75  * @brief Check if there is error.
76  * @return true if there is an error.
77  */
78 inline bool UniFile::UniError::HasError() const
79 {
80         return !desc.empty();
81 }
82
83 /**
84  * @brief Clears the existing error.
85  */
86 inline void UniFile::UniError::ClearError()
87 {
88         desc.erase();
89 }
90
91 /**
92  * @brief Get the error string.
93  * @return Error string.
94  */
95 inline String UniFile::UniError::GetError() const
96 {
97         return desc;
98 }
99
100 /**
101  * @brief Local file access code used by both UniMemFile and UniStdioFile
102  *
103  * This class lacks an actual handle to a file
104  */
105 class UniLocalFile : public UniFile
106 {
107 public:
108         UniLocalFile();
109         void Clear();
110
111         virtual String GetFullyQualifiedPath() const override { return m_filepath; }
112         virtual const UniError & GetLastUniError() const override { return m_lastError; }
113
114         virtual ucr::UNICODESET GetUnicoding() const override { return m_unicoding; }
115         virtual void SetUnicoding(ucr::UNICODESET unicoding) override { m_unicoding = unicoding; }
116         virtual int GetCodepage() const override { return m_codepage; }
117         virtual void SetCodepage(int codepage) override { 
118                 m_codepage = codepage;
119                 switch (m_codepage)
120                 {
121                 case ucr::CP_UCS2LE:
122                         m_unicoding = ucr::UCS2LE;
123                         m_charsize = 2;
124                         break;
125                 case ucr::CP_UCS2BE:
126                         m_unicoding = ucr::UCS2BE;
127                         m_charsize = 2;
128                         break;
129                 case ucr::CP_UTF_8:
130                         m_charsize = 1;
131                         m_unicoding = ucr::UTF8;
132                         break;
133                 default:
134                         m_charsize = 1;
135                         m_unicoding = ucr::NONE;
136                         break;
137                 }
138         }
139
140         virtual int GetLineNumber() const override { return m_lineno; }
141         virtual const txtstats & GetTxtStats() const override { return m_txtstats; }
142         virtual int64_t GetFileSize() const{ return m_filesize; }
143
144         bool IsUnicode() override;
145
146 protected:
147         virtual bool DoGetFileStatus();
148         virtual void LastErrorCustom(const String& desc);
149
150 protected:
151         int m_statusFetched; // 0 not fetched, -1 error, +1 success
152         int64_t m_filesize;
153         String m_filepath;
154         String m_filename;
155         int m_lineno; // current 0-based line of m_current
156         UniError m_lastError;
157         ucr::UNICODESET m_unicoding;
158         int m_charsize; // 2 for UCS-2, else 1
159         int m_codepage; // only valid if m_unicoding==ucr::NONE;
160         txtstats m_txtstats;
161         bool m_bom; /**< Did the file have a BOM when reading? */
162         bool m_bUnicodingChecked; /**< Has unicoding been checked for the file? */
163         bool m_bUnicode; /**< Is the file unicode file? */
164 };
165
166 /**
167  * @brief Memory-Mapped disk file (read-only access)
168  */
169 class UniMemFile : public UniLocalFile
170 {
171 public:
172         enum AccessMode
173         {
174                 AM_READ = 0,
175                 AM_WRITE
176         };
177
178         UniMemFile();
179         virtual ~UniMemFile() { Close(); }
180
181         virtual bool GetFileStatus();
182
183         virtual bool OpenReadOnly(const String& filename) override;
184         virtual bool Open(const String& filename);
185         virtual bool Open(const String& filename, AccessMode mode);
186         void Close() override;
187         virtual bool IsOpen() const override;
188
189         virtual bool ReadBom() override;
190         virtual bool HasBom() const override;
191         virtual void SetBom(bool bom) override;
192
193 public:
194         virtual bool ReadString(String & line, bool * lossy) override;
195         virtual bool ReadString(String & line, String & eol, bool * lossy) override;
196         virtual bool ReadStringAll(String & line) override;
197         virtual int64_t GetPosition() const override { return m_current - m_base; }
198         virtual bool WriteString(const String & line) override;
199         unsigned char* GetBase() const { return m_base; }
200
201 // Implementation methods
202 protected:
203         virtual bool DoOpen(const String& filename, AccessMode mode);
204
205 // Implementation data
206 private:
207         Poco::SharedMemory *m_hMapping;
208         unsigned char *m_base; // points to base of mapping
209         unsigned char *m_data; // similar to m_base, but after BOM if any
210         unsigned char *m_current; // current location in file
211 };
212
213 /** @brief Is it currently attached to a file ? */
214 inline bool UniMemFile::IsOpen() const
215 {
216         // We don't test the handle here, because we allow "opening" empty file
217         // but memory-mapping doesn't work on that, so that uses a special state
218         // of no handle, but linenumber of 0
219         return m_lineno >= 0;
220 }
221
222 /**
223  * @brief Returns if file has a BOM bytes.
224  * @return true if file has BOM bytes, false otherwise.
225  */
226 inline bool UniMemFile::HasBom() const
227 {
228         return m_bom;
229 }
230
231 /**
232  * @brief Sets if file has BOM or not.
233  * @param [in] true to have a BOM in file, false to not to have.
234  */
235 inline void UniMemFile::SetBom(bool bom)
236 {
237         m_bom = bom;
238 }
239
240 /**
241  * @brief Regular buffered file (write-only access)
242  * (ReadString methods have never been implemented,
243  *  because UniMemFile above is good for reading)
244  */
245 class UniStdioFile : public UniLocalFile
246 {
247 public:
248         UniStdioFile();
249         ~UniStdioFile();
250
251         virtual bool GetFileStatus();
252
253         virtual bool OpenReadOnly(const String& filename) override;
254         virtual bool OpenCreate(const String& filename);
255         virtual bool OpenCreateUtf8(const String& filename);
256         virtual bool Open(const String& filename, const String& mode);
257         void Close() override;
258
259         virtual bool IsOpen() const override;
260
261         virtual bool ReadBom() override;
262         virtual bool HasBom() const override;
263         virtual void SetBom(bool bom) override;
264
265 protected:
266         virtual bool ReadString(String & line, bool * lossy) override;
267         virtual bool ReadString(String & line, String & eol, bool * lossy) override;
268         virtual bool ReadStringAll(String & line) override;
269
270 public:
271         virtual int64_t GetPosition() const override;
272
273         virtual int WriteBom();
274         virtual bool WriteString(const String & line) override;
275
276 // Implementation methods
277 protected:
278         virtual bool DoOpen(const String& filename, const String& mode);
279         virtual void LastErrorCustom(const String& desc) override;
280
281 // Implementation data
282 private:
283         FILE * m_fp;
284         int64_t m_data; // offset after any initial BOM
285         ucr::buffer m_ucrbuff;
286 };
287
288 /** @brief Is it currently attached to a file ? */
289 inline bool UniStdioFile::IsOpen() const
290 {
291         return m_fp != 0;
292 }
293
294 /**
295  * @brief Returns if file has a BOM bytes.
296  * @return true if file has BOM bytes, false otherwise.
297  */
298 inline bool UniStdioFile::HasBom() const
299 {
300         return m_bom;
301 }
302
303 /**
304  * @brief Sets if file has BOM or not.
305  * @param [in] true to have a BOM in file, false to not to have.
306  */
307 inline void UniStdioFile::SetBom(bool bom)
308 {
309         m_bom = bom;
310 }
311
312