10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
137
138
139
140
141
142
143
144
145
146
149
150
151
152
153
154
155
156
157
158
159
160
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
180
181
182
183
184
185
186
187
188
189
190
193#include "private/qtextstream_p.h"
198#include <private/qdebug_p.h>
199#include <private/qnumeric_p.h>
200#include <private/qtools_p.h>
203#include "private/qlocale_p.h"
204#include "private/qstringconverter_p.h"
212#define CHECK_VALID_STREAM(x) do {
213 if (!d->string && !d->device) {
214 qWarning("QTextStream: No device");
219#define IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(type) do {
223 switch (d->getNumber(&tmp)) {
224 case QTextStreamPrivate::npsOk:
227 case QTextStreamPrivate::npsMissingDigit:
228 case QTextStreamPrivate::npsInvalidPrefix:
230 setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData);
233 return *this; } while (0
)
235#define IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(type) do {
239 if (d->getReal(&tmp)) {
243 setStatus(atEnd() ? QTextStream::ReadPastEnd : QTextStream::ReadCorruptData);
245 return *this; } while (0
)
249using namespace Qt::StringLiterals;
250using namespace QtMiscUtils;
257
258
259QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
260 : readConverterSavedStateOffset(0),
268
269
270QTextStreamPrivate::~QTextStreamPrivate()
272 disconnectFromDevice();
275 device->blockSignals(
true);
281void QTextStreamPrivate::Params::reset()
283 realNumberPrecision = 6;
287 fieldAlignment = QTextStream::AlignRight;
288 realNumberNotation = QTextStream::SmartNotation;
293
294
295void QTextStreamPrivate::reset()
300 deleteDevice =
false;
303 stringOpenMode = QTextStream::NotOpen;
305 readBufferOffset = 0;
306 readBufferStartDevicePos = 0;
309 hasWrittenData =
false;
311 encoding = QStringConverter::Utf8;
312 toUtf16 = QStringDecoder(encoding);
313 fromUtf16 = QStringEncoder(encoding);
314 autoDetectUnicode =
true;
317void QTextStreamPrivate::setupDevice(QIODevice *device)
319 disconnectFromDevice();
326 aboutToCloseConnection = QObject::connect(
327 device, &QIODevice::aboutToClose, device, [
this] { flushWriteBuffer(); },
328 Qt::DirectConnection);
335void QTextStreamPrivate::disconnectFromDevice()
338 QObject::disconnect(aboutToCloseConnection);
339 aboutToCloseConnection = {};
344
345
346bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
354 bool textModeEnabled = device->isTextModeEnabled();
356 device->setTextModeEnabled(
false);
359 char buf[QTEXTSTREAM_BUFFERSIZE];
360 qint64 bytesRead = 0;
367 if (device->isSequential()
368#if !defined(QT_NO_QOBJECT)
369 && (file = qobject_cast<QFile *>(device)) && file->handle() == 0
373 bytesRead = device->readLine(buf, qMin<qint64>(
sizeof(buf), maxBytes));
375 bytesRead = device->readLine(buf,
sizeof(buf));
380 bytesRead = device->read(buf, qMin<qint64>(
sizeof(buf), maxBytes));
382 bytesRead = device->read(buf,
sizeof(buf));
387 device->setTextModeEnabled(
true);
392#ifndef QT_BOOTSTRAPPED
393 if (autoDetectUnicode) {
394 autoDetectUnicode =
false;
396 auto e = QStringConverter::encodingForData(QByteArrayView(buf, bytesRead));
400 toUtf16 = QStringDecoder(encoding);
401 fromUtf16 = QStringEncoder(encoding);
404#if defined (QTEXTSTREAM_DEBUG)
405 qDebug(
"QTextStreamPrivate::fillReadBuffer(), using %s encoding", QStringConverter::nameForEncoding(encoding));
409#if defined (QTEXTSTREAM_DEBUG)
410 qDebug(
"QTextStreamPrivate::fillReadBuffer(), device->read(\"%s\", %d) == %d",
411 QtDebugUtils::toPrintable(buf, bytesRead, 32).constData(),
412 int(
sizeof(buf)),
int(bytesRead));
415 qsizetype oldReadBufferSize = readBuffer.size();
416 readBuffer += toUtf16(QByteArrayView(buf, bytesRead));
419 if (readBuffer.size() > oldReadBufferSize && textModeEnabled) {
421 QChar *writePtr = readBuffer.data() + oldReadBufferSize;
422 QChar *readPtr = readBuffer.data() + oldReadBufferSize;
423 QChar *endPtr = readBuffer.data() + readBuffer.size();
425 qsizetype n = oldReadBufferSize;
426 if (readPtr < endPtr) {
428 while (*readPtr++ != CR) {
430 if (++writePtr == endPtr)
434 while (readPtr < endPtr) {
435 QChar ch = *readPtr++;
439 if (n < readBufferOffset)
445 readBuffer.resize(writePtr - readBuffer.data());
448#if defined (QTEXTSTREAM_DEBUG)
449 qDebug(
"QTextStreamPrivate::fillReadBuffer() read %d bytes from device. readBuffer = [%s]",
451 QtDebugUtils::toPrintable(readBuffer.toLatin1(), readBuffer.size(),
452 readBuffer.size()).constData());
458
459
460void QTextStreamPrivate::resetReadBuffer()
463 readBufferOffset = 0;
464 readBufferStartDevicePos = (device ? device->pos() : 0);
468
469
470void QTextStreamPrivate::flushWriteBuffer()
474 if (string || !device)
479 if (status != QTextStream::Ok)
482 if (writeBuffer.isEmpty())
485#if defined (Q_OS_WIN)
487 bool textModeEnabled = device->isTextModeEnabled();
488 if (textModeEnabled) {
489 device->setTextModeEnabled(
false);
490 writeBuffer.replace(u'\n',
"\r\n"_L1);
494 QByteArray data = fromUtf16(writeBuffer);
496 hasWrittenData =
true;
499 qint64 bytesWritten = device->write(data);
500#if defined (QTEXTSTREAM_DEBUG)
501 qDebug(
"QTextStreamPrivate::flushWriteBuffer(), device->write(\"%s\") == %d",
502 QtDebugUtils::toPrintable(data.constData(), data.size(), 32).constData(),
506#if defined (Q_OS_WIN)
509 device->setTextModeEnabled(
true);
512 if (bytesWritten <= 0) {
513 status = QTextStream::WriteFailed;
519 QFileDevice *file = qobject_cast<QFileDevice *>(device);
520 bool flushed = !file || file->flush();
525#if defined (QTEXTSTREAM_DEBUG)
526 qDebug(
"QTextStreamPrivate::flushWriteBuffer() wrote %d bytes",
int(bytesWritten));
528 if (!flushed || bytesWritten != qint64(data.size()))
529 status = QTextStream::WriteFailed;
532QString QTextStreamPrivate::read(qsizetype maxlen)
536 lastTokenSize = qMin(maxlen, string->size() - stringOffset);
537 ret = string->mid(stringOffset, lastTokenSize);
539 while (readBuffer.size() - readBufferOffset < maxlen && fillReadBuffer()) {}
540 lastTokenSize = qMin(maxlen, readBuffer.size() - readBufferOffset);
541 ret = readBuffer.mid(readBufferOffset, lastTokenSize);
545#if defined (QTEXTSTREAM_DEBUG)
546 qDebug(
"QTextStreamPrivate::read() maxlen = %d, token length = %d",
547 int(maxlen),
int(ret.length()));
553
554
555
556
557
558
559bool QTextStreamPrivate::scan(
const QChar **ptr, qsizetype *length, qsizetype maxlen,
560 TokenDelimiter delimiter)
562 qsizetype totalSize = 0;
563 qsizetype delimSize = 0;
564 bool consumeDelimiter =
false;
565 bool foundToken =
false;
566 qsizetype startOffset = device ? readBufferOffset : stringOffset;
573 chPtr = readBuffer.constData();
574 endOffset = readBuffer.size();
576 chPtr = string->constData();
577 endOffset = string->size();
579 chPtr += startOffset;
581 for (; !foundToken && startOffset < endOffset && (!maxlen || totalSize < maxlen); ++startOffset) {
582 const QChar ch = *chPtr++;
601 delimSize = (lastChar == u'\r') ? 2 : 1;
602 consumeDelimiter =
true;
609 && (!maxlen || totalSize < maxlen)
610 && device && fillReadBuffer());
612 if (totalSize == 0) {
613#if defined (QTEXTSTREAM_DEBUG)
614 qDebug(
"QTextStreamPrivate::scan() reached the end of input.");
621 if (delimiter == EndOfLine && totalSize > 0 && !foundToken) {
622 if (((string && stringOffset + totalSize == string->size()) || (device && device->atEnd()))
623 && lastChar == u'\r') {
624 consumeDelimiter =
true;
631 *length = totalSize - delimSize;
637 lastTokenSize = totalSize;
638 if (!consumeDelimiter)
639 lastTokenSize -= delimSize;
641#if defined (QTEXTSTREAM_DEBUG)
642 qDebug(
"QTextStreamPrivate::scan(%p, %p, %d, %x) token length = %d, delimiter = %d",
643 ptr, length,
int(maxlen), uint(delimiter),
int(totalSize - delimSize),
int(delimSize));
649
650
651inline const QChar *QTextStreamPrivate::readPtr()
const
653 Q_ASSERT(readBufferOffset <= readBuffer.size());
655 return string->constData() + stringOffset;
656 return readBuffer.constData() + readBufferOffset;
660
661
662inline void QTextStreamPrivate::consumeLastToken()
665 consume(lastTokenSize);
670
671
672inline void QTextStreamPrivate::consume(qsizetype size)
674#if defined (QTEXTSTREAM_DEBUG)
675 qDebug(
"QTextStreamPrivate::consume(%d)",
int(size));
678 stringOffset += size;
679 if (stringOffset > string->size())
680 stringOffset = string->size();
682 readBufferOffset += size;
683 if (readBufferOffset >= readBuffer.size()) {
684 readBufferOffset = 0;
686 saveConverterState(device->pos());
687 }
else if (readBufferOffset > QTEXTSTREAM_BUFFERSIZE) {
688 readBuffer = readBuffer.remove(0,readBufferOffset);
689 readConverterSavedStateOffset += readBufferOffset;
690 readBufferOffset = 0;
696
697
698inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
701 memcpy((
void *)&savedToUtf16, (
void *)&toUtf16,
sizeof(QStringDecoder));
702 readBufferStartDevicePos = newPos;
703 readConverterSavedStateOffset = 0;
707
708
709inline void QTextStreamPrivate::restoreToSavedConverterState()
711 if (savedToUtf16.isValid())
712 memcpy((
void *)&toUtf16, (
void *)&savedToUtf16,
sizeof(QStringDecoder));
714 toUtf16.resetState();
715 savedToUtf16 = QStringDecoder();
719
720
721template <
typename Appendable>
722void QTextStreamPrivate::writeImpl(Appendable s)
728 writeBuffer.append(s);
729 if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE)
735
736
737void QTextStreamPrivate::write(QStringView s)
743
744
745void QTextStreamPrivate::write(QChar ch)
751
752
753void QTextStreamPrivate::write(QLatin1StringView data)
759
760
761void QTextStreamPrivate::writePadding(qsizetype len)
765 string->resize(string->size() + len, params.padChar);
767 writeBuffer.resize(writeBuffer.size() + len, params.padChar);
768 if (writeBuffer.size() > QTEXTSTREAM_BUFFERSIZE)
774
775
776inline bool QTextStreamPrivate::getChar(QChar *ch)
778 if ((string && stringOffset == string->size())
779 || (device && readBuffer.isEmpty() && !fillReadBuffer())) {
791
792
793inline void QTextStreamPrivate::ungetChar(QChar ch)
796 if (stringOffset == 0)
799 (*string)[--stringOffset] = ch;
803 if (readBufferOffset == 0) {
804 readBuffer.prepend(ch);
808 readBuffer[--readBufferOffset] = ch;
812
813
814inline void QTextStreamPrivate::putChar(QChar ch)
816 if (params.fieldWidth > 0)
817 putString(QStringView{&ch, 1});
824
825
826QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(qsizetype len)
const
828 Q_ASSERT(params.fieldWidth > len);
830 qsizetype left = 0, right = 0;
832 const qsizetype padSize = params.fieldWidth - len;
834 switch (params.fieldAlignment) {
835 case QTextStream::AlignLeft:
838 case QTextStream::AlignRight:
839 case QTextStream::AlignAccountingStyle:
842 case QTextStream::AlignCenter:
844 right = padSize - padSize/2;
847 return { left, right };
851template <
typename StringView>
852auto parseSign(StringView data,
const QLocale &loc)
855 StringView sign, rest;
856 explicit operator
bool()
const noexcept {
return !sign.isEmpty(); }
860 if (
const QString sign = loc.negativeSign(); data.startsWith(sign))
861 return R{data.first(sign.size()), data.sliced(sign.size())};
862 if (
const QString sign = loc.positiveSign(); data.startsWith(sign))
863 return R{data.first(sign.size()), data.sliced(sign.size())};
864 return R{
nullptr, data};
869
870
871template <
typename StringView>
872void QTextStreamPrivate::putStringImpl(StringView data, PutStringMode mode)
874 const bool number = mode == PutStringMode::Number;
875 if (Q_UNLIKELY(params.fieldWidth > data.size())) {
879 const PaddingResult pad = padding(data.size());
881 if (params.fieldAlignment == QTextStream::AlignAccountingStyle && number) {
882 if (
const auto r = parseSign(data, locale)) {
889 writePadding(pad.left);
891 writePadding(pad.right);
898
899
900void QTextStreamPrivate::putString(QLatin1StringView data, PutStringMode mode)
902 putStringImpl(data, mode);
906
907
908void QTextStreamPrivate::putString(QStringView data, PutStringMode mode)
910 putStringImpl(data, mode);
914
915
916void QTextStreamPrivate::putString(QUtf8StringView data, PutStringMode mode)
918 putString(data.toString(), mode);
922
923
924
925
926
927QTextStream::QTextStream()
928 : d_ptr(
new QTextStreamPrivate(
this))
930#if defined (QTEXTSTREAM_DEBUG)
931 qDebug(
"QTextStream::QTextStream()");
938
939
940QTextStream::QTextStream(QIODevice *device)
941 : d_ptr(
new QTextStreamPrivate(
this))
943#if defined (QTEXTSTREAM_DEBUG)
944 qDebug(
"QTextStream::QTextStream(QIODevice *device == *%p)",
949 d->setupDevice(device);
954
955
956
957QTextStream::QTextStream(QString *string, OpenMode openMode)
958 : d_ptr(
new QTextStreamPrivate(
this))
960#if defined (QTEXTSTREAM_DEBUG)
961 qDebug(
"QTextStream::QTextStream(QString *string == *%p, openMode = %d)",
962 string,
int(openMode.toInt()));
966 d->stringOpenMode = openMode;
970#ifndef QT_BOOTSTRAPPED
972
973
974
975
976QTextStream::QTextStream(QByteArray *array, OpenMode openMode)
977 : d_ptr(
new QTextStreamPrivate(
this))
979#if defined (QTEXTSTREAM_DEBUG)
980 qDebug(
"QTextStream::QTextStream(QByteArray *array == *%p, openMode = %d)",
981 array,
int(openMode.toInt()));
984 d->device =
new QBuffer(array);
985 d->device->open(openMode);
986 d->deleteDevice =
true;
987 d->setupDevice(d->device);
992
993
994
995
996
997
998
999
1000
1001QTextStream::QTextStream(
const QByteArray &array, OpenMode openMode)
1002 : d_ptr(
new QTextStreamPrivate(
this))
1004#if defined (QTEXTSTREAM_DEBUG)
1005 qDebug(
"QTextStream::QTextStream(const QByteArray &array == *(%p), openMode = %d)",
1006 &array,
int(openMode.toInt()));
1008 QBuffer *buffer =
new QBuffer;
1009 buffer->setData(array);
1010 buffer->open(openMode);
1014 d->deleteDevice =
true;
1015 d->setupDevice(d->device);
1021
1022
1023
1024
1025
1026
1027
1028
1029
1031QTextStream::QTextStream(FILE *fileHandle, OpenMode openMode)
1032 : d_ptr(
new QTextStreamPrivate(
this))
1034#if defined (QTEXTSTREAM_DEBUG)
1035 qDebug(
"QTextStream::QTextStream(FILE *fileHandle = %p, openMode = %d)",
1036 fileHandle,
int(openMode.toInt()));
1038 QFile *file =
new QFile;
1042 (
void)file->open(fileHandle, openMode);
1046 d->deleteDevice =
true;
1047 d->setupDevice(d->device);
1052
1053
1054
1055
1056
1057QTextStream::~QTextStream()
1060#if defined (QTEXTSTREAM_DEBUG)
1061 qDebug(
"QTextStream::~QTextStream()");
1063 if (!d->writeBuffer.isEmpty())
1064 d->flushWriteBuffer();
1068
1069
1070
1071
1072void QTextStream::reset()
1080
1081
1082
1083
1084void QTextStream::flush()
1087 d->flushWriteBuffer();
1091
1092
1093
1094bool QTextStream::seek(qint64 pos)
1097 d->lastTokenSize = 0;
1101 d->flushWriteBuffer();
1102 if (!d->device->seek(pos))
1104 d->resetReadBuffer();
1106 d->toUtf16.resetState();
1107 d->fromUtf16.resetState();
1112 if (d->string && pos <= d->string->size()) {
1113 d->stringOffset = pos;
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133qint64 QTextStream::pos()
const
1135 Q_D(
const QTextStream);
1138 if (d->readBuffer.isEmpty())
1139 return d->device->pos();
1140 if (d->device->isSequential())
1144 if (!d->device->seek(d->readBufferStartDevicePos))
1148 QTextStreamPrivate *thatd =
const_cast<QTextStreamPrivate *>(d);
1149 thatd->readBuffer.clear();
1151 thatd->restoreToSavedConverterState();
1152 if (d->readBufferStartDevicePos == 0)
1153 thatd->autoDetectUnicode =
true;
1157 qsizetype oldReadBufferOffset = d->readBufferOffset + d->readConverterSavedStateOffset;
1158 while (d->readBuffer.size() < oldReadBufferOffset) {
1159 if (!thatd->fillReadBuffer(1))
1162 thatd->readBufferOffset = oldReadBufferOffset;
1163 thatd->readConverterSavedStateOffset = 0;
1166 return d->device->pos();
1170 return d->stringOffset;
1172 qWarning(
"QTextStream::pos: no device");
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187void QTextStream::skipWhiteSpace()
1191 d->scan(
nullptr,
nullptr, 0, QTextStreamPrivate::NotSpace);
1192 d->consumeLastToken();
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205void QTextStream::setDevice(QIODevice *device)
1209 if (d->deleteDevice) {
1210 d->disconnectFromDevice();
1212 d->deleteDevice =
false;
1218 d->resetReadBuffer();
1219 d->setupDevice(d->device);
1223
1224
1225
1226
1227
1228QIODevice *QTextStream::device()
const
1230 Q_D(
const QTextStream);
1235
1236
1237
1238
1239
1240
1241void QTextStream::setString(QString *string, OpenMode openMode)
1245 if (d->deleteDevice) {
1246#ifndef QT_NO_QOBJECT
1247 d->setupDevice(d->device);
1248 d->device->blockSignals(
true);
1251 d->deleteDevice =
false;
1257 d->stringOpenMode = openMode;
1261
1262
1263
1264
1265
1266QString *QTextStream::string()
const
1268 Q_D(
const QTextStream);
1273
1274
1275
1276
1277
1278
1279
1280void QTextStream::setFieldAlignment(FieldAlignment mode)
1283 d->params.fieldAlignment = mode;
1287
1288
1289
1290
1291QTextStream::FieldAlignment QTextStream::fieldAlignment()
const
1293 Q_D(
const QTextStream);
1294 return d->params.fieldAlignment;
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312void QTextStream::setPadChar(QChar ch)
1315 d->params.padChar = ch;
1319
1320
1321
1322
1323QChar QTextStream::padChar()
const
1325 Q_D(
const QTextStream);
1326 return d->params.padChar;
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341void QTextStream::setFieldWidth(
int width)
1344 d->params.fieldWidth = width;
1348
1349
1350
1351
1352int QTextStream::fieldWidth()
const
1354 Q_D(
const QTextStream);
1355 return d->params.fieldWidth;
1359
1360
1361
1362
1363
1364
1365
1366void QTextStream::setNumberFlags(NumberFlags flags)
1369 d->params.numberFlags = flags;
1373
1374
1375
1376
1377QTextStream::NumberFlags QTextStream::numberFlags()
const
1379 Q_D(
const QTextStream);
1380 return d->params.numberFlags;
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393void QTextStream::setIntegerBase(
int base)
1396 d->params.integerBase = base;
1400
1401
1402
1403
1404
1405int QTextStream::integerBase()
const
1407 Q_D(
const QTextStream);
1408 return d->params.integerBase;
1412
1413
1414
1415
1416
1417
1418
1419void QTextStream::setRealNumberNotation(RealNumberNotation notation)
1422 d->params.realNumberNotation = notation;
1426
1427
1428
1429
1430QTextStream::RealNumberNotation QTextStream::realNumberNotation()
const
1432 Q_D(
const QTextStream);
1433 return d->params.realNumberNotation;
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446void QTextStream::setRealNumberPrecision(
int precision)
1449 if (precision < 0) {
1450 qWarning(
"QTextStream::setRealNumberPrecision: Invalid precision (%d)", precision);
1451 d->params.realNumberPrecision = 6;
1454 d->params.realNumberPrecision = precision;
1458
1459
1460
1461
1462
1463
1464
1465int QTextStream::realNumberPrecision()
const
1467 Q_D(
const QTextStream);
1468 return d->params.realNumberPrecision;
1472
1473
1474
1475
1477QTextStream::Status QTextStream::status()
const
1479 Q_D(
const QTextStream);
1484
1485
1486
1487
1488
1489
1490void QTextStream::resetStatus()
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506void QTextStream::setStatus(Status status)
1509 if (d->status == Ok)
1514
1515
1516
1517
1518
1519bool QTextStream::atEnd()
const
1521 Q_D(
const QTextStream);
1525 return d->string->size() == d->stringOffset;
1526 return d->readBuffer.isEmpty() && d->device->atEnd();
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539QString QTextStream::readAll()
1544 return d->read(std::numeric_limits<qsizetype>::max());
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564QString QTextStream::readLine(qint64 maxlen)
1568 readLineInto(&line, maxlen);
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597bool QTextStream::readLineInto(QString *line, qint64 maxlen)
1601 if (!d->string && !d->device) {
1602 qWarning(
"QTextStream: No device");
1603 if (line && !line->isNull())
1608 const QChar *readPtr;
1610 if (!d->scan(&readPtr, &length, qsizetype(maxlen), QTextStreamPrivate::EndOfLine)) {
1611 if (line && !line->isNull())
1617 line->setUnicode(readPtr, length);
1618 d->consumeLastToken();
1623
1624
1625
1626
1627
1628
1629
1630QString QTextStream::read(qint64 maxlen)
1636 return QString::fromLatin1(
"");
1638 return d->read(q26::saturate_cast<qsizetype>(maxlen));
1642
1643
1644QTextStreamPrivate::NumberParsingStatus QTextStreamPrivate::getNumber(qulonglong *ret)
1646 scan(
nullptr,
nullptr, 0, NotSpace);
1650 int base = params.integerBase;
1654 return npsInvalidPrefix;
1657 if (!getChar(&ch2)) {
1662 ch2 = ch2.toLower();
1666 }
else if (ch2 == u'b') {
1668 }
else if (ch2.isDigit() && ch2.digitValue() >= 0 && ch2.digitValue() <= 7) {
1674 }
else if (ch == locale.negativeSign() || ch == locale.positiveSign() || ch.isDigit()) {
1678 return npsInvalidPrefix;
1689 QChar pf1, pf2, dig;
1691 if (!getChar(&pf1) || pf1 != u'0')
1692 return npsInvalidPrefix;
1693 if (!getChar(&pf2) || pf2.toLower() != u'b')
1694 return npsInvalidPrefix;
1696 qsizetype ndigits = 0;
1697 while (getChar(&dig)) {
1698 char16_t n = dig.toLower().unicode();
1699 if (n == u'0' || n == u'1') {
1712 return npsMissingDigit;
1719 if (!getChar(&pf) || pf != u'0')
1720 return npsInvalidPrefix;
1722 qsizetype ndigits = 0;
1723 while (getChar(&dig)) {
1724 char16_t n = dig.toLower().unicode();
1725 if (isOctalDigit(n)) {
1737 return npsMissingDigit;
1744 qsizetype ndigits = 0;
1745 if (!getChar(&sign))
1746 return npsMissingDigit;
1747 if (sign != locale.negativeSign() && sign != locale.positiveSign()) {
1748 if (!sign.isDigit()) {
1750 return npsMissingDigit;
1752 val += sign.digitValue();
1757 while (getChar(&ch)) {
1760 val += ch.digitValue();
1761 }
else if (locale != QLocale::c() && ch == locale.groupSeparator()) {
1770 return npsMissingDigit;
1771 if (sign == locale.negativeSign()) {
1772 qlonglong ival = qlonglong(val);
1775 val = qulonglong(ival);
1780 QChar pf1, pf2, dig;
1782 if (!getChar(&pf1) || pf1 != u'0')
1783 return npsInvalidPrefix;
1784 if (!getChar(&pf2) || pf2.toLower() != u'x')
1785 return npsInvalidPrefix;
1787 qsizetype ndigits = 0;
1788 while (getChar(&dig)) {
1789 const int h = fromHex(dig.unicode());
1800 return npsMissingDigit;
1806 return npsInvalidPrefix;
1815
1816
1817
1818bool QTextStreamPrivate::getReal(
double *f)
1852 static const uchar table[13][10] = {
1854 { 0, Sign, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 },
1855 { 0, 0, Mantissa, Dot, 0, Inf1, Nan1, 0, 0, 0 },
1856 { Done, Done, Mantissa, Dot, ExpMark, 0, 0, 0, 0, 0 },
1857 { 0, 0, Abscissa, 0, 0, 0, 0, 0, 0, 0 },
1858 { Done, Done, Abscissa, Done, ExpMark, 0, 0, 0, 0, 0 },
1859 { 0, ExpSign, Exponent, 0, 0, 0, 0, 0, 0, 0 },
1860 { 0, 0, Exponent, 0, 0, 0, 0, 0, 0, 0 },
1861 { Done, Done, Exponent, Done, Done, 0, 0, 0, 0, 0 },
1862 { 0, 0, 0, 0, 0, 0, 0, 0, Nan2, 0 },
1863 { 0, 0, 0, 0, 0, 0, NanInf, 0, 0, 0 },
1864 { 0, 0, 0, 0, 0, 0, Inf2, 0, 0, 0 },
1865 { 0, 0, 0, 0, 0, 0, 0, NanInf, 0, 0 },
1866 { Done, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
1869 ParserState state = Init;
1870 InputToken input = None;
1872 scan(
nullptr,
nullptr, 0, NotSpace);
1875 const qsizetype BufferSize = 128;
1876 char buf[BufferSize];
1880 while (getChar(&c)) {
1881 switch (c.unicode()) {
1882 case u'0':
case u'1':
case u'2':
case u'3':
case u'4':
1883 case u'5':
case u'6':
case u'7':
case u'8':
case u'9':
1886 case u'i':
case u'I':
1889 case u'n':
case u'N':
1892 case u'f':
case u'F':
1895 case u'a':
case u'A':
1898 case u't':
case u'T':
1902 QChar lc = c.toLower();
1903 if (lc == locale.decimalPoint().toLower())
1905 else if (lc == locale.exponential().toLower())
1907 else if (lc == locale.negativeSign().toLower()
1908 || lc == locale.positiveSign().toLower())
1910 else if (locale != QLocale::c()
1911 && lc == locale.groupSeparator().toLower())
1919 state = ParserState(table[state][input]);
1921 if (state == Init || state == Done || i > (BufferSize - 5)) {
1923 if (i > (BufferSize - 5)) {
1924 while (getChar(&c)) {
1934 buf[i++] = c.toLatin1();
1947 if (!qstricmp(buf,
"nan") || !qstricmp(buf,
"+nan") || !qstricmp(buf,
"-nan")) {
1950 }
else if (!qstricmp(buf,
"+inf") || !qstricmp(buf,
"inf")) {
1953 }
else if (!qstricmp(buf,
"-inf")) {
1958 *f = locale.toDouble(QString::fromLatin1(buf), &ok);
1963
1964
1965
1966
1967
1968
1969
1970
1972QTextStream &QTextStream::operator>>(QChar &c)
1976 d->scan(
nullptr,
nullptr, 0, QTextStreamPrivate::NotSpace);
1977 if (!d->getChar(&c))
1978 setStatus(ReadPastEnd);
1983
1984
1985
1986
1987
1988
1989
1990
1991QTextStream &QTextStream::operator>>(
char &c)
2000
2001
2002
2003
2004
2005
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031QTextStream &QTextStream::operator>>(
signed short &i)
2037
2038
2039
2040
2041QTextStream &QTextStream::operator>>(
unsigned short &i)
2047
2048
2049
2050
2051QTextStream &QTextStream::operator>>(
signed int &i)
2057
2058
2059
2060
2061QTextStream &QTextStream::operator>>(
unsigned int &i)
2067
2068
2069
2070
2071QTextStream &QTextStream::operator>>(
signed long &i)
2077
2078
2079
2080
2081QTextStream &QTextStream::operator>>(
unsigned long &i)
2087
2088
2089
2090
2091QTextStream &QTextStream::operator>>(qlonglong &i)
2097
2098
2099
2100
2101QTextStream &QTextStream::operator>>(qulonglong &i)
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117QTextStream &QTextStream::operator>>(
float &f)
2123
2124
2125
2126
2127QTextStream &QTextStream::operator>>(
double &f)
2133
2134
2135
2136
2137
2138
2139QTextStream &QTextStream::operator>>(QString &str)
2145 d->scan(
nullptr,
nullptr, 0, QTextStreamPrivate::NotSpace);
2146 d->consumeLastToken();
2150 if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
2151 setStatus(ReadPastEnd);
2155 str = QString(ptr, length);
2156 d->consumeLastToken();
2161
2162
2163
2164
2165
2166
2167QTextStream &QTextStream::operator>>(QByteArray &array)
2172 d->scan(
nullptr,
nullptr, 0, QTextStreamPrivate::NotSpace);
2173 d->consumeLastToken();
2177 if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
2178 setStatus(ReadPastEnd);
2183 array = QStringView(ptr, length).toUtf8();
2185 d->consumeLastToken();
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203QTextStream &QTextStream::operator>>(
char *c)
2208 d->scan(
nullptr,
nullptr, 0, QTextStreamPrivate::NotSpace);
2209 d->consumeLastToken();
2213 if (!d->scan(&ptr, &length, 0, QTextStreamPrivate::Space)) {
2214 setStatus(ReadPastEnd);
2218 QStringEncoder encoder(QStringConverter::Utf8);
2219 char *e = encoder.appendToBuffer(c, QStringView(ptr, length));
2221 d->consumeLastToken();
2226
2227
2228void QTextStreamPrivate::putNumber(qulonglong number,
bool negative)
2231 const QTextStream::NumberFlags numberFlags = params.numberFlags;
2232 if (numberFlags & QTextStream::ShowBase)
2233 flags |= QLocaleData::ShowBase;
2235 if ((numberFlags & QTextStream::ForceSign) && !negative)
2236 flags |= QLocaleData::AlwaysShowSign;
2237 if (numberFlags & QTextStream::UppercaseBase)
2238 flags |= QLocaleData::UppercaseBase;
2239 if (numberFlags & QTextStream::UppercaseDigits)
2240 flags |= QLocaleData::CapitalEorX;
2243 if (locale != QLocale::c() && !locale.numberOptions().testFlag(QLocale::OmitGroupSeparator))
2244 flags |= QLocaleData::GroupDigits;
2246 const QLocaleData *dd = locale.d->m_data;
2247 int base = params.integerBase ? params.integerBase : 10;
2248 QString result = dd->unsLongLongToString(number, -1, base, -1, flags);
2250 result.prepend(locale.negativeSign());
2251 }
else if (number == 0 && base == 8 && params.numberFlags & QTextStream::ShowBase
2252 && result ==
"0"_L1) {
2257 result.prepend(u'0');
2259 putString(result, PutStringMode::Number);
2263
2264
2265
2266
2267
2268QTextStream &QTextStream::operator<<(QChar c)
2277
2278
2279
2280
2281QTextStream &QTextStream::operator<<(
char c)
2285 d->putChar(QChar::fromLatin1(c));
2290
2291
2292
2293
2294
2295
2296
2299
2300
2301
2302
2303
2304
2305
2306QTextStream &QTextStream::operator<<(
signed short i)
2310 d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
2315
2316
2317
2318
2319QTextStream &QTextStream::operator<<(
unsigned short i)
2323 d->putNumber((qulonglong)i,
false);
2328
2329
2330
2331
2332QTextStream &QTextStream::operator<<(
signed int i)
2336 d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
2341
2342
2343
2344
2345QTextStream &QTextStream::operator<<(
unsigned int i)
2349 d->putNumber((qulonglong)i,
false);
2354
2355
2356
2357
2358QTextStream &QTextStream::operator<<(
signed long i)
2362 d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
2367
2368
2369
2370
2371QTextStream &QTextStream::operator<<(
unsigned long i)
2375 d->putNumber((qulonglong)i,
false);
2380
2381
2382
2383
2384QTextStream &QTextStream::operator<<(qlonglong i)
2388 d->putNumber(QtPrivate::qUnsignedAbs(i), i < 0);
2393
2394
2395
2396
2397QTextStream &QTextStream::operator<<(qulonglong i)
2401 d->putNumber(i,
false);
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416QTextStream &QTextStream::operator<<(
float f)
2418 return *
this <<
double(f);
2422
2423
2424
2425
2426QTextStream &QTextStream::operator<<(
double f)
2431 QLocaleData::DoubleForm form = QLocaleData::DFDecimal;
2432 switch (realNumberNotation()) {
2434 form = QLocaleData::DFDecimal;
2436 case ScientificNotation:
2437 form = QLocaleData::DFExponent;
2440 form = QLocaleData::DFSignificantDigits;
2445 const QLocale::NumberOptions numberOptions = locale().numberOptions();
2446 if (numberFlags() & ShowBase)
2447 flags |= QLocaleData::ShowBase;
2448 if (numberFlags() & ForceSign)
2449 flags |= QLocaleData::AlwaysShowSign;
2450 if (numberFlags() & UppercaseBase)
2451 flags |= QLocaleData::UppercaseBase;
2452 if (numberFlags() & UppercaseDigits)
2453 flags |= QLocaleData::CapitalEorX;
2454 if (numberFlags() & ForcePoint) {
2455 flags |= QLocaleData::ForcePoint;
2458 flags |= QLocaleData::AddTrailingZeroes | QLocaleData::ShowBase;
2460 if (locale() != QLocale::c() && !(numberOptions & QLocale::OmitGroupSeparator))
2461 flags |= QLocaleData::GroupDigits;
2462 if (!(numberOptions & QLocale::OmitLeadingZeroInExponent))
2463 flags |= QLocaleData::ZeroPadExponent;
2464 if (numberOptions & QLocale::IncludeTrailingZeroesAfterDot)
2465 flags |= QLocaleData::AddTrailingZeroes;
2467 const QLocaleData *dd = d->locale.d->m_data;
2468 QString num = dd->doubleToString(f, d->params.realNumberPrecision, form, -1, flags);
2469 d->putString(num, QTextStreamPrivate::PutStringMode::Number);
2474
2475
2476
2477
2478
2479
2480QTextStream &QTextStream::operator<<(
const QString &string)
2484 d->putString(string);
2489
2490
2491
2492
2493
2494
2495QTextStream &QTextStream::operator<<(QStringView string)
2499 d->putString(string);
2504
2505
2506
2507
2508
2509QTextStream &QTextStream::operator<<(QLatin1StringView string)
2513 d->putString(string);
2518
2519
2520
2521
2522
2523QTextStream &QTextStream::operator<<(
const QByteArray &array)
2527 d->putString(QUtf8StringView{array});
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544QTextStream &QTextStream::operator<<(
const char *string)
2548 d->putString(QUtf8StringView(string));
2553
2554
2555
2556
2558QTextStream &QTextStream::operator<<(
const void *ptr)
2562 const int oldBase = d->params.integerBase;
2563 const NumberFlags oldFlags = d->params.numberFlags;
2564 d->params.integerBase = 16;
2565 d->params.numberFlags |= ShowBase;
2566 d->putNumber(
reinterpret_cast<quintptr>(ptr),
false);
2567 d->params.integerBase = oldBase;
2568 d->params.numberFlags = oldFlags;
2573
2574
2575
2576
2577
2582
2583
2584
2585
2586
2587
2588
2596
2597
2598
2599
2600
2601
2602
2610
2611
2612
2613
2614
2615
2616
2624
2625
2626
2627
2628
2629
2630
2631
2639
2640
2641
2642
2643
2644
2645
2653
2654
2655
2656
2657
2658
2659
2667
2668
2669
2670
2671
2672
2673
2681
2682
2683
2684
2685
2686
2687
2695
2696
2697
2698
2699
2700
2701
2709
2710
2711
2712
2713
2714
2715
2723
2724
2725
2726
2727
2728
2729
2737
2738
2739
2740
2741
2742
2743
2751
2752
2753
2754
2755
2756
2757
2765
2766
2767
2768
2769
2770
2771
2779
2780
2781
2782
2783
2784
2785
2793
2794
2795
2796
2797
2798
2799
2807
2808
2809
2810
2811
2812
2813
2821
2822
2823
2824
2825
2826
2827
2835
2836
2837
2838
2839
2840
2841
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2868
2869
2870
2871
2872
2873
2881
2882
2883
2884
2885
2886
2894
2895
2896
2897
2898
2899
2909
2910
2911
2912
2913
2916
2917
2918
2919
2920
2923
2924
2925
2926
2927
2932
2933
2934
2935
2936
2937
2938
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964void QTextStream::setEncoding(QStringConverter::Encoding encoding)
2967 if (d->encoding == encoding)
2970 qint64 seekPos = -1;
2971 if (!d->readBuffer.isEmpty()) {
2972 if (!d->device->isSequential()) {
2977 d->encoding = encoding;
2978 d->toUtf16 = QStringDecoder(d->encoding);
2979 bool generateBOM = !d->hasWrittenData && d->generateBOM;
2980 d->fromUtf16 = QStringEncoder(d->encoding,
2981 generateBOM ? QStringEncoder::Flag::WriteBom : QStringEncoder::Flag::Default);
2983 if (seekPos >=0 && !d->readBuffer.isEmpty())
2988
2989
2990
2991
2992QStringConverter::Encoding QTextStream::encoding()
const
2994 Q_D(
const QTextStream);
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009void QTextStream::setAutoDetectUnicode(
bool enabled)
3012 d->autoDetectUnicode = enabled;
3016
3017
3018
3019
3020
3021bool QTextStream::autoDetectUnicode()
const
3023 Q_D(
const QTextStream);
3024 return d->autoDetectUnicode;
3028
3029
3030
3031
3032
3033
3034
3035void QTextStream::setGenerateByteOrderMark(
bool generate)
3038 if (d->hasWrittenData || d->generateBOM == generate)
3041 d->generateBOM = generate;
3042 d->fromUtf16 = QStringEncoder(d->encoding, generate ? QStringConverter::Flag::WriteBom : QStringConverter::Flag::Default);
3046
3047
3048
3049
3050
3051
3052bool QTextStream::generateByteOrderMark()
const
3054 Q_D(
const QTextStream);
3055 return d->generateBOM;
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069void QTextStream::setLocale(
const QLocale &locale)
3076
3077
3078
3079
3080
3081
3082QLocale QTextStream::locale()
const
3084 Q_D(
const QTextStream);
static const qsizetype QTEXTSTREAM_BUFFERSIZE
#define IMPLEMENT_STREAM_RIGHT_REAL_OPERATOR(type)
#define IMPLEMENT_STREAM_RIGHT_INT_OPERATOR(type)
#define CHECK_VALID_STREAM(x)