]> git.saurik.com Git - wxWidgets.git/blame - src/common/ffile.cpp
Ensure that strings returned by wxMBConv_cf are in NFC form.
[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
45// ----------------------------------------------------------------------------
46// opening the file
47// ----------------------------------------------------------------------------
48
6626de90 49wxFFile::wxFFile(const wxString& filename, const wxString& mode)
a1b82138
VZ
50{
51 Detach();
52
53 (void)Open(filename, mode);
54}
55
6626de90 56bool wxFFile::Open(const wxString& filename, const wxString& mode)
a1b82138 57{
223d09f6 58 wxASSERT_MSG( !m_fp, wxT("should close or detach the old file first") );
a1b82138 59
90e2cbf7 60 m_fp = wxFopen(filename, mode);
a1b82138
VZ
61
62 if ( !m_fp )
63 {
64 wxLogSysError(_("can't open file '%s'"), filename);
65
a62848fd 66 return false;
a1b82138
VZ
67 }
68
69 m_name = filename;
70
a62848fd 71 return true;
a1b82138
VZ
72}
73
74bool wxFFile::Close()
75{
76 if ( IsOpened() )
77 {
d2e1ef19 78 if ( fclose(m_fp) != 0 )
a1b82138
VZ
79 {
80 wxLogSysError(_("can't close file '%s'"), m_name.c_str());
81
a62848fd 82 return false;
a1b82138
VZ
83 }
84
85 Detach();
86 }
87
a62848fd 88 return true;
a1b82138
VZ
89}
90
91// ----------------------------------------------------------------------------
92// read/write
93// ----------------------------------------------------------------------------
94
830f8f11 95bool wxFFile::ReadAll(wxString *str, const wxMBConv& conv)
a1b82138 96{
a62848fd
WS
97 wxCHECK_MSG( str, false, wxT("invalid parameter") );
98 wxCHECK_MSG( IsOpened(), false, wxT("can't read from closed file") );
11846af3 99 wxCHECK_MSG( Length() >= 0, false, wxT("invalid length") );
17a1ebd1 100 size_t length = wx_truncate_cast(size_t, Length());
c3816108 101 wxCHECK_MSG( (wxFileOffset)length == Length(), false, wxT("huge file not supported") );
a1b82138
VZ
102
103 clearerr(m_fp);
104
2a9c0905 105 wxCharBuffer buf(length + 1);
f281f29f 106
2a9c0905 107 // note that real length may be less than file length for text files with DOS EOLs
f281f29f
VZ
108 // ('\r's get dropped by CRT when reading which means that we have
109 // realLen = fileLen - numOfLinesInTheFile)
2a9c0905 110 length = fread(buf.data(), sizeof(char), length, m_fp);
f281f29f 111
03647350 112 if ( Error() )
a1b82138 113 {
3e15dde3 114 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
a1b82138 115
3e15dde3 116 return false;
a1b82138
VZ
117 }
118
2a9c0905 119 buf.data()[length] = 0;
3e15dde3
VZ
120 *str = wxString(buf, conv);
121
a62848fd 122 return true;
a1b82138
VZ
123}
124
125size_t wxFFile::Read(void *pBuf, size_t nCount)
126{
2a9c0905
WS
127 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
128 wxCHECK_MSG( IsOpened(), 0, wxT("can't read from closed file") );
a1b82138
VZ
129
130 size_t nRead = fread(pBuf, 1, nCount, m_fp);
131 if ( (nRead < nCount) && Error() )
132 {
133 wxLogSysError(_("Read error on file '%s'"), m_name.c_str());
134 }
135
136 return nRead;
137}
138
139size_t wxFFile::Write(const void *pBuf, size_t nCount)
140{
2a9c0905
WS
141 wxCHECK_MSG( pBuf, 0, wxT("invalid parameter") );
142 wxCHECK_MSG( IsOpened(), 0, wxT("can't write to closed file") );
a1b82138
VZ
143
144 size_t nWritten = fwrite(pBuf, 1, nCount, m_fp);
145 if ( nWritten < nCount )
146 {
147 wxLogSysError(_("Write error on file '%s'"), m_name.c_str());
148 }
149
150 return nWritten;
151}
152
b1c67394
VZ
153bool wxFFile::Write(const wxString& s, const wxMBConv& conv)
154{
155 const wxWX2MBbuf buf = s.mb_str(conv);
156 if ( !buf )
157 return false;
158
159 const size_t size = strlen(buf); // FIXME: use buf.length() when available
160 return Write(buf, size) == size;
161}
162
a1b82138
VZ
163bool wxFFile::Flush()
164{
165 if ( IsOpened() )
166 {
b1c67394 167 if ( fflush(m_fp) != 0 )
a1b82138
VZ
168 {
169 wxLogSysError(_("failed to flush the file '%s'"), m_name.c_str());
170
a62848fd 171 return false;
a1b82138
VZ
172 }
173 }
174
a62848fd 175 return true;
a1b82138
VZ
176}
177
178// ----------------------------------------------------------------------------
179// seeking
180// ----------------------------------------------------------------------------
181
70a7bd90 182bool wxFFile::Seek(wxFileOffset ofs, wxSeekMode mode)
a1b82138 183{
a62848fd 184 wxCHECK_MSG( IsOpened(), false, wxT("can't seek on closed file") );
a1b82138
VZ
185
186 int origin;
187 switch ( mode )
188 {
189 default:
223d09f6 190 wxFAIL_MSG(wxT("unknown seek mode"));
a1b82138
VZ
191 // still fall through
192
193 case wxFromStart:
194 origin = SEEK_SET;
195 break;
196
197 case wxFromCurrent:
198 origin = SEEK_CUR;
199 break;
200
201 case wxFromEnd:
202 origin = SEEK_END;
203 break;
204 }
205
224d978f 206#ifndef wxHAS_LARGE_FFILES
70a7bd90
VZ
207 if ((long)ofs != ofs)
208 {
209 wxLogError(_("Seek error on file '%s' (large files not supported by stdio)"), m_name.c_str());
210
211 return false;
212 }
70a7bd90 213
11846af3
WS
214 if ( wxFseek(m_fp, (long)ofs, origin) != 0 )
215#else
70a7bd90 216 if ( wxFseek(m_fp, ofs, origin) != 0 )
11846af3 217#endif
a1b82138
VZ
218 {
219 wxLogSysError(_("Seek error on file '%s'"), m_name.c_str());
220
a62848fd 221 return false;
a1b82138
VZ
222 }
223
a62848fd 224 return true;
a1b82138
VZ
225}
226
70a7bd90 227wxFileOffset wxFFile::Tell() const
a1b82138 228{
70a7bd90 229 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
9a83f860 230 wxT("wxFFile::Tell(): file is closed!") );
de2ce07c 231
70a7bd90
VZ
232 wxFileOffset rc = wxFtell(m_fp);
233 if ( rc == wxInvalidOffset )
a1b82138
VZ
234 {
235 wxLogSysError(_("Can't find current position in file '%s'"),
236 m_name.c_str());
237 }
238
70a7bd90 239 return rc;
a1b82138
VZ
240}
241
70a7bd90 242wxFileOffset wxFFile::Length() const
a1b82138 243{
70a7bd90 244 wxCHECK_MSG( IsOpened(), wxInvalidOffset,
9a83f860 245 wxT("wxFFile::Length(): file is closed!") );
de2ce07c 246
f48a1159 247 wxFFile& self = *const_cast<wxFFile *>(this);
a1b82138 248
70a7bd90
VZ
249 wxFileOffset posOld = Tell();
250 if ( posOld != wxInvalidOffset )
a1b82138
VZ
251 {
252 if ( self.SeekEnd() )
253 {
70a7bd90 254 wxFileOffset len = Tell();
a1b82138
VZ
255
256 (void)self.Seek(posOld);
257
258 return len;
259 }
260 }
261
11846af3 262 return wxInvalidOffset;
a1b82138
VZ
263}
264
1e6feb95 265#endif // wxUSE_FFILE