source: trunk/src/qt3support/text/q3textstream.cpp@ 858

Last change on this file since 858 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 55.8 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the Qt3Support module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "q3textstream.h"
43#include <qdebug.h>
44
45#ifndef QT_NO_TEXTSTREAM
46#include "qtextcodec.h"
47#include "qregexp.h"
48#include "qbuffer.h"
49#include "qfile.h"
50#include "q3cstring.h"
51#include <stdio.h>
52#include <ctype.h>
53#include <stdlib.h>
54#ifndef Q_OS_WINCE
55#include <locale.h>
56#endif
57
58#if defined(Q_OS_WIN32)
59#include "qt_windows.h"
60#endif
61
62QT_BEGIN_NAMESPACE
63
64#ifndef QT_NO_TEXTCODEC
65static void resetCodecConverterState(QTextCodec::ConverterState *state) {
66 state->flags = QTextCodec::DefaultConversion;
67 state->remainingChars = state->invalidChars =
68 state->state_data[0] = state->state_data[1] = state->state_data[2] = 0;
69 if (state->d) qFree(state->d);
70 state->d = 0;
71}
72#endif
73
74/*!
75 \class Q3TextStream
76 \compat
77 \reentrant
78 \brief The Q3TextStream class provides basic functions for reading
79 and writing text using a QIODevice.
80
81 The text stream class has a functional interface that is very
82 similar to that of the standard C++ iostream class.
83
84 Qt provides several global functions similar to the ones in iostream:
85 \table
86 \header \i Function \i Meaning
87 \row \i bin \i sets the Q3TextStream to read/write binary numbers
88 \row \i oct \i sets the Q3TextStream to read/write octal numbers
89 \row \i dec \i sets the Q3TextStream to read/write decimal numbers
90 \row \i hex \i sets the Q3TextStream to read/write hexadecimal numbers
91 \row \i endl \i forces a line break
92 \row \i flush \i forces the QIODevice to flush any buffered data
93 \row \i ws \i eats any available whitespace (on input)
94 \row \i reset \i resets the Q3TextStream to its default mode (see reset())
95 \row \i qSetW(int) \i sets the \link width() field width \endlink
96 to the given argument
97 \row \i qSetFill(int) \i sets the \link fill() fill character
98 \endlink to the given argument
99 \row \i qSetPrecision(int) \i sets the \link precision() precision
100 \endlink to the given argument
101 \endtable
102
103 \warning By default Q3TextStream will automatically detect whether
104 integers in the stream are in decimal, octal, hexadecimal or
105 binary format when reading from the stream. In particular, a
106 leading '0' signifies octal, i.e. the sequence "0100" will be
107 interpreted as 64.
108
109 The Q3TextStream class reads and writes text; it is not appropriate
110 for dealing with binary data (but QDataStream is).
111
112 By default, output of Unicode text (i.e. QString) is done using
113 the local 8-bit encoding. This can be changed using the
114 setEncoding() method. For input, the Q3TextStream will auto-detect
115 standard Unicode "byte order marked" text files; otherwise the
116 local 8-bit encoding is used.
117
118 The QIODevice is set in the constructor, or later using
119 setDevice(). If the end of the input is reached atEnd() returns
120 TRUE. Data can be read into variables of the appropriate type
121 using the operator>>() overloads, or read in its entirety into a
122 single string using read(), or read a line at a time using
123 readLine(). Whitespace can be skipped over using skipWhiteSpace().
124 You can set flags for the stream using flags() or setf(). The
125 stream also supports width(), precision() and fill(); use reset()
126 to reset the defaults.
127
128 \sa QDataStream
129*/
130
131/*!
132 \enum Q3TextStream::Encoding
133
134 \value Locale
135 \value Latin1
136 \value Unicode
137 \value UnicodeNetworkOrder
138 \value UnicodeReverse
139 \value RawUnicode
140 \value UnicodeUTF8
141
142 See setEncoding() for an explanation of the encodings.
143*/
144
145/*
146 \class QTSManip
147 \internal
148*/
149
150#if defined(QT_CHECK_STATE)
151#undef CHECK_STREAM_PRECOND
152#define CHECK_STREAM_PRECOND if ( !dev ) { \
153 qWarning( "Q3TextStream: No device" ); \
154 return *this; }
155#else
156#define CHECK_STREAM_PRECOND
157#endif
158
159
160#define I_SHORT 0x0010
161#define I_INT 0x0020
162#define I_LONG 0x0030
163#define I_TYPE_MASK 0x00f0
164
165#define I_BASE_2 Q3TextStream::bin
166#define I_BASE_8 Q3TextStream::oct
167#define I_BASE_10 Q3TextStream::dec
168#define I_BASE_16 Q3TextStream::hex
169#define I_BASE_MASK (Q3TextStream::bin | Q3TextStream::oct | Q3TextStream::dec | Q3TextStream::hex)
170
171#define I_SIGNED 0x0100
172#define I_UNSIGNED 0x0200
173#define I_SIGN_MASK 0x0f00
174
175
176static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character.
177static const uint getline_buf_size = 256; // bufsize used by ts_getline()
178
179const int Q3TextStream::basefield = I_BASE_MASK;
180const int Q3TextStream::adjustfield = ( Q3TextStream::left |
181 Q3TextStream::right |
182 Q3TextStream::internal );
183const int Q3TextStream::floatfield = ( Q3TextStream::scientific |
184 Q3TextStream::fixed );
185
186
187class Q3TextStreamPrivate {
188public:
189#ifndef QT_NO_TEXTCODEC
190 Q3TextStreamPrivate()
191 : sourceType( NotSet ) { }
192 ~Q3TextStreamPrivate() {
193 }
194#else
195 Q3TextStreamPrivate() : sourceType( NotSet ) { }
196 ~Q3TextStreamPrivate() { }
197#endif
198 QString ungetcBuf;
199
200 enum SourceType { NotSet, IODevice, String, ByteArray, File };
201 SourceType sourceType;
202};
203
204
205// skips whitespace and returns the first non-whitespace character
206QChar Q3TextStream::eat_ws()
207{
208 QChar c;
209 do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) );
210 return c;
211}
212
213void Q3TextStream::init()
214{
215 // ### ungetcBuf = QEOF;
216 dev = 0;
217 owndev = FALSE;
218 mapper = 0;
219#ifndef QT_NO_TEXTCODEC
220 resetCodecConverterState(&mapperReadState);
221 resetCodecConverterState(&mapperWriteState);
222#endif
223 d = new Q3TextStreamPrivate;
224 doUnicodeHeader = TRUE; // autodetect
225 latin1 = TRUE; // should use locale?
226 internalOrder = QChar::networkOrdered();
227 networkOrder = TRUE;
228}
229
230/*!
231 Constructs a data stream that has no IO device.
232*/
233
234Q3TextStream::Q3TextStream()
235{
236 init();
237 setEncoding( Locale );
238 reset();
239 d->sourceType = Q3TextStreamPrivate::NotSet;
240}
241
242/*!
243 Constructs a text stream that uses the IO device \a iod.
244*/
245
246Q3TextStream::Q3TextStream( QIODevice *iod )
247{
248 init();
249 setEncoding( Locale );
250 dev = iod;
251 reset();
252 d->sourceType = Q3TextStreamPrivate::IODevice;
253}
254
255// TODO: use special-case handling of this case in Q3TextStream, and
256// simplify this class to only deal with QChar or QString data.
257class QStringBuffer : public QIODevice {
258public:
259 QStringBuffer( QString* str );
260 ~QStringBuffer();
261 bool open( OpenMode m );
262 void close();
263 qint64 size() const;
264
265protected:
266 qint64 readData( char *p, qint64 len );
267 qint64 writeData( const char *p, qint64 len );
268
269 QString* s;
270
271private:
272 QStringBuffer( const QStringBuffer & );
273 QStringBuffer &operator=( const QStringBuffer & );
274};
275
276
277QStringBuffer::QStringBuffer( QString* str )
278{
279 s = str;
280}
281
282QStringBuffer::~QStringBuffer()
283{
284}
285
286
287bool QStringBuffer::open( OpenMode m )
288{
289 if ( !s ) {
290#if defined(QT_CHECK_STATE)
291 qWarning( "QStringBuffer::open: No string" );
292#endif
293 return FALSE;
294 }
295 if ( isOpen() ) {
296#if defined(QT_CHECK_STATE)
297 qWarning( "QStringBuffer::open: Buffer already open" );
298#endif
299 return FALSE;
300 }
301 setOpenMode( m );
302 if ( m & QIODevice::Truncate )
303 s->truncate( 0 );
304
305 if ( m & QIODevice::Append ) {
306 seek(s->length()*sizeof(QChar));
307 } else {
308 seek(0);
309 }
310 return TRUE;
311}
312
313void QStringBuffer::close()
314{
315 if ( isOpen() ) {
316 seek(0);
317 QIODevice::close();
318 }
319}
320
321qint64 QStringBuffer::size() const
322{
323 return s ? s->length()*sizeof(QChar) : 0;
324}
325
326qint64 QStringBuffer::readData( char *p, qint64 len )
327{
328#if defined(QT_CHECK_STATE)
329 Q_CHECK_PTR( p );
330 if ( !isOpen() ) {
331 qWarning( "QStringBuffer::readBlock: Buffer not open" );
332 return qint64(-1);
333 }
334 if ( !isReadable() ) {
335 qWarning( "QStringBuffer::readBlock: Read operation not permitted" );
336 return qint64(-1);
337 }
338#endif
339 if ( pos() + len > qint64(s->length()*sizeof(QChar)) ) {
340 // overflow
341 if ( pos() >= qint64(s->length()*sizeof(QChar)) ) {
342 return -1;
343 } else {
344 len = s->length()*2 - pos();
345 }
346 }
347 memcpy( p, ((const char*)(s->unicode()))+pos(), len );
348 return len;
349}
350
351qint64 QStringBuffer::writeData( const char *p, qint64 len )
352{
353#if defined(QT_CHECK_NULL)
354 if ( p == 0 && len != 0 )
355 qWarning( "QStringBuffer::writeBlock: Null pointer error" );
356#endif
357#if defined(QT_CHECK_STATE)
358 if ( !isOpen() ) {
359 qWarning( "QStringBuffer::writeBlock: Buffer not open" );
360 return -1;
361 }
362 if ( !isWritable() ) {
363 qWarning( "QStringBuffer::writeBlock: Write operation not permitted" );
364 return -1;
365 }
366 if ( pos()&1 ) {
367 qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" );
368 return -1;
369 }
370 if ( len&1 ) {
371 qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" );
372 return -1;
373 }
374#endif
375 s->replace(pos()/2, len/2, (QChar*)p, len/2);
376 return len;
377}
378
379/*!
380 Constructs a text stream that operates on the Unicode QString, \a
381 str, through an internal device. The \a filemode argument is
382 passed to the device's open() function; see \l{QIODevice::mode()}.
383
384 If you set an encoding or codec with setEncoding() or setCodec(),
385 this setting is ignored for text streams that operate on QString.
386
387 Example:
388 \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 0
389
390 Writing data to the text stream will modify the contents of the
391 string. The string will be expanded when data is written beyond
392 the end of the string. Note that the string will not be truncated:
393 \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 1
394
395 Note that because QString is Unicode, you should not use
396 readRawBytes() or writeRawBytes() on such a stream.
397*/
398
399Q3TextStream::Q3TextStream( QString* str, int filemode )
400{
401 // TODO: optimize for this case as it becomes more common
402 // (see QStringBuffer above)
403 init();
404 dev = new QStringBuffer( str );
405 ((QStringBuffer *)dev)->open( QIODevice::OpenMode(filemode) );
406 owndev = TRUE;
407 setEncoding(RawUnicode);
408 reset();
409 d->sourceType = Q3TextStreamPrivate::String;
410}
411
412/*! \obsolete
413
414 This constructor is equivalent to the constructor taking a QString*
415 parameter.
416*/
417
418Q3TextStream::Q3TextStream( QString& str, int filemode )
419{
420 init();
421 dev = new QStringBuffer( &str );
422 ((QStringBuffer *)dev)->open( QIODevice::OpenMode(filemode) );
423 owndev = TRUE;
424 setEncoding(RawUnicode);
425 reset();
426 d->sourceType = Q3TextStreamPrivate::String;
427}
428
429/*!
430 Constructs a text stream that operates on the byte array, \a a,
431 through an internal QBuffer device. The \a mode argument is passed
432 to the device's open() function; see \l{QIODevice::mode()}.
433
434 Example:
435 \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 2
436
437 Writing data to the text stream will modify the contents of the
438 array. The array will be expanded when data is written beyond the
439 end of the string.
440
441 Same example, using a QBuffer:
442 \snippet doc/src/snippets/code/src_qt3support_text_q3textstream.cpp 3
443*/
444
445Q3TextStream::Q3TextStream( QByteArray &a, int mode )
446{
447 init();
448 QBuffer *buffer = new QBuffer;
449 buffer->setBuffer( &a );
450 buffer->open( QIODevice::OpenMode(mode) );
451 dev = buffer;
452 owndev = TRUE;
453 setEncoding( Latin1 ); //### Locale???
454 reset();
455 d->sourceType = Q3TextStreamPrivate::ByteArray;
456}
457
458/*!
459 Constructs a text stream that operates on an existing file handle
460 \a fh through an internal QFile device. The \a mode argument is
461 passed to the device's open() function; see \l{QIODevice::mode()}.
462
463 Note that if you create a Q3TextStream \c cout or another name that
464 is also used for another variable of a different type, some
465 linkers may confuse the two variables, which will often cause
466 crashes.
467*/
468
469Q3TextStream::Q3TextStream( FILE *fh, int mode )
470{
471 init();
472 setEncoding( Locale ); //###
473 dev = new QFile;
474 ((QFile *)dev)->open( QIODevice::OpenMode(mode), fh );
475 owndev = TRUE;
476 reset();
477 d->sourceType = Q3TextStreamPrivate::File;
478}
479
480/*!
481 Destroys the text stream.
482
483 The destructor does not affect the current IO device.
484*/
485
486Q3TextStream::~Q3TextStream()
487{
488 if ( owndev )
489 delete dev;
490 delete d;
491}
492
493/*!
494 \since 4.2
495
496 Positions the read pointer at the first non-whitespace character.
497*/
498void Q3TextStream::skipWhiteSpace()
499{
500 ts_ungetc( eat_ws() );
501}
502
503
504/*!
505 Tries to read \a len characters from the stream and stores them in
506 \a buf. Returns the number of characters really read.
507
508 \warning There will no QEOF appended if the read reaches the end
509 of the file. EOF is reached when the return value does not equal
510 \a len.
511*/
512uint Q3TextStream::ts_getbuf( QChar* buf, uint len )
513{
514 if ( len < 1 )
515 return 0;
516
517 uint rnum = 0; // the number of QChars really read
518
519 if ( d && d->ungetcBuf.length() ) {
520 while ( rnum < len && rnum < uint(d->ungetcBuf.length()) ) {
521 *buf = d->ungetcBuf.constref( rnum );
522 buf++;
523 rnum++;
524 }
525 d->ungetcBuf = d->ungetcBuf.mid( rnum );
526 if ( rnum >= len )
527 return rnum;
528 }
529
530 // we use dev->ungetch() for one of the bytes of the unicode
531 // byte-order mark, but a local unget hack for the other byte:
532 int ungetHack = EOF;
533
534 if ( doUnicodeHeader ) {
535 doUnicodeHeader = FALSE; // only at the top
536 int c1 = dev->getch();
537 if ( c1 == EOF )
538 return rnum;
539 int c2 = dev->getch();
540 if ( c1 == 0xfe && c2 == 0xff ) {
541 mapper = 0;
542 latin1 = FALSE;
543 internalOrder = QChar::networkOrdered();
544 networkOrder = TRUE;
545 } else if ( c1 == 0xff && c2 == 0xfe ) {
546 mapper = 0;
547 latin1 = FALSE;
548 internalOrder = !QChar::networkOrdered();
549 networkOrder = FALSE;
550 } else {
551 if ( c2 != EOF ) {
552 dev->ungetch( c2 );
553 ungetHack = c1;
554 } else {
555 /*
556 A small bug might hide here. If only the first byte
557 of a file has made it so far, and that first byte
558 is half of the byte-order mark, then the utfness
559 will not be detected.
560 */
561 dev->ungetch( c1 );
562 }
563 }
564 }
565
566#ifndef QT_NO_TEXTCODEC
567 if ( mapper ) {
568 bool shortRead = FALSE;
569 while( rnum < len ) {
570 QString s;
571 bool readBlock = !( len == 1+rnum );
572 for (;;) {
573 // for efficiency: normally read a whole block
574 if ( readBlock ) {
575 // guess buffersize; this may be wrong (too small or too
576 // big). But we can handle this (either iterate reading
577 // or use ungetcBuf).
578 // Note that this might cause problems for codecs where
579 // one byte can result in >1 Unicode Characters if bytes
580 // are written to the stream in the meantime (loss of
581 // synchronicity).
582 uint rlen = len - rnum;
583 char *cbuf = new char[ rlen ];
584 if ( ungetHack != EOF ) {
585 rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
586 cbuf[0] = (char)ungetHack;
587 ungetHack = EOF;
588 } else {
589 rlen = dev->readBlock( cbuf, rlen );
590 }
591 s += mapper->toUnicode( cbuf, rlen, &mapperWriteState );
592 delete[] cbuf;
593 // use buffered reading only for the first time, because we
594 // have to get the stream synchronous again (this is easier
595 // with single character reading)
596 readBlock = FALSE;
597 }
598 // get stream (and codec) in sync
599 int c;
600 if ( ungetHack == EOF ) {
601 c = dev->getch();
602 } else {
603 c = ungetHack;
604 ungetHack = EOF;
605 }
606 if ( c == EOF ) {
607 shortRead = TRUE;
608 break;
609 }
610 char b = c;
611 uint lengthBefore = s.length();
612 s += mapper->toUnicode( &b, 1, &mapperWriteState );
613
614 if ( uint(s.length()) > lengthBefore )
615 break; // it seems we are in sync now
616 }
617 uint i = 0;
618 uint end = QMIN( len-rnum, uint(s.length()) );
619 while( i < end ) {
620 *buf = s.constref(i++);
621 buf++;
622 }
623 rnum += end;
624 if ( uint(s.length()) > i ) {
625 // could be = but append is clearer
626 d->ungetcBuf.append( s.mid( i ) );
627 }
628 if ( shortRead )
629 return rnum;
630 }
631 } else
632#endif
633 if ( latin1 ) {
634 if ( len == 1+rnum ) {
635 // use this method for one character because it is more efficient
636 // (arnt doubts whether it makes a difference, but lets it stand)
637 int c = (ungetHack == EOF) ? dev->getch() : ungetHack;
638 if ( c != EOF ) {
639 *buf = QLatin1Char((char)c);
640 buf++;
641 rnum++;
642 }
643 } else {
644 if ( ungetHack != EOF ) {
645 *buf = QLatin1Char((char)ungetHack);
646 buf++;
647 rnum++;
648 ungetHack = EOF;
649 }
650 char *cbuf = new char[len - rnum];
651 while ( !dev->atEnd() && rnum < len ) {
652 uint rlen = len - rnum;
653 rlen = dev->readBlock( cbuf, rlen );
654 char *it = cbuf;
655 char *end = cbuf + rlen;
656 while ( it < end ) {
657 *buf = QLatin1Char(*it);
658 buf++;
659 it++;
660 }
661 rnum += rlen;
662 }
663 delete[] cbuf;
664 }
665 } else { // UCS-2 or UTF-16
666 if ( len == 1+rnum ) {
667 int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack;
668
669
670 if ( c1 == EOF )
671 return rnum;
672 int c2 = dev->getch();
673
674
675 if ( c2 == EOF )
676 return rnum;
677
678 if ( networkOrder ) {
679 *buf = QChar( c2, c1 );
680 } else {
681 *buf = QChar( c1, c2 );
682 }
683 buf++;
684 rnum++;
685 } else {
686 char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible
687 while ( !dev->atEnd() && rnum < len ) {
688 uint rlen = 2 * ( len-rnum );
689 if ( ungetHack != EOF ) {
690 rlen = 1+dev->readBlock( cbuf+1, rlen-1 );
691 cbuf[0] = (char)ungetHack;
692 ungetHack = EOF;
693 } else {
694 rlen = dev->readBlock( cbuf, rlen );
695 }
696 // We can't use an odd number of bytes, so put it back. But
697 // do it only if we are capable of reading more -- normally
698 // there should not be an odd number, but the file might be
699 // truncated or not in UTF-16...
700 if ( (rlen & 1) == 1 )
701 if ( !dev->atEnd() )
702 dev->ungetch( cbuf[--rlen] );
703 uint i = 0;
704 if ( networkOrder ) {
705 while( i < rlen ) {
706 *buf = QChar( cbuf[i+1], cbuf[i] );
707 buf++;
708 i+=2;
709 }
710 } else {
711 while( i < rlen ) {
712 *buf = QChar( cbuf[i], cbuf[i+1] );
713 buf++;
714 i+=2;
715 }
716 }
717 rnum += i/2;
718 }
719 delete[] cbuf;
720 }
721 }
722 return rnum;
723}
724
725/*!
726 Tries to read one line, but at most len characters from the stream
727 and stores them in \a buf.
728
729 Returns the number of characters really read. Newlines are not
730 stripped.
731
732 There will be a QEOF appended if the read reaches the end of file;
733 this is different to ts_getbuf().
734
735 This function works only if a newline (as byte) is also a newline
736 (as resulting character) since it uses QIODevice::readLine(). So
737 use it only for such codecs where this is true!
738
739 This function is (almost) a no-op for UTF 16. Don't use it if
740 doUnicodeHeader is TRUE!
741*/
742uint Q3TextStream::ts_getline( QChar* buf )
743{
744 uint rnum=0; // the number of QChars really read
745 char cbuf[ getline_buf_size+1 ];
746
747 if ( d && d->ungetcBuf.length() ) {
748 while( rnum < getline_buf_size && rnum < uint(d->ungetcBuf.length()) ) {
749 buf[rnum] = d->ungetcBuf.constref(rnum);
750 rnum++;
751 }
752 d->ungetcBuf = d->ungetcBuf.mid( rnum );
753 if ( rnum >= getline_buf_size )
754 return rnum;
755 }
756
757#ifndef QT_NO_TEXTCODEC
758 if ( mapper ) {
759 QString s;
760 bool readBlock = TRUE;
761 for (;;) {
762 // for efficiency: try to read a line
763 if ( readBlock ) {
764 int rlen = getline_buf_size - rnum;
765 rlen = dev->readLine( cbuf, rlen+1 );
766 if ( rlen == -1 )
767 rlen = 0;
768 s += mapper->toUnicode( cbuf, rlen, &mapperWriteState );
769 readBlock = FALSE;
770 }
771 if ( dev->atEnd()
772 || s.at( s.length()-1 ) == QLatin1Char('\n')
773 || s.at( s.length()-1 ) == QLatin1Char('\r')
774 ) {
775 break;
776 } else {
777 // get stream (and codec) in sync
778 int c;
779 c = dev->getch();
780 if ( c == EOF ) {
781 break;
782 }
783 char b = c;
784 uint lengthBefore = s.length();
785 s += mapper->toUnicode( &b, 1, &mapperWriteState );
786 if ( uint(s.length()) > lengthBefore )
787 break; // it seems we are in sync now
788 }
789 }
790 uint i = 0;
791 while( rnum < getline_buf_size && i < uint(s.length()) )
792 buf[rnum++] = s.constref(i++);
793 if ( uint(s.length()) > i )
794 // could be = but append is clearer
795 d->ungetcBuf.append( s.mid( i ) );
796 if ( rnum < getline_buf_size && dev->atEnd() )
797 buf[rnum++] = QEOF;
798 } else
799#endif
800 if ( latin1 ) {
801 int rlen = getline_buf_size - rnum;
802 rlen = dev->readLine( cbuf, rlen+1 );
803 if ( rlen == -1 )
804 rlen = 0;
805 char *end = cbuf+rlen;
806 char *it = cbuf;
807 buf +=rnum;
808 while ( it != end ) {
809 buf->setCell( *(it++) );
810 buf->setRow( 0 );
811 buf++;
812 }
813 rnum += rlen;
814 if ( rnum < getline_buf_size && dev->atEnd() )
815 buf[1] = QEOF;
816 }
817 return rnum;
818}
819
820
821/*!
822 Puts one character into the stream.
823*/
824void Q3TextStream::ts_putc( QChar c )
825{
826#ifndef QT_NO_TEXTCODEC
827 if ( mapper ) {
828 int len = 1;
829 QString s = c;
830 Q3CString block = mapper->fromUnicode( s.data(), len );//, &mapperReadState );
831 dev->writeBlock( block );
832 } else
833#endif
834 if ( latin1 ) {
835 if ( c.row() )
836 dev->putch( '?' ); // unknown character
837 else
838 dev->putch( c.cell() );
839 } else {
840 if ( doUnicodeHeader ) {
841 doUnicodeHeader = FALSE;
842 ts_putc( QChar::ByteOrderMark );
843 }
844 if ( internalOrder ) {
845 // this case is needed by QStringBuffer
846 dev->writeBlock( (char*)&c, sizeof(QChar) );
847 } else if ( networkOrder ) {
848 dev->putch( c.row() );
849 dev->putch( c.cell() );
850 } else {
851 dev->putch( c.cell() );
852 dev->putch( c.row() );
853 }
854 }
855}
856
857/*!
858 Puts one character into the stream.
859*/
860void Q3TextStream::ts_putc( int ch )
861{
862 ts_putc( QChar((ushort)ch) );
863}
864
865bool Q3TextStream::ts_isdigit( QChar c )
866{
867 return c.isDigit();
868}
869
870bool Q3TextStream::ts_isspace( QChar c )
871{
872 return c.isSpace();
873}
874
875void Q3TextStream::ts_ungetc( QChar c )
876{
877 if ( c.unicode() == 0xffff )
878 return;
879
880 d->ungetcBuf.prepend( c );
881}
882
883/*!
884 \since 4.2
885
886 Reads \a len bytes from the stream into \a s and returns a
887 reference to the stream.
888
889 The buffer \a s must be preallocated.
890
891 Note that no encoding is done by this function.
892
893 \warning The behavior of this function is undefined unless the
894 stream's encoding is set to Unicode or Latin1.
895
896 \sa QIODevice::readBlock()
897*/
898
899Q3TextStream &Q3TextStream::readRawBytes( char *s, uint len )
900{
901 dev->readBlock( s, len );
902 return *this;
903}
904
905/*!
906 \since 4.2
907
908 Writes the \a len bytes from \a s to the stream and returns a
909 reference to the stream.
910
911 Note that no encoding is done by this function.
912
913 \sa QIODevice::writeBlock()
914*/
915
916Q3TextStream &Q3TextStream::writeRawBytes( const char* s, uint len )
917{
918 dev->writeBlock( s, len );
919 return *this;
920}
921
922
923Q3TextStream &Q3TextStream::writeBlock( const char* p, uint len )
924{
925 if ( doUnicodeHeader ) {
926 doUnicodeHeader = FALSE;
927 if ( !mapper && !latin1 ) {
928 ts_putc( QChar::ByteOrderMark );
929 }
930 }
931 // QCString and const char * are treated as Latin-1
932 if ( !mapper && latin1 ) {
933 dev->writeBlock( p, len );
934 } else if ( !mapper && internalOrder ) {
935 QChar *u = new QChar[len];
936 for ( uint i = 0; i < len; i++ )
937 u[i] = QLatin1Char(p[i]);
938 dev->writeBlock( (char*)u, len * sizeof(QChar) );
939 delete [] u;
940 }
941#ifndef QT_NO_TEXTCODEC
942 else if (mapper) {
943 QString s = QString::fromLatin1(p, len);
944 int l = len;
945 Q3CString block = mapper->fromUnicode(s.data(), l );//, &mapperReadState );
946 dev->writeBlock( block );
947 }
948#endif
949 else {
950 for ( uint i = 0; i < len; i++ )
951 ts_putc( (uchar)p[i] );
952 }
953 return *this;
954}
955
956Q3TextStream &Q3TextStream::writeBlock( const QChar* p, uint len )
957{
958#ifndef QT_NO_TEXTCODEC
959 if ( mapper ) {
960 QConstString s( p, len );
961 int l = len;
962 Q3CString block = mapper->fromUnicode( s.string().data(), l );//, &mapperReadState );
963 dev->writeBlock( block );
964 } else
965#endif
966 if ( latin1 ) {
967 dev->write(QString( p, len ).toLatin1());
968 } else if ( internalOrder ) {
969 if ( doUnicodeHeader ) {
970 doUnicodeHeader = FALSE;
971 ts_putc( QChar::ByteOrderMark );
972 }
973 dev->writeBlock( (char*)p, sizeof(QChar)*len );
974 } else {
975 for (uint i=0; i<len; i++)
976 ts_putc( p[i] );
977 }
978 return *this;
979}
980
981/*!
982 \since 4.2
983
984 Resets the text stream.
985
986 \list
987 \i All flags are set to 0.
988 \i The field width is set to 0.
989 \i The fill character is set to ' ' (Space).
990 \i The precision is set to 6.
991 \endlist
992
993 \sa setf(), width(), fill(), precision()
994*/
995
996void Q3TextStream::reset()
997{
998 fflags = 0;
999 fwidth = 0;
1000 fillchar = ' ';
1001 fprec = 6;
1002}
1003
1004/*!
1005 \fn QIODevice *Q3TextStream::device() const
1006 \since 4.2
1007
1008 Returns the IO device currently set.
1009
1010 \sa setDevice(), unsetDevice()
1011*/
1012
1013/*!
1014 \since 4.2
1015
1016 Sets the IO device to \a iod.
1017
1018 \sa device(), unsetDevice()
1019*/
1020
1021void Q3TextStream::setDevice( QIODevice *iod )
1022{
1023 if ( owndev ) {
1024 delete dev;
1025 owndev = FALSE;
1026 }
1027 dev = iod;
1028 d->sourceType = Q3TextStreamPrivate::IODevice;
1029}
1030
1031/*!
1032 \since 4.2
1033
1034 Unsets the IO device. Equivalent to setDevice( 0 ).
1035
1036 \sa device(), setDevice()
1037*/
1038
1039void Q3TextStream::unsetDevice()
1040{
1041 setDevice( 0 );
1042 d->sourceType = Q3TextStreamPrivate::NotSet;
1043}
1044
1045/*!
1046 \fn bool Q3TextStream::atEnd() const
1047 \since 4.2
1048
1049 Returns TRUE if the IO device has reached the end position (end of
1050 the stream or file) or if there is no IO device set; otherwise
1051 returns FALSE.
1052
1053 \sa QIODevice::atEnd()
1054*/
1055
1056/*!\fn bool Q3TextStream::eof() const
1057
1058 \obsolete
1059
1060 This function has been renamed to atEnd().
1061
1062 \sa QIODevice::atEnd()
1063*/
1064
1065/*****************************************************************************
1066 Q3TextStream read functions
1067 *****************************************************************************/
1068
1069
1070/*!
1071 \overload
1072
1073 Reads a char \a c from the stream and returns a reference to the
1074 stream. Note that whitespace is skipped.
1075*/
1076
1077Q3TextStream &Q3TextStream::operator>>( char &c )
1078{
1079 CHECK_STREAM_PRECOND
1080 c = eat_ws().toLatin1();
1081 return *this;
1082}
1083
1084/*!
1085 Reads a char \a c from the stream and returns a reference to the
1086 stream. Note that whitespace is \e not skipped.
1087*/
1088
1089Q3TextStream &Q3TextStream::operator>>( QChar &c )
1090{
1091 CHECK_STREAM_PRECOND
1092 c = ts_getc();
1093 return *this;
1094}
1095
1096
1097ulong Q3TextStream::input_bin()
1098{
1099 ulong val = 0;
1100 QChar ch = eat_ws();
1101 int dv = ch.digitValue();
1102 while ( dv == 0 || dv == 1 ) {
1103 val = ( val << 1 ) + dv;
1104 ch = ts_getc();
1105 dv = ch.digitValue();
1106 }
1107 if ( ch != QEOF )
1108 ts_ungetc( ch );
1109 return val;
1110}
1111
1112ulong Q3TextStream::input_oct()
1113{
1114 ulong val = 0;
1115 QChar ch = eat_ws();
1116 int dv = ch.digitValue();
1117 while ( dv >= 0 && dv <= 7 ) {
1118 val = ( val << 3 ) + dv;
1119 ch = ts_getc();
1120 dv = ch.digitValue();
1121 }
1122 if ( dv == 8 || dv == 9 ) {
1123 while ( ts_isdigit(ch) )
1124 ch = ts_getc();
1125 }
1126 if ( ch != QEOF )
1127 ts_ungetc( ch );
1128 return val;
1129}
1130
1131ulong Q3TextStream::input_dec()
1132{
1133 ulong val = 0;
1134 QChar ch = eat_ws();
1135 int dv = ch.digitValue();
1136 while ( ts_isdigit(ch) ) {
1137 val = val * 10 + dv;
1138 ch = ts_getc();
1139 dv = ch.digitValue();
1140 }
1141 if ( ch != QEOF )
1142 ts_ungetc( ch );
1143 return val;
1144}
1145
1146ulong Q3TextStream::input_hex()
1147{
1148 ulong val = 0;
1149 QChar ch = eat_ws();
1150 char c = ch.toLatin1();
1151 while ( isxdigit((uchar) c) ) {
1152 val <<= 4;
1153 if ( ts_isdigit(QLatin1Char(c)) )
1154 val += c - '0';
1155 else
1156 val += 10 + tolower( (uchar) c ) - 'a';
1157 ch = ts_getc();
1158 c = ch.toLatin1();
1159 }
1160 if ( ch != QEOF )
1161 ts_ungetc( ch );
1162 return val;
1163}
1164
1165long Q3TextStream::input_int()
1166{
1167 long val;
1168 QChar ch;
1169 char c;
1170 switch ( flags() & basefield ) {
1171 case bin:
1172 val = (long)input_bin();
1173 break;
1174 case oct:
1175 val = (long)input_oct();
1176 break;
1177 case dec:
1178 ch = eat_ws();
1179 c = ch.toLatin1();
1180 if ( ch == QEOF ) {
1181 val = 0;
1182 } else {
1183 if ( !(c == '-' || c == '+') )
1184 ts_ungetc( ch );
1185 if ( c == '-' ) {
1186 ulong v = input_dec();
1187 if ( v ) { // ensure that LONG_MIN can be read
1188 v--;
1189 val = -((long)v) - 1;
1190 } else {
1191 val = 0;
1192 }
1193 } else {
1194 val = (long)input_dec();
1195 }
1196 }
1197 break;
1198 case hex:
1199 val = (long)input_hex();
1200 break;
1201 default:
1202 val = 0;
1203 ch = eat_ws();
1204 c = ch.toLatin1();
1205 if ( c == '0' ) { // bin, oct or hex
1206 ch = ts_getc();
1207 c = ch.toLatin1();
1208 if ( tolower((uchar) c) == 'x' )
1209 val = (long)input_hex();
1210 else if ( tolower((uchar) c) == 'b' )
1211 val = (long)input_bin();
1212 else { // octal
1213 ts_ungetc( ch );
1214 if ( c >= '0' && c <= '7' ) {
1215 val = (long)input_oct();
1216 } else {
1217 val = 0;
1218 }
1219 }
1220 } else if ( ts_isdigit(ch) ) {
1221 ts_ungetc( ch );
1222 val = (long)input_dec();
1223 } else if ( c == '-' || c == '+' ) {
1224 ulong v = input_dec();
1225 if ( c == '-' ) {
1226 if ( v ) { // ensure that LONG_MIN can be read
1227 v--;
1228 val = -((long)v) - 1;
1229 } else {
1230 val = 0;
1231 }
1232 } else {
1233 val = (long)v;
1234 }
1235 }
1236 }
1237 return val;
1238}
1239
1240//
1241// We use a table-driven FSM to parse floating point numbers
1242// strtod() cannot be used directly since we're reading from a QIODevice
1243//
1244
1245double Q3TextStream::input_double()
1246{
1247 const int Init = 0; // states
1248 const int Sign = 1;
1249 const int Mantissa = 2;
1250 const int Dot = 3;
1251 const int Abscissa = 4;
1252 const int ExpMark = 5;
1253 const int ExpSign = 6;
1254 const int Exponent = 7;
1255 const int Done = 8;
1256
1257 const int InputSign = 1; // input tokens
1258 const int InputDigit = 2;
1259 const int InputDot = 3;
1260 const int InputExp = 4;
1261
1262 static const uchar table[8][5] = {
1263 /* None InputSign InputDigit InputDot InputExp */
1264 { 0, Sign, Mantissa, Dot, 0, }, // Init
1265 { 0, 0, Mantissa, Dot, 0, }, // Sign
1266 { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa
1267 { 0, 0, Abscissa, 0, 0, }, // Dot
1268 { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa
1269 { 0, ExpSign, Exponent, 0, 0, }, // ExpMark
1270 { 0, 0, Exponent, 0, 0, }, // ExpSign
1271 { Done, Done, Exponent, Done, Done } // Exponent
1272 };
1273
1274 int state = Init; // parse state
1275 int input; // input token
1276
1277 char buf[256];
1278 int i = 0;
1279 QChar c = eat_ws();
1280
1281 for (;;) {
1282
1283 switch ( c.toLatin1() ) {
1284 case '+':
1285 case '-':
1286 input = InputSign;
1287 break;
1288 case '0': case '1': case '2': case '3': case '4':
1289 case '5': case '6': case '7': case '8': case '9':
1290 input = InputDigit;
1291 break;
1292 case '.':
1293 input = InputDot;
1294 break;
1295 case 'e':
1296 case 'E':
1297 input = InputExp;
1298 break;
1299 default:
1300 input = 0;
1301 break;
1302 }
1303
1304 state = table[state][input];
1305
1306 if ( state == 0 || state == Done || i > 250 ) {
1307 if ( i > 250 ) { // ignore rest of digits
1308 do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) );
1309 }
1310 if ( c != QEOF )
1311 ts_ungetc( c );
1312 buf[i] = '\0';
1313 char *end;
1314 return strtod( buf, &end );
1315 }
1316
1317 buf[i++] = c.toLatin1();
1318 c = ts_getc();
1319 }
1320
1321#if !defined(Q_CC_EDG)
1322 return 0.0;
1323#endif
1324}
1325
1326
1327/*!
1328 \overload
1329
1330 Reads a signed \c short integer \a i from the stream and returns a
1331 reference to the stream. See flags() for an explanation of the
1332 expected input format.
1333*/
1334
1335Q3TextStream &Q3TextStream::operator>>( signed short &i )
1336{
1337 CHECK_STREAM_PRECOND
1338 i = (signed short)input_int();
1339 return *this;
1340}
1341
1342
1343/*!
1344 \overload
1345
1346 Reads an unsigned \c short integer \a i from the stream and
1347 returns a reference to the stream. See flags() for an explanation
1348 of the expected input format.
1349*/
1350
1351Q3TextStream &Q3TextStream::operator>>( unsigned short &i )
1352{
1353 CHECK_STREAM_PRECOND
1354 i = (unsigned short)input_int();
1355 return *this;
1356}
1357
1358
1359/*!
1360 \overload
1361
1362 Reads a signed \c int \a i from the stream and returns a reference
1363 to the stream. See flags() for an explanation of the expected
1364 input format.
1365*/
1366
1367Q3TextStream &Q3TextStream::operator>>( signed int &i )
1368{
1369 CHECK_STREAM_PRECOND
1370 i = (signed int)input_int();
1371 return *this;
1372}
1373
1374
1375/*!
1376 \overload
1377
1378 Reads an unsigned \c int \a i from the stream and returns a
1379 reference to the stream. See flags() for an explanation of the
1380 expected input format.
1381*/
1382
1383Q3TextStream &Q3TextStream::operator>>( unsigned int &i )
1384{
1385 CHECK_STREAM_PRECOND
1386 i = (unsigned int)input_int();
1387 return *this;
1388}
1389
1390
1391/*!
1392 \overload
1393
1394 Reads a signed \c long int \a i from the stream and returns a
1395 reference to the stream. See flags() for an explanation of the
1396 expected input format.
1397*/
1398
1399Q3TextStream &Q3TextStream::operator>>( signed long &i )
1400{
1401 CHECK_STREAM_PRECOND
1402 i = (signed long)input_int();
1403 return *this;
1404}
1405
1406
1407/*!
1408 \overload
1409
1410 Reads an unsigned \c long int \a i from the stream and returns a
1411 reference to the stream. See flags() for an explanation of the
1412 expected input format.
1413*/
1414
1415Q3TextStream &Q3TextStream::operator>>( unsigned long &i )
1416{
1417 CHECK_STREAM_PRECOND
1418 i = (unsigned long)input_int();
1419 return *this;
1420}
1421
1422
1423/*!
1424 \overload
1425
1426 Reads a \c float \a f from the stream and returns a reference to
1427 the stream. See flags() for an explanation of the expected input
1428 format.
1429*/
1430
1431Q3TextStream &Q3TextStream::operator>>( float &f )
1432{
1433 CHECK_STREAM_PRECOND
1434 f = (float)input_double();
1435 return *this;
1436}
1437
1438
1439/*!
1440 \overload
1441
1442 Reads a \c double \a f from the stream and returns a reference to
1443 the stream. See flags() for an explanation of the expected input
1444 format.
1445*/
1446
1447Q3TextStream &Q3TextStream::operator>>( double &f )
1448{
1449 CHECK_STREAM_PRECOND
1450 f = input_double();
1451 return *this;
1452}
1453
1454
1455/*!
1456 \overload
1457
1458 Reads a "word" from the stream into \a s and returns a reference
1459 to the stream.
1460
1461 A word consists of characters for which isspace() returns FALSE.
1462*/
1463
1464Q3TextStream &Q3TextStream::operator>>( char *s )
1465{
1466 CHECK_STREAM_PRECOND
1467 int maxlen = width( 0 );
1468 QChar c = eat_ws();
1469 if ( !maxlen )
1470 maxlen = -1;
1471 while ( c != QEOF ) {
1472 if ( ts_isspace(c) || maxlen-- == 0 ) {
1473 ts_ungetc( c );
1474 break;
1475 }
1476 *s++ = c.toLatin1();
1477 c = ts_getc();
1478 }
1479
1480 *s = '\0';
1481 return *this;
1482}
1483
1484/*!
1485 \overload
1486
1487 Reads a "word" from the stream into \a str and returns a reference
1488 to the stream.
1489
1490 A word consists of characters for which isspace() returns FALSE.
1491*/
1492
1493Q3TextStream &Q3TextStream::operator>>( QString &str )
1494{
1495 CHECK_STREAM_PRECOND
1496 str=QString::fromLatin1("");
1497 QChar c = eat_ws();
1498
1499 while ( c != QEOF ) {
1500 if ( ts_isspace(c) ) {
1501 ts_ungetc( c );
1502 break;
1503 }
1504
1505 str += c;
1506 c = ts_getc();
1507 }
1508
1509 return *this;
1510}
1511
1512/*!
1513 \overload
1514
1515 Reads a "word" from the stream into \a str and returns a reference
1516 to the stream.
1517
1518 A word consists of characters for which isspace() returns FALSE.
1519*/
1520
1521Q3TextStream &Q3TextStream::operator>>( Q3CString &str )
1522{
1523 CHECK_STREAM_PRECOND
1524 Q3CString *dynbuf = 0;
1525 const int buflen = 256;
1526 char buffer[buflen];
1527 char *s = buffer;
1528 int i = 0;
1529 QChar c = eat_ws();
1530
1531 while ( c != QEOF ) {
1532 if ( ts_isspace(c) ) {
1533 ts_ungetc( c );
1534 break;
1535 }
1536 if ( i >= buflen-1 ) {
1537 if ( !dynbuf ) { // create dynamic buffer
1538 dynbuf = new Q3CString(buflen*2);
1539 memcpy( dynbuf->data(), s, i ); // copy old data
1540 } else if ( i >= (int)dynbuf->size()-1 ) {
1541 dynbuf->resize( dynbuf->size()*2 );
1542 }
1543 s = dynbuf->data();
1544 }
1545 s[i++] = c.toLatin1();
1546 c = ts_getc();
1547 }
1548 str.resize( i );
1549 memcpy( str.data(), s, i );
1550
1551 delete dynbuf;
1552 return *this;
1553}
1554
1555
1556/*!
1557 \since 4.2
1558
1559 Reads a line from the stream and returns a string containing the
1560 text.
1561
1562 The returned string does not contain any trailing newline or
1563 carriage return. Note that this is different from
1564 QIODevice::readLine(), which does not strip the newline at the end
1565 of the line.
1566
1567 On EOF you will get a QString that is null. On reading an empty
1568 line the returned QString is empty but not null.
1569
1570 \sa QIODevice::readLine()
1571*/
1572
1573QString Q3TextStream::readLine()
1574{
1575#if defined(QT_CHECK_STATE)
1576 if ( !dev ) {
1577 qWarning( "Q3TextStream::readLine: No device" );
1578 return QString::null;
1579 }
1580#endif
1581 bool readCharByChar = TRUE;
1582 QString result;
1583#if 0
1584 if ( !doUnicodeHeader && (
1585 (latin1) ||
1586 (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8
1587 ) ) {
1588 readCharByChar = FALSE;
1589 // use optimized read line
1590 QChar c[getline_buf_size];
1591 int pos = 0;
1592 bool eof = FALSE;
1593
1594 for (;;) {
1595 pos = ts_getline( c );
1596 if ( pos == 0 ) {
1597 // something went wrong; try fallback
1598 readCharByChar = TRUE;
1599 //dev->resetStatus();
1600 break;
1601 }
1602 if ( c[pos-1] == QEOF || c[pos-1] == '\n' ) {
1603 if ( pos>2 && c[pos-1]==QEOF && c[pos-2]=='\n' ) {
1604 result += QString( c, pos-2 );
1605 } else if ( pos > 1 ) {
1606 result += QString( c, pos-1 );
1607 }
1608 if ( pos == 1 && c[pos-1] == QEOF )
1609 eof = TRUE;
1610 break;
1611 } else {
1612 result += QString( c, pos );
1613 }
1614 }
1615 if ( eof && result.isEmpty() )
1616 return QString::null;
1617 }
1618#endif
1619 if ( readCharByChar ) {
1620 const int buf_size = 256;
1621 QChar c[buf_size];
1622 int pos = 0;
1623
1624 c[pos] = ts_getc();
1625 if ( c[pos] == QEOF )
1626 return QString::null;
1627
1628 while ( c[pos] != QEOF && c[pos] != QLatin1Char('\n') ) {
1629 if ( c[pos] == QLatin1Char('\r') ) { // ( handle mac and dos )
1630 QChar nextc = ts_getc();
1631 if ( nextc != QLatin1Char('\n') )
1632 ts_ungetc( nextc );
1633 break;
1634 }
1635 pos++;
1636 if ( pos >= buf_size ) {
1637 result += QString( c, pos );
1638 pos = 0;
1639 }
1640 c[pos] = ts_getc();
1641 }
1642 result += QString( c, pos );
1643 }
1644
1645 return result;
1646}
1647
1648
1649/*!
1650 \since 4.2
1651
1652 Reads the entire stream from the current position, and returns a string
1653 containing the text.
1654
1655 \sa readLine()
1656*/
1657
1658QString Q3TextStream::read()
1659{
1660#if defined(QT_CHECK_STATE)
1661 if ( !dev ) {
1662 qWarning( "Q3TextStream::read: No device" );
1663 return QString::null;
1664 }
1665#endif
1666 QString result;
1667 const uint bufsize = 512;
1668 QChar buf[bufsize];
1669 uint i, num, start;
1670 bool skipped_cr = FALSE;
1671
1672 for (;;) {
1673 num = ts_getbuf(buf,bufsize);
1674 // convert dos (\r\n) and mac (\r) style eol to unix style (\n)
1675 start = 0;
1676 for ( i=0; i<num; i++ ) {
1677 if ( buf[i] == QLatin1Char('\r') ) {
1678 // Only skip single cr's preceding lf's
1679 if ( skipped_cr ) {
1680 result += buf[i];
1681 start++;
1682 } else {
1683 result += QString( &buf[start], i-start );
1684 start = i+1;
1685 skipped_cr = TRUE;
1686 }
1687 } else {
1688 if ( skipped_cr ) {
1689 if ( buf[i] != QLatin1Char('\n') ) {
1690 // Should not have skipped it
1691 result += QLatin1Char('\n');
1692 }
1693 skipped_cr = FALSE;
1694 }
1695 }
1696 }
1697 if ( start < num )
1698 result += QString( &buf[start], i-start );
1699 if ( num != bufsize ) // if ( EOF )
1700 break;
1701 }
1702 return result;
1703}
1704
1705
1706
1707/*****************************************************************************
1708 Q3TextStream write functions
1709 *****************************************************************************/
1710
1711/*!
1712 \since 4.2
1713
1714 Writes character \c char to the stream and returns a reference to
1715 the stream.
1716
1717 The character \a c is assumed to be Latin1 encoded independent of
1718 the Encoding set for the Q3TextStream.
1719*/
1720Q3TextStream &Q3TextStream::operator<<( QChar c )
1721{
1722 CHECK_STREAM_PRECOND
1723 ts_putc( c );
1724 return *this;
1725}
1726
1727/*!
1728 \overload
1729 \since 4.2
1730
1731 Writes character \a c to the stream and returns a reference to the
1732 stream.
1733*/
1734Q3TextStream &Q3TextStream::operator<<( char c )
1735{
1736 CHECK_STREAM_PRECOND
1737 unsigned char uc = (unsigned char) c;
1738 ts_putc( uc );
1739 return *this;
1740}
1741
1742Q3TextStream &Q3TextStream::output_int( int format, ulong n, bool neg )
1743{
1744 static const char hexdigits_lower[] = "0123456789abcdef";
1745 static const char hexdigits_upper[] = "0123456789ABCDEF";
1746 CHECK_STREAM_PRECOND
1747 char buf[76];
1748 register char *p;
1749 int len;
1750 const char *hexdigits;
1751
1752 switch ( flags() & I_BASE_MASK ) {
1753
1754 case I_BASE_2: // output binary number
1755 switch ( format & I_TYPE_MASK ) {
1756 case I_SHORT: len=16; break;
1757 case I_INT: len=sizeof(int)*8; break;
1758 case I_LONG: len=32; break;
1759 default: len = 0;
1760 }
1761 p = &buf[74]; // go reverse order
1762 *p = '\0';
1763 while ( len-- ) {
1764 *--p = (char)(n&1) + '0';
1765 n >>= 1;
1766 if ( !n )
1767 break;
1768 }
1769 if ( flags() & showbase ) { // show base
1770 *--p = (flags() & uppercase) ? 'B' : 'b';
1771 *--p = '0';
1772 }
1773 break;
1774
1775 case I_BASE_8: // output octal number
1776 p = &buf[74];
1777 *p = '\0';
1778 do {
1779 *--p = (char)(n&7) + '0';
1780 n >>= 3;
1781 } while ( n );
1782 if ( flags() & showbase )
1783 *--p = '0';
1784 break;
1785
1786 case I_BASE_16: // output hexadecimal number
1787 p = &buf[74];
1788 *p = '\0';
1789 hexdigits = (flags() & uppercase) ?
1790 hexdigits_upper : hexdigits_lower;
1791 do {
1792 *--p = hexdigits[(int)n&0xf];
1793 n >>= 4;
1794 } while ( n );
1795 if ( flags() & showbase ) {
1796 *--p = (flags() & uppercase) ? 'X' : 'x';
1797 *--p = '0';
1798 }
1799 break;
1800
1801 default: // decimal base is default
1802 p = &buf[74];
1803 *p = '\0';
1804 if ( neg )
1805 n = (ulong)(-(long)n);
1806 do {
1807 *--p = ((int)(n%10)) + '0';
1808 n /= 10;
1809 } while ( n );
1810 if ( neg )
1811 *--p = '-';
1812 else if ( flags() & showpos )
1813 *--p = '+';
1814 if ( (flags() & internal) && fwidth && !ts_isdigit(QLatin1Char(*p)) ) {
1815 ts_putc( *p ); // special case for internal
1816 ++p; // padding
1817 fwidth--;
1818 return *this << (const char*)p;
1819 }
1820 }
1821 if ( fwidth ) { // adjustment required
1822 if ( !(flags() & left) ) { // but NOT left adjustment
1823 len = qstrlen(p);
1824 int padlen = fwidth - len;
1825 if ( padlen <= 0 ) { // no padding required
1826 writeBlock( p, len );
1827 } else if ( padlen < (int)(p-buf) ) { // speeds up padding
1828 memset( p-padlen, (char)fillchar, padlen );
1829 writeBlock( p-padlen, padlen+len );
1830 }
1831 else // standard padding
1832 *this << (const char*)p;
1833 }
1834 else
1835 *this << (const char*)p;
1836 fwidth = 0; // reset field width
1837 }
1838 else {
1839 writeBlock( p, qstrlen(p) );
1840 }
1841 return *this;
1842}
1843
1844
1845/*!
1846 \overload
1847 \since 4.2
1848
1849 Writes a \c short integer \a i to the stream and returns a
1850 reference to the stream.
1851*/
1852
1853Q3TextStream &Q3TextStream::operator<<( signed short i )
1854{
1855 return output_int( I_SHORT | I_SIGNED, i, i < 0 );
1856}
1857
1858
1859/*!
1860 \overload
1861 \since 4.2
1862
1863 Writes an \c unsigned \c short integer \a i to the stream and
1864 returns a reference to the stream.
1865*/
1866
1867Q3TextStream &Q3TextStream::operator<<( unsigned short i )
1868{
1869 return output_int( I_SHORT | I_UNSIGNED, i, FALSE );
1870}
1871
1872
1873/*!
1874 \overload
1875 \since 4.2
1876
1877 Writes an \c int \a i to the stream and returns a reference to the
1878 stream.
1879*/
1880
1881Q3TextStream &Q3TextStream::operator<<( signed int i )
1882{
1883 return output_int( I_INT | I_SIGNED, i, i < 0 );
1884}
1885
1886
1887/*!
1888 \overload
1889 \since 4.2
1890
1891 Writes an \c unsigned \c int \a i to the stream and returns a
1892 reference to the stream.
1893*/
1894
1895Q3TextStream &Q3TextStream::operator<<( unsigned int i )
1896{
1897 return output_int( I_INT | I_UNSIGNED, i, FALSE );
1898}
1899
1900
1901/*!
1902 \overload
1903 \since 4.2
1904
1905 Writes a \c long \c int \a i to the stream and returns a reference
1906 to the stream.
1907*/
1908
1909Q3TextStream &Q3TextStream::operator<<( signed long i )
1910{
1911 return output_int( I_LONG | I_SIGNED, i, i < 0 );
1912}
1913
1914
1915/*!
1916 \overload
1917 \since 4.2
1918
1919 Writes an \c unsigned \c long \c int \a i to the stream and
1920 returns a reference to the stream.
1921*/
1922
1923Q3TextStream &Q3TextStream::operator<<( unsigned long i )
1924{
1925 return output_int( I_LONG | I_UNSIGNED, i, FALSE );
1926}
1927
1928
1929/*!
1930 \overload
1931 \since 4.2
1932
1933 Writes a \c float \a f to the stream and returns a reference to
1934 the stream.
1935*/
1936
1937Q3TextStream &Q3TextStream::operator<<( float f )
1938{
1939 return *this << (double)f;
1940}
1941
1942/*!
1943 \overload
1944 \since 4.2
1945
1946 Writes a \c double \a f to the stream and returns a reference to
1947 the stream.
1948*/
1949
1950Q3TextStream &Q3TextStream::operator<<( double f )
1951{
1952 CHECK_STREAM_PRECOND
1953 char f_char;
1954 char format[16];
1955 if ( (flags()&floatfield) == fixed )
1956 f_char = 'f';
1957 else if ( (flags()&floatfield) == scientific )
1958 f_char = (flags() & uppercase) ? 'E' : 'e';
1959 else
1960 f_char = (flags() & uppercase) ? 'G' : 'g';
1961 register char *fs = format; // generate format string
1962 *fs++ = '%'; // "%.<prec>l<f_char>"
1963 *fs++ = '.';
1964 int prec = precision();
1965 if ( prec > 99 )
1966 prec = 99;
1967 if ( prec >= 10 ) {
1968 *fs++ = prec / 10 + '0';
1969 *fs++ = prec % 10 + '0';
1970 } else {
1971 *fs++ = prec + '0';
1972 }
1973 *fs++ = 'l';
1974 *fs++ = f_char;
1975 *fs = '\0';
1976 QString num;
1977 num.sprintf(format, f); // convert to text
1978 if ( fwidth ) // padding
1979 *this << num.latin1();
1980 else // just write it
1981 writeBlock(num.latin1(), num.length());
1982 return *this;
1983}
1984
1985
1986/*!
1987 \overload
1988 \since 4.2
1989
1990 Writes a string to the stream and returns a reference to the
1991 stream.
1992
1993 The string \a s is assumed to be Latin1 encoded independent of the
1994 Encoding set for the Q3TextStream.
1995*/
1996
1997Q3TextStream &Q3TextStream::operator<<( const char* s )
1998{
1999 CHECK_STREAM_PRECOND
2000 char padbuf[48];
2001 uint len = qstrlen( s ); // don't write null terminator
2002 if ( fwidth ) { // field width set
2003 int padlen = fwidth - len;
2004 fwidth = 0; // reset width
2005 if ( padlen > 0 ) {
2006 char *ppad;
2007 if ( padlen > 46 ) { // create extra big fill buffer
2008 ppad = new char[padlen];
2009 Q_CHECK_PTR( ppad );
2010 } else {
2011 ppad = padbuf;
2012 }
2013 memset( ppad, (char)fillchar, padlen ); // fill with fillchar
2014 if ( !(flags() & left) ) {
2015 writeBlock( ppad, padlen );
2016 padlen = 0;
2017 }
2018 writeBlock( s, len );
2019 if ( padlen )
2020 writeBlock( ppad, padlen );
2021 if ( ppad != padbuf ) // delete extra big fill buf
2022 delete[] ppad;
2023 return *this;
2024 }
2025 }
2026 writeBlock( s, len );
2027 return *this;
2028}
2029
2030/*!
2031 \overload
2032 \since 4.2
2033
2034 Writes \a s to the stream and returns a reference to the stream.
2035
2036 The string \a s is assumed to be Latin1 encoded independent of the
2037 Encoding set for the Q3TextStream.
2038*/
2039
2040Q3TextStream &Q3TextStream::operator<<( const Q3CString & s )
2041{
2042 return operator<<(s.data());
2043}
2044