author | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
---|---|---|
committer | kergoth <kergoth> | 2002-11-01 00:10:42 (UTC) |
commit | 5042e3cf0d3514552769e441f5aad590c8eaf967 (patch) (unidiff) | |
tree | 4a5ea45f3519d981a172ab5275bf38c6fa778dec /qmake/tools/qtextstream.cpp | |
parent | 108c1c753e74e989cc13923086996791428c9af4 (diff) | |
download | opie-5042e3cf0d3514552769e441f5aad590c8eaf967.zip opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.gz opie-5042e3cf0d3514552769e441f5aad590c8eaf967.tar.bz2 |
Adding qmake in preperation for new build system
-rw-r--r-- | qmake/tools/qtextstream.cpp | 2593 |
1 files changed, 2593 insertions, 0 deletions
diff --git a/qmake/tools/qtextstream.cpp b/qmake/tools/qtextstream.cpp new file mode 100644 index 0000000..75c6531 --- a/dev/null +++ b/qmake/tools/qtextstream.cpp | |||
@@ -0,0 +1,2593 @@ | |||
1 | /**************************************************************************** | ||
2 | ** $Id$ | ||
3 | ** | ||
4 | ** Implementation of QTextStream class | ||
5 | ** | ||
6 | ** Created : 940922 | ||
7 | ** | ||
8 | ** Copyright (C) 1992-2002 Trolltech AS. All rights reserved. | ||
9 | ** | ||
10 | ** This file is part of the tools module of the Qt GUI Toolkit. | ||
11 | ** | ||
12 | ** This file may be distributed under the terms of the Q Public License | ||
13 | ** as defined by Trolltech AS of Norway and appearing in the file | ||
14 | ** LICENSE.QPL included in the packaging of this file. | ||
15 | ** | ||
16 | ** This file may be distributed and/or modified under the terms of the | ||
17 | ** GNU General Public License version 2 as published by the Free Software | ||
18 | ** Foundation and appearing in the file LICENSE.GPL included in the | ||
19 | ** packaging of this file. | ||
20 | ** | ||
21 | ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition | ||
22 | ** licenses may use this file in accordance with the Qt Commercial License | ||
23 | ** Agreement provided with the Software. | ||
24 | ** | ||
25 | ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | ||
26 | ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | ||
27 | ** | ||
28 | ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for | ||
29 | ** information about Qt Commercial License Agreements. | ||
30 | ** See http://www.trolltech.com/qpl/ for QPL licensing information. | ||
31 | ** See http://www.trolltech.com/gpl/ for GPL licensing information. | ||
32 | ** | ||
33 | ** Contact info@trolltech.com if any conditions of this licensing are | ||
34 | ** not clear to you. | ||
35 | ** | ||
36 | **********************************************************************/ | ||
37 | |||
38 | #include "qtextstream.h" | ||
39 | |||
40 | #ifndef QT_NO_TEXTSTREAM | ||
41 | #include "qtextcodec.h" | ||
42 | #include "qregexp.h" | ||
43 | #include "qbuffer.h" | ||
44 | #include "qfile.h" | ||
45 | #include <stdio.h> | ||
46 | #include <ctype.h> | ||
47 | #include <stdlib.h> | ||
48 | |||
49 | #if defined(Q_OS_WIN32) | ||
50 | #include <windows.h> | ||
51 | #endif | ||
52 | |||
53 | /*! | ||
54 | \class QTextStream qtextstream.h | ||
55 | \reentrant | ||
56 | \brief The QTextStream class provides basic functions for reading | ||
57 | and writing text using a QIODevice. | ||
58 | |||
59 | \ingroup io | ||
60 | \ingroup text | ||
61 | \mainclass | ||
62 | |||
63 | The text stream class has a functional interface that is very | ||
64 | similar to that of the standard C++ iostream class. | ||
65 | |||
66 | Qt provides several global functions similar to the ones in iostream: | ||
67 | \table | ||
68 | \header \i Function \i Meaning | ||
69 | \row \i bin \i sets the QTextStream to read/write binary numbers | ||
70 | \row \i oct \i sets the QTextStream to read/write octal numbers | ||
71 | \row \i dec \i sets the QTextStream to read/write decimal numbers | ||
72 | \row \i hex \i sets the QTextStream to read/write hexadecimal numbers | ||
73 | \row \i endl \i forces a line break | ||
74 | \row \i flush \i forces the QIODevice to flush any buffered data | ||
75 | \row \i ws \i eats any available whitespace (on input) | ||
76 | \row \i reset \i resets the QTextStream to its default mode (see reset()) | ||
77 | \row \i qSetW(int) \i sets the \link width() field width \endlink | ||
78 | to the given argument | ||
79 | \row \i qSetFill(int) \i sets the \link fill() fill character | ||
80 | \endlink to the given argument | ||
81 | \row \i qSetPrecision(int) \i sets the \link precision() precision | ||
82 | \endlink to the given argument | ||
83 | \endtable | ||
84 | |||
85 | \warning By default QTextStream will automatically detect whether | ||
86 | integers in the stream are in decimal, octal, hexadecimal or | ||
87 | binary format when reading from the stream. In particular, a | ||
88 | leading '0' signifies octal, i.e. the sequence "0100" will be | ||
89 | interpreted as 64. | ||
90 | |||
91 | The QTextStream class reads and writes text; it is not appropriate | ||
92 | for dealing with binary data (but QDataStream is). | ||
93 | |||
94 | By default, output of Unicode text (i.e. QString) is done using | ||
95 | the local 8-bit encoding. This can be changed using the | ||
96 | setEncoding() method. For input, the QTextStream will auto-detect | ||
97 | standard Unicode "byte order marked" text files; otherwise the | ||
98 | local 8-bit encoding is used. | ||
99 | |||
100 | The QIODevice is set in the constructor, or later using | ||
101 | setDevice(). If the end of the input is reached atEnd() returns | ||
102 | TRUE. Data can be read into variables of the appropriate type | ||
103 | using the operator>>() overloads, or read in its entirety into a | ||
104 | single string using read(), or read a line at a time using | ||
105 | readLine(). Whitespace can be skipped over using skipWhiteSpace(). | ||
106 | You can set flags for the stream using flags() or setf(). The | ||
107 | stream also supports width(), precision() and fill(); use reset() | ||
108 | to reset the defaults. | ||
109 | |||
110 | \sa QDataStream | ||
111 | */ | ||
112 | |||
113 | /*! | ||
114 | \enum QTextStream::Encoding | ||
115 | |||
116 | \value Locale | ||
117 | \value Latin1 | ||
118 | \value Unicode | ||
119 | \value UnicodeNetworkOrder | ||
120 | \value UnicodeReverse | ||
121 | \value RawUnicode | ||
122 | \value UnicodeUTF8 | ||
123 | |||
124 | See setEncoding() for an explanation of the encodings. | ||
125 | */ | ||
126 | |||
127 | /* | ||
128 | \class QTSManip | ||
129 | |||
130 | \brief The QTSManip class is an internal helper class for the | ||
131 | QTextStream. | ||
132 | |||
133 | It is generally a very bad idea to use this class directly in | ||
134 | application programs. | ||
135 | |||
136 | \internal | ||
137 | |||
138 | This class makes it possible to give the QTextStream function objects | ||
139 | with arguments, like this: | ||
140 | \code | ||
141 | QTextStream cout( stdout, IO_WriteOnly ); | ||
142 | cout << setprecision( 8 ); // QTSManip used here! | ||
143 | cout << 3.14159265358979323846; | ||
144 | \endcode | ||
145 | |||
146 | The setprecision() function returns a QTSManip object. | ||
147 | The QTSManip object contains a pointer to a member function in | ||
148 | QTextStream and an integer argument. | ||
149 | When serializing a QTSManip into a QTextStream, the function | ||
150 | is executed with the argument. | ||
151 | */ | ||
152 | |||
153 | /*! \fn QTSManip::QTSManip( QTSMFI m, int a ) | ||
154 | |||
155 | Constructs a QTSManip object which will call \a m (a member function | ||
156 | in QTextStream which accepts a single int) with argument \a a when | ||
157 | QTSManip::exec() is called. Used internally in e.g. endl: | ||
158 | |||
159 | \code | ||
160 | s << "some text" << endl << "more text"; | ||
161 | \endcode | ||
162 | */ | ||
163 | |||
164 | /*! \fn void QTSManip::exec( QTextStream& s ) | ||
165 | |||
166 | Calls the member function specified in the constructor, for object | ||
167 | \a s. Used internally in e.g. endl: | ||
168 | |||
169 | \code | ||
170 | s << "some text" << endl << "more text"; | ||
171 | \endcode | ||
172 | */ | ||
173 | |||
174 | |||
175 | /***************************************************************************** | ||
176 | QTextStream member functions | ||
177 | *****************************************************************************/ | ||
178 | |||
179 | #if defined(QT_CHECK_STATE) | ||
180 | #undef CHECK_STREAM_PRECOND | ||
181 | #define CHECK_STREAM_PRECOND if ( !dev ) { \ | ||
182 | qWarning( "QTextStream: No device" );\ | ||
183 | return *this; } | ||
184 | #else | ||
185 | #define CHECK_STREAM_PRECOND | ||
186 | #endif | ||
187 | |||
188 | |||
189 | #define I_SHORT 0x0010 | ||
190 | #define I_INT 0x0020 | ||
191 | #define I_LONG 0x0030 | ||
192 | #define I_TYPE_MASK0x00f0 | ||
193 | |||
194 | #define I_BASE_2QTS::bin | ||
195 | #define I_BASE_8QTS::oct | ||
196 | #define I_BASE_10QTS::dec | ||
197 | #define I_BASE_16QTS::hex | ||
198 | #define I_BASE_MASK(QTS::bin | QTS::oct | QTS::dec | QTS::hex) | ||
199 | |||
200 | #define I_SIGNED0x0100 | ||
201 | #define I_UNSIGNED0x0200 | ||
202 | #define I_SIGN_MASK0x0f00 | ||
203 | |||
204 | |||
205 | static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character. | ||
206 | static const uint getline_buf_size = 256; // bufsize used by ts_getline() | ||
207 | |||
208 | const int QTextStream::basefield = I_BASE_MASK; | ||
209 | const int QTextStream::adjustfield = ( QTextStream::left | | ||
210 | QTextStream::right | | ||
211 | QTextStream::internal ); | ||
212 | const int QTextStream::floatfield = ( QTextStream::scientific | | ||
213 | QTextStream::fixed ); | ||
214 | |||
215 | |||
216 | class QTextStreamPrivate { | ||
217 | public: | ||
218 | #ifndef QT_NO_TEXTCODEC | ||
219 | QTextStreamPrivate() | ||
220 | : decoder( 0 ), encoder( 0 ), sourceType( NotSet ) { } | ||
221 | ~QTextStreamPrivate() { | ||
222 | delete decoder; | ||
223 | delete encoder; | ||
224 | } | ||
225 | QTextDecoder *decoder; | ||
226 | QTextEncoder *encoder; | ||
227 | #else | ||
228 | QTextStreamPrivate() : sourceType( NotSet ) { } | ||
229 | ~QTextStreamPrivate() { } | ||
230 | #endif | ||
231 | QString ungetcBuf; | ||
232 | |||
233 | enum SourceType { NotSet, IODevice, String, ByteArray, File }; | ||
234 | SourceType sourceType; | ||
235 | }; | ||
236 | |||
237 | |||
238 | // skips whitespace and returns the first non-whitespace character | ||
239 | QChar QTextStream::eat_ws() | ||
240 | { | ||
241 | QChar c; | ||
242 | do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) ); | ||
243 | return c; | ||
244 | } | ||
245 | |||
246 | void QTextStream::init() | ||
247 | { | ||
248 | // ### ungetcBuf = QEOF; | ||
249 | dev = 0; | ||
250 | owndev = FALSE; | ||
251 | mapper = 0; | ||
252 | d = new QTextStreamPrivate; | ||
253 | doUnicodeHeader = TRUE; // autodetect | ||
254 | latin1 = TRUE; // should use locale? | ||
255 | internalOrder = QChar::networkOrdered(); | ||
256 | networkOrder = TRUE; | ||
257 | } | ||
258 | |||
259 | /*! | ||
260 | Constructs a data stream that has no IO device. | ||
261 | */ | ||
262 | |||
263 | QTextStream::QTextStream() | ||
264 | { | ||
265 | init(); | ||
266 | setEncoding( Locale ); //### | ||
267 | reset(); | ||
268 | d->sourceType = QTextStreamPrivate::NotSet; | ||
269 | } | ||
270 | |||
271 | /*! | ||
272 | Constructs a text stream that uses the IO device \a iod. | ||
273 | */ | ||
274 | |||
275 | QTextStream::QTextStream( QIODevice *iod ) | ||
276 | { | ||
277 | init(); | ||
278 | setEncoding( Locale ); //### | ||
279 | dev = iod; | ||
280 | reset(); | ||
281 | d->sourceType = QTextStreamPrivate::IODevice; | ||
282 | } | ||
283 | |||
284 | // TODO: use special-case handling of this case in QTextStream, and | ||
285 | // simplify this class to only deal with QChar or QString data. | ||
286 | class QStringBuffer : public QIODevice { | ||
287 | public: | ||
288 | QStringBuffer( QString* str ); | ||
289 | ~QStringBuffer(); | ||
290 | bool open( int m ); | ||
291 | void close(); | ||
292 | void flush(); | ||
293 | Offset size() const; | ||
294 | Offset at() const; | ||
295 | bool at( Offset pos ); | ||
296 | Q_LONG readBlock( char *p, Q_ULONG len ); | ||
297 | Q_LONG writeBlock( const char *p, Q_ULONG len ); | ||
298 | int getch(); | ||
299 | int putch( int ch ); | ||
300 | int ungetch( int ch ); | ||
301 | protected: | ||
302 | QString* s; | ||
303 | |||
304 | private: // Disabled copy constructor and operator= | ||
305 | QStringBuffer( const QStringBuffer & ); | ||
306 | QStringBuffer &operator=( const QStringBuffer & ); | ||
307 | }; | ||
308 | |||
309 | |||
310 | QStringBuffer::QStringBuffer( QString* str ) | ||
311 | { | ||
312 | s = str; | ||
313 | } | ||
314 | |||
315 | QStringBuffer::~QStringBuffer() | ||
316 | { | ||
317 | } | ||
318 | |||
319 | |||
320 | bool QStringBuffer::open( int m ) | ||
321 | { | ||
322 | if ( !s ) { | ||
323 | #if defined(QT_CHECK_STATE) | ||
324 | qWarning( "QStringBuffer::open: No string" ); | ||
325 | #endif | ||
326 | return FALSE; | ||
327 | } | ||
328 | if ( isOpen() ) { // buffer already open | ||
329 | #if defined(QT_CHECK_STATE) | ||
330 | qWarning( "QStringBuffer::open: Buffer already open" ); | ||
331 | #endif | ||
332 | return FALSE; | ||
333 | } | ||
334 | setMode( m ); | ||
335 | if ( m & IO_Truncate ) { // truncate buffer | ||
336 | s->truncate( 0 ); | ||
337 | } | ||
338 | if ( m & IO_Append ) { // append to end of buffer | ||
339 | ioIndex = s->length()*sizeof(QChar); | ||
340 | } else { | ||
341 | ioIndex = 0; | ||
342 | } | ||
343 | setState( IO_Open ); | ||
344 | setStatus( 0 ); | ||
345 | return TRUE; | ||
346 | } | ||
347 | |||
348 | void QStringBuffer::close() | ||
349 | { | ||
350 | if ( isOpen() ) { | ||
351 | setFlags( IO_Direct ); | ||
352 | ioIndex = 0; | ||
353 | } | ||
354 | } | ||
355 | |||
356 | void QStringBuffer::flush() | ||
357 | { | ||
358 | } | ||
359 | |||
360 | QIODevice::Offset QStringBuffer::size() const | ||
361 | { | ||
362 | return s ? s->length()*sizeof(QChar) : 0; | ||
363 | } | ||
364 | |||
365 | QIODevice::Offset QStringBuffer::at() const | ||
366 | { | ||
367 | return ioIndex; | ||
368 | } | ||
369 | |||
370 | bool QStringBuffer::at( Offset pos ) | ||
371 | { | ||
372 | #if defined(QT_CHECK_STATE) | ||
373 | if ( !isOpen() ) { | ||
374 | qWarning( "QStringBuffer::at: Buffer is not open" ); | ||
375 | return FALSE; | ||
376 | } | ||
377 | #endif | ||
378 | if ( pos >= s->length()*2 ) { | ||
379 | #if defined(QT_CHECK_RANGE) | ||
380 | #if defined(QT_LARGEFILE_SUPPORT) && defined(QT_ABI_64BITOFFSET) | ||
381 | qWarning( "QStringBuffer::at: Index %llu out of range", pos ); | ||
382 | #else | ||
383 | qWarning( "QStringBuffer::at: Index %lu out of range", pos ); | ||
384 | #endif | ||
385 | #endif | ||
386 | return FALSE; | ||
387 | } | ||
388 | ioIndex = pos; | ||
389 | return TRUE; | ||
390 | } | ||
391 | |||
392 | |||
393 | Q_LONG QStringBuffer::readBlock( char *p, Q_ULONG len ) | ||
394 | { | ||
395 | #if defined(QT_CHECK_STATE) | ||
396 | Q_CHECK_PTR( p ); | ||
397 | if ( !isOpen() ) { // buffer not open | ||
398 | qWarning( "QStringBuffer::readBlock: Buffer not open" ); | ||
399 | return -1; | ||
400 | } | ||
401 | if ( !isReadable() ) { // reading not permitted | ||
402 | qWarning( "QStringBuffer::readBlock: Read operation not permitted" ); | ||
403 | return -1; | ||
404 | } | ||
405 | #endif | ||
406 | if ( ioIndex + len > s->length()*sizeof(QChar) ) { | ||
407 | // overflow | ||
408 | if ( (uint)ioIndex >= s->length()*sizeof(QChar) ) { | ||
409 | setStatus( IO_ReadError ); | ||
410 | return -1; | ||
411 | } else { | ||
412 | len = s->length()*2 - (uint)ioIndex; | ||
413 | } | ||
414 | } | ||
415 | memcpy( p, ((const char*)(s->unicode()))+ioIndex, len ); | ||
416 | ioIndex += len; | ||
417 | return len; | ||
418 | } | ||
419 | |||
420 | Q_LONG QStringBuffer::writeBlock( const char *p, Q_ULONG len ) | ||
421 | { | ||
422 | #if defined(QT_CHECK_NULL) | ||
423 | if ( p == 0 && len != 0 ) | ||
424 | qWarning( "QStringBuffer::writeBlock: Null pointer error" ); | ||
425 | #endif | ||
426 | #if defined(QT_CHECK_STATE) | ||
427 | if ( !isOpen() ) { // buffer not open | ||
428 | qWarning( "QStringBuffer::writeBlock: Buffer not open" ); | ||
429 | return -1; | ||
430 | } | ||
431 | if ( !isWritable() ) { // writing not permitted | ||
432 | qWarning( "QStringBuffer::writeBlock: Write operation not permitted" ); | ||
433 | return -1; | ||
434 | } | ||
435 | if ( ioIndex&1 ) { | ||
436 | qWarning( "QStringBuffer::writeBlock: non-even index - non Unicode" ); | ||
437 | return -1; | ||
438 | } | ||
439 | if ( len&1 ) { | ||
440 | qWarning( "QStringBuffer::writeBlock: non-even length - non Unicode" ); | ||
441 | return -1; | ||
442 | } | ||
443 | #endif | ||
444 | s->replace(ioIndex/2, len/2, (QChar*)p, len/2); | ||
445 | ioIndex += len; | ||
446 | return len; | ||
447 | } | ||
448 | |||
449 | int QStringBuffer::getch() | ||
450 | { | ||
451 | #if defined(QT_CHECK_STATE) | ||
452 | if ( !isOpen() ) { // buffer not open | ||
453 | qWarning( "QStringBuffer::getch: Buffer not open" ); | ||
454 | return -1; | ||
455 | } | ||
456 | if ( !isReadable() ) { // reading not permitted | ||
457 | qWarning( "QStringBuffer::getch: Read operation not permitted" ); | ||
458 | return -1; | ||
459 | } | ||
460 | #endif | ||
461 | if ( (uint)ioIndex >= s->length()*2 ) { // overflow | ||
462 | setStatus( IO_ReadError ); | ||
463 | return -1; | ||
464 | } | ||
465 | return (int) *( (const char *) s->unicode() + ioIndex++ ); | ||
466 | } | ||
467 | |||
468 | int QStringBuffer::putch( int ch ) | ||
469 | { | ||
470 | char c = ch; | ||
471 | if ( writeBlock(&c,1) < 0 ) | ||
472 | return -1; | ||
473 | else | ||
474 | return ch; | ||
475 | } | ||
476 | |||
477 | int QStringBuffer::ungetch( int ch ) | ||
478 | { | ||
479 | #if defined(QT_CHECK_STATE) | ||
480 | if ( !isOpen() ) { // buffer not open | ||
481 | qWarning( "QStringBuffer::ungetch: Buffer not open" ); | ||
482 | return -1; | ||
483 | } | ||
484 | if ( !isReadable() ) { // reading not permitted | ||
485 | qWarning( "QStringBuffer::ungetch: Read operation not permitted" ); | ||
486 | return -1; | ||
487 | } | ||
488 | #endif | ||
489 | if ( ch != -1 ) { // something to do with eof | ||
490 | if ( ioIndex ) | ||
491 | ioIndex--; | ||
492 | else | ||
493 | ch = -1; | ||
494 | } | ||
495 | return ch; | ||
496 | } | ||
497 | |||
498 | |||
499 | /*! | ||
500 | Constructs a text stream that operates on the Unicode QString, \a | ||
501 | str, through an internal device. The \a filemode argument is | ||
502 | passed to the device's open() function; see \l{QIODevice::mode()}. | ||
503 | |||
504 | If you set an encoding or codec with setEncoding() or setCodec(), | ||
505 | this setting is ignored for text streams that operate on QString. | ||
506 | |||
507 | Example: | ||
508 | \code | ||
509 | QString str; | ||
510 | QTextStream ts( &str, IO_WriteOnly ); | ||
511 | ts << "pi = " << 3.14; // str == "pi = 3.14" | ||
512 | \endcode | ||
513 | |||
514 | Writing data to the text stream will modify the contents of the | ||
515 | string. The string will be expanded when data is written beyond | ||
516 | the end of the string. Note that the string will not be truncated: | ||
517 | \code | ||
518 | QString str = "pi = 3.14"; | ||
519 | QTextStream ts( &str, IO_WriteOnly ); | ||
520 | ts << "2+2 = " << 2+2; // str == "2+2 = 414" | ||
521 | \endcode | ||
522 | |||
523 | Note that because QString is Unicode, you should not use | ||
524 | readRawBytes() or writeRawBytes() on such a stream. | ||
525 | */ | ||
526 | |||
527 | QTextStream::QTextStream( QString* str, int filemode ) | ||
528 | { | ||
529 | // TODO: optimize for this case as it becomes more common | ||
530 | // (see QStringBuffer above) | ||
531 | init(); | ||
532 | dev = new QStringBuffer( str ); | ||
533 | ((QStringBuffer *)dev)->open( filemode ); | ||
534 | owndev = TRUE; | ||
535 | setEncoding(RawUnicode); | ||
536 | reset(); | ||
537 | d->sourceType = QTextStreamPrivate::String; | ||
538 | } | ||
539 | |||
540 | /*! \obsolete | ||
541 | |||
542 | This constructor is equivalent to the constructor taking a QString* | ||
543 | parameter. | ||
544 | */ | ||
545 | |||
546 | QTextStream::QTextStream( QString& str, int filemode ) | ||
547 | { | ||
548 | init(); | ||
549 | dev = new QStringBuffer( &str ); | ||
550 | ((QStringBuffer *)dev)->open( filemode ); | ||
551 | owndev = TRUE; | ||
552 | setEncoding(RawUnicode); | ||
553 | reset(); | ||
554 | d->sourceType = QTextStreamPrivate::String; | ||
555 | } | ||
556 | |||
557 | /*! | ||
558 | Constructs a text stream that operates on the byte array, \a a, | ||
559 | through an internal QBuffer device. The \a mode argument is passed | ||
560 | to the device's open() function; see \l{QIODevice::mode()}. | ||
561 | |||
562 | Example: | ||
563 | \code | ||
564 | QByteArray array; | ||
565 | QTextStream ts( array, IO_WriteOnly ); | ||
566 | ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" | ||
567 | \endcode | ||
568 | |||
569 | Writing data to the text stream will modify the contents of the | ||
570 | array. The array will be expanded when data is written beyond the | ||
571 | end of the string. | ||
572 | |||
573 | Same example, using a QBuffer: | ||
574 | \code | ||
575 | QByteArray array; | ||
576 | QBuffer buf( array ); | ||
577 | buf.open( IO_WriteOnly ); | ||
578 | QTextStream ts( &buf ); | ||
579 | ts << "pi = " << 3.14 << '\0'; // array == "pi = 3.14" | ||
580 | buf.close(); | ||
581 | \endcode | ||
582 | */ | ||
583 | |||
584 | QTextStream::QTextStream( QByteArray a, int mode ) | ||
585 | { | ||
586 | init(); | ||
587 | dev = new QBuffer( a ); | ||
588 | ((QBuffer *)dev)->open( mode ); | ||
589 | owndev = TRUE; | ||
590 | setEncoding( Latin1 ); //### Locale??? | ||
591 | reset(); | ||
592 | d->sourceType = QTextStreamPrivate::ByteArray; | ||
593 | } | ||
594 | |||
595 | /*! | ||
596 | Constructs a text stream that operates on an existing file handle | ||
597 | \a fh through an internal QFile device. The \a mode argument is | ||
598 | passed to the device's open() function; see \l{QIODevice::mode()}. | ||
599 | |||
600 | Note that if you create a QTextStream \c cout or another name that | ||
601 | is also used for another variable of a different type, some | ||
602 | linkers may confuse the two variables, which will often cause | ||
603 | crashes. | ||
604 | */ | ||
605 | |||
606 | QTextStream::QTextStream( FILE *fh, int mode ) | ||
607 | { | ||
608 | init(); | ||
609 | setEncoding( Locale ); //### | ||
610 | dev = new QFile; | ||
611 | ((QFile *)dev)->open( mode, fh ); | ||
612 | owndev = TRUE; | ||
613 | reset(); | ||
614 | d->sourceType = QTextStreamPrivate::File; | ||
615 | } | ||
616 | |||
617 | /*! | ||
618 | Destroys the text stream. | ||
619 | |||
620 | The destructor does not affect the current IO device. | ||
621 | */ | ||
622 | |||
623 | QTextStream::~QTextStream() | ||
624 | { | ||
625 | if ( owndev ) | ||
626 | delete dev; | ||
627 | delete d; | ||
628 | } | ||
629 | |||
630 | /*! | ||
631 | Positions the read pointer at the first non-whitespace character. | ||
632 | */ | ||
633 | void QTextStream::skipWhiteSpace() | ||
634 | { | ||
635 | ts_ungetc( eat_ws() ); | ||
636 | } | ||
637 | |||
638 | |||
639 | /*! | ||
640 | Tries to read \a len characters from the stream and stores them in | ||
641 | \a buf. Returns the number of characters really read. | ||
642 | |||
643 | \warning There will no QEOF appended if the read reaches the end | ||
644 | of the file. EOF is reached when the return value does not equal | ||
645 | \a len. | ||
646 | */ | ||
647 | uint QTextStream::ts_getbuf( QChar* buf, uint len ) | ||
648 | { | ||
649 | if( len < 1 ) | ||
650 | return 0; | ||
651 | |||
652 | uint rnum=0; // the number of QChars really read | ||
653 | |||
654 | if ( d && d->ungetcBuf.length() ) { | ||
655 | while( rnum < len && rnum < d->ungetcBuf.length() ) { | ||
656 | *buf = d->ungetcBuf.constref( rnum ); | ||
657 | buf++; | ||
658 | rnum++; | ||
659 | } | ||
660 | d->ungetcBuf = d->ungetcBuf.mid( rnum ); | ||
661 | if ( rnum >= len ) | ||
662 | return rnum; | ||
663 | } | ||
664 | |||
665 | // we use dev->ungetch() for one of the bytes of the unicode | ||
666 | // byte-order mark, but a local unget hack for the other byte: | ||
667 | int ungetHack = EOF; | ||
668 | |||
669 | if ( doUnicodeHeader ) { | ||
670 | doUnicodeHeader = FALSE; // only at the top | ||
671 | int c1 = dev->getch(); | ||
672 | if ( c1 == EOF ) | ||
673 | return rnum; | ||
674 | int c2 = dev->getch(); | ||
675 | if ( c1 == 0xfe && c2 == 0xff ) { | ||
676 | mapper = 0; | ||
677 | latin1 = FALSE; | ||
678 | internalOrder = QChar::networkOrdered(); | ||
679 | networkOrder = TRUE; | ||
680 | } else if ( c1 == 0xff && c2 == 0xfe ) { | ||
681 | mapper = 0; | ||
682 | latin1 = FALSE; | ||
683 | internalOrder = !QChar::networkOrdered(); | ||
684 | networkOrder = FALSE; | ||
685 | } else { | ||
686 | if ( c2 != EOF ) { | ||
687 | dev->ungetch( c2 ); | ||
688 | ungetHack = c1; | ||
689 | } else { | ||
690 | /* | ||
691 | A small bug might hide here. If only the first byte | ||
692 | of a file has made it so far, and that first byte | ||
693 | is half of the byte-order mark, then the utfness | ||
694 | will not be detected. | ||
695 | */ | ||
696 | dev->ungetch( c1 ); | ||
697 | } | ||
698 | } | ||
699 | } | ||
700 | |||
701 | #ifndef QT_NO_TEXTCODEC | ||
702 | if ( mapper ) { | ||
703 | bool shortRead = FALSE; | ||
704 | if ( !d->decoder ) | ||
705 | d->decoder = mapper->makeDecoder(); | ||
706 | while( rnum < len ) { | ||
707 | QString s; | ||
708 | bool readBlock = !( len == 1+rnum ); | ||
709 | for (;;) { | ||
710 | // for efficiency: normally read a whole block | ||
711 | if ( readBlock ) { | ||
712 | // guess buffersize; this may be wrong (too small or too | ||
713 | // big). But we can handle this (either iterate reading | ||
714 | // or use ungetcBuf). | ||
715 | // Note that this might cause problems for codecs where | ||
716 | // one byte can result in >1 Unicode Characters if bytes | ||
717 | // are written to the stream in the meantime (loss of | ||
718 | // synchronicity). | ||
719 | uint rlen = len - rnum; | ||
720 | char *cbuf = new char[ rlen ]; | ||
721 | if ( ungetHack != EOF ) { | ||
722 | rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); | ||
723 | cbuf[0] = (char)ungetHack; | ||
724 | ungetHack = EOF; | ||
725 | } else { | ||
726 | rlen = dev->readBlock( cbuf, rlen ); | ||
727 | } | ||
728 | s += d->decoder->toUnicode( cbuf, rlen ); | ||
729 | delete[] cbuf; | ||
730 | // use buffered reading only for the first time, because we | ||
731 | // have to get the stream synchronous again (this is easier | ||
732 | // with single character reading) | ||
733 | readBlock = FALSE; | ||
734 | } | ||
735 | // get stream (and codec) in sync | ||
736 | int c; | ||
737 | if ( ungetHack == EOF ) { | ||
738 | c = dev->getch(); | ||
739 | } else { | ||
740 | c = ungetHack; | ||
741 | ungetHack = EOF; | ||
742 | } | ||
743 | if ( c == EOF ) { | ||
744 | shortRead = TRUE; | ||
745 | break; | ||
746 | } | ||
747 | char b = c; | ||
748 | uint lengthBefore = s.length(); | ||
749 | s += d->decoder->toUnicode( &b, 1 ); | ||
750 | if ( s.length() > lengthBefore ) | ||
751 | break; // it seems we are in sync now | ||
752 | } | ||
753 | uint i = 0; | ||
754 | uint end = QMIN( len-rnum, s.length() ); | ||
755 | while( i < end ) { | ||
756 | *buf = s.constref(i++); | ||
757 | buf++; | ||
758 | } | ||
759 | rnum += end; | ||
760 | if ( s.length() > i ) | ||
761 | // could be = but append is clearer | ||
762 | d->ungetcBuf.append( s.mid( i ) ); | ||
763 | if ( shortRead ) | ||
764 | return rnum; | ||
765 | } | ||
766 | } else | ||
767 | #endif | ||
768 | if ( latin1 ) { | ||
769 | if ( len == 1+rnum ) { | ||
770 | // use this method for one character because it is more efficient | ||
771 | // (arnt doubts whether it makes a difference, but lets it stand) | ||
772 | int c = (ungetHack == EOF) ? dev->getch() : ungetHack; | ||
773 | if ( c != EOF ) { | ||
774 | *buf = (char)c; | ||
775 | buf++; | ||
776 | rnum++; | ||
777 | } | ||
778 | } else { | ||
779 | if ( ungetHack != EOF ) { | ||
780 | *buf = (char)ungetHack; | ||
781 | buf++; | ||
782 | rnum++; | ||
783 | ungetHack = EOF; | ||
784 | } | ||
785 | char *cbuf = new char[len - rnum]; | ||
786 | while ( !dev->atEnd() && rnum < len ) { | ||
787 | uint rlen = len - rnum; | ||
788 | rlen = dev->readBlock( cbuf, rlen ); | ||
789 | char *it = cbuf; | ||
790 | char *end = cbuf + rlen; | ||
791 | while ( it < end ) { | ||
792 | *buf = *it; | ||
793 | buf++; | ||
794 | it++; | ||
795 | } | ||
796 | rnum += rlen; | ||
797 | } | ||
798 | delete[] cbuf; | ||
799 | } | ||
800 | } else { // UCS-2 or UTF-16 | ||
801 | if ( len == 1+rnum ) { | ||
802 | int c1 = (ungetHack == EOF) ? dev->getch() : ungetHack; | ||
803 | if ( c1 == EOF ) | ||
804 | return rnum; | ||
805 | int c2 = dev->getch(); | ||
806 | if ( c2 == EOF ) | ||
807 | return rnum; | ||
808 | |||
809 | if ( networkOrder ) { | ||
810 | *buf = QChar( c2, c1 ); | ||
811 | } else { | ||
812 | *buf = QChar( c1, c2 ); | ||
813 | } | ||
814 | buf++; | ||
815 | rnum++; | ||
816 | } else { | ||
817 | char *cbuf = new char[ 2*( len - rnum ) ]; // for paranoids: overflow possible | ||
818 | while ( !dev->atEnd() && rnum < len ) { | ||
819 | uint rlen = 2 * ( len-rnum ); | ||
820 | if ( ungetHack != EOF ) { | ||
821 | rlen = 1+dev->readBlock( cbuf+1, rlen-1 ); | ||
822 | cbuf[0] = (char)ungetHack; | ||
823 | ungetHack = EOF; | ||
824 | } else { | ||
825 | rlen = dev->readBlock( cbuf, rlen ); | ||
826 | } | ||
827 | // We can't use an odd number of bytes, so put it back. But | ||
828 | // do it only if we are capable of reading more -- normally | ||
829 | // there should not be an odd number, but the file might be | ||
830 | // truncated or not in UTF-16... | ||
831 | if ( (rlen & 1) == 1 ) | ||
832 | if ( !dev->atEnd() ) | ||
833 | dev->ungetch( cbuf[--rlen] ); | ||
834 | uint i = 0; | ||
835 | if ( networkOrder ) { | ||
836 | while( i < rlen ) { | ||
837 | *buf = QChar( cbuf[i+1], cbuf[i] ); | ||
838 | buf++; | ||
839 | i+=2; | ||
840 | } | ||
841 | } else { | ||
842 | while( i < rlen ) { | ||
843 | *buf = QChar( cbuf[i], cbuf[i+1] ); | ||
844 | buf++; | ||
845 | i+=2; | ||
846 | } | ||
847 | } | ||
848 | rnum += i/2; | ||
849 | } | ||
850 | delete[] cbuf; | ||
851 | } | ||
852 | } | ||
853 | return rnum; | ||
854 | } | ||
855 | |||
856 | /*! | ||
857 | Tries to read one line, but at most len characters from the stream | ||
858 | and stores them in \a buf. | ||
859 | |||
860 | Returns the number of characters really read. Newlines are not | ||
861 | stripped. | ||
862 | |||
863 | There will be a QEOF appended if the read reaches the end of file; | ||
864 | this is different to ts_getbuf(). | ||
865 | |||
866 | This function works only if a newline (as byte) is also a newline | ||
867 | (as resulting character) since it uses QIODevice::readLine(). So | ||
868 | use it only for such codecs where this is true! | ||
869 | |||
870 | This function is (almost) a no-op for UTF 16. Don't use it if | ||
871 | doUnicodeHeader is TRUE! | ||
872 | */ | ||
873 | uint QTextStream::ts_getline( QChar* buf ) | ||
874 | { | ||
875 | uint rnum=0; // the number of QChars really read | ||
876 | char cbuf[ getline_buf_size+1 ]; | ||
877 | |||
878 | if ( d && d->ungetcBuf.length() ) { | ||
879 | while( rnum < getline_buf_size && rnum < d->ungetcBuf.length() ) { | ||
880 | buf[rnum] = d->ungetcBuf.constref(rnum); | ||
881 | rnum++; | ||
882 | } | ||
883 | d->ungetcBuf = d->ungetcBuf.mid( rnum ); | ||
884 | if ( rnum >= getline_buf_size ) | ||
885 | return rnum; | ||
886 | } | ||
887 | |||
888 | #ifndef QT_NO_TEXTCODEC | ||
889 | if ( mapper ) { | ||
890 | if ( !d->decoder ) | ||
891 | d->decoder = mapper->makeDecoder(); | ||
892 | QString s; | ||
893 | bool readBlock = TRUE; | ||
894 | for (;;) { | ||
895 | // for efficiency: try to read a line | ||
896 | if ( readBlock ) { | ||
897 | int rlen = getline_buf_size - rnum; | ||
898 | rlen = dev->readLine( cbuf, rlen+1 ); | ||
899 | if ( rlen == -1 ) | ||
900 | rlen = 0; | ||
901 | s += d->decoder->toUnicode( cbuf, rlen ); | ||
902 | readBlock = FALSE; | ||
903 | } | ||
904 | if ( dev->atEnd() | ||
905 | || s.at( s.length()-1 ) == '\n' | ||
906 | || s.at( s.length()-1 ) == '\r' | ||
907 | ) { | ||
908 | break; | ||
909 | } else { | ||
910 | // get stream (and codec) in sync | ||
911 | int c; | ||
912 | c = dev->getch(); | ||
913 | if ( c == EOF ) { | ||
914 | break; | ||
915 | } | ||
916 | char b = c; | ||
917 | uint lengthBefore = s.length(); | ||
918 | s += d->decoder->toUnicode( &b, 1 ); | ||
919 | if ( s.length() > lengthBefore ) | ||
920 | break; // it seems we are in sync now | ||
921 | } | ||
922 | } | ||
923 | uint i = 0; | ||
924 | while( rnum < getline_buf_size && i < s.length() ) | ||
925 | buf[rnum++] = s.constref(i++); | ||
926 | if ( s.length() > i ) | ||
927 | // could be = but append is clearer | ||
928 | d->ungetcBuf.append( s.mid( i ) ); | ||
929 | if ( rnum < getline_buf_size && dev->atEnd() ) | ||
930 | buf[rnum++] = QEOF; | ||
931 | } else | ||
932 | #endif | ||
933 | if ( latin1 ) { | ||
934 | int rlen = getline_buf_size - rnum; | ||
935 | rlen = dev->readLine( cbuf, rlen+1 ); | ||
936 | if ( rlen == -1 ) | ||
937 | rlen = 0; | ||
938 | char *end = cbuf+rlen; | ||
939 | char *it = cbuf; | ||
940 | buf +=rnum; | ||
941 | while ( it != end ) { | ||
942 | buf->setCell( *(it++) ); | ||
943 | buf->setRow( 0 ); | ||
944 | buf++; | ||
945 | } | ||
946 | rnum += rlen; | ||
947 | if ( rnum < getline_buf_size && dev->atEnd() ) | ||
948 | buf[1] = QEOF; | ||
949 | } | ||
950 | return rnum; | ||
951 | } | ||
952 | |||
953 | |||
954 | /*! | ||
955 | Puts one character into the stream. | ||
956 | */ | ||
957 | void QTextStream::ts_putc( QChar c ) | ||
958 | { | ||
959 | #ifndef QT_NO_TEXTCODEC | ||
960 | if ( mapper ) { | ||
961 | if ( !d->encoder ) | ||
962 | d->encoder = mapper->makeEncoder(); | ||
963 | int len = 1; | ||
964 | QString s = c; | ||
965 | QCString block = d->encoder->fromUnicode( s, len ); | ||
966 | dev->writeBlock( block, len ); | ||
967 | } else | ||
968 | #endif | ||
969 | if ( latin1 ) { | ||
970 | if ( c.row() ) | ||
971 | dev->putch( '?' ); // unknown character | ||
972 | else | ||
973 | dev->putch( c.cell() ); | ||
974 | } else { | ||
975 | if ( doUnicodeHeader ) { | ||
976 | doUnicodeHeader = FALSE; | ||
977 | ts_putc( QChar::byteOrderMark ); | ||
978 | } | ||
979 | if ( internalOrder ) { | ||
980 | // this case is needed by QStringBuffer | ||
981 | dev->writeBlock( (char*)&c, sizeof(QChar) ); | ||
982 | } else if ( networkOrder ) { | ||
983 | dev->putch( c.row() ); | ||
984 | dev->putch( c.cell() ); | ||
985 | } else { | ||
986 | dev->putch( c.cell() ); | ||
987 | dev->putch( c.row() ); | ||
988 | } | ||
989 | } | ||
990 | } | ||
991 | |||
992 | /*! | ||
993 | Puts one character into the stream. | ||
994 | */ | ||
995 | void QTextStream::ts_putc( int ch ) | ||
996 | { | ||
997 | ts_putc( QChar((ushort)ch) ); | ||
998 | } | ||
999 | |||
1000 | bool QTextStream::ts_isdigit( QChar c ) | ||
1001 | { | ||
1002 | return c.isDigit(); | ||
1003 | } | ||
1004 | |||
1005 | bool QTextStream::ts_isspace( QChar c ) | ||
1006 | { | ||
1007 | return c.isSpace(); | ||
1008 | } | ||
1009 | |||
1010 | void QTextStream::ts_ungetc( QChar c ) | ||
1011 | { | ||
1012 | if ( c.unicode() == 0xffff ) | ||
1013 | return; | ||
1014 | |||
1015 | d->ungetcBuf.prepend( c ); | ||
1016 | } | ||
1017 | |||
1018 | |||
1019 | |||
1020 | /*! | ||
1021 | Reads \a len bytes from the stream into \a s and returns a | ||
1022 | reference to the stream. | ||
1023 | |||
1024 | The buffer \a s must be preallocated. | ||
1025 | |||
1026 | Note that no encoding is done by this function. | ||
1027 | |||
1028 | \warning The behavior of this function is undefined unless the | ||
1029 | stream's encoding is set to Unicode or Latin1. | ||
1030 | |||
1031 | \sa QIODevice::readBlock() | ||
1032 | */ | ||
1033 | |||
1034 | QTextStream &QTextStream::readRawBytes( char *s, uint len ) | ||
1035 | { | ||
1036 | dev->readBlock( s, len ); | ||
1037 | return *this; | ||
1038 | } | ||
1039 | |||
1040 | /*! | ||
1041 | Writes the \a len bytes from \a s to the stream and returns a | ||
1042 | reference to the stream. | ||
1043 | |||
1044 | Note that no encoding is done by this function. | ||
1045 | |||
1046 | \sa QIODevice::writeBlock() | ||
1047 | */ | ||
1048 | |||
1049 | QTextStream &QTextStream::writeRawBytes( const char* s, uint len ) | ||
1050 | { | ||
1051 | dev->writeBlock( s, len ); | ||
1052 | return *this; | ||
1053 | } | ||
1054 | |||
1055 | |||
1056 | QTextStream &QTextStream::writeBlock( const char* p, uint len ) | ||
1057 | { | ||
1058 | if ( doUnicodeHeader ) { | ||
1059 | doUnicodeHeader = FALSE; | ||
1060 | if ( !mapper && !latin1 ) | ||
1061 | ts_putc( QChar::byteOrderMark ); | ||
1062 | } | ||
1063 | // QCString and const char * are treated as Latin-1 | ||
1064 | if ( !mapper && latin1 ) { | ||
1065 | dev->writeBlock( p, len ); | ||
1066 | } else if ( !mapper && internalOrder ) { | ||
1067 | QChar *u = new QChar[len]; | ||
1068 | for ( uint i = 0; i < len; i++ ) | ||
1069 | u[i] = p[i]; | ||
1070 | dev->writeBlock( (char*)u, len * sizeof(QChar) ); | ||
1071 | delete [] u; | ||
1072 | } else { | ||
1073 | for ( uint i = 0; i < len; i++ ) | ||
1074 | ts_putc( (uchar)p[i] ); | ||
1075 | } | ||
1076 | return *this; | ||
1077 | } | ||
1078 | |||
1079 | QTextStream &QTextStream::writeBlock( const QChar* p, uint len ) | ||
1080 | { | ||
1081 | #ifndef QT_NO_TEXTCODEC | ||
1082 | if ( mapper ) { | ||
1083 | if ( !d->encoder ) | ||
1084 | d->encoder = mapper->makeEncoder(); | ||
1085 | QConstString s( p, len ); | ||
1086 | int l = len; | ||
1087 | QCString block = d->encoder->fromUnicode( s.string(), l ); | ||
1088 | dev->writeBlock( block, l ); | ||
1089 | } else | ||
1090 | #endif | ||
1091 | if ( latin1 ) { | ||
1092 | char *str = QString::unicodeToAscii( p, len ); | ||
1093 | dev->writeBlock( str, len ); | ||
1094 | delete [] str; | ||
1095 | } else if ( internalOrder ) { | ||
1096 | if ( doUnicodeHeader ) { | ||
1097 | doUnicodeHeader = FALSE; | ||
1098 | ts_putc( QChar::byteOrderMark ); | ||
1099 | } | ||
1100 | dev->writeBlock( (char*)p, sizeof(QChar)*len ); | ||
1101 | } else { | ||
1102 | for (uint i=0; i<len; i++) | ||
1103 | ts_putc( p[i] ); | ||
1104 | } | ||
1105 | return *this; | ||
1106 | } | ||
1107 | |||
1108 | /*! | ||
1109 | Resets the text stream. | ||
1110 | |||
1111 | \list | ||
1112 | \i All flags are set to 0. | ||
1113 | \i The field width is set to 0. | ||
1114 | \i The fill character is set to ' ' (Space). | ||
1115 | \i The precision is set to 6. | ||
1116 | \endlist | ||
1117 | |||
1118 | \sa setf(), width(), fill(), precision() | ||
1119 | */ | ||
1120 | |||
1121 | void QTextStream::reset() | ||
1122 | { | ||
1123 | fflags = 0; | ||
1124 | fwidth = 0; | ||
1125 | fillchar = ' '; | ||
1126 | fprec = 6; | ||
1127 | } | ||
1128 | |||
1129 | /*! | ||
1130 | \fn QIODevice *QTextStream::device() const | ||
1131 | |||
1132 | Returns the IO device currently set. | ||
1133 | |||
1134 | \sa setDevice(), unsetDevice() | ||
1135 | */ | ||
1136 | |||
1137 | /*! | ||
1138 | Sets the IO device to \a iod. | ||
1139 | |||
1140 | \sa device(), unsetDevice() | ||
1141 | */ | ||
1142 | |||
1143 | void QTextStream::setDevice( QIODevice *iod ) | ||
1144 | { | ||
1145 | if ( owndev ) { | ||
1146 | delete dev; | ||
1147 | owndev = FALSE; | ||
1148 | } | ||
1149 | dev = iod; | ||
1150 | d->sourceType = QTextStreamPrivate::IODevice; | ||
1151 | } | ||
1152 | |||
1153 | /*! | ||
1154 | Unsets the IO device. Equivalent to setDevice( 0 ). | ||
1155 | |||
1156 | \sa device(), setDevice() | ||
1157 | */ | ||
1158 | |||
1159 | void QTextStream::unsetDevice() | ||
1160 | { | ||
1161 | setDevice( 0 ); | ||
1162 | d->sourceType = QTextStreamPrivate::NotSet; | ||
1163 | } | ||
1164 | |||
1165 | /*! | ||
1166 | \fn bool QTextStream::atEnd() const | ||
1167 | |||
1168 | Returns TRUE if the IO device has reached the end position (end of | ||
1169 | the stream or file) or if there is no IO device set; otherwise | ||
1170 | returns FALSE. | ||
1171 | |||
1172 | \sa QIODevice::atEnd() | ||
1173 | */ | ||
1174 | |||
1175 | /*!\fn bool QTextStream::eof() const | ||
1176 | |||
1177 | \obsolete | ||
1178 | |||
1179 | This function has been renamed to atEnd(). | ||
1180 | |||
1181 | \sa QIODevice::atEnd() | ||
1182 | */ | ||
1183 | |||
1184 | /***************************************************************************** | ||
1185 | QTextStream read functions | ||
1186 | *****************************************************************************/ | ||
1187 | |||
1188 | |||
1189 | /*! | ||
1190 | \overload | ||
1191 | |||
1192 | Reads a char \a c from the stream and returns a reference to the | ||
1193 | stream. Note that whitespace is skipped. | ||
1194 | */ | ||
1195 | |||
1196 | QTextStream &QTextStream::operator>>( char &c ) | ||
1197 | { | ||
1198 | CHECK_STREAM_PRECOND | ||
1199 | c = eat_ws(); | ||
1200 | return *this; | ||
1201 | } | ||
1202 | |||
1203 | /*! | ||
1204 | Reads a char \a c from the stream and returns a reference to the | ||
1205 | stream. Note that whitespace is \e not skipped. | ||
1206 | */ | ||
1207 | |||
1208 | QTextStream &QTextStream::operator>>( QChar &c ) | ||
1209 | { | ||
1210 | CHECK_STREAM_PRECOND | ||
1211 | c = ts_getc(); | ||
1212 | return *this; | ||
1213 | } | ||
1214 | |||
1215 | |||
1216 | ulong QTextStream::input_bin() | ||
1217 | { | ||
1218 | ulong val = 0; | ||
1219 | QChar ch = eat_ws(); | ||
1220 | int dv = ch.digitValue(); | ||
1221 | while ( dv == 0 || dv == 1 ) { | ||
1222 | val = ( val << 1 ) + dv; | ||
1223 | ch = ts_getc(); | ||
1224 | dv = ch.digitValue(); | ||
1225 | } | ||
1226 | if ( ch != QEOF ) | ||
1227 | ts_ungetc( ch ); | ||
1228 | return val; | ||
1229 | } | ||
1230 | |||
1231 | ulong QTextStream::input_oct() | ||
1232 | { | ||
1233 | ulong val = 0; | ||
1234 | QChar ch = eat_ws(); | ||
1235 | int dv = ch.digitValue(); | ||
1236 | while ( dv >= 0 && dv <= 7 ) { | ||
1237 | val = ( val << 3 ) + dv; | ||
1238 | ch = ts_getc(); | ||
1239 | dv = ch.digitValue(); | ||
1240 | } | ||
1241 | if ( dv == 8 || dv == 9 ) { | ||
1242 | while ( ts_isdigit(ch) ) | ||
1243 | ch = ts_getc(); | ||
1244 | } | ||
1245 | if ( ch != QEOF ) | ||
1246 | ts_ungetc( ch ); | ||
1247 | return val; | ||
1248 | } | ||
1249 | |||
1250 | ulong QTextStream::input_dec() | ||
1251 | { | ||
1252 | ulong val = 0; | ||
1253 | QChar ch = eat_ws(); | ||
1254 | int dv = ch.digitValue(); | ||
1255 | while ( ts_isdigit(ch) ) { | ||
1256 | val = val * 10 + dv; | ||
1257 | ch = ts_getc(); | ||
1258 | dv = ch.digitValue(); | ||
1259 | } | ||
1260 | if ( ch != QEOF ) | ||
1261 | ts_ungetc( ch ); | ||
1262 | return val; | ||
1263 | } | ||
1264 | |||
1265 | ulong QTextStream::input_hex() | ||
1266 | { | ||
1267 | ulong val = 0; | ||
1268 | QChar ch = eat_ws(); | ||
1269 | char c = ch; | ||
1270 | while ( isxdigit((uchar) c) ) { | ||
1271 | val <<= 4; | ||
1272 | if ( ts_isdigit(c) ) | ||
1273 | val += c - '0'; | ||
1274 | else | ||
1275 | val += 10 + tolower( (uchar) c ) - 'a'; | ||
1276 | c = ch = ts_getc(); | ||
1277 | } | ||
1278 | if ( ch != QEOF ) | ||
1279 | ts_ungetc( ch ); | ||
1280 | return val; | ||
1281 | } | ||
1282 | |||
1283 | long QTextStream::input_int() | ||
1284 | { | ||
1285 | long val; | ||
1286 | QChar ch; | ||
1287 | char c; | ||
1288 | switch ( flags() & basefield ) { | ||
1289 | case bin: | ||
1290 | val = (long)input_bin(); | ||
1291 | break; | ||
1292 | case oct: | ||
1293 | val = (long)input_oct(); | ||
1294 | break; | ||
1295 | case dec: | ||
1296 | c = ch = eat_ws(); | ||
1297 | if ( ch == QEOF ) { | ||
1298 | val = 0; | ||
1299 | } else { | ||
1300 | if ( !(c == '-' || c == '+') ) | ||
1301 | ts_ungetc( ch ); | ||
1302 | if ( c == '-' ) { | ||
1303 | ulong v = input_dec(); | ||
1304 | if ( v ) { // ensure that LONG_MIN can be read | ||
1305 | v--; | ||
1306 | val = -((long)v) - 1; | ||
1307 | } else { | ||
1308 | val = 0; | ||
1309 | } | ||
1310 | } else { | ||
1311 | val = (long)input_dec(); | ||
1312 | } | ||
1313 | } | ||
1314 | break; | ||
1315 | case hex: | ||
1316 | val = (long)input_hex(); | ||
1317 | break; | ||
1318 | default: | ||
1319 | val = 0; | ||
1320 | c = ch = eat_ws(); | ||
1321 | if ( c == '0' ) { // bin, oct or hex | ||
1322 | c = ch = ts_getc(); | ||
1323 | if ( tolower((uchar) c) == 'x' ) | ||
1324 | val = (long)input_hex(); | ||
1325 | else if ( tolower((uchar) c) == 'b' ) | ||
1326 | val = (long)input_bin(); | ||
1327 | else { // octal | ||
1328 | ts_ungetc( ch ); | ||
1329 | if ( c >= '0' && c <= '7' ) { | ||
1330 | val = (long)input_oct(); | ||
1331 | } else { | ||
1332 | val = 0; | ||
1333 | } | ||
1334 | } | ||
1335 | } else if ( ts_isdigit(ch) ) { | ||
1336 | ts_ungetc( ch ); | ||
1337 | val = (long)input_dec(); | ||
1338 | } else if ( c == '-' || c == '+' ) { | ||
1339 | ulong v = input_dec(); | ||
1340 | if ( c == '-' ) { | ||
1341 | if ( v ) { // ensure that LONG_MIN can be read | ||
1342 | v--; | ||
1343 | val = -((long)v) - 1; | ||
1344 | } else { | ||
1345 | val = 0; | ||
1346 | } | ||
1347 | } else { | ||
1348 | val = (long)v; | ||
1349 | } | ||
1350 | } | ||
1351 | } | ||
1352 | return val; | ||
1353 | } | ||
1354 | |||
1355 | // | ||
1356 | // We use a table-driven FSM to parse floating point numbers | ||
1357 | // strtod() cannot be used directly since we're reading from a QIODevice | ||
1358 | // | ||
1359 | |||
1360 | double QTextStream::input_double() | ||
1361 | { | ||
1362 | const int Init = 0; // states | ||
1363 | const int Sign = 1; | ||
1364 | const int Mantissa = 2; | ||
1365 | const int Dot = 3; | ||
1366 | const int Abscissa = 4; | ||
1367 | const int ExpMark = 5; | ||
1368 | const int ExpSign = 6; | ||
1369 | const int Exponent = 7; | ||
1370 | const int Done = 8; | ||
1371 | |||
1372 | const int InputSign = 1; // input tokens | ||
1373 | const int InputDigit = 2; | ||
1374 | const int InputDot = 3; | ||
1375 | const int InputExp = 4; | ||
1376 | |||
1377 | static const uchar table[8][5] = { | ||
1378 | /* None InputSign InputDigit InputDot InputExp */ | ||
1379 | { 0, Sign, Mantissa, Dot, 0, }, // Init | ||
1380 | { 0, 0, Mantissa, Dot, 0, }, // Sign | ||
1381 | { Done, Done, Mantissa, Dot, ExpMark,}, // Mantissa | ||
1382 | { 0, 0, Abscissa, 0, 0, }, // Dot | ||
1383 | { Done, Done, Abscissa, Done, ExpMark,}, // Abscissa | ||
1384 | { 0, ExpSign, Exponent, 0, 0, }, // ExpMark | ||
1385 | { 0, 0, Exponent, 0, 0, }, // ExpSign | ||
1386 | { Done, Done, Exponent, Done, Done } // Exponent | ||
1387 | }; | ||
1388 | |||
1389 | int state = Init; // parse state | ||
1390 | int input; // input token | ||
1391 | |||
1392 | char buf[256]; | ||
1393 | int i = 0; | ||
1394 | QChar c = eat_ws(); | ||
1395 | |||
1396 | for (;;) { | ||
1397 | |||
1398 | switch ( c ) { | ||
1399 | case '+': | ||
1400 | case '-': | ||
1401 | input = InputSign; | ||
1402 | break; | ||
1403 | case '0': case '1': case '2': case '3': case '4': | ||
1404 | case '5': case '6': case '7': case '8': case '9': | ||
1405 | input = InputDigit; | ||
1406 | break; | ||
1407 | case '.': | ||
1408 | input = InputDot; | ||
1409 | break; | ||
1410 | case 'e': | ||
1411 | case 'E': | ||
1412 | input = InputExp; | ||
1413 | break; | ||
1414 | default: | ||
1415 | input = 0; | ||
1416 | break; | ||
1417 | } | ||
1418 | |||
1419 | state = table[state][input]; | ||
1420 | |||
1421 | if ( state == 0 || state == Done || i > 250 ) { | ||
1422 | if ( i > 250 ) { // ignore rest of digits | ||
1423 | do { c = ts_getc(); } while ( c != QEOF && ts_isdigit(c) ); | ||
1424 | } | ||
1425 | if ( c != QEOF ) | ||
1426 | ts_ungetc( c ); | ||
1427 | buf[i] = '\0'; | ||
1428 | char *end; | ||
1429 | return strtod( buf, &end ); | ||
1430 | } | ||
1431 | |||
1432 | buf[i++] = c; | ||
1433 | c = ts_getc(); | ||
1434 | } | ||
1435 | |||
1436 | #if !defined(Q_CC_EDG) | ||
1437 | return 0.0; | ||
1438 | #endif | ||
1439 | } | ||
1440 | |||
1441 | |||
1442 | /*! | ||
1443 | \overload | ||
1444 | |||
1445 | Reads a signed \c short integer \a i from the stream and returns a | ||
1446 | reference to the stream. See flags() for an explanation of the | ||
1447 | expected input format. | ||
1448 | */ | ||
1449 | |||
1450 | QTextStream &QTextStream::operator>>( signed short &i ) | ||
1451 | { | ||
1452 | CHECK_STREAM_PRECOND | ||
1453 | i = (signed short)input_int(); | ||
1454 | return *this; | ||
1455 | } | ||
1456 | |||
1457 | |||
1458 | /*! | ||
1459 | \overload | ||
1460 | |||
1461 | Reads an unsigned \c short integer \a i from the stream and | ||
1462 | returns a reference to the stream. See flags() for an explanation | ||
1463 | of the expected input format. | ||
1464 | */ | ||
1465 | |||
1466 | QTextStream &QTextStream::operator>>( unsigned short &i ) | ||
1467 | { | ||
1468 | CHECK_STREAM_PRECOND | ||
1469 | i = (unsigned short)input_int(); | ||
1470 | return *this; | ||
1471 | } | ||
1472 | |||
1473 | |||
1474 | /*! | ||
1475 | \overload | ||
1476 | |||
1477 | Reads a signed \c int \a i from the stream and returns a reference | ||
1478 | to the stream. See flags() for an explanation of the expected | ||
1479 | input format. | ||
1480 | */ | ||
1481 | |||
1482 | QTextStream &QTextStream::operator>>( signed int &i ) | ||
1483 | { | ||
1484 | CHECK_STREAM_PRECOND | ||
1485 | i = (signed int)input_int(); | ||
1486 | return *this; | ||
1487 | } | ||
1488 | |||
1489 | |||
1490 | /*! | ||
1491 | \overload | ||
1492 | |||
1493 | Reads an unsigned \c int \a i from the stream and returns a | ||
1494 | reference to the stream. See flags() for an explanation of the | ||
1495 | expected input format. | ||
1496 | */ | ||
1497 | |||
1498 | QTextStream &QTextStream::operator>>( unsigned int &i ) | ||
1499 | { | ||
1500 | CHECK_STREAM_PRECOND | ||
1501 | i = (unsigned int)input_int(); | ||
1502 | return *this; | ||
1503 | } | ||
1504 | |||
1505 | |||
1506 | /*! | ||
1507 | \overload | ||
1508 | |||
1509 | Reads a signed \c long int \a i from the stream and returns a | ||
1510 | reference to the stream. See flags() for an explanation of the | ||
1511 | expected input format. | ||
1512 | */ | ||
1513 | |||
1514 | QTextStream &QTextStream::operator>>( signed long &i ) | ||
1515 | { | ||
1516 | CHECK_STREAM_PRECOND | ||
1517 | i = (signed long)input_int(); | ||
1518 | return *this; | ||
1519 | } | ||
1520 | |||
1521 | |||
1522 | /*! | ||
1523 | \overload | ||
1524 | |||
1525 | Reads an unsigned \c long int \a i from the stream and returns a | ||
1526 | reference to the stream. See flags() for an explanation of the | ||
1527 | expected input format. | ||
1528 | */ | ||
1529 | |||
1530 | QTextStream &QTextStream::operator>>( unsigned long &i ) | ||
1531 | { | ||
1532 | CHECK_STREAM_PRECOND | ||
1533 | i = (unsigned long)input_int(); | ||
1534 | return *this; | ||
1535 | } | ||
1536 | |||
1537 | |||
1538 | /*! | ||
1539 | \overload | ||
1540 | |||
1541 | Reads a \c float \a f from the stream and returns a reference to | ||
1542 | the stream. See flags() for an explanation of the expected input | ||
1543 | format. | ||
1544 | */ | ||
1545 | |||
1546 | QTextStream &QTextStream::operator>>( float &f ) | ||
1547 | { | ||
1548 | CHECK_STREAM_PRECOND | ||
1549 | f = (float)input_double(); | ||
1550 | return *this; | ||
1551 | } | ||
1552 | |||
1553 | |||
1554 | /*! | ||
1555 | \overload | ||
1556 | |||
1557 | Reads a \c double \a f from the stream and returns a reference to | ||
1558 | the stream. See flags() for an explanation of the expected input | ||
1559 | format. | ||
1560 | */ | ||
1561 | |||
1562 | QTextStream &QTextStream::operator>>( double &f ) | ||
1563 | { | ||
1564 | CHECK_STREAM_PRECOND | ||
1565 | f = input_double(); | ||
1566 | return *this; | ||
1567 | } | ||
1568 | |||
1569 | |||
1570 | /*! | ||
1571 | \overload | ||
1572 | |||
1573 | Reads a "word" from the stream into \a s and returns a reference | ||
1574 | to the stream. | ||
1575 | |||
1576 | A word consists of characters for which isspace() returns FALSE. | ||
1577 | */ | ||
1578 | |||
1579 | QTextStream &QTextStream::operator>>( char *s ) | ||
1580 | { | ||
1581 | CHECK_STREAM_PRECOND | ||
1582 | int maxlen = width( 0 ); | ||
1583 | QChar c = eat_ws(); | ||
1584 | if ( !maxlen ) | ||
1585 | maxlen = -1; | ||
1586 | while ( c != QEOF ) { | ||
1587 | if ( ts_isspace(c) || maxlen-- == 0 ) { | ||
1588 | ts_ungetc( c ); | ||
1589 | break; | ||
1590 | } | ||
1591 | *s++ = c; | ||
1592 | c = ts_getc(); | ||
1593 | } | ||
1594 | |||
1595 | *s = '\0'; | ||
1596 | return *this; | ||
1597 | } | ||
1598 | |||
1599 | /*! | ||
1600 | \overload | ||
1601 | |||
1602 | Reads a "word" from the stream into \a str and returns a reference | ||
1603 | to the stream. | ||
1604 | |||
1605 | A word consists of characters for which isspace() returns FALSE. | ||
1606 | */ | ||
1607 | |||
1608 | QTextStream &QTextStream::operator>>( QString &str ) | ||
1609 | { | ||
1610 | CHECK_STREAM_PRECOND | ||
1611 | str=QString::fromLatin1(""); | ||
1612 | QCharc = eat_ws(); | ||
1613 | |||
1614 | while ( c != QEOF ) { | ||
1615 | if ( ts_isspace(c) ) { | ||
1616 | ts_ungetc( c ); | ||
1617 | break; | ||
1618 | } | ||
1619 | str += c; | ||
1620 | c = ts_getc(); | ||
1621 | } | ||
1622 | return *this; | ||
1623 | } | ||
1624 | |||
1625 | /*! | ||
1626 | \overload | ||
1627 | |||
1628 | Reads a "word" from the stream into \a str and returns a reference | ||
1629 | to the stream. | ||
1630 | |||
1631 | A word consists of characters for which isspace() returns FALSE. | ||
1632 | */ | ||
1633 | |||
1634 | QTextStream &QTextStream::operator>>( QCString &str ) | ||
1635 | { | ||
1636 | CHECK_STREAM_PRECOND | ||
1637 | QCString *dynbuf = 0; | ||
1638 | const int buflen = 256; | ||
1639 | char buffer[buflen]; | ||
1640 | char *s = buffer; | ||
1641 | int i = 0; | ||
1642 | QChar c = eat_ws(); | ||
1643 | |||
1644 | while ( c != QEOF ) { | ||
1645 | if ( ts_isspace(c) ) { | ||
1646 | ts_ungetc( c ); | ||
1647 | break; | ||
1648 | } | ||
1649 | if ( i >= buflen-1 ) { | ||
1650 | if ( !dynbuf ) { // create dynamic buffer | ||
1651 | dynbuf = new QCString(buflen*2); | ||
1652 | memcpy( dynbuf->data(), s, i );// copy old data | ||
1653 | } else if ( i >= (int)dynbuf->size()-1 ) { | ||
1654 | dynbuf->resize( dynbuf->size()*2 ); | ||
1655 | } | ||
1656 | s = dynbuf->data(); | ||
1657 | } | ||
1658 | s[i++] = c; | ||
1659 | c = ts_getc(); | ||
1660 | } | ||
1661 | str.resize( i+1 ); | ||
1662 | memcpy( str.data(), s, i ); | ||
1663 | delete dynbuf; | ||
1664 | return *this; | ||
1665 | } | ||
1666 | |||
1667 | |||
1668 | /*! | ||
1669 | Reads a line from the stream and returns a string containing the | ||
1670 | text. | ||
1671 | |||
1672 | The returned string does not contain any trailing newline or | ||
1673 | carriage return. Note that this is different from | ||
1674 | QIODevice::readLine(), which does not strip the newline at the end | ||
1675 | of the line. | ||
1676 | |||
1677 | On EOF you will get a QString that is null. On reading an empty | ||
1678 | line the returned QString is empty but not null. | ||
1679 | |||
1680 | \sa QIODevice::readLine() | ||
1681 | */ | ||
1682 | |||
1683 | QString QTextStream::readLine() | ||
1684 | { | ||
1685 | #if defined(QT_CHECK_STATE) | ||
1686 | if ( !dev ) { | ||
1687 | qWarning( "QTextStream::readLine: No device" ); | ||
1688 | return QString::null; | ||
1689 | } | ||
1690 | #endif | ||
1691 | bool readCharByChar = TRUE; | ||
1692 | QString result; | ||
1693 | #if 0 | ||
1694 | if ( !doUnicodeHeader && ( | ||
1695 | (latin1) || | ||
1696 | (mapper != 0 && mapper->mibEnum() == 106 ) // UTF 8 | ||
1697 | ) ) { | ||
1698 | readCharByChar = FALSE; | ||
1699 | // use optimized read line | ||
1700 | QChar c[getline_buf_size]; | ||
1701 | int pos = 0; | ||
1702 | bool eof = FALSE; | ||
1703 | |||
1704 | for (;;) { | ||
1705 | pos = ts_getline( c ); | ||
1706 | if ( pos == 0 ) { | ||
1707 | // something went wrong; try fallback | ||
1708 | readCharByChar = TRUE; | ||
1709 | //dev->resetStatus(); | ||
1710 | break; | ||
1711 | } | ||
1712 | if ( c[pos-1] == QEOF || c[pos-1] == '\n' ) { | ||
1713 | if ( pos>2 && c[pos-1]==QEOF && c[pos-2]=='\n' ) { | ||
1714 | result += QString( c, pos-2 ); | ||
1715 | } else if ( pos > 1 ) { | ||
1716 | result += QString( c, pos-1 ); | ||
1717 | } | ||
1718 | if ( pos == 1 && c[pos-1] == QEOF ) | ||
1719 | eof = TRUE; | ||
1720 | break; | ||
1721 | } else { | ||
1722 | result += QString( c, pos ); | ||
1723 | } | ||
1724 | } | ||
1725 | if ( eof && result.isEmpty() ) | ||
1726 | return QString::null; | ||
1727 | } | ||
1728 | #endif | ||
1729 | if ( readCharByChar ) { | ||
1730 | // read character by character | ||
1731 | const int buf_size = 256; | ||
1732 | QChar c[buf_size]; | ||
1733 | int pos = 0; | ||
1734 | |||
1735 | c[pos] = ts_getc(); | ||
1736 | if ( c[pos] == QEOF ) { | ||
1737 | return QString::null; | ||
1738 | } | ||
1739 | |||
1740 | while ( c[pos] != QEOF && c[pos] != '\n' ) { | ||
1741 | if ( c[pos] == '\r' ) { // ( handle mac and dos ) | ||
1742 | QChar nextc = ts_getc(); | ||
1743 | if ( nextc != '\n' ) | ||
1744 | ts_ungetc( nextc ); | ||
1745 | break; | ||
1746 | } | ||
1747 | pos++; | ||
1748 | if ( pos >= buf_size ) { | ||
1749 | result += QString( c, pos ); | ||
1750 | pos = 0; | ||
1751 | } | ||
1752 | c[pos] = ts_getc(); | ||
1753 | } | ||
1754 | result += QString( c, pos ); | ||
1755 | } | ||
1756 | |||
1757 | return result; | ||
1758 | } | ||
1759 | |||
1760 | |||
1761 | /*! | ||
1762 | Reads the entire stream and returns a string containing the text. | ||
1763 | |||
1764 | \sa QIODevice::readLine() | ||
1765 | */ | ||
1766 | |||
1767 | QString QTextStream::read() | ||
1768 | { | ||
1769 | #if defined(QT_CHECK_STATE) | ||
1770 | if ( !dev ) { | ||
1771 | qWarning( "QTextStream::read: No device" ); | ||
1772 | return QString::null; | ||
1773 | } | ||
1774 | #endif | ||
1775 | QString result; | ||
1776 | const uint bufsize = 512; | ||
1777 | QChar buf[bufsize]; | ||
1778 | uint i, num, start; | ||
1779 | bool skipped_cr = FALSE; | ||
1780 | |||
1781 | for (;;) { | ||
1782 | num = ts_getbuf(buf,bufsize); | ||
1783 | // convert dos (\r\n) and mac (\r) style eol to unix style (\n) | ||
1784 | start = 0; | ||
1785 | for ( i=0; i<num; i++ ) { | ||
1786 | if ( buf[i] == '\r' ) { | ||
1787 | // Only skip single cr's preceding lf's | ||
1788 | if ( skipped_cr ) { | ||
1789 | result += buf[i]; | ||
1790 | start++; | ||
1791 | } else { | ||
1792 | result += QString( &buf[start], i-start ); | ||
1793 | start = i+1; | ||
1794 | skipped_cr = TRUE; | ||
1795 | } | ||
1796 | } else { | ||
1797 | if ( skipped_cr ) { | ||
1798 | if ( buf[i] != '\n' ) { | ||
1799 | // Should not have skipped it | ||
1800 | result += '\n'; | ||
1801 | } | ||
1802 | skipped_cr = FALSE; | ||
1803 | } | ||
1804 | } | ||
1805 | } | ||
1806 | if ( start < num ) | ||
1807 | result += QString( &buf[start], i-start ); | ||
1808 | if ( num != bufsize ) // if ( EOF ) | ||
1809 | break; | ||
1810 | } | ||
1811 | return result; | ||
1812 | } | ||
1813 | |||
1814 | |||
1815 | |||
1816 | /***************************************************************************** | ||
1817 | QTextStream write functions | ||
1818 | *****************************************************************************/ | ||
1819 | |||
1820 | /*! | ||
1821 | Writes character \c char to the stream and returns a reference to | ||
1822 | the stream. | ||
1823 | |||
1824 | The character \a c is assumed to be Latin1 encoded independent of | ||
1825 | the Encoding set for the QTextStream. | ||
1826 | */ | ||
1827 | QTextStream &QTextStream::operator<<( QChar c ) | ||
1828 | { | ||
1829 | CHECK_STREAM_PRECOND | ||
1830 | ts_putc( c ); | ||
1831 | return *this; | ||
1832 | } | ||
1833 | |||
1834 | /*! | ||
1835 | \overload | ||
1836 | |||
1837 | Writes character \a c to the stream and returns a reference to the | ||
1838 | stream. | ||
1839 | */ | ||
1840 | QTextStream &QTextStream::operator<<( char c ) | ||
1841 | { | ||
1842 | CHECK_STREAM_PRECOND | ||
1843 | unsigned char uc = (unsigned char) c; | ||
1844 | ts_putc( uc ); | ||
1845 | return *this; | ||
1846 | } | ||
1847 | |||
1848 | QTextStream &QTextStream::output_int( int format, ulong n, bool neg ) | ||
1849 | { | ||
1850 | static const char hexdigits_lower[] = "0123456789abcdef"; | ||
1851 | static const char hexdigits_upper[] = "0123456789ABCDEF"; | ||
1852 | CHECK_STREAM_PRECOND | ||
1853 | char buf[76]; | ||
1854 | register char *p; | ||
1855 | int len; | ||
1856 | const char *hexdigits; | ||
1857 | |||
1858 | switch ( flags() & I_BASE_MASK ) { | ||
1859 | |||
1860 | case I_BASE_2: // output binary number | ||
1861 | switch ( format & I_TYPE_MASK ) { | ||
1862 | case I_SHORT: len=16; break; | ||
1863 | case I_INT: len=sizeof(int)*8; break; | ||
1864 | case I_LONG: len=32; break; | ||
1865 | default: len = 0; | ||
1866 | } | ||
1867 | p = &buf[74]; // go reverse order | ||
1868 | *p = '\0'; | ||
1869 | while ( len-- ) { | ||
1870 | *--p = (char)(n&1) + '0'; | ||
1871 | n >>= 1; | ||
1872 | if ( !n ) | ||
1873 | break; | ||
1874 | } | ||
1875 | if ( flags() & showbase ) { // show base | ||
1876 | *--p = (flags() & uppercase) ? 'B' : 'b'; | ||
1877 | *--p = '0'; | ||
1878 | } | ||
1879 | break; | ||
1880 | |||
1881 | case I_BASE_8: // output octal number | ||
1882 | p = &buf[74]; | ||
1883 | *p = '\0'; | ||
1884 | do { | ||
1885 | *--p = (char)(n&7) + '0'; | ||
1886 | n >>= 3; | ||
1887 | } while ( n ); | ||
1888 | if ( flags() & showbase ) | ||
1889 | *--p = '0'; | ||
1890 | break; | ||
1891 | |||
1892 | case I_BASE_16: // output hexadecimal number | ||
1893 | p = &buf[74]; | ||
1894 | *p = '\0'; | ||
1895 | hexdigits = (flags() & uppercase) ? | ||
1896 | hexdigits_upper : hexdigits_lower; | ||
1897 | do { | ||
1898 | *--p = hexdigits[(int)n&0xf]; | ||
1899 | n >>= 4; | ||
1900 | } while ( n ); | ||
1901 | if ( flags() & showbase ) { | ||
1902 | *--p = (flags() & uppercase) ? 'X' : 'x'; | ||
1903 | *--p = '0'; | ||
1904 | } | ||
1905 | break; | ||
1906 | |||
1907 | default: // decimal base is default | ||
1908 | p = &buf[74]; | ||
1909 | *p = '\0'; | ||
1910 | if ( neg ) | ||
1911 | n = (ulong)(-(long)n); | ||
1912 | do { | ||
1913 | *--p = ((int)(n%10)) + '0'; | ||
1914 | n /= 10; | ||
1915 | } while ( n ); | ||
1916 | if ( neg ) | ||
1917 | *--p = '-'; | ||
1918 | else if ( flags() & showpos ) | ||
1919 | *--p = '+'; | ||
1920 | if ( (flags() & internal) && fwidth && !ts_isdigit(*p) ) { | ||
1921 | ts_putc( *p ); // special case for internal | ||
1922 | ++p; // padding | ||
1923 | fwidth--; | ||
1924 | return *this << (const char*)p; | ||
1925 | } | ||
1926 | } | ||
1927 | if ( fwidth ) { // adjustment required | ||
1928 | if ( !(flags() & left) ) { // but NOT left adjustment | ||
1929 | len = qstrlen(p); | ||
1930 | int padlen = fwidth - len; | ||
1931 | if ( padlen <= 0 ) { // no padding required | ||
1932 | writeBlock( p, len ); | ||
1933 | } else if ( padlen < (int)(p-buf) ) { // speeds up padding | ||
1934 | memset( p-padlen, (char)fillchar, padlen ); | ||
1935 | writeBlock( p-padlen, padlen+len ); | ||
1936 | } | ||
1937 | else // standard padding | ||
1938 | *this << (const char*)p; | ||
1939 | } | ||
1940 | else | ||
1941 | *this << (const char*)p; | ||
1942 | fwidth = 0; // reset field width | ||
1943 | } | ||
1944 | else | ||
1945 | writeBlock( p, qstrlen(p) ); | ||
1946 | return *this; | ||
1947 | } | ||
1948 | |||
1949 | |||
1950 | /*! | ||
1951 | \overload | ||
1952 | |||
1953 | Writes a \c short integer \a i to the stream and returns a | ||
1954 | reference to the stream. | ||
1955 | */ | ||
1956 | |||
1957 | QTextStream &QTextStream::operator<<( signed short i ) | ||
1958 | { | ||
1959 | return output_int( I_SHORT | I_SIGNED, i, i < 0 ); | ||
1960 | } | ||
1961 | |||
1962 | |||
1963 | /*! | ||
1964 | \overload | ||
1965 | |||
1966 | Writes an \c unsigned \c short integer \a i to the stream and | ||
1967 | returns a reference to the stream. | ||
1968 | */ | ||
1969 | |||
1970 | QTextStream &QTextStream::operator<<( unsigned short i ) | ||
1971 | { | ||
1972 | return output_int( I_SHORT | I_UNSIGNED, i, FALSE ); | ||
1973 | } | ||
1974 | |||
1975 | |||
1976 | /*! | ||
1977 | \overload | ||
1978 | |||
1979 | Writes an \c int \a i to the stream and returns a reference to the | ||
1980 | stream. | ||
1981 | */ | ||
1982 | |||
1983 | QTextStream &QTextStream::operator<<( signed int i ) | ||
1984 | { | ||
1985 | return output_int( I_INT | I_SIGNED, i, i < 0 ); | ||
1986 | } | ||
1987 | |||
1988 | |||
1989 | /*! | ||
1990 | \overload | ||
1991 | |||
1992 | Writes an \c unsigned \c int \a i to the stream and returns a | ||
1993 | reference to the stream. | ||
1994 | */ | ||
1995 | |||
1996 | QTextStream &QTextStream::operator<<( unsigned int i ) | ||
1997 | { | ||
1998 | return output_int( I_INT | I_UNSIGNED, i, FALSE ); | ||
1999 | } | ||
2000 | |||
2001 | |||
2002 | /*! | ||
2003 | \overload | ||
2004 | |||
2005 | Writes a \c long \c int \a i to the stream and returns a reference | ||
2006 | to the stream. | ||
2007 | */ | ||
2008 | |||
2009 | QTextStream &QTextStream::operator<<( signed long i ) | ||
2010 | { | ||
2011 | return output_int( I_LONG | I_SIGNED, i, i < 0 ); | ||
2012 | } | ||
2013 | |||
2014 | |||
2015 | /*! | ||
2016 | \overload | ||
2017 | |||
2018 | Writes an \c unsigned \c long \c int \a i to the stream and | ||
2019 | returns a reference to the stream. | ||
2020 | */ | ||
2021 | |||
2022 | QTextStream &QTextStream::operator<<( unsigned long i ) | ||
2023 | { | ||
2024 | return output_int( I_LONG | I_UNSIGNED, i, FALSE ); | ||
2025 | } | ||
2026 | |||
2027 | |||
2028 | /*! | ||
2029 | \overload | ||
2030 | |||
2031 | Writes a \c float \a f to the stream and returns a reference to | ||
2032 | the stream. | ||
2033 | */ | ||
2034 | |||
2035 | QTextStream &QTextStream::operator<<( float f ) | ||
2036 | { | ||
2037 | return *this << (double)f; | ||
2038 | } | ||
2039 | |||
2040 | |||
2041 | /*! | ||
2042 | \overload | ||
2043 | |||
2044 | Writes a \c double \a f to the stream and returns a reference to | ||
2045 | the stream. | ||
2046 | */ | ||
2047 | |||
2048 | QTextStream &QTextStream::operator<<( double f ) | ||
2049 | { | ||
2050 | CHECK_STREAM_PRECOND | ||
2051 | char buf[64]; | ||
2052 | char f_char; | ||
2053 | char format[16]; | ||
2054 | if ( (flags()&floatfield) == fixed ) | ||
2055 | f_char = 'f'; | ||
2056 | else if ( (flags()&floatfield) == scientific ) | ||
2057 | f_char = (flags() & uppercase) ? 'E' : 'e'; | ||
2058 | else | ||
2059 | f_char = (flags() & uppercase) ? 'G' : 'g'; | ||
2060 | register char *fs = format; // generate format string | ||
2061 | *fs++ = '%'; // "%.<prec>l<f_char>" | ||
2062 | *fs++ = '.'; | ||
2063 | int prec = precision(); | ||
2064 | if ( prec > 99 ) | ||
2065 | prec = 99; | ||
2066 | if ( prec >= 10 ) { | ||
2067 | *fs++ = prec / 10 + '0'; | ||
2068 | *fs++ = prec % 10 + '0'; | ||
2069 | } else { | ||
2070 | *fs++ = prec + '0'; | ||
2071 | } | ||
2072 | *fs++ = 'l'; | ||
2073 | *fs++ = f_char; | ||
2074 | *fs = '\0'; | ||
2075 | sprintf( buf, format, f ); // convert to text | ||
2076 | if ( fwidth ) // padding | ||
2077 | *this << (const char*)buf; | ||
2078 | else // just write it | ||
2079 | writeBlock( buf, qstrlen(buf) ); | ||
2080 | return *this; | ||
2081 | } | ||
2082 | |||
2083 | |||
2084 | /*! | ||
2085 | \overload | ||
2086 | |||
2087 | Writes a string to the stream and returns a reference to the | ||
2088 | stream. | ||
2089 | |||
2090 | The string \a s is assumed to be Latin1 encoded independent of the | ||
2091 | Encoding set for the QTextStream. | ||
2092 | */ | ||
2093 | |||
2094 | QTextStream &QTextStream::operator<<( const char* s ) | ||
2095 | { | ||
2096 | CHECK_STREAM_PRECOND | ||
2097 | char padbuf[48]; | ||
2098 | uint len = qstrlen( s ); // don't write null terminator | ||
2099 | if ( fwidth ) { // field width set | ||
2100 | int padlen = fwidth - len; | ||
2101 | fwidth = 0; // reset width | ||
2102 | if ( padlen > 0 ) { | ||
2103 | char *ppad; | ||
2104 | if ( padlen > 46 ) { // create extra big fill buffer | ||
2105 | ppad = new char[padlen]; | ||
2106 | Q_CHECK_PTR( ppad ); | ||
2107 | } else { | ||
2108 | ppad = padbuf; | ||
2109 | } | ||
2110 | memset( ppad, (char)fillchar, padlen );// fill with fillchar | ||
2111 | if ( !(flags() & left) ) { | ||
2112 | writeBlock( ppad, padlen ); | ||
2113 | padlen = 0; | ||
2114 | } | ||
2115 | writeBlock( s, len ); | ||
2116 | if ( padlen ) | ||
2117 | writeBlock( ppad, padlen ); | ||
2118 | if ( ppad != padbuf ) // delete extra big fill buf | ||
2119 | delete[] ppad; | ||
2120 | return *this; | ||
2121 | } | ||
2122 | } | ||
2123 | writeBlock( s, len ); | ||
2124 | return *this; | ||
2125 | } | ||
2126 | |||
2127 | /*! | ||
2128 | \overload | ||
2129 | |||
2130 | Writes \a s to the stream and returns a reference to the stream. | ||
2131 | |||
2132 | The string \a s is assumed to be Latin1 encoded independent of the | ||
2133 | Encoding set for the QTextStream. | ||
2134 | */ | ||
2135 | |||
2136 | QTextStream &QTextStream::operator<<( const QCString & s ) | ||
2137 | { | ||
2138 | return operator<<(s.data()); | ||
2139 | } | ||
2140 | |||
2141 | /*! | ||
2142 | \overload | ||
2143 | |||
2144 | Writes \a s to the stream and returns a reference to the stream. | ||
2145 | */ | ||
2146 | |||
2147 | QTextStream &QTextStream::operator<<( const QString& s ) | ||
2148 | { | ||
2149 | if ( !mapper && latin1 ) | ||
2150 | return operator<<(s.latin1()); | ||
2151 | CHECK_STREAM_PRECOND | ||
2152 | QString s1 = s; | ||
2153 | if ( fwidth ) { // field width set | ||
2154 | if ( !(flags() & left) ) { | ||
2155 | s1 = s.rightJustify(fwidth, (char)fillchar); | ||
2156 | } else { | ||
2157 | s1 = s.leftJustify(fwidth, (char)fillchar); | ||
2158 | } | ||
2159 | fwidth = 0; // reset width | ||
2160 | } | ||
2161 | writeBlock( s1.unicode(), s1.length() ); | ||
2162 | return *this; | ||
2163 | } | ||
2164 | |||
2165 | |||
2166 | /*! | ||
2167 | \overload | ||
2168 | |||
2169 | Writes a pointer to the stream and returns a reference to the | ||
2170 | stream. | ||
2171 | |||
2172 | The \a ptr is output as an unsigned long hexadecimal integer. | ||
2173 | */ | ||
2174 | |||
2175 | QTextStream &QTextStream::operator<<( void *ptr ) | ||
2176 | { | ||
2177 | int f = flags(); | ||
2178 | setf( hex, basefield ); | ||
2179 | setf( showbase ); | ||
2180 | unsetf( uppercase ); | ||
2181 | output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE ); | ||
2182 | flags( f ); | ||
2183 | return *this; | ||
2184 | } | ||
2185 | |||
2186 | |||
2187 | /*! | ||
2188 | \fn int QTextStream::flags() const | ||
2189 | |||
2190 | Returns the current stream flags. The default value is 0. | ||
2191 | |||
2192 | \table | ||
2193 | \header \i Flag \i Meaning | ||
2194 | \row \i \c skipws \i Not currently used; whitespace always skipped | ||
2195 | \row \i \c left \i Numeric fields are left-aligned | ||
2196 | \row \i \c right | ||
2197 | \i Not currently used (by default, numerics are right-aligned) | ||
2198 | \row \i \c internal \i Puts any padding spaces between +/- and value | ||
2199 | \row \i \c bin \i Output \e and input only in binary | ||
2200 | \row \i \c oct \i Output \e and input only in octal | ||
2201 | \row \i \c dec \i Output \e and input only in decimal | ||
2202 | \row \i \c hex \i Output \e and input only in hexadecimal | ||
2203 | \row \i \c showbase | ||
2204 | \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin, | ||
2205 | \c oct, or \c hex format | ||
2206 | \row \i \c showpoint \i Not currently used | ||
2207 | \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x | ||
2208 | \row \i \c showpos \i Shows + for positive numeric values | ||
2209 | \row \i \c scientific \i Uses scientific notation for floating point values | ||
2210 | \row \i \c fixed \i Uses fixed-point notation for floating point values | ||
2211 | \endtable | ||
2212 | |||
2213 | Note that unless \c bin, \c oct, \c dec, or \c hex is set, the | ||
2214 | input base is octal if the value starts with 0, hexadecimal if it | ||
2215 | starts with 0x, binary if it starts with 0b, and decimal | ||
2216 | otherwise. | ||
2217 | |||
2218 | \sa setf(), unsetf() | ||
2219 | */ | ||
2220 | |||
2221 | /*! | ||
2222 | \fn int QTextStream::flags( int f ) | ||
2223 | |||
2224 | \overload | ||
2225 | |||
2226 | Sets the stream flags to \a f. Returns the previous stream flags. | ||
2227 | |||
2228 | \sa setf(), unsetf(), flags() | ||
2229 | */ | ||
2230 | |||
2231 | /*! | ||
2232 | \fn int QTextStream::setf( int bits ) | ||
2233 | |||
2234 | Sets the stream flag bits \a bits. Returns the previous stream | ||
2235 | flags. | ||
2236 | |||
2237 | Equivalent to \c{flags( flags() | bits )}. | ||
2238 | |||
2239 | \sa setf(), unsetf() | ||
2240 | */ | ||
2241 | |||
2242 | /*! | ||
2243 | \fn int QTextStream::setf( int bits, int mask ) | ||
2244 | |||
2245 | \overload | ||
2246 | |||
2247 | Sets the stream flag bits \a bits with a bit mask \a mask. Returns | ||
2248 | the previous stream flags. | ||
2249 | |||
2250 | Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}. | ||
2251 | |||
2252 | \sa setf(), unsetf() | ||
2253 | */ | ||
2254 | |||
2255 | /*! | ||
2256 | \fn int QTextStream::unsetf( int bits ) | ||
2257 | |||
2258 | Clears the stream flag bits \a bits. Returns the previous stream | ||
2259 | flags. | ||
2260 | |||
2261 | Equivalent to \c{flags( flags() & ~mask )}. | ||
2262 | |||
2263 | \sa setf() | ||
2264 | */ | ||
2265 | |||
2266 | /*! | ||
2267 | \fn int QTextStream::width() const | ||
2268 | |||
2269 | Returns the field width. The default value is 0. | ||
2270 | */ | ||
2271 | |||
2272 | /*! | ||
2273 | \fn int QTextStream::width( int w ) | ||
2274 | |||
2275 | \overload | ||
2276 | |||
2277 | Sets the field width to \a w. Returns the previous field width. | ||
2278 | */ | ||
2279 | |||
2280 | /*! | ||
2281 | \fn int QTextStream::fill() const | ||
2282 | |||
2283 | Returns the fill character. The default value is ' ' (space). | ||
2284 | */ | ||
2285 | |||
2286 | /*! | ||
2287 | \overload int QTextStream::fill( int f ) | ||
2288 | |||
2289 | Sets the fill character to \a f. Returns the previous fill character. | ||
2290 | */ | ||
2291 | |||
2292 | /*! | ||
2293 | \fn int QTextStream::precision() const | ||
2294 | |||
2295 | Returns the precision. The default value is 6. | ||
2296 | */ | ||
2297 | |||
2298 | /*! | ||
2299 | \fn int QTextStream::precision( int p ) | ||
2300 | |||
2301 | \overload | ||
2302 | |||
2303 | Sets the precision to \a p. Returns the previous precision setting. | ||
2304 | */ | ||
2305 | |||
2306 | |||
2307 | /***************************************************************************** | ||
2308 | QTextStream manipulators | ||
2309 | *****************************************************************************/ | ||
2310 | |||
2311 | QTextStream &bin( QTextStream &s ) | ||
2312 | { | ||
2313 | s.setf(QTS::bin,QTS::basefield); | ||
2314 | return s; | ||
2315 | } | ||
2316 | |||
2317 | QTextStream &oct( QTextStream &s ) | ||
2318 | { | ||
2319 | s.setf(QTS::oct,QTS::basefield); | ||
2320 | return s; | ||
2321 | } | ||
2322 | |||
2323 | QTextStream &dec( QTextStream &s ) | ||
2324 | { | ||
2325 | s.setf(QTS::dec,QTS::basefield); | ||
2326 | return s; | ||
2327 | } | ||
2328 | |||
2329 | QTextStream &hex( QTextStream &s ) | ||
2330 | { | ||
2331 | s.setf(QTS::hex,QTS::basefield); | ||
2332 | return s; | ||
2333 | } | ||
2334 | |||
2335 | QTextStream &endl( QTextStream &s ) | ||
2336 | { | ||
2337 | return s << '\n'; | ||
2338 | } | ||
2339 | |||
2340 | QTextStream &flush( QTextStream &s ) | ||
2341 | { | ||
2342 | if ( s.device() ) | ||
2343 | s.device()->flush(); | ||
2344 | return s; | ||
2345 | } | ||
2346 | |||
2347 | QTextStream &ws( QTextStream &s ) | ||
2348 | { | ||
2349 | s.skipWhiteSpace(); | ||
2350 | return s; | ||
2351 | } | ||
2352 | |||
2353 | QTextStream &reset( QTextStream &s ) | ||
2354 | { | ||
2355 | s.reset(); | ||
2356 | return s; | ||
2357 | } | ||
2358 | |||
2359 | |||
2360 | /*! | ||
2361 | \class QTextIStream qtextstream.h | ||
2362 | \reentrant | ||
2363 | \brief The QTextIStream class is a convenience class for input streams. | ||
2364 | |||
2365 | \ingroup io | ||
2366 | \ingroup text | ||
2367 | |||
2368 | This class provides a shorthand for creating simple input | ||
2369 | \l{QTextStream}s without having to pass a \e mode argument to the | ||
2370 | constructor. | ||
2371 | |||
2372 | This class makes it easy, for example, to write things like this: | ||
2373 | \code | ||
2374 | QString data = "123 456"; | ||
2375 | int a, b; | ||
2376 | QTextIStream(&data) >> a >> b; | ||
2377 | \endcode | ||
2378 | |||
2379 | \sa QTextOStream | ||
2380 | */ | ||
2381 | |||
2382 | /*! | ||
2383 | \fn QTextIStream::QTextIStream( const QString *s ) | ||
2384 | |||
2385 | Constructs a stream to read from the string \a s. | ||
2386 | */ | ||
2387 | /*! | ||
2388 | \fn QTextIStream::QTextIStream( QByteArray ba ) | ||
2389 | |||
2390 | Constructs a stream to read from the array \a ba. | ||
2391 | */ | ||
2392 | /*! | ||
2393 | \fn QTextIStream::QTextIStream( FILE *f ) | ||
2394 | |||
2395 | Constructs a stream to read from the file \a f. | ||
2396 | */ | ||
2397 | |||
2398 | |||
2399 | /*! | ||
2400 | \class QTextOStream | ||
2401 | \reentrant | ||
2402 | \brief The QTextOStream class is a convenience class for output streams. | ||
2403 | |||
2404 | \ingroup io | ||
2405 | \ingroup text | ||
2406 | |||
2407 | This class provides a shorthand for creating simple output | ||
2408 | \l{QTextStream}s without having to pass a \e mode argument to the | ||
2409 | constructor. | ||
2410 | |||
2411 | This makes it easy for example, to write things like this: | ||
2412 | \code | ||
2413 | QString result; | ||
2414 | QTextOStream(&result) << "pi = " << 3.14; | ||
2415 | \endcode | ||
2416 | */ | ||
2417 | |||
2418 | /*! | ||
2419 | \fn QTextOStream::QTextOStream( QString *s ) | ||
2420 | |||
2421 | Constructs a stream to write to string \a s. | ||
2422 | */ | ||
2423 | /*! | ||
2424 | \fn QTextOStream::QTextOStream( QByteArray ba ) | ||
2425 | |||
2426 | Constructs a stream to write to the array \a ba. | ||
2427 | */ | ||
2428 | /*! | ||
2429 | \fn QTextOStream::QTextOStream( FILE *f ) | ||
2430 | |||
2431 | Constructs a stream to write to the file \a f. | ||
2432 | */ | ||
2433 | |||
2434 | |||
2435 | |||
2436 | /*! | ||
2437 | Sets the encoding of this stream to \a e, where \a e is one of the | ||
2438 | following values: | ||
2439 | \table | ||
2440 | \header \i Encoding \i Meaning | ||
2441 | \row \i Locale | ||
2442 | \i Uses local file format (Latin1 if locale is not set), but | ||
2443 | autodetecting Unicode(utf16) on input. | ||
2444 | \row \i Unicode | ||
2445 | \i Uses Unicode(utf16) for input and output. Output will be | ||
2446 | written in the order most efficient for the current platform | ||
2447 | (i.e. the order used internally in QString). | ||
2448 | \row \i UnicodeUTF8 | ||
2449 | \i Using Unicode(utf8) for input and output. If you use it for | ||
2450 | input it will autodetect utf16 and use it instead of utf8. | ||
2451 | \row \i Latin1 | ||
2452 | \i ISO-8859-1. Will not autodetect utf16. | ||
2453 | \row \i UnicodeNetworkOrder | ||
2454 | \i Uses network order Unicode(utf16) for input and output. | ||
2455 | Useful when reading Unicode data that does not start with the | ||
2456 | byte order marker. | ||
2457 | \row \i UnicodeReverse | ||
2458 | \i Uses reverse network order Unicode(utf16) for input and | ||
2459 | output. Useful when reading Unicode data that does not start | ||
2460 | with the byte order marker or when writing data that should be | ||
2461 | read by buggy Windows applications. | ||
2462 | \row \i RawUnicode | ||
2463 | \i Like Unicode, but does not write the byte order marker nor | ||
2464 | does it auto-detect the byte order. Useful only when writing to | ||
2465 | non-persistent storage used by a single process. | ||
2466 | \endtable | ||
2467 | |||
2468 | \c Locale and all Unicode encodings, except \c RawUnicode, will look | ||
2469 | at the first two bytes in an input stream to determine the byte | ||
2470 | order. The initial byte order marker will be stripped off before | ||
2471 | data is read. | ||
2472 | |||
2473 | Note that this function should be called before any data is read to | ||
2474 | or written from the stream. | ||
2475 | |||
2476 | \sa setCodec() | ||
2477 | */ | ||
2478 | |||
2479 | void QTextStream::setEncoding( Encoding e ) | ||
2480 | { | ||
2481 | if ( d->sourceType == QTextStreamPrivate::String ) | ||
2482 | return; | ||
2483 | |||
2484 | switch ( e ) { | ||
2485 | case Unicode: | ||
2486 | mapper = 0; | ||
2487 | latin1 = FALSE; | ||
2488 | doUnicodeHeader = TRUE; | ||
2489 | internalOrder = TRUE; | ||
2490 | networkOrder = QChar::networkOrdered(); | ||
2491 | break; | ||
2492 | case UnicodeUTF8: | ||
2493 | #ifndef QT_NO_TEXTCODEC | ||
2494 | mapper = QTextCodec::codecForMib( 106 ); | ||
2495 | latin1 = FALSE; | ||
2496 | doUnicodeHeader = TRUE; | ||
2497 | internalOrder = TRUE; | ||
2498 | networkOrder = QChar::networkOrdered(); | ||
2499 | #else | ||
2500 | mapper = 0; | ||
2501 | latin1 = TRUE; | ||
2502 | doUnicodeHeader = TRUE; | ||
2503 | #endif | ||
2504 | break; | ||
2505 | case UnicodeNetworkOrder: | ||
2506 | mapper = 0; | ||
2507 | latin1 = FALSE; | ||
2508 | doUnicodeHeader = TRUE; | ||
2509 | internalOrder = QChar::networkOrdered(); | ||
2510 | networkOrder = TRUE; | ||
2511 | break; | ||
2512 | case UnicodeReverse: | ||
2513 | mapper = 0; | ||
2514 | latin1 = FALSE; | ||
2515 | doUnicodeHeader = TRUE; | ||
2516 | internalOrder = !QChar::networkOrdered(); | ||
2517 | networkOrder = FALSE; | ||
2518 | break; | ||
2519 | case RawUnicode: | ||
2520 | mapper = 0; | ||
2521 | latin1 = FALSE; | ||
2522 | doUnicodeHeader = FALSE; | ||
2523 | internalOrder = TRUE; | ||
2524 | networkOrder = QChar::networkOrdered(); | ||
2525 | break; | ||
2526 | case Locale: | ||
2527 | latin1 = TRUE; // fallback to Latin-1 | ||
2528 | #ifndef QT_NO_TEXTCODEC | ||
2529 | mapper = QTextCodec::codecForLocale(); | ||
2530 | // optimized Latin-1 processing | ||
2531 | #if defined(Q_OS_WIN32) | ||
2532 | if ( GetACP() == 1252 ) | ||
2533 | mapper = 0; | ||
2534 | #endif | ||
2535 | if ( mapper && mapper->mibEnum() == 4 ) | ||
2536 | #endif | ||
2537 | mapper = 0; | ||
2538 | |||
2539 | doUnicodeHeader = TRUE; // If it reads as Unicode, accept it | ||
2540 | break; | ||
2541 | case Latin1: | ||
2542 | mapper = 0; | ||
2543 | doUnicodeHeader = FALSE; | ||
2544 | latin1 = TRUE; | ||
2545 | break; | ||
2546 | } | ||
2547 | } | ||
2548 | |||
2549 | |||
2550 | #ifndef QT_NO_TEXTCODEC | ||
2551 | /*! | ||
2552 | Sets the codec for this stream to \a codec. Will not try to | ||
2553 | autodetect Unicode. | ||
2554 | |||
2555 | Note that this function should be called before any data is read | ||
2556 | to/written from the stream. | ||
2557 | |||
2558 | \sa setEncoding(), codec() | ||
2559 | */ | ||
2560 | |||
2561 | void QTextStream::setCodec( QTextCodec *codec ) | ||
2562 | { | ||
2563 | if ( d->sourceType == QTextStreamPrivate::String ) | ||
2564 | return; // QString does not need any codec | ||
2565 | mapper = codec; | ||
2566 | latin1 = ( codec->mibEnum() == 4 ); | ||
2567 | if ( latin1 ) | ||
2568 | mapper = 0; | ||
2569 | doUnicodeHeader = FALSE; | ||
2570 | } | ||
2571 | |||
2572 | /*! | ||
2573 | Returns the codec actually used for this stream. | ||
2574 | |||
2575 | If Unicode is automatically detected in input, a codec with \link | ||
2576 | QTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned. | ||
2577 | |||
2578 | \sa setCodec() | ||
2579 | */ | ||
2580 | |||
2581 | QTextCodec *QTextStream::codec() | ||
2582 | { | ||
2583 | if ( mapper ) { | ||
2584 | return mapper; | ||
2585 | } else { | ||
2586 | // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2" | ||
2587 | return QTextCodec::codecForMib( latin1 ? 4 : 1000 ); | ||
2588 | } | ||
2589 | } | ||
2590 | |||
2591 | #endif | ||
2592 | |||
2593 | #endif // QT_NO_TEXTSTREAM | ||