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