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 48wxFFile::wxFFile(const wxChar *filename, const wxChar *mode) 49{ 50 Detach(); 51 52 (void)Open(filename, mode); 53} 54 55bool 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 73bool 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 94bool 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 124size_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 138size_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 152bool 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 173bool 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 218wxFileOffset 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 233wxFileOffset 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