OSDN Git Service

f37a165181b2e176e935e6e432edb8f22eb04602
[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         friend class UniMarkdownFile;
172 public:
173         enum AccessMode
174         {
175                 AM_READ = 0,
176                 AM_WRITE
177         };
178
179         UniMemFile();
180         virtual ~UniMemFile() { Close(); }
181
182         virtual bool GetFileStatus();
183
184         virtual bool OpenReadOnly(const String& filename) override;
185         virtual bool Open(const String& filename);
186         virtual bool Open(const String& filename, AccessMode mode);
187         void Close() override;
188         virtual bool IsOpen() const override;
189
190         virtual bool ReadBom() override;
191         virtual bool HasBom() const override;
192         virtual void SetBom(bool bom) override;
193
194 public:
195         virtual bool ReadString(String & line, bool * lossy) override;
196         virtual bool ReadString(String & line, String & eol, bool * lossy) override;
197         virtual bool ReadStringAll(String & line) override;
198         virtual int64_t GetPosition() const override { return m_current - m_base; }
199         virtual bool WriteString(const String & line) override;
200         unsigned char* GetBase() const { return m_base; }
201
202 // Implementation methods
203 protected:
204         virtual bool DoOpen(const String& filename, AccessMode mode);
205
206 // Implementation data
207 private:
208         Poco::SharedMemory *m_hMapping;
209         unsigned char *m_base; // points to base of mapping
210         unsigned char *m_data; // similar to m_base, but after BOM if any
211         unsigned char *m_current; // current location in file
212 };
213
214 /** @brief Is it currently attached to a file ? */
215 inline bool UniMemFile::IsOpen() const
216 {
217         // We don't test the handle here, because we allow "opening" empty file
218         // but memory-mapping doesn't work on that, so that uses a special state
219         // of no handle, but linenumber of 0
220         return m_lineno >= 0;
221 }
222
223 /**
224  * @brief Returns if file has a BOM bytes.
225  * @return true if file has BOM bytes, false otherwise.
226  */
227 inline bool UniMemFile::HasBom() const
228 {
229         return m_bom;
230 }
231
232 /**
233  * @brief Sets if file has BOM or not.
234  * @param [in] true to have a BOM in file, false to not to have.
235  */
236 inline void UniMemFile::SetBom(bool bom)
237 {
238         m_bom = bom;
239 }
240
241 /**
242  * @brief Regular buffered file (write-only access)
243  * (ReadString methods have never been implemented,
244  *  because UniMemFile above is good for reading)
245  */
246 class UniStdioFile : public UniLocalFile
247 {
248 public:
249         UniStdioFile();
250         ~UniStdioFile();
251
252         virtual bool GetFileStatus();
253
254         virtual bool OpenReadOnly(const String& filename) override;
255         virtual bool OpenCreate(const String& filename);
256         virtual bool OpenCreateUtf8(const String& filename);
257         virtual bool Open(const String& filename, const String& mode);
258         void Close() override;
259
260         virtual bool IsOpen() const override;
261
262         virtual bool ReadBom() override;
263         virtual bool HasBom() const override;
264         virtual void SetBom(bool bom) override;
265
266 protected:
267         virtual bool ReadString(String & line, bool * lossy) override;
268         virtual bool ReadString(String & line, String & eol, bool * lossy) override;
269         virtual bool ReadStringAll(String & line) override;
270
271 public:
272         virtual int64_t GetPosition() const override;
273
274         virtual int WriteBom();
275         virtual bool WriteString(const String & line) override;
276
277 // Implementation methods
278 protected:
279         virtual bool DoOpen(const String& filename, const String& mode);
280         virtual void LastErrorCustom(const String& desc) override;
281
282 // Implementation data
283 private:
284         FILE * m_fp;
285         int64_t m_data; // offset after any initial BOM
286         ucr::buffer m_ucrbuff;
287 };
288
289 /** @brief Is it currently attached to a file ? */
290 inline bool UniStdioFile::IsOpen() const
291 {
292         return m_fp != 0;
293 }
294
295 /**
296  * @brief Returns if file has a BOM bytes.
297  * @return true if file has BOM bytes, false otherwise.
298  */
299 inline bool UniStdioFile::HasBom() const
300 {
301         return m_bom;
302 }
303
304 /**
305  * @brief Sets if file has BOM or not.
306  * @param [in] true to have a BOM in file, false to not to have.
307  */
308 inline void UniStdioFile::SetBom(bool bom)
309 {
310         m_bom = bom;
311 }
312
313