]> git.saurik.com Git - wxWidgets.git/blame - src/common/txtstrm.cpp
fixed memory leak in RestoreState
[wxWidgets.git] / src / common / txtstrm.cpp
CommitLineData
5a96d2f4 1///////////////////////////////////////////////////////////////////////////////
40ff126a 2// Name: src/common/txtstrm.cpp
fae05df5
GL
3// Purpose: Text stream classes
4// Author: Guilhem Lavaux
5// Modified by:
6// Created: 28/06/98
7// RCS-ID: $Id$
717b9bf2 8// Copyright: (c) Guilhem Lavaux
65571936 9// Licence: wxWindows licence
fae05df5
GL
10/////////////////////////////////////////////////////////////////////////////
11
fae05df5
GL
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
15#ifdef __BORLANDC__
16 #pragma hdrstop
17#endif
18
19#if wxUSE_STREAMS
20
0bf751e7
VS
21#ifndef WX_PRECOMP
22 #include "wx/crt.h"
23#endif
24
fae05df5 25#include "wx/txtstrm.h"
c980c992 26#include <ctype.h>
fae05df5 27
cd25b18c
RR
28
29// ----------------------------------------------------------------------------
30// constants
31// ----------------------------------------------------------------------------
32
33// Unix: "\n"
34// Dos: "\r\n"
35// Mac: "\r"
36
37// ----------------------------------------------------------------------------
38// wxTextInputStream
39// ----------------------------------------------------------------------------
40
2b5f62a0 41#if wxUSE_UNICODE
830f8f11
VZ
42wxTextInputStream::wxTextInputStream(wxInputStream &s,
43 const wxString &sep,
44 const wxMBConv& conv)
d36c9347 45 : m_input(s), m_separators(sep), m_conv(conv.Clone())
2b5f62a0 46{
2348a842 47 memset((void*)m_lastBytes, 0, 10);
2b5f62a0
VZ
48}
49#else
191549ed
SB
50wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep)
51 : m_input(s), m_separators(sep)
fae05df5 52{
2348a842 53 memset((void*)m_lastBytes, 0, 10);
fae05df5 54}
2b5f62a0 55#endif
fae05df5
GL
56
57wxTextInputStream::~wxTextInputStream()
58{
d36c9347
VZ
59#if wxUSE_UNICODE
60 delete m_conv;
61#endif // wxUSE_UNICODE
fae05df5
GL
62}
63
2348a842
VZ
64void wxTextInputStream::UngetLast()
65{
66 size_t byteCount = 0;
67 while(m_lastBytes[byteCount]) // pseudo ANSI strlen (even for Unicode!)
68 byteCount++;
69 m_input.Ungetch(m_lastBytes, byteCount);
70 memset((void*)m_lastBytes, 0, 10);
71}
72
73wxChar wxTextInputStream::NextChar()
74{
75#if wxUSE_UNICODE
76 wxChar wbuf[2];
77 memset((void*)m_lastBytes, 0, 10);
cb719f2e 78 for(size_t inlen = 0; inlen < 9; inlen++)
2348a842 79 {
253170d6
JS
80 if (!m_input.CanRead())
81 return wxEOT;
82
2348a842
VZ
83 // actually read the next character
84 m_lastBytes[inlen] = m_input.GetC();
85
cb719f2e 86 if(m_input.LastRead() <= 0)
2348a842 87 return wxEOT;
cb719f2e 88
d7f73361
VZ
89 if ( m_conv->ToWChar(wbuf, WXSIZEOF(wbuf), m_lastBytes, inlen + 1)
90 != wxCONV_FAILED )
2348a842
VZ
91 return wbuf[0];
92 }
93 // there should be no encoding which requires more than nine bytes for one character...
94 return wxEOT;
95#else
253170d6
JS
96 if (!m_input.CanRead())
97 return wxEOT;
98
2348a842 99 m_lastBytes[0] = m_input.GetC();
cb719f2e
WS
100
101 if(m_input.LastRead() <= 0)
2348a842 102 return wxEOT;
cb719f2e 103
2348a842
VZ
104 return m_lastBytes[0];
105#endif
cb719f2e 106
2348a842
VZ
107}
108
191549ed 109wxChar wxTextInputStream::NextNonSeparators()
fae05df5 110{
cd25b18c
RR
111 for (;;)
112 {
999836aa 113 wxChar c = NextChar();
2348a842 114 if (c == wxEOT) return (wxChar) 0;
cd6ce4a9
VZ
115
116 if (c != wxT('\n') &&
117 c != wxT('\r') &&
118 !m_separators.Contains(c))
119 return c;
cd25b18c 120 }
717b9bf2 121
cd25b18c 122}
fae05df5 123
f6bcfd97 124bool wxTextInputStream::EatEOL(const wxChar &c)
cd25b18c 125{
cb719f2e 126 if (c == wxT('\n')) return true; // eat on UNIX
cd6ce4a9 127
f6bcfd97 128 if (c == wxT('\r')) // eat on both Mac and DOS
717b9bf2 129 {
2348a842 130 wxChar c2 = NextChar();
cb719f2e 131 if(c2 == wxEOT) return true; // end of stream reached, had enough :-)
cd6ce4a9 132
2348a842 133 if (c2 != wxT('\n')) UngetLast(); // Don't eat on Mac
cb719f2e 134 return true;
cd25b18c 135 }
717b9bf2 136
cb719f2e 137 return false;
191549ed
SB
138}
139
2348a842 140wxUint32 wxTextInputStream::Read32(int base)
191549ed 141{
2348a842
VZ
142 wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
143 if(!m_input) return 0;
144
145 wxString word = ReadWord();
7448de8d 146 if(word.empty())
2348a842
VZ
147 return 0;
148 return wxStrtoul(word.c_str(), 0, base);
cd25b18c 149}
fae05df5 150
2348a842 151wxUint16 wxTextInputStream::Read16(int base)
cd25b18c 152{
2348a842
VZ
153 return (wxUint16)Read32(base);
154}
cd6ce4a9 155
2348a842
VZ
156wxUint8 wxTextInputStream::Read8(int base)
157{
158 return (wxUint8)Read32(base);
159}
717b9bf2 160
2348a842
VZ
161wxInt32 wxTextInputStream::Read32S(int base)
162{
163 wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
164 if(!m_input) return 0;
cd25b18c 165
2348a842 166 wxString word = ReadWord();
7448de8d 167 if(word.empty())
cd25b18c 168 return 0;
2348a842 169 return wxStrtol(word.c_str(), 0, base);
fae05df5
GL
170}
171
2348a842 172wxInt16 wxTextInputStream::Read16S(int base)
fae05df5 173{
2348a842 174 return (wxInt16)Read32S(base);
fae05df5
GL
175}
176
2348a842 177wxInt8 wxTextInputStream::Read8S(int base)
fae05df5 178{
2348a842 179 return (wxInt8)Read32S(base);
fae05df5
GL
180}
181
182double wxTextInputStream::ReadDouble()
183{
2348a842
VZ
184 if(!m_input) return 0;
185 wxString word = ReadWord();
7448de8d 186 if(word.empty())
f6bcfd97 187 return 0;
2348a842 188 return wxStrtod(word.c_str(), 0);
fae05df5
GL
189}
190
40ff126a
WS
191#if WXWIN_COMPATIBILITY_2_6
192
fae05df5 193wxString wxTextInputStream::ReadString()
9853d977 194{
cd6ce4a9 195 return ReadLine();
9853d977
SB
196}
197
40ff126a
WS
198#endif // WXWIN_COMPATIBILITY_2_6
199
9853d977 200wxString wxTextInputStream::ReadLine()
fae05df5 201{
cd25b18c
RR
202 wxString line;
203
cd6ce4a9 204 while ( !m_input.Eof() )
cd25b18c 205 {
2348a842
VZ
206 wxChar c = NextChar();
207 if(c == wxEOT)
208 break;
cb719f2e 209
cd6ce4a9
VZ
210 if (EatEOL(c))
211 break;
212
cd25b18c
RR
213 line += c;
214 }
717b9bf2 215
cd25b18c 216 return line;
fae05df5 217}
717b9bf2 218
9853d977
SB
219wxString wxTextInputStream::ReadWord()
220{
9853d977 221 wxString word;
9853d977 222
cd6ce4a9
VZ
223 if ( !m_input )
224 return word;
225
226 wxChar c = NextNonSeparators();
227 if ( !c )
228 return word;
229
f6bcfd97 230 word += c;
cb719f2e 231
cd6ce4a9 232 while ( !m_input.Eof() )
9853d977 233 {
2348a842
VZ
234 c = NextChar();
235 if(c == wxEOT)
f6bcfd97 236 break;
cb719f2e 237
cd6ce4a9
VZ
238 if (m_separators.Contains(c))
239 break;
240
241 if (EatEOL(c))
242 break;
243
9853d977 244 word += c;
9853d977
SB
245 }
246
247 return word;
248}
249
250wxTextInputStream& wxTextInputStream::operator>>(wxString& word)
fae05df5 251{
cd6ce4a9
VZ
252 word = ReadWord();
253 return *this;
fae05df5
GL
254}
255
f6bcfd97 256wxTextInputStream& wxTextInputStream::operator>>(char& c)
fae05df5 257{
191549ed 258 c = m_input.GetC();
2348a842 259 if(m_input.LastRead() <= 0) c = 0;
717b9bf2 260
f6bcfd97
BP
261 if (EatEOL(c))
262 c = '\n';
263
cd25b18c 264 return *this;
fae05df5
GL
265}
266
fcbe123e
VZ
267#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE
268
269wxTextInputStream& wxTextInputStream::operator>>(wchar_t& wc)
270{
271 wc = GetChar();
272
273 return *this;
274}
275
276#endif // wxUSE_UNICODE
277
fae05df5
GL
278wxTextInputStream& wxTextInputStream::operator>>(wxInt16& i)
279{
cd25b18c
RR
280 i = (wxInt16)Read16();
281 return *this;
fae05df5
GL
282}
283
284wxTextInputStream& wxTextInputStream::operator>>(wxInt32& i)
285{
cd25b18c
RR
286 i = (wxInt32)Read32();
287 return *this;
fae05df5
GL
288}
289
fae05df5
GL
290wxTextInputStream& wxTextInputStream::operator>>(wxUint16& i)
291{
cd25b18c
RR
292 i = Read16();
293 return *this;
fae05df5
GL
294}
295
296wxTextInputStream& wxTextInputStream::operator>>(wxUint32& i)
297{
cd25b18c
RR
298 i = Read32();
299 return *this;
fae05df5
GL
300}
301
302wxTextInputStream& wxTextInputStream::operator>>(double& i)
303{
cd25b18c
RR
304 i = ReadDouble();
305 return *this;
fae05df5
GL
306}
307
308wxTextInputStream& wxTextInputStream::operator>>(float& f)
309{
cd25b18c
RR
310 f = (float)ReadDouble();
311 return *this;
fae05df5
GL
312}
313
2b5f62a0
VZ
314
315
316#if wxUSE_UNICODE
830f8f11
VZ
317wxTextOutputStream::wxTextOutputStream(wxOutputStream& s,
318 wxEOL mode,
319 const wxMBConv& conv)
d36c9347 320 : m_output(s), m_conv(conv.Clone())
2b5f62a0 321#else
c7a9fa36 322wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode)
191549ed 323 : m_output(s)
2b5f62a0 324#endif
fae05df5 325{
c7a9fa36
RR
326 m_mode = mode;
327 if (m_mode == wxEOL_NATIVE)
328 {
329#if defined(__WXMSW__) || defined(__WXPM__)
330 m_mode = wxEOL_DOS;
f3ff3813 331#elif defined(__WXMAC__) && !defined(__DARWIN__)
c7a9fa36
RR
332 m_mode = wxEOL_MAC;
333#else
334 m_mode = wxEOL_UNIX;
335#endif
336 }
fae05df5
GL
337}
338
339wxTextOutputStream::~wxTextOutputStream()
340{
d36c9347
VZ
341#if wxUSE_UNICODE
342 delete m_conv;
343#endif // wxUSE_UNICODE
fae05df5
GL
344}
345
cd0b1709 346void wxTextOutputStream::SetMode(wxEOL mode)
c7a9fa36
RR
347{
348 m_mode = mode;
349 if (m_mode == wxEOL_NATIVE)
350 {
351#if defined(__WXMSW__) || defined(__WXPM__)
352 m_mode = wxEOL_DOS;
f3ff3813 353#elif defined(__WXMAC__) && !defined(__DARWIN__)
c7a9fa36
RR
354 m_mode = wxEOL_MAC;
355#else
356 m_mode = wxEOL_UNIX;
357#endif
358 }
359}
360
fae05df5
GL
361void wxTextOutputStream::Write32(wxUint32 i)
362{
cd25b18c 363 wxString str;
223d09f6 364 str.Printf(wxT("%u"), i);
717b9bf2 365
cd25b18c 366 WriteString(str);
fae05df5
GL
367}
368
369void wxTextOutputStream::Write16(wxUint16 i)
370{
cd25b18c 371 wxString str;
17a1ebd1 372 str.Printf(wxT("%u"), (unsigned)i);
717b9bf2 373
cd25b18c 374 WriteString(str);
fae05df5
GL
375}
376
377void wxTextOutputStream::Write8(wxUint8 i)
378{
cd25b18c 379 wxString str;
17a1ebd1 380 str.Printf(wxT("%u"), (unsigned)i);
717b9bf2 381
cd25b18c 382 WriteString(str);
fae05df5
GL
383}
384
385void wxTextOutputStream::WriteDouble(double d)
386{
cd25b18c 387 wxString str;
fae05df5 388
223d09f6 389 str.Printf(wxT("%f"), d);
cd25b18c 390 WriteString(str);
fae05df5
GL
391}
392
393void wxTextOutputStream::WriteString(const wxString& string)
394{
20ea6894
VZ
395 size_t len = string.length();
396
397 wxString out;
398 out.reserve(len);
399
400 for ( size_t i = 0; i < len; i++ )
cd25b18c 401 {
20ea6894
VZ
402 const wxChar c = string[i];
403 if ( c == wxT('\n') )
cd25b18c 404 {
20ea6894 405 switch ( m_mode )
cd6ce4a9 406 {
20ea6894
VZ
407 case wxEOL_DOS:
408 out << _T("\r\n");
409 continue;
410
411 case wxEOL_MAC:
412 out << _T('\r');
413 continue;
414
415 default:
416 wxFAIL_MSG( _T("unknown EOL mode in wxTextOutputStream") );
417 // fall through
418
419 case wxEOL_UNIX:
420 // don't treat '\n' specially
421 ;
c7a9fa36 422 }
cd25b18c 423 }
20ea6894
VZ
424
425 out << c;
7448de8d 426 }
20ea6894 427
2b5f62a0 428#if wxUSE_UNICODE
86501081
VS
429 // FIXME-UTF8: use wxCharBufferWithLength if/when we have it
430 wxCharBuffer buffer = m_conv->cWC2MB(out.wc_str(), out.length(), &len);
bfaee57e 431 m_output.Write(buffer, len);
2b5f62a0
VZ
432#else
433 m_output.Write(out.c_str(), out.length() );
434#endif
fae05df5
GL
435}
436
ba854691
RN
437wxTextOutputStream& wxTextOutputStream::PutChar(wxChar c)
438{
439#if wxUSE_UNICODE
d36c9347 440 WriteString( wxString(&c, *m_conv, 1) );
ba854691
RN
441#else
442 WriteString( wxString(&c, wxConvLocal, 1) );
443#endif
444 return *this;
445}
446
fae05df5
GL
447wxTextOutputStream& wxTextOutputStream::operator<<(const wxString& string)
448{
cd25b18c
RR
449 WriteString( string );
450 return *this;
fae05df5
GL
451}
452
f6bcfd97 453wxTextOutputStream& wxTextOutputStream::operator<<(char c)
fae05df5 454{
2b5f62a0 455 WriteString( wxString::FromAscii(c) );
cb719f2e 456
cd25b18c 457 return *this;
fae05df5
GL
458}
459
e4940feb 460#if wxUSE_UNICODE && wxWCHAR_T_IS_REAL_TYPE
3ca1bf5a
VZ
461
462wxTextOutputStream& wxTextOutputStream::operator<<(wchar_t wc)
463{
d36c9347 464 WriteString( wxString(&wc, *m_conv, 1) );
65a1bb98
VZ
465
466 return *this;
3ca1bf5a
VZ
467}
468
e4940feb 469#endif // wxUSE_UNICODE
3ca1bf5a 470
fae05df5
GL
471wxTextOutputStream& wxTextOutputStream::operator<<(wxInt16 c)
472{
78e848ca
RR
473 wxString str;
474 str.Printf(wxT("%d"), (signed int)c);
475 WriteString(str);
cd6ce4a9 476
cd25b18c 477 return *this;
fae05df5
GL
478}
479
480wxTextOutputStream& wxTextOutputStream::operator<<(wxInt32 c)
481{
78e848ca
RR
482 wxString str;
483 str.Printf(wxT("%ld"), (signed long)c);
484 WriteString(str);
cd6ce4a9 485
cd25b18c 486 return *this;
fae05df5
GL
487}
488
fae05df5
GL
489wxTextOutputStream& wxTextOutputStream::operator<<(wxUint16 c)
490{
78e848ca
RR
491 wxString str;
492 str.Printf(wxT("%u"), (unsigned int)c);
493 WriteString(str);
cd6ce4a9 494
cd25b18c 495 return *this;
fae05df5
GL
496}
497
498wxTextOutputStream& wxTextOutputStream::operator<<(wxUint32 c)
499{
78e848ca
RR
500 wxString str;
501 str.Printf(wxT("%lu"), (unsigned long)c);
502 WriteString(str);
503
cd25b18c 504 return *this;
fae05df5
GL
505}
506
507wxTextOutputStream &wxTextOutputStream::operator<<(double f)
508{
cd25b18c
RR
509 WriteDouble(f);
510 return *this;
fae05df5
GL
511}
512
513wxTextOutputStream& wxTextOutputStream::operator<<(float f)
514{
cd25b18c
RR
515 WriteDouble((double)f);
516 return *this;
fae05df5
GL
517}
518
ed58dbea
RR
519wxTextOutputStream &endl( wxTextOutputStream &stream )
520{
ba854691 521 return stream.PutChar(wxT('\n'));
ed58dbea
RR
522}
523
fae05df5
GL
524#endif
525 // wxUSE_STREAMS