Fixed copyrights and licence spelling
[wxWidgets.git] / src / common / txtstrm.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: txtstrm.cpp
3 // Purpose: Text stream classes
4 // Author: Guilhem Lavaux
5 // Modified by:
6 // Created: 28/06/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Guilhem Lavaux
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "txtstrm.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #if wxUSE_STREAMS
24
25 #include "wx/txtstrm.h"
26 #include <ctype.h>
27
28
29 // ----------------------------------------------------------------------------
30 // constants
31 // ----------------------------------------------------------------------------
32
33 // Unix: "\n"
34 // Dos: "\r\n"
35 // Mac: "\r"
36
37 // ----------------------------------------------------------------------------
38 // wxTextInputStream
39 // ----------------------------------------------------------------------------
40
41 #if wxUSE_UNICODE
42 wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep, wxMBConv& conv)
43 : m_input(s), m_separators(sep), m_conv(conv)
44 {
45 }
46 #else
47 wxTextInputStream::wxTextInputStream(wxInputStream &s, const wxString &sep)
48 : m_input(s), m_separators(sep)
49 {
50 }
51 #endif
52
53 wxTextInputStream::~wxTextInputStream()
54 {
55 }
56
57 wxChar wxTextInputStream::NextNonSeparators()
58 {
59 wxChar c = (wxChar) 0;
60 for (;;)
61 {
62 if (!m_input) return (wxChar) 0;
63 c = m_input.GetC();
64
65 if (c != wxT('\n') &&
66 c != wxT('\r') &&
67 !m_separators.Contains(c))
68 return c;
69 }
70
71 }
72
73 bool wxTextInputStream::EatEOL(const wxChar &c)
74 {
75 if (c == wxT('\n')) return TRUE; // eat on UNIX
76
77 if (c == wxT('\r')) // eat on both Mac and DOS
78 {
79 if (!m_input) return TRUE;
80 wxChar c2 = m_input.GetC();
81
82 if (c2 != wxT('\n')) m_input.Ungetch( c2 ); // Don't eat on Mac
83 return TRUE;
84 }
85
86 return FALSE;
87 }
88
89 void wxTextInputStream::SkipIfEndOfLine( wxChar c )
90 {
91 if (EatEOL(c)) return;
92 else m_input.Ungetch( c ); // no line terminator
93 }
94
95 wxUint32 wxTextInputStream::Read32()
96 {
97 /* I only implemented a simple integer parser */
98 // VZ: what about using strtol()?? (TODO)
99
100 int sign;
101 wxInt32 i;
102
103 if (!m_input) return 0;
104 int c = NextNonSeparators();
105 if (c==(wxChar)0) return 0;
106
107 i = 0;
108 if (! (c == wxT('-') || c == wxT('+') || isdigit(c)) )
109 {
110 m_input.Ungetch(c);
111 return 0;
112 }
113
114 if (c == wxT('-'))
115 {
116 sign = -1;
117 c = m_input.GetC();
118 } else
119 if (c == wxT('+'))
120 {
121 sign = 1;
122 c = m_input.GetC();
123 } else
124 {
125 sign = 1;
126 }
127
128 while (isdigit(c))
129 {
130 i = i*10 + (c - (int)wxT('0'));
131 c = m_input.GetC();
132 }
133
134 SkipIfEndOfLine( c );
135
136 i *= sign;
137
138 return (wxUint32)i;
139 }
140
141 wxUint16 wxTextInputStream::Read16()
142 {
143 return (wxUint16)Read32();
144 }
145
146 wxUint8 wxTextInputStream::Read8()
147 {
148 return (wxUint8)Read32();
149 }
150
151 double wxTextInputStream::ReadDouble()
152 {
153 /* I only implemented a simple float parser
154 * VZ: what about using strtod()?? (TODO)
155 */
156
157 double f;
158 int theSign;
159
160 if (!m_input)
161 return 0;
162
163 int c = NextNonSeparators();
164 if (c==(wxChar)0) return 0;
165
166 f = 0.0;
167 if (! (c == wxT('.') || c == wxT(',') || c == wxT('-') || c == wxT('+') || isdigit(c)) )
168 {
169 m_input.Ungetch(c);
170 return 0;
171 }
172
173 if (c == wxT('-'))
174 {
175 theSign = -1;
176 c = m_input.GetC();
177 } else
178 if (c == wxT('+'))
179 {
180 theSign = 1;
181 c = m_input.GetC();
182 }
183 else
184 {
185 theSign = 1;
186 }
187
188 while (isdigit(c))
189 {
190 f = f*10 + (c - wxT('0'));
191 c = m_input.GetC();
192 }
193
194 if (c == wxT('.') || c == wxT(','))
195 {
196 double f_multiplicator = (double) 0.1;
197
198 c = m_input.GetC();
199
200 while (isdigit(c))
201 {
202 f += (c-wxT('0'))*f_multiplicator;
203 f_multiplicator /= 10;
204 c = m_input.GetC();
205 }
206
207 if (c == wxT('e'))
208 {
209 double f_multiplicator = 0.0;
210 int i, e;
211
212 c = m_input.GetC();
213
214 switch (c)
215 {
216 case wxT('-'): f_multiplicator = 0.1; break;
217 case wxT('+'): f_multiplicator = 10.0; break;
218 }
219
220 e = Read8(); // why only max 256 ?
221
222 for (i=0;i<e;i++)
223 f *= f_multiplicator;
224 }
225 else
226 SkipIfEndOfLine( c );
227 }
228 else
229 {
230 m_input.Ungetch(c);
231 }
232
233 f *= theSign;
234 return f;
235 }
236
237 wxString wxTextInputStream::ReadString()
238 {
239 return ReadLine();
240 }
241
242 wxString wxTextInputStream::ReadLine()
243 {
244 wxString line;
245
246 while ( !m_input.Eof() )
247 {
248 #if wxUSE_UNICODE
249 // FIXME: this is only works for single byte encodings
250 // How-to read a single char in an unkown encoding???
251 char buf[10];
252 buf[0] = m_input.GetC();
253 buf[1] = 0;
254
255 wxChar wbuf[2];
256 m_conv.MB2WC( wbuf, buf, 2 );
257 wxChar c = wbuf[0];
258 #else
259 char c = m_input.GetC();
260 #endif
261
262 if ( !m_input )
263 break;
264
265 if (EatEOL(c))
266 break;
267
268 line += c;
269 }
270
271 return line;
272 }
273
274 wxString wxTextInputStream::ReadWord()
275 {
276 wxString word;
277
278 if ( !m_input )
279 return word;
280
281 wxChar c = NextNonSeparators();
282 if ( !c )
283 return word;
284
285 word += c;
286
287 while ( !m_input.Eof() )
288 {
289 c = m_input.GetC();
290
291 if (!m_input)
292 break;
293
294 if (m_separators.Contains(c))
295 break;
296
297 if (EatEOL(c))
298 break;
299
300 word += c;
301 }
302
303 return word;
304 }
305
306 wxTextInputStream& wxTextInputStream::operator>>(wxString& word)
307 {
308 word = ReadWord();
309 return *this;
310 }
311
312 wxTextInputStream& wxTextInputStream::operator>>(char& c)
313 {
314 if (!m_input)
315 {
316 c = 0;
317 return *this;
318 }
319
320 c = m_input.GetC();
321
322 if (EatEOL(c))
323 c = '\n';
324
325 return *this;
326 }
327
328 wxTextInputStream& wxTextInputStream::operator>>(wxInt16& i)
329 {
330 i = (wxInt16)Read16();
331 return *this;
332 }
333
334 wxTextInputStream& wxTextInputStream::operator>>(wxInt32& i)
335 {
336 i = (wxInt32)Read32();
337 return *this;
338 }
339
340 wxTextInputStream& wxTextInputStream::operator>>(wxUint16& i)
341 {
342 i = Read16();
343 return *this;
344 }
345
346 wxTextInputStream& wxTextInputStream::operator>>(wxUint32& i)
347 {
348 i = Read32();
349 return *this;
350 }
351
352 wxTextInputStream& wxTextInputStream::operator>>(double& i)
353 {
354 i = ReadDouble();
355 return *this;
356 }
357
358 wxTextInputStream& wxTextInputStream::operator>>(float& f)
359 {
360 f = (float)ReadDouble();
361 return *this;
362 }
363
364
365
366 #if wxUSE_UNICODE
367 wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode, wxMBConv& conv)
368 : m_output(s), m_conv(conv)
369 #else
370 wxTextOutputStream::wxTextOutputStream(wxOutputStream& s, wxEOL mode)
371 : m_output(s)
372 #endif
373 {
374 m_mode = mode;
375 if (m_mode == wxEOL_NATIVE)
376 {
377 #if defined(__WXMSW__) || defined(__WXPM__)
378 m_mode = wxEOL_DOS;
379 #elif defined(__WXMAC__) && !defined(__DARWIN__)
380 m_mode = wxEOL_MAC;
381 #else
382 m_mode = wxEOL_UNIX;
383 #endif
384 }
385 }
386
387 wxTextOutputStream::~wxTextOutputStream()
388 {
389 }
390
391 void wxTextOutputStream::SetMode(wxEOL mode)
392 {
393 m_mode = mode;
394 if (m_mode == wxEOL_NATIVE)
395 {
396 #if defined(__WXMSW__) || defined(__WXPM__)
397 m_mode = wxEOL_DOS;
398 #elif defined(__WXMAC__) && !defined(__DARWIN__)
399 m_mode = wxEOL_MAC;
400 #else
401 m_mode = wxEOL_UNIX;
402 #endif
403 }
404 }
405
406 void wxTextOutputStream::Write32(wxUint32 i)
407 {
408 wxString str;
409 str.Printf(wxT("%u"), i);
410
411 WriteString(str);
412 }
413
414 void wxTextOutputStream::Write16(wxUint16 i)
415 {
416 wxString str;
417 str.Printf(wxT("%u"), i);
418
419 WriteString(str);
420 }
421
422 void wxTextOutputStream::Write8(wxUint8 i)
423 {
424 wxString str;
425 str.Printf(wxT("%u"), i);
426
427 WriteString(str);
428 }
429
430 void wxTextOutputStream::WriteDouble(double d)
431 {
432 wxString str;
433
434 str.Printf(wxT("%f"), d);
435 WriteString(str);
436 }
437
438 void wxTextOutputStream::WriteString(const wxString& string)
439 {
440 size_t len = string.length();
441
442 wxString out;
443 out.reserve(len);
444
445 for ( size_t i = 0; i < len; i++ )
446 {
447 const wxChar c = string[i];
448 if ( c == wxT('\n') )
449 {
450 switch ( m_mode )
451 {
452 case wxEOL_DOS:
453 out << _T("\r\n");
454 continue;
455
456 case wxEOL_MAC:
457 out << _T('\r');
458 continue;
459
460 default:
461 wxFAIL_MSG( _T("unknown EOL mode in wxTextOutputStream") );
462 // fall through
463
464 case wxEOL_UNIX:
465 // don't treat '\n' specially
466 ;
467 }
468 }
469
470 out << c;
471 }
472
473 // We must not write the trailing NULL here
474 #if wxUSE_UNICODE
475 wxCharBuffer buffer = m_conv.cWC2MB( out );
476 m_output.Write( (const char*) buffer, strlen( (const char*) buffer ) );
477 #else
478 m_output.Write(out.c_str(), out.length() );
479 #endif
480 }
481
482 wxTextOutputStream& wxTextOutputStream::operator<<(const wxChar *string)
483 {
484 WriteString( wxString(string) );
485 return *this;
486 }
487
488 wxTextOutputStream& wxTextOutputStream::operator<<(const wxString& string)
489 {
490 WriteString( string );
491 return *this;
492 }
493
494 wxTextOutputStream& wxTextOutputStream::operator<<(char c)
495 {
496 WriteString( wxString::FromAscii(c) );
497
498 return *this;
499 }
500
501 wxTextOutputStream& wxTextOutputStream::operator<<(wxInt16 c)
502 {
503 wxString str;
504 str.Printf(wxT("%d"), (signed int)c);
505 WriteString(str);
506
507 return *this;
508 }
509
510 wxTextOutputStream& wxTextOutputStream::operator<<(wxInt32 c)
511 {
512 wxString str;
513 str.Printf(wxT("%ld"), (signed long)c);
514 WriteString(str);
515
516 return *this;
517 }
518
519 wxTextOutputStream& wxTextOutputStream::operator<<(wxUint16 c)
520 {
521 wxString str;
522 str.Printf(wxT("%u"), (unsigned int)c);
523 WriteString(str);
524
525 return *this;
526 }
527
528 wxTextOutputStream& wxTextOutputStream::operator<<(wxUint32 c)
529 {
530 wxString str;
531 str.Printf(wxT("%lu"), (unsigned long)c);
532 WriteString(str);
533
534 return *this;
535 }
536
537 wxTextOutputStream &wxTextOutputStream::operator<<(double f)
538 {
539 WriteDouble(f);
540 return *this;
541 }
542
543 wxTextOutputStream& wxTextOutputStream::operator<<(float f)
544 {
545 WriteDouble((double)f);
546 return *this;
547 }
548
549 wxTextOutputStream &endl( wxTextOutputStream &stream )
550 {
551 return stream << wxT('\n');
552 }
553
554 #endif
555 // wxUSE_STREAMS