]> git.saurik.com Git - wxWidgets.git/blame - src/common/ffile.cpp
Pass length including the null-terminator to cWC2MB
[wxWidgets.git] / src / common / ffile.cpp
CommitLineData
a1b82138
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: ffile.cpp
90e2cbf7 3// Purpose: wxFFile encapsulates "FILE *" IO stream
a1b82138
VZ
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>
65571936 9// Licence: wxWindows licence
a1b82138
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
a1b82138
VZ
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
1e6feb95 27#if wxUSE_FFILE
a1b82138
VZ
28
29#ifndef WX_PRECOMP
0efe5ba7
VZ
30 #include "wx/intl.h"
31 #include "wx/log.h"
0bf751e7 32 #include "wx/crt.h"
a1b82138
VZ
33#endif
34
89220a94
CE
35#ifdef __WINDOWS__
36#include "wx/msw/mslu.h"
37#endif
38
a1b82138
VZ
39#include "wx/ffile.h"
40
41// ============================================================================
42// implementation
43// ============================================================================
44
70a7bd90
VZ
45// ----------------------------------------------------------------------------
46// seek and tell with large file support if available
47// ----------------------------------------------------------------------------
48
49#ifdef HAVE_FSEEKO
50# define wxFseek fseeko
51# define wxFtell ftello
52#else
53# define wxFseek fseek
54# define wxFtell ftell
55#endif
56
a1b82138
VZ
57// ----------------------------------------------------------------------------
58// opening the file
59// ----------------------------------------------------------------------------
60
6626de90 61wxFFile::wxFFile(const wxString& filename, const wxString& mode)
a1b82138
VZ
62{
63 Detach();
64
65 (void)Open(filename, mode);
66}
67
6626de90 68bool wxFFile::Open(const wxString& filename, const wxString& mode)
a1b82138 69{
223d09f6 70 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
a1b82138 71
90e2cbf7 72 m_fp = wxFopen(filename, mode);
a1b82138
VZ
73
74 if ( !m_fp )
75 {
76 wxLogSysError(_("can't open file '%s'"), filename);
77
a62848fd 78 return false;
a1b82138
VZ
79 }
80
81 m_name = filename;
82
a62848fd 83 return true;
a1b82138
VZ
84}
85
86bool wxFFile::Close()
87{
88 if ( IsOpened() )
89 {
d2e1ef19 90 if ( fclose(m_fp) != 0 )
a1b82138
VZ
91 {
92 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
93
a62848fd 94 return false;
a1b82138
VZ
95 }
96
97 Detach();
98 }
99
a62848fd 100 return true;
a1b82138
VZ
101}
102
103// ----------------------------------------------------------------------------
104// read/write
105// ----------------------------------------------------------------------------
106
830f8f11 107bool wxFFile::ReadAll(wxString *str, const wxMBConv& conv)
a1b82138 108{
a62848fd
WS
109 wxCHECK_MSG( str, false, wxT("invalid parameter") );
110 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
11846af3 111 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
17a1ebd1 112 size_t length = wx_truncate_cast(size_t, Length());
c3816108 113 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
a1b82138
VZ
114
115 clearerr(m_fp);
116
2a9c0905 117 wxCharBuffer buf(length + 1);
f281f29f 118
2a9c0905 119 // note that real length may be less than file length for text files with DOS EOLs
f281f29f
VZ
120 // ('\r's get dropped by CRT when reading which means that we have
121 // realLen = fileLen - numOfLinesInTheFile)
2a9c0905 122 length = fread(buf.data(), sizeof(char), length, m_fp);
f281f29f
VZ
123
124 if ( Error() )
a1b82138 125 {
3e15dde3 126 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
a1b82138 127
3e15dde3 128 return false;
a1b82138
VZ
129 }
130
2a9c0905 131 buf.data()[length] = 0;
3e15dde3
VZ
132 *str = wxString(buf, conv);
133
a62848fd 134 return true;
a1b82138
VZ
135}
136
137size_t wxFFile::Read(void *pBuf, size_t nCount)
138{
2a9c0905
WS
139 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
140 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
a1b82138
VZ
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
151size_t wxFFile::Write(const void *pBuf, size_t nCount)
152{
2a9c0905
WS
153 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
154 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
a1b82138
VZ
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
b1c67394
VZ
165bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
166{
167 const wxWX2MBbuf buf = s.mb_str(conv);
168 if ( !buf )
169 return false;
170
171 const size_t size = strlen(buf); // FIXME: use buf.length() when available
172 return Write(buf, size) == size;
173}
174
a1b82138
VZ
175bool wxFFile::Flush()
176{
177 if ( IsOpened() )
178 {
b1c67394 179 if ( fflush(m_fp) != 0 )
a1b82138
VZ
180 {
181 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
182
a62848fd 183 return false;
a1b82138
VZ
184 }
185 }
186
a62848fd 187 return true;
a1b82138
VZ
188}
189
190// ----------------------------------------------------------------------------
191// seeking
192// ----------------------------------------------------------------------------
193
70a7bd90 194bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
a1b82138 195{
a62848fd 196 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
a1b82138
VZ
197
198 int origin;
199 switch ( mode )
200 {
201 default:
223d09f6 202 wxFAIL_MSG(wxT("unknown seek mode"));
a1b82138
VZ
203 // still fall through
204
205 case wxFromStart:
206 origin = SEEK_SET;
207 break;
208
209 case wxFromCurrent:
210 origin = SEEK_CUR;
211 break;
212
213 case wxFromEnd:
214 origin = SEEK_END;
215 break;
216 }
217
11846af3 218#ifndef HAVE_FSEEKO
70a7bd90
VZ
219 if ((long)ofs != ofs)
220 {
221 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
222
223 return false;
224 }
70a7bd90 225
11846af3
WS
226 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
227#else
70a7bd90 228 if ( wxFseek(m_fp, ofs, origin) != 0 )
11846af3 229#endif
a1b82138
VZ
230 {
231 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
232
a62848fd 233 return false;
a1b82138
VZ
234 }
235
a62848fd 236 return true;
a1b82138
VZ
237}
238
70a7bd90 239wxFileOffset wxFFile::Tell() const
a1b82138 240{
70a7bd90 241 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
de2ce07c
VZ
242 _T("wxFFile::Tell(): file is closed!") );
243
70a7bd90
VZ
244 wxFileOffset rc = wxFtell(m_fp);
245 if ( rc == wxInvalidOffset )
a1b82138
VZ
246 {
247 wxLogSysError(_("Can't find current position in file '%s'"),
248 m_name.c_str());
249 }
250
70a7bd90 251 return rc;
a1b82138
VZ
252}
253
70a7bd90 254wxFileOffset wxFFile::Length() const
a1b82138 255{
70a7bd90 256 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
de2ce07c
VZ
257 _T("wxFFile::Length(): file is closed!") );
258
a1b82138
VZ
259 wxFFile& self = *(wxFFile *)this; // const_cast
260
70a7bd90
VZ
261 wxFileOffset posOld = Tell();
262 if ( posOld != wxInvalidOffset )
a1b82138
VZ
263 {
264 if ( self.SeekEnd() )
265 {
70a7bd90 266 wxFileOffset len = Tell();
a1b82138
VZ
267
268 (void)self.Seek(posOld);
269
270 return len;
271 }
272 }
273
11846af3 274 return wxInvalidOffset;
a1b82138
VZ
275}
276
1e6feb95 277#endif // wxUSE_FFILE