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