]> git.saurik.com Git - wxWidgets.git/blob - src/common/ffile.cpp
fixed bug in ReadAll(): it always returned error when reading files with DOS EOLs...
[wxWidgets.git] / src / common / ffile.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: ffile.cpp
3 // Purpose: wxFFile encapsulates "FILE *" IO stream
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 14.07.99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "ffile.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_FFILE
32
33 #ifndef WX_PRECOMP
34 #include "wx/intl.h"
35 #include "wx/log.h"
36 #endif
37
38 #include "wx/ffile.h"
39
40 // ============================================================================
41 // implementation
42 // ============================================================================
43
44 // ----------------------------------------------------------------------------
45 // seek and tell with large file support if available
46 // ----------------------------------------------------------------------------
47
48 #ifdef HAVE_FSEEKO
49 # define wxFseek fseeko
50 # define wxFtell ftello
51 #else
52 # define wxFseek fseek
53 # define wxFtell ftell
54 #endif
55
56 // ----------------------------------------------------------------------------
57 // opening the file
58 // ----------------------------------------------------------------------------
59
60 wxFFile::wxFFile(const wxChar *filename, const wxChar *mode)
61 {
62 Detach();
63
64 (void)Open(filename, mode);
65 }
66
67 bool wxFFile::Open(const wxChar *filename, const wxChar *mode)
68 {
69 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
70
71 m_fp = wxFopen(filename, mode);
72
73 if ( !m_fp )
74 {
75 wxLogSysError(_("can't open file '%s'"), filename);
76
77 return false;
78 }
79
80 m_name = filename;
81
82 return true;
83 }
84
85 bool wxFFile::Close()
86 {
87 if ( IsOpened() )
88 {
89 if ( fclose(m_fp) != 0 )
90 {
91 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
92
93 return false;
94 }
95
96 Detach();
97 }
98
99 return true;
100 }
101
102 // ----------------------------------------------------------------------------
103 // read/write
104 // ----------------------------------------------------------------------------
105
106 bool wxFFile::ReadAll(wxString *str, wxMBConv& conv)
107 {
108 wxCHECK_MSG( str, false, wxT("invalid parameter") );
109 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
110 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
111 size_t length = (size_t)Length();
112 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
113
114 clearerr(m_fp);
115
116 const size_t fileLen = Length();
117 wxCharBuffer buf(fileLen + 1);
118
119 // note that realLen may be less than fileLen for text files with DOS EOLs
120 // ('\r's get dropped by CRT when reading which means that we have
121 // realLen = fileLen - numOfLinesInTheFile)
122 size_t realLen = fread(buf.data(), sizeof(char), fileLen, m_fp);
123
124 if ( Error() )
125 {
126 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
127
128 return false;
129 }
130
131 buf.data()[realLen] = 0;
132 *str = wxString(buf, conv);
133
134 return true;
135 }
136
137 size_t wxFFile::Read(void *pBuf, size_t nCount)
138 {
139 wxCHECK_MSG( pBuf, FALSE, wxT("invalid parameter") );
140 wxCHECK_MSG( IsOpened(), FALSE, wxT("can't read from closed file") );
141
142 size_t nRead = fread(pBuf, 1, nCount, m_fp);
143 if ( (nRead < nCount) && Error() )
144 {
145 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
146 }
147
148 return nRead;
149 }
150
151 size_t wxFFile::Write(const void *pBuf, size_t nCount)
152 {
153 wxCHECK_MSG( pBuf, FALSE, wxT("invalid parameter") );
154 wxCHECK_MSG( IsOpened(), FALSE, wxT("can't write to closed file") );
155
156 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
157 if ( nWritten < nCount )
158 {
159 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
160 }
161
162 return nWritten;
163 }
164
165 bool wxFFile::Flush()
166 {
167 if ( IsOpened() )
168 {
169 // fflush returns non-zero on error
170 //
171 if ( fflush(m_fp) )
172 {
173 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
174
175 return false;
176 }
177 }
178
179 return true;
180 }
181
182 // ----------------------------------------------------------------------------
183 // seeking
184 // ----------------------------------------------------------------------------
185
186 bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
187 {
188 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
189
190 int origin;
191 switch ( mode )
192 {
193 default:
194 wxFAIL_MSG(wxT("unknown seek mode"));
195 // still fall through
196
197 case wxFromStart:
198 origin = SEEK_SET;
199 break;
200
201 case wxFromCurrent:
202 origin = SEEK_CUR;
203 break;
204
205 case wxFromEnd:
206 origin = SEEK_END;
207 break;
208 }
209
210 #ifndef HAVE_FSEEKO
211 if ((long)ofs != ofs)
212 {
213 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
214
215 return false;
216 }
217
218 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
219 #else
220 if ( wxFseek(m_fp, ofs, origin) != 0 )
221 #endif
222 {
223 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
224
225 return false;
226 }
227
228 return true;
229 }
230
231 wxFileOffset wxFFile::Tell() const
232 {
233 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
234 _T("wxFFile::Tell(): file is closed!") );
235
236 wxFileOffset rc = wxFtell(m_fp);
237 if ( rc == wxInvalidOffset )
238 {
239 wxLogSysError(_("Can't find current position in file '%s'"),
240 m_name.c_str());
241 }
242
243 return rc;
244 }
245
246 wxFileOffset wxFFile::Length() const
247 {
248 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
249 _T("wxFFile::Length(): file is closed!") );
250
251 wxFFile& self = *(wxFFile *)this; // const_cast
252
253 wxFileOffset posOld = Tell();
254 if ( posOld != wxInvalidOffset )
255 {
256 if ( self.SeekEnd() )
257 {
258 wxFileOffset len = Tell();
259
260 (void)self.Seek(posOld);
261
262 return len;
263 }
264 }
265
266 return wxInvalidOffset;
267 }
268
269 #endif // wxUSE_FFILE