]> git.saurik.com Git - wxWidgets.git/blob - src/common/ffile.cpp
invalidate the best size when adding or deleting items
[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 // 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 // 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, const 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 = wx_truncate_cast(size_t, Length());
112 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
113
114 clearerr(m_fp);
115
116 wxCharBuffer buf(length + 1);
117
118 // note that real length may be less than file length for text files with DOS EOLs
119 // ('\r's get dropped by CRT when reading which means that we have
120 // realLen = fileLen - numOfLinesInTheFile)
121 length = fread(buf.data(), sizeof(char), length, m_fp);
122
123 if ( Error() )
124 {
125 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
126
127 return false;
128 }
129
130 buf.data()[length] = 0;
131 *str = wxString(buf, conv);
132
133 return true;
134 }
135
136 size_t wxFFile::Read(void *pBuf, size_t nCount)
137 {
138 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
139 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
140
141 size_t nRead = fread(pBuf, 1, nCount, m_fp);
142 if ( (nRead < nCount) && Error() )
143 {
144 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
145 }
146
147 return nRead;
148 }
149
150 size_t wxFFile::Write(const void *pBuf, size_t nCount)
151 {
152 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
153 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
154
155 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
156 if ( nWritten < nCount )
157 {
158 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
159 }
160
161 return nWritten;
162 }
163
164 bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
165 {
166 const wxWX2MBbuf buf = s.mb_str(conv);
167 if ( !buf )
168 return false;
169
170 const size_t size = strlen(buf); // FIXME: use buf.length() when available
171 return Write(buf, size) == size;
172 }
173
174 bool wxFFile::Flush()
175 {
176 if ( IsOpened() )
177 {
178 if ( fflush(m_fp) != 0 )
179 {
180 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
181
182 return false;
183 }
184 }
185
186 return true;
187 }
188
189 // ----------------------------------------------------------------------------
190 // seeking
191 // ----------------------------------------------------------------------------
192
193 bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
194 {
195 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
196
197 int origin;
198 switch ( mode )
199 {
200 default:
201 wxFAIL_MSG(wxT("unknown seek mode"));
202 // still fall through
203
204 case wxFromStart:
205 origin = SEEK_SET;
206 break;
207
208 case wxFromCurrent:
209 origin = SEEK_CUR;
210 break;
211
212 case wxFromEnd:
213 origin = SEEK_END;
214 break;
215 }
216
217 #ifndef HAVE_FSEEKO
218 if ((long)ofs != ofs)
219 {
220 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
221
222 return false;
223 }
224
225 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
226 #else
227 if ( wxFseek(m_fp, ofs, origin) != 0 )
228 #endif
229 {
230 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
231
232 return false;
233 }
234
235 return true;
236 }
237
238 wxFileOffset wxFFile::Tell() const
239 {
240 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
241 _T("wxFFile::Tell(): file is closed!") );
242
243 wxFileOffset rc = wxFtell(m_fp);
244 if ( rc == wxInvalidOffset )
245 {
246 wxLogSysError(_("Can't find current position in file '%s'"),
247 m_name.c_str());
248 }
249
250 return rc;
251 }
252
253 wxFileOffset wxFFile::Length() const
254 {
255 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
256 _T("wxFFile::Length(): file is closed!") );
257
258 wxFFile& self = *(wxFFile *)this; // const_cast
259
260 wxFileOffset posOld = Tell();
261 if ( posOld != wxInvalidOffset )
262 {
263 if ( self.SeekEnd() )
264 {
265 wxFileOffset len = Tell();
266
267 (void)self.Seek(posOld);
268
269 return len;
270 }
271 }
272
273 return wxInvalidOffset;
274 }
275
276 #endif // wxUSE_FFILE