/[pcsx2_0.9.7]/trunk/3rdparty/wxWidgets/src/common/textfile.cpp
ViewVC logotype

Annotation of /trunk/3rdparty/wxWidgets/src/common/textfile.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (hide annotations) (download)
Tue Sep 7 03:24:11 2010 UTC (10 years, 4 months ago) by william
File size: 9009 byte(s)
committing r3113 initial commit again...
1 william 31 ///////////////////////////////////////////////////////////////////////////////
2     // Name: src/common/textfile.cpp
3     // Purpose: implementation of wxTextFile class
4     // Author: Vadim Zeitlin
5     // Modified by:
6     // Created: 03.04.98
7     // RCS-ID: $Id: textfile.cpp 49298 2007-10-21 18:05:49Z SC $
8     // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9     // Licence: wxWindows licence
10     ///////////////////////////////////////////////////////////////////////////////
11    
12     // ============================================================================
13     // headers
14     // ============================================================================
15    
16     #include "wx/wxprec.h"
17    
18     #ifdef __BORLANDC__
19     #pragma hdrstop
20     #endif //__BORLANDC__
21    
22     #if !wxUSE_FILE || !wxUSE_TEXTBUFFER
23     #undef wxUSE_TEXTFILE
24     #define wxUSE_TEXTFILE 0
25     #endif // wxUSE_FILE
26    
27     #if wxUSE_TEXTFILE
28    
29     #ifndef WX_PRECOMP
30     #include "wx/string.h"
31     #include "wx/intl.h"
32     #include "wx/file.h"
33     #include "wx/log.h"
34     #endif
35    
36     #include "wx/textfile.h"
37     #include "wx/filename.h"
38     #include "wx/buffer.h"
39    
40     // ============================================================================
41     // wxTextFile class implementation
42     // ============================================================================
43    
44     wxTextFile::wxTextFile(const wxString& strFileName)
45     : wxTextBuffer(strFileName)
46     {
47     }
48    
49    
50     // ----------------------------------------------------------------------------
51     // file operations
52     // ----------------------------------------------------------------------------
53    
54     bool wxTextFile::OnExists() const
55     {
56     return wxFile::Exists(m_strBufferName);
57     }
58    
59    
60     bool wxTextFile::OnOpen(const wxString &strBufferName, wxTextBufferOpenMode OpenMode)
61     {
62     wxFile::OpenMode FileOpenMode;
63    
64     switch ( OpenMode )
65     {
66     default:
67     wxFAIL_MSG( _T("unknown open mode in wxTextFile::Open") );
68     // fall through
69    
70     case ReadAccess :
71     FileOpenMode = wxFile::read;
72     break;
73    
74     case WriteAccess :
75     FileOpenMode = wxFile::write;
76     break;
77     }
78    
79     return m_file.Open(strBufferName.c_str(), FileOpenMode);
80     }
81    
82    
83     bool wxTextFile::OnClose()
84     {
85     return m_file.Close();
86     }
87    
88    
89     bool wxTextFile::OnRead(const wxMBConv& conv)
90     {
91     // file should be opened
92     wxASSERT_MSG( m_file.IsOpened(), _T("can't read closed file") );
93    
94     // read the entire file in memory: this is not the most efficient thing to
95     // do but there is no good way to avoid it in Unicode build because if we
96     // read the file block by block we can't convert each block to Unicode
97     // separately (the last multibyte char in the block might be only partially
98     // read and so the conversion would fail) and, as the file contents is kept
99     // in memory by wxTextFile anyhow, it shouldn't be a big problem to read
100     // the file entirely
101     size_t bufSize = 0,
102     bufPos = 0;
103     char block[1024];
104     wxCharBuffer buf;
105    
106     // first determine if the file is seekable or not and so whether we can
107     // determine its length in advance
108     wxFileOffset fileLength;
109     {
110     wxLogNull logNull;
111     fileLength = m_file.Length();
112     }
113    
114     // some non-seekable files under /proc under Linux pretend that they're
115     // seekable but always return 0; others do return an error
116     const bool seekable = fileLength != wxInvalidOffset && fileLength != 0;
117     if ( seekable )
118     {
119     // we know the required length, so set the buffer size in advance
120     bufSize = fileLength;
121     if ( !buf.extend(bufSize - 1 /* it adds 1 internally */) )
122     return false;
123    
124     // if the file is seekable, also check that we're at its beginning
125     wxASSERT_MSG( m_file.Tell() == 0, _T("should be at start of file") );
126     }
127    
128     for ( ;; )
129     {
130     ssize_t nRead = m_file.Read(block, WXSIZEOF(block));
131    
132     if ( nRead == wxInvalidOffset )
133     {
134     // read error (error message already given in wxFile::Read)
135     return false;
136     }
137    
138     if ( nRead == 0 )
139     {
140     // if no bytes have been read, presumably this is a valid-but-empty file
141     if ( bufPos == 0 )
142     return true;
143    
144     // otherwise we've finished reading the file
145     break;
146     }
147    
148     if ( seekable )
149     {
150     // this shouldn't happen but don't overwrite the buffer if it does
151     wxCHECK_MSG( bufPos + nRead <= bufSize, false,
152     _T("read more than file length?") );
153     }
154     else // !seekable
155     {
156     // for non-seekable files we have to allocate more memory on the go
157     if ( !buf.extend(bufPos + nRead - 1 /* it adds 1 internally */) )
158     return false;
159     }
160    
161     // append to the buffer
162     memcpy(buf.data() + bufPos, block, nRead);
163     bufPos += nRead;
164     }
165    
166     if ( !seekable )
167     {
168     bufSize = bufPos;
169     }
170    
171     const wxString str(buf, conv, bufPos);
172    
173     // there's no risk of this happening in ANSI build
174     #if wxUSE_UNICODE
175     if ( bufSize > 4 && str.empty() )
176     {
177     wxLogError(_("Failed to convert file \"%s\" to Unicode."), GetName());
178     return false;
179     }
180     #endif // wxUSE_UNICODE
181    
182     // we don't need this memory any more
183     // PCSX2 : So let's free it using the buffer object's API, instead of some idiotic
184     // low-level hack (bug found thanks to the use of custom heap allocation). --air
185     //free(buf.release());
186     buf.reset();
187    
188    
189     // now break the buffer in lines
190    
191     // last processed character, we need to know if it was a CR or not
192     wxChar chLast = '\0';
193    
194     // the beginning of the current line, changes inside the loop
195     wxString::const_iterator lineStart = str.begin();
196     const wxString::const_iterator end = str.end();
197     for ( wxString::const_iterator p = lineStart; p != end; p++ )
198     {
199     const wxChar ch = *p;
200     switch ( ch )
201     {
202     case '\n':
203     // could be a DOS or Unix EOL
204     if ( chLast == '\r' )
205     {
206     if ( p - 1 >= lineStart )
207     {
208     AddLine(wxString(lineStart, p - 1), wxTextFileType_Dos);
209     }
210     else
211     {
212     // there were two line endings, so add an empty line:
213     AddLine(wxEmptyString, wxTextFileType_Dos);
214     }
215     }
216     else // bare '\n', Unix style
217     {
218     AddLine(wxString(lineStart, p), wxTextFileType_Unix);
219     }
220    
221     lineStart = p + 1;
222     break;
223    
224     case '\r':
225     if ( chLast == '\r' )
226     {
227     if ( p - 1 >= lineStart )
228     {
229     AddLine(wxString(lineStart, p - 1), wxTextFileType_Mac);
230     }
231     // Mac empty line
232     AddLine(wxEmptyString, wxTextFileType_Mac);
233     lineStart = p + 1;
234     }
235     //else: we don't know what this is yet -- could be a Mac EOL or
236     // start of DOS EOL so wait for next char
237     break;
238    
239     default:
240     if ( chLast == '\r' )
241     {
242     // Mac line termination
243     if ( p - 1 >= lineStart )
244     {
245     AddLine(wxString(lineStart, p - 1), wxTextFileType_Mac);
246     }
247     else
248     {
249     // there were two line endings, so add an empty line:
250     AddLine(wxEmptyString, wxTextFileType_Mac);
251     }
252     lineStart = p;
253     }
254     }
255    
256     chLast = ch;
257     }
258    
259     // anything in the last line?
260     if ( lineStart != end )
261     {
262     // add unterminated last line
263     AddLine(wxString(lineStart, end), wxTextFileType_None);
264     }
265    
266     return true;
267     }
268    
269    
270     bool wxTextFile::OnWrite(wxTextFileType typeNew, const wxMBConv& conv)
271     {
272     wxFileName fn = m_strBufferName;
273    
274     // We do NOT want wxPATH_NORM_CASE here, or the case will not
275     // be preserved.
276     if ( !fn.IsAbsolute() )
277     fn.Normalize(wxPATH_NORM_ENV_VARS | wxPATH_NORM_DOTS | wxPATH_NORM_TILDE |
278     wxPATH_NORM_ABSOLUTE | wxPATH_NORM_LONG);
279    
280     wxTempFile fileTmp(fn.GetFullPath());
281    
282     if ( !fileTmp.IsOpened() ) {
283     wxLogError(_("can't write buffer '%s' to disk."), m_strBufferName.c_str());
284     return false;
285     }
286    
287     size_t nCount = GetLineCount();
288     for ( size_t n = 0; n < nCount; n++ ) {
289     fileTmp.Write(GetLine(n) +
290     GetEOL(typeNew == wxTextFileType_None ? GetLineType(n)
291     : typeNew),
292     conv);
293     }
294    
295     // replace the old file with this one
296     return fileTmp.Commit();
297     }
298    
299     #endif // wxUSE_TEXTFILE

  ViewVC Help
Powered by ViewVC 1.1.22