don't fail in wxTransferStreamToFile if file size is exact multiple of 4KB (bug 1835918)
[wxWidgets.git] / src / common / wfstream.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/fstream.cpp
3 // Purpose: "File stream" classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 11/07/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #if wxUSE_STREAMS
20
21 #include "wx/wfstream.h"
22
23 #ifndef WX_PRECOMP
24 #include "wx/stream.h"
25 #endif
26
27 #include <stdio.h>
28
29 #if wxUSE_FILE
30
31 // ----------------------------------------------------------------------------
32 // wxFileInputStream
33 // ----------------------------------------------------------------------------
34
35 wxFileInputStream::wxFileInputStream(const wxString& fileName)
36 : wxInputStream()
37 {
38 m_file = new wxFile(fileName, wxFile::read);
39 m_file_destroy = true;
40 if ( !m_file->IsOpened() )
41 m_lasterror = wxSTREAM_READ_ERROR;
42 }
43
44 wxFileInputStream::wxFileInputStream()
45 : wxInputStream()
46 {
47 m_file_destroy = false;
48 m_file = NULL;
49 }
50
51 wxFileInputStream::wxFileInputStream(wxFile& file)
52 {
53 m_file = &file;
54 m_file_destroy = false;
55 }
56
57 wxFileInputStream::wxFileInputStream(int fd)
58 {
59 m_file = new wxFile(fd);
60 m_file_destroy = true;
61 }
62
63 wxFileInputStream::~wxFileInputStream()
64 {
65 if (m_file_destroy)
66 delete m_file;
67 }
68
69 wxFileOffset wxFileInputStream::GetLength() const
70 {
71 return m_file->Length();
72 }
73
74 size_t wxFileInputStream::OnSysRead(void *buffer, size_t size)
75 {
76 ssize_t ret = m_file->Read(buffer, size);
77
78 // NB: we can't use a switch here because HP-UX CC doesn't allow
79 // switching over long long (which size_t is in 64bit mode)
80
81 if ( !ret )
82 {
83 // nothing read, so nothing more to read
84 m_lasterror = wxSTREAM_EOF;
85 }
86 else if ( ret == wxInvalidOffset )
87 {
88 m_lasterror = wxSTREAM_READ_ERROR;
89 ret = 0;
90 }
91 else
92 {
93 // normal case
94 m_lasterror = wxSTREAM_NO_ERROR;
95 }
96
97 return ret;
98 }
99
100 wxFileOffset wxFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
101 {
102 return m_file->Seek(pos, mode);
103 }
104
105 wxFileOffset wxFileInputStream::OnSysTell() const
106 {
107 return m_file->Tell();
108 }
109
110 bool wxFileInputStream::IsOk() const
111 {
112 return wxInputStream::IsOk() && m_file->IsOpened();
113 }
114
115 // ----------------------------------------------------------------------------
116 // wxFileOutputStream
117 // ----------------------------------------------------------------------------
118
119 wxFileOutputStream::wxFileOutputStream(const wxString& fileName)
120 {
121 m_file = new wxFile(fileName, wxFile::write);
122 m_file_destroy = true;
123
124 if (!m_file->IsOpened())
125 m_lasterror = wxSTREAM_WRITE_ERROR;
126 }
127
128 wxFileOutputStream::wxFileOutputStream(wxFile& file)
129 {
130 m_file = &file;
131 m_file_destroy = false;
132 }
133
134 wxFileOutputStream::wxFileOutputStream()
135 : wxOutputStream()
136 {
137 m_file_destroy = false;
138 m_file = NULL;
139 }
140
141 wxFileOutputStream::wxFileOutputStream(int fd)
142 {
143 m_file = new wxFile(fd);
144 m_file_destroy = true;
145 }
146
147 wxFileOutputStream::~wxFileOutputStream()
148 {
149 if (m_file_destroy)
150 {
151 Sync();
152 delete m_file;
153 }
154 }
155
156 size_t wxFileOutputStream::OnSysWrite(const void *buffer, size_t size)
157 {
158 size_t ret = m_file->Write(buffer, size);
159
160 m_lasterror = m_file->Error() ? wxSTREAM_WRITE_ERROR : wxSTREAM_NO_ERROR;
161
162 return ret;
163 }
164
165 wxFileOffset wxFileOutputStream::OnSysTell() const
166 {
167 return m_file->Tell();
168 }
169
170 wxFileOffset wxFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
171 {
172 return m_file->Seek(pos, mode);
173 }
174
175 void wxFileOutputStream::Sync()
176 {
177 wxOutputStream::Sync();
178 m_file->Flush();
179 }
180
181 wxFileOffset wxFileOutputStream::GetLength() const
182 {
183 return m_file->Length();
184 }
185
186 bool wxFileOutputStream::IsOk() const
187 {
188 return wxOutputStream::IsOk() && m_file->IsOpened();
189 }
190
191 // ----------------------------------------------------------------------------
192 // wxTempFileOutputStream
193 // ----------------------------------------------------------------------------
194
195 wxTempFileOutputStream::wxTempFileOutputStream(const wxString& fileName)
196 {
197 m_file = new wxTempFile(fileName);
198
199 if (!m_file->IsOpened())
200 m_lasterror = wxSTREAM_WRITE_ERROR;
201 }
202
203 wxTempFileOutputStream::~wxTempFileOutputStream()
204 {
205 if (m_file->IsOpened())
206 Discard();
207 delete m_file;
208 }
209
210 size_t wxTempFileOutputStream::OnSysWrite(const void *buffer, size_t size)
211 {
212 if (IsOk() && m_file->Write(buffer, size))
213 return size;
214 m_lasterror = wxSTREAM_WRITE_ERROR;
215 return 0;
216 }
217
218 // ----------------------------------------------------------------------------
219 // wxFileStream
220 // ----------------------------------------------------------------------------
221
222 wxFileStream::wxFileStream(const wxString& fileName)
223 : wxFileInputStream(fileName)
224 {
225 wxFileOutputStream::m_file = wxFileInputStream::m_file;
226 }
227
228 bool wxFileStream::IsOk() const
229 {
230 return wxFileOutputStream::IsOk() && wxFileInputStream::IsOk();
231 }
232
233 #endif // wxUSE_FILE
234
235 #if wxUSE_FFILE
236
237 // ----------------------------------------------------------------------------
238 // wxFFileInputStream
239 // ----------------------------------------------------------------------------
240
241 wxFFileInputStream::wxFFileInputStream(const wxString& fileName,
242 const wxString& mode)
243 : wxInputStream()
244 {
245 m_file = new wxFFile(fileName, mode);
246 m_file_destroy = true;
247
248 if (!m_file->IsOpened())
249 m_lasterror = wxSTREAM_WRITE_ERROR;
250 }
251
252 wxFFileInputStream::wxFFileInputStream()
253 : wxInputStream()
254 {
255 m_file = NULL;
256 m_file_destroy = false;
257 }
258
259 wxFFileInputStream::wxFFileInputStream(wxFFile& file)
260 {
261 m_file = &file;
262 m_file_destroy = false;
263 }
264
265 wxFFileInputStream::wxFFileInputStream(FILE *file)
266 {
267 m_file = new wxFFile(file);
268 m_file_destroy = true;
269 }
270
271 wxFFileInputStream::~wxFFileInputStream()
272 {
273 if (m_file_destroy)
274 delete m_file;
275 }
276
277 wxFileOffset wxFFileInputStream::GetLength() const
278 {
279 return m_file->Length();
280 }
281
282 size_t wxFFileInputStream::OnSysRead(void *buffer, size_t size)
283 {
284 ssize_t ret = m_file->Read(buffer, size);
285
286 // It is not safe to call Eof() if the file is not opened.
287 if (!m_file->IsOpened() || m_file->Eof())
288 m_lasterror = wxSTREAM_EOF;
289 if (ret == wxInvalidOffset)
290 {
291 m_lasterror = wxSTREAM_READ_ERROR;
292 ret = 0;
293 }
294
295 return ret;
296 }
297
298 wxFileOffset wxFFileInputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
299 {
300 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
301 }
302
303 wxFileOffset wxFFileInputStream::OnSysTell() const
304 {
305 return m_file->Tell();
306 }
307
308 bool wxFFileInputStream::IsOk() const
309 {
310 return wxStreamBase::IsOk() && m_file->IsOpened();
311 }
312
313 // ----------------------------------------------------------------------------
314 // wxFFileOutputStream
315 // ----------------------------------------------------------------------------
316
317 wxFFileOutputStream::wxFFileOutputStream(const wxString& fileName,
318 const wxString& mode)
319 {
320 m_file = new wxFFile(fileName, mode);
321 m_file_destroy = true;
322
323 if (!m_file->IsOpened())
324 {
325 m_lasterror = wxSTREAM_WRITE_ERROR;
326 }
327 else
328 {
329 if (m_file->Error())
330 m_lasterror = wxSTREAM_WRITE_ERROR;
331 }
332 }
333
334 wxFFileOutputStream::wxFFileOutputStream(wxFFile& file)
335 {
336 m_file = &file;
337 m_file_destroy = false;
338 }
339
340 wxFFileOutputStream::wxFFileOutputStream()
341 : wxOutputStream()
342 {
343 m_file = NULL;
344 m_file_destroy = false;
345 }
346
347 wxFFileOutputStream::wxFFileOutputStream(FILE *file)
348 {
349 m_file = new wxFFile(file);
350 m_file_destroy = true;
351 }
352
353 wxFFileOutputStream::~wxFFileOutputStream()
354 {
355 if (m_file_destroy)
356 {
357 Sync();
358 delete m_file;
359 }
360 }
361
362 size_t wxFFileOutputStream::OnSysWrite(const void *buffer, size_t size)
363 {
364 size_t ret = m_file->Write(buffer, size);
365 // It is not safe to call Error() if the file is not opened.
366 if (!m_file->IsOpened() || m_file->Error())
367 m_lasterror = wxSTREAM_WRITE_ERROR;
368 else
369 m_lasterror = wxSTREAM_NO_ERROR;
370 return ret;
371 }
372
373 wxFileOffset wxFFileOutputStream::OnSysTell() const
374 {
375 return m_file->Tell();
376 }
377
378 wxFileOffset wxFFileOutputStream::OnSysSeek(wxFileOffset pos, wxSeekMode mode)
379 {
380 return m_file->Seek(pos, mode) ? m_file->Tell() : wxInvalidOffset;
381 }
382
383 void wxFFileOutputStream::Sync()
384 {
385 wxOutputStream::Sync();
386 m_file->Flush();
387 }
388
389 wxFileOffset wxFFileOutputStream::GetLength() const
390 {
391 return m_file->Length();
392 }
393
394 bool wxFFileOutputStream::IsOk() const
395 {
396 return wxStreamBase::IsOk() && m_file->IsOpened();
397 }
398
399 // ----------------------------------------------------------------------------
400 // wxFFileStream
401 // ----------------------------------------------------------------------------
402
403 wxFFileStream::wxFFileStream(const wxString& fileName)
404 : wxFFileInputStream(fileName)
405 {
406 wxFFileOutputStream::m_file = wxFFileInputStream::m_file;
407 }
408
409 bool wxFFileStream::IsOk() const
410 {
411 return wxFFileOutputStream::IsOk() && wxFFileInputStream::IsOk();
412 }
413
414 #endif //wxUSE_FFILE
415
416 #endif // wxUSE_STREAMS