|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt3Support module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
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 |
|
62 QT_BEGIN_NAMESPACE |
|
63 |
|
64 #ifndef QT_NO_TEXTCODEC |
|
65 static 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 |
|
176 static const QChar QEOF = QChar((ushort)0xffff); //guaranteed not to be a character. |
|
177 static const uint getline_buf_size = 256; // bufsize used by ts_getline() |
|
178 |
|
179 const int Q3TextStream::basefield = I_BASE_MASK; |
|
180 const int Q3TextStream::adjustfield = ( Q3TextStream::left | |
|
181 Q3TextStream::right | |
|
182 Q3TextStream::internal ); |
|
183 const int Q3TextStream::floatfield = ( Q3TextStream::scientific | |
|
184 Q3TextStream::fixed ); |
|
185 |
|
186 |
|
187 class Q3TextStreamPrivate { |
|
188 public: |
|
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 |
|
206 QChar Q3TextStream::eat_ws() |
|
207 { |
|
208 QChar c; |
|
209 do { c = ts_getc(); } while ( c != QEOF && ts_isspace(c) ); |
|
210 return c; |
|
211 } |
|
212 |
|
213 void 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 |
|
234 Q3TextStream::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 |
|
246 Q3TextStream::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. |
|
257 class QStringBuffer : public QIODevice { |
|
258 public: |
|
259 QStringBuffer( QString* str ); |
|
260 ~QStringBuffer(); |
|
261 bool open( OpenMode m ); |
|
262 void close(); |
|
263 qint64 size() const; |
|
264 |
|
265 protected: |
|
266 qint64 readData( char *p, qint64 len ); |
|
267 qint64 writeData( const char *p, qint64 len ); |
|
268 |
|
269 QString* s; |
|
270 |
|
271 private: |
|
272 QStringBuffer( const QStringBuffer & ); |
|
273 QStringBuffer &operator=( const QStringBuffer & ); |
|
274 }; |
|
275 |
|
276 |
|
277 QStringBuffer::QStringBuffer( QString* str ) |
|
278 { |
|
279 s = str; |
|
280 } |
|
281 |
|
282 QStringBuffer::~QStringBuffer() |
|
283 { |
|
284 } |
|
285 |
|
286 |
|
287 bool 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 |
|
313 void QStringBuffer::close() |
|
314 { |
|
315 if ( isOpen() ) { |
|
316 seek(0); |
|
317 QIODevice::close(); |
|
318 } |
|
319 } |
|
320 |
|
321 qint64 QStringBuffer::size() const |
|
322 { |
|
323 return s ? s->length()*sizeof(QChar) : 0; |
|
324 } |
|
325 |
|
326 qint64 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 |
|
351 qint64 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 |
|
399 Q3TextStream::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 |
|
418 Q3TextStream::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 |
|
445 Q3TextStream::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 |
|
469 Q3TextStream::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 |
|
486 Q3TextStream::~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 */ |
|
498 void 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 */ |
|
512 uint 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 */ |
|
742 uint 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 */ |
|
824 void 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 */ |
|
860 void Q3TextStream::ts_putc( int ch ) |
|
861 { |
|
862 ts_putc( QChar((ushort)ch) ); |
|
863 } |
|
864 |
|
865 bool Q3TextStream::ts_isdigit( QChar c ) |
|
866 { |
|
867 return c.isDigit(); |
|
868 } |
|
869 |
|
870 bool Q3TextStream::ts_isspace( QChar c ) |
|
871 { |
|
872 return c.isSpace(); |
|
873 } |
|
874 |
|
875 void 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 |
|
899 Q3TextStream &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 |
|
916 Q3TextStream &Q3TextStream::writeRawBytes( const char* s, uint len ) |
|
917 { |
|
918 dev->writeBlock( s, len ); |
|
919 return *this; |
|
920 } |
|
921 |
|
922 |
|
923 Q3TextStream &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 |
|
956 Q3TextStream &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 |
|
996 void 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 |
|
1021 void 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 |
|
1039 void 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 |
|
1077 Q3TextStream &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 |
|
1089 Q3TextStream &Q3TextStream::operator>>( QChar &c ) |
|
1090 { |
|
1091 CHECK_STREAM_PRECOND |
|
1092 c = ts_getc(); |
|
1093 return *this; |
|
1094 } |
|
1095 |
|
1096 |
|
1097 ulong 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 |
|
1112 ulong 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 |
|
1131 ulong 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 |
|
1146 ulong 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 |
|
1165 long 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 |
|
1245 double 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 |
|
1335 Q3TextStream &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 |
|
1351 Q3TextStream &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 |
|
1367 Q3TextStream &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 |
|
1383 Q3TextStream &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 |
|
1399 Q3TextStream &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 |
|
1415 Q3TextStream &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 |
|
1431 Q3TextStream &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 |
|
1447 Q3TextStream &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 |
|
1464 Q3TextStream &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 |
|
1493 Q3TextStream &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 |
|
1521 Q3TextStream &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 |
|
1573 QString 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 |
|
1658 QString 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 */ |
|
1720 Q3TextStream &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 */ |
|
1734 Q3TextStream &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 |
|
1742 Q3TextStream &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 |
|
1853 Q3TextStream &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 |
|
1867 Q3TextStream &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 |
|
1881 Q3TextStream &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 |
|
1895 Q3TextStream &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 |
|
1909 Q3TextStream &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 |
|
1923 Q3TextStream &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 |
|
1937 Q3TextStream &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 |
|
1950 Q3TextStream &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 |
|
1997 Q3TextStream &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 |
|
2040 Q3TextStream &Q3TextStream::operator<<( const Q3CString & s ) |
|
2041 { |
|
2042 return operator<<(s.data()); |
|
2043 } |
|
2044 |
|
2045 /*! |
|
2046 \overload |
|
2047 \since 4.2 |
|
2048 |
|
2049 Writes \a s to the stream and returns a reference to the stream. |
|
2050 */ |
|
2051 |
|
2052 Q3TextStream &Q3TextStream::operator<<( const QString& s ) |
|
2053 { |
|
2054 if ( !mapper && latin1 ) |
|
2055 return operator<<(s.latin1()); |
|
2056 CHECK_STREAM_PRECOND |
|
2057 QString s1 = s; |
|
2058 if ( fwidth ) { // field width set |
|
2059 if ( !(flags() & left) ) { |
|
2060 s1 = s.rightJustify(fwidth, QLatin1Char((char)fillchar)); |
|
2061 } else { |
|
2062 s1 = s.leftJustify(fwidth, QLatin1Char((char)fillchar)); |
|
2063 } |
|
2064 fwidth = 0; // reset width |
|
2065 } |
|
2066 writeBlock( s1.unicode(), s1.length() ); |
|
2067 return *this; |
|
2068 } |
|
2069 |
|
2070 |
|
2071 /*! |
|
2072 \overload |
|
2073 \since 4.2 |
|
2074 |
|
2075 Writes a pointer to the stream and returns a reference to the |
|
2076 stream. |
|
2077 |
|
2078 The \a ptr is output as an unsigned long hexadecimal integer. |
|
2079 */ |
|
2080 |
|
2081 Q3TextStream &Q3TextStream::operator<<( void *ptr ) |
|
2082 { |
|
2083 int f = flags(); |
|
2084 setf( hex, basefield ); |
|
2085 setf( showbase ); |
|
2086 unsetf( uppercase ); |
|
2087 output_int( I_LONG | I_UNSIGNED, (ulong)ptr, FALSE ); |
|
2088 flags( f ); |
|
2089 return *this; |
|
2090 } |
|
2091 |
|
2092 |
|
2093 /*! |
|
2094 \fn int Q3TextStream::flags() const |
|
2095 \since 4.2 |
|
2096 |
|
2097 Returns the current stream flags. The default value is 0. |
|
2098 |
|
2099 \table |
|
2100 \header \i Flag \i Meaning |
|
2101 \row \i \c skipws \i Not currently used; whitespace always skipped |
|
2102 \row \i \c left \i Numeric fields are left-aligned |
|
2103 \row \i \c right |
|
2104 \i Not currently used (by default, numerics are right-aligned) |
|
2105 \row \i \c internal \i Puts any padding spaces between +/- and value |
|
2106 \row \i \c bin \i Output \e and input only in binary |
|
2107 \row \i \c oct \i Output \e and input only in octal |
|
2108 \row \i \c dec \i Output \e and input only in decimal |
|
2109 \row \i \c hex \i Output \e and input only in hexadecimal |
|
2110 \row \i \c showbase |
|
2111 \i Annotates numeric outputs with 0b, 0, or 0x if in \c bin, |
|
2112 \c oct, or \c hex format |
|
2113 \row \i \c showpoint \i Not currently used |
|
2114 \row \i \c uppercase \i Uses 0B and 0X rather than 0b and 0x |
|
2115 \row \i \c showpos \i Shows + for positive numeric values |
|
2116 \row \i \c scientific \i Uses scientific notation for floating point values |
|
2117 \row \i \c fixed \i Uses fixed-point notation for floating point values |
|
2118 \endtable |
|
2119 |
|
2120 Note that unless \c bin, \c oct, \c dec, or \c hex is set, the |
|
2121 input base is octal if the value starts with 0, hexadecimal if it |
|
2122 starts with 0x, binary if it starts with 0b, and decimal |
|
2123 otherwise. |
|
2124 |
|
2125 \sa setf(), unsetf() |
|
2126 */ |
|
2127 |
|
2128 /*! |
|
2129 \fn int Q3TextStream::flags( int f ) |
|
2130 |
|
2131 \overload |
|
2132 |
|
2133 Sets the stream flags to \a f. Returns the previous stream flags. |
|
2134 |
|
2135 \sa setf(), unsetf(), flags() |
|
2136 */ |
|
2137 |
|
2138 /*! |
|
2139 \fn int Q3TextStream::setf( int bits ) |
|
2140 \since 4.2 |
|
2141 |
|
2142 Sets the stream flag bits \a bits. Returns the previous stream |
|
2143 flags. |
|
2144 |
|
2145 Equivalent to \c{flags( flags() | bits )}. |
|
2146 |
|
2147 \sa unsetf() |
|
2148 */ |
|
2149 |
|
2150 /*! |
|
2151 \fn int Q3TextStream::setf( int bits, int mask ) |
|
2152 |
|
2153 \overload |
|
2154 |
|
2155 Sets the stream flag bits \a bits with a bit mask \a mask. Returns |
|
2156 the previous stream flags. |
|
2157 |
|
2158 Equivalent to \c{flags( (flags() & ~mask) | (bits & mask) )}. |
|
2159 |
|
2160 \sa setf(), unsetf() |
|
2161 */ |
|
2162 |
|
2163 /*! |
|
2164 \fn int Q3TextStream::unsetf( int bits ) |
|
2165 \since 4.2 |
|
2166 |
|
2167 Clears the stream flag bits \a bits. Returns the previous stream |
|
2168 flags. |
|
2169 |
|
2170 Equivalent to \c{flags( flags() & ~mask )}. |
|
2171 |
|
2172 \sa setf() |
|
2173 */ |
|
2174 |
|
2175 /*! |
|
2176 \fn int Q3TextStream::width() const |
|
2177 \since 4.2 |
|
2178 |
|
2179 Returns the field width. The default value is 0. |
|
2180 */ |
|
2181 |
|
2182 /*! |
|
2183 \fn int Q3TextStream::width( int w ) |
|
2184 |
|
2185 \overload |
|
2186 |
|
2187 Sets the field width to \a w. Returns the previous field width. |
|
2188 */ |
|
2189 |
|
2190 /*! |
|
2191 \fn int Q3TextStream::fill() const |
|
2192 \since 4.2 |
|
2193 |
|
2194 Returns the fill character. The default value is ' ' (space). |
|
2195 */ |
|
2196 |
|
2197 /*! |
|
2198 \fn int Q3TextStream::fill( int f ) |
|
2199 \overload |
|
2200 |
|
2201 Sets the fill character to \a f. Returns the previous fill character. |
|
2202 */ |
|
2203 |
|
2204 /*! |
|
2205 \fn int Q3TextStream::precision() const |
|
2206 \since 4.2 |
|
2207 |
|
2208 Returns the precision. The default value is 6. |
|
2209 */ |
|
2210 |
|
2211 /*! |
|
2212 \fn int Q3TextStream::precision( int p ) |
|
2213 |
|
2214 \overload |
|
2215 |
|
2216 Sets the precision to \a p. Returns the previous precision setting. |
|
2217 */ |
|
2218 |
|
2219 |
|
2220 Q3TextStream &bin( Q3TextStream &s ) |
|
2221 { |
|
2222 s.setf(Q3TextStream::bin,Q3TextStream::basefield); |
|
2223 return s; |
|
2224 } |
|
2225 |
|
2226 Q3TextStream &oct( Q3TextStream &s ) |
|
2227 { |
|
2228 s.setf(Q3TextStream::oct,Q3TextStream::basefield); |
|
2229 return s; |
|
2230 } |
|
2231 |
|
2232 Q3TextStream &dec( Q3TextStream &s ) |
|
2233 { |
|
2234 s.setf(Q3TextStream::dec,Q3TextStream::basefield); |
|
2235 return s; |
|
2236 } |
|
2237 |
|
2238 Q3TextStream &hex( Q3TextStream &s ) |
|
2239 { |
|
2240 s.setf(Q3TextStream::hex,Q3TextStream::basefield); |
|
2241 return s; |
|
2242 } |
|
2243 |
|
2244 Q3TextStream &endl( Q3TextStream &s ) |
|
2245 { |
|
2246 return s << '\n'; |
|
2247 } |
|
2248 |
|
2249 Q3TextStream &flush( Q3TextStream &s ) |
|
2250 { |
|
2251 return s; |
|
2252 } |
|
2253 |
|
2254 Q3TextStream &ws( Q3TextStream &s ) |
|
2255 { |
|
2256 s.skipWhiteSpace(); |
|
2257 return s; |
|
2258 } |
|
2259 |
|
2260 Q3TextStream &reset( Q3TextStream &s ) |
|
2261 { |
|
2262 s.reset(); |
|
2263 return s; |
|
2264 } |
|
2265 |
|
2266 /*! |
|
2267 \since 4.2 |
|
2268 |
|
2269 Sets the encoding of this stream to \a e, where \a e is one of the |
|
2270 following values: |
|
2271 \table |
|
2272 \header \i Encoding \i Meaning |
|
2273 \row \i Locale |
|
2274 \i Uses local file format (Latin1 if locale is not set), but |
|
2275 autodetecting Unicode(utf16) on input. |
|
2276 \row \i Unicode |
|
2277 \i Uses Unicode(utf16) for input and output. Output will be |
|
2278 written in the order most efficient for the current platform |
|
2279 (i.e. the order used internally in QString). |
|
2280 \row \i UnicodeUTF8 |
|
2281 \i Using Unicode(utf8) for input and output. If you use it for |
|
2282 input it will autodetect utf16 and use it instead of utf8. |
|
2283 \row \i Latin1 |
|
2284 \i ISO-8859-1. Will not autodetect utf16. |
|
2285 \row \i UnicodeNetworkOrder |
|
2286 \i Uses network order Unicode(utf16) for input and output. |
|
2287 Useful when reading Unicode data that does not start with the |
|
2288 byte order marker. |
|
2289 \row \i UnicodeReverse |
|
2290 \i Uses reverse network order Unicode(utf16) for input and |
|
2291 output. Useful when reading Unicode data that does not start |
|
2292 with the byte order marker or when writing data that should be |
|
2293 read by buggy Windows applications. |
|
2294 \row \i RawUnicode |
|
2295 \i Like Unicode, but does not write the byte order marker nor |
|
2296 does it auto-detect the byte order. Useful only when writing to |
|
2297 non-persistent storage used by a single process. |
|
2298 \endtable |
|
2299 |
|
2300 \c Locale and all Unicode encodings, except \c RawUnicode, will look |
|
2301 at the first two bytes in an input stream to determine the byte |
|
2302 order. The initial byte order marker will be stripped off before |
|
2303 data is read. |
|
2304 |
|
2305 Note that this function should be called before any data is read to |
|
2306 or written from the stream. |
|
2307 |
|
2308 \sa setCodec() |
|
2309 */ |
|
2310 |
|
2311 void Q3TextStream::setEncoding( Encoding e ) |
|
2312 { |
|
2313 resetCodecConverterState(&mapperReadState); |
|
2314 resetCodecConverterState(&mapperWriteState); |
|
2315 |
|
2316 if ( d->sourceType == Q3TextStreamPrivate::String ) |
|
2317 return; |
|
2318 |
|
2319 switch ( e ) { |
|
2320 case Unicode: |
|
2321 mapper = 0; |
|
2322 latin1 = FALSE; |
|
2323 doUnicodeHeader = TRUE; |
|
2324 internalOrder = TRUE; |
|
2325 networkOrder = QChar::networkOrdered(); |
|
2326 break; |
|
2327 case UnicodeUTF8: |
|
2328 #ifndef QT_NO_TEXTCODEC |
|
2329 mapper = QTextCodec::codecForMib( 106 ); |
|
2330 mapperWriteState.flags |= QTextCodec::IgnoreHeader; |
|
2331 latin1 = FALSE; |
|
2332 doUnicodeHeader = TRUE; |
|
2333 internalOrder = TRUE; |
|
2334 networkOrder = QChar::networkOrdered(); |
|
2335 #else |
|
2336 mapper = 0; |
|
2337 latin1 = TRUE; |
|
2338 doUnicodeHeader = TRUE; |
|
2339 #endif |
|
2340 break; |
|
2341 case UnicodeNetworkOrder: |
|
2342 mapper = 0; |
|
2343 latin1 = FALSE; |
|
2344 doUnicodeHeader = TRUE; |
|
2345 internalOrder = QChar::networkOrdered(); |
|
2346 networkOrder = TRUE; |
|
2347 break; |
|
2348 case UnicodeReverse: |
|
2349 mapper = 0; |
|
2350 latin1 = FALSE; |
|
2351 doUnicodeHeader = TRUE; |
|
2352 internalOrder = !QChar::networkOrdered(); |
|
2353 networkOrder = FALSE; |
|
2354 break; |
|
2355 case RawUnicode: |
|
2356 mapper = 0; |
|
2357 latin1 = FALSE; |
|
2358 doUnicodeHeader = FALSE; |
|
2359 internalOrder = TRUE; |
|
2360 networkOrder = QChar::networkOrdered(); |
|
2361 break; |
|
2362 case Locale: |
|
2363 latin1 = TRUE; // fallback to Latin-1 |
|
2364 #ifndef QT_NO_TEXTCODEC |
|
2365 mapper = QTextCodec::codecForLocale(); |
|
2366 mapperReadState.flags |= QTextCodec::IgnoreHeader; |
|
2367 mapperWriteState.flags |= QTextCodec::IgnoreHeader; |
|
2368 // optimized Latin-1 processing |
|
2369 #if defined(Q_OS_WIN32) |
|
2370 if ( GetACP() == 1252 ) |
|
2371 mapper = 0; |
|
2372 #endif |
|
2373 if ( mapper && mapper->mibEnum() == 4 ) |
|
2374 #endif |
|
2375 mapper = 0; |
|
2376 |
|
2377 doUnicodeHeader = TRUE; // If it reads as Unicode, accept it |
|
2378 break; |
|
2379 case Latin1: |
|
2380 mapper = 0; |
|
2381 doUnicodeHeader = FALSE; |
|
2382 latin1 = TRUE; |
|
2383 break; |
|
2384 } |
|
2385 } |
|
2386 |
|
2387 |
|
2388 #ifndef QT_NO_TEXTCODEC |
|
2389 /*! |
|
2390 \since 4.2 |
|
2391 |
|
2392 Sets the codec for this stream to \a codec. Will not try to |
|
2393 autodetect Unicode. |
|
2394 |
|
2395 Note that this function should be called before any data is read |
|
2396 to/written from the stream. |
|
2397 |
|
2398 \sa setEncoding(), codec() |
|
2399 */ |
|
2400 |
|
2401 void Q3TextStream::setCodec( QTextCodec *codec ) |
|
2402 { |
|
2403 if ( d->sourceType == Q3TextStreamPrivate::String ) |
|
2404 return; // QString does not need any codec |
|
2405 mapper = codec; |
|
2406 latin1 = ( codec->mibEnum() == 4 ); |
|
2407 if ( latin1 ) |
|
2408 mapper = 0; |
|
2409 doUnicodeHeader = FALSE; |
|
2410 } |
|
2411 |
|
2412 /*! |
|
2413 Returns the codec actually used for this stream. |
|
2414 \since 4.2 |
|
2415 |
|
2416 If Unicode is automatically detected in input, a codec with \link |
|
2417 QTextCodec::name() name() \endlink "ISO-10646-UCS-2" is returned. |
|
2418 |
|
2419 \sa setCodec() |
|
2420 */ |
|
2421 |
|
2422 QTextCodec *Q3TextStream::codec() |
|
2423 { |
|
2424 if ( mapper ) { |
|
2425 return mapper; |
|
2426 } else { |
|
2427 // 4 is "ISO 8859-1", 1000 is "ISO-10646-UCS-2" |
|
2428 return QTextCodec::codecForMib( latin1 ? 4 : 1000 ); |
|
2429 } |
|
2430 } |
|
2431 |
|
2432 #endif |
|
2433 |
|
2434 QT_END_NAMESPACE |
|
2435 |
|
2436 #endif // QT_NO_TEXTSTREAM |