|
6 | 6 | #include <QtCore/qfile.h>
|
7 | 7 | #include <QtCore/qlibraryinfo.h>
|
8 | 8 | #include <QtCore/private/qlocking_p.h>
|
| 9 | +#include <QtCore/qscopedvaluerollback.h> |
9 | 10 | #include <QtCore/qstandardpaths.h>
|
10 | 11 | #include <QtCore/qstringtokenizer.h>
|
11 |
| -#include <QtCore/qtextstream.h> |
12 | 12 | #include <QtCore/qdir.h>
|
13 | 13 | #include <QtCore/qcoreapplication.h>
|
14 |
| -#include <QtCore/qscopedvaluerollback.h> |
| 14 | +#include <qplatformdefs.h> |
15 | 15 |
|
16 | 16 | #if QT_CONFIG(settings)
|
17 | 17 | #include <QtCore/qsettings.h>
|
@@ -163,12 +163,39 @@ void QLoggingSettingsParser::setContent(QStringView content, char16_t separator)
|
163 | 163 | \internal
|
164 | 164 | Parses configuration from \a stream.
|
165 | 165 | */
|
166 |
| -void QLoggingSettingsParser::setContent(QTextStream &stream) |
| 166 | +void QLoggingSettingsParser::setContent(FILE *stream) |
167 | 167 | {
|
168 | 168 | _rules.clear();
|
169 |
| - QString line; |
170 |
| - while (stream.readLineInto(&line)) |
171 |
| - parseNextLine(qToStringViewIgnoringNull(line)); |
| 169 | + |
| 170 | + constexpr size_t ChunkSize = 240; |
| 171 | + QByteArray buffer(ChunkSize, Qt::Uninitialized); |
| 172 | + auto readline = [&](FILE *stream) { |
| 173 | + // Read one line into the buffer |
| 174 | + |
| 175 | + // fgets() always writes the terminating null into the buffer, so we'll |
| 176 | + // allow it to write to the QByteArray's null (thus the off by 1). |
| 177 | + char *s = fgets(buffer.begin(), buffer.size() + 1, stream); |
| 178 | + if (!s) |
| 179 | + return QByteArrayView{}; |
| 180 | + |
| 181 | + qsizetype len = strlen(s); |
| 182 | + while (len == buffer.size()) { |
| 183 | + // need to grow the buffer |
| 184 | + buffer.resizeForOverwrite(buffer.size() + ChunkSize); |
| 185 | + s = fgets(buffer.end() - ChunkSize, ChunkSize + 1, stream); |
| 186 | + if (!s) |
| 187 | + break; |
| 188 | + len += strlen(s); |
| 189 | + } |
| 190 | + QByteArrayView result(buffer.constBegin(), len); |
| 191 | + if (result.endsWith('\n')) |
| 192 | + result.chop(1); |
| 193 | + return result; |
| 194 | + }; |
| 195 | + |
| 196 | + QByteArrayView line; |
| 197 | + while (!(line = readline(stream)).isNull()) |
| 198 | + parseNextLine(QString::fromUtf8(line)); |
172 | 199 | }
|
173 | 200 |
|
174 | 201 | /*!
|
@@ -262,19 +289,38 @@ static bool qtLoggingDebug()
|
262 | 289 |
|
263 | 290 | static QList<QLoggingRule> loadRulesFromFile(const QString &filePath)
|
264 | 291 | {
|
| 292 | + Q_ASSERT(!filePath.isEmpty()); |
265 | 293 | if (qtLoggingDebug()) {
|
266 | 294 | debugMsg("Checking \"%s\" for rules",
|
267 | 295 | QDir::toNativeSeparators(filePath).toUtf8().constData());
|
268 | 296 | }
|
269 | 297 |
|
270 |
| - QFile file(filePath); |
271 |
| - if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { |
272 |
| - QTextStream stream(&file); |
| 298 | + // We bypass QFile here because QFile is a QObject. |
| 299 | + if (Q_UNLIKELY(filePath.at(0) == u':')) { |
| 300 | + if (qtLoggingDebug()) { |
| 301 | + warnMsg("Attempted to load config rules from Qt resource path \"%ls\"", |
| 302 | + qUtf16Printable(filePath)); |
| 303 | + } |
| 304 | + return {}; |
| 305 | + } |
| 306 | + |
| 307 | +#ifdef Q_OS_WIN |
| 308 | + // text mode: let the runtime do CRLF translation |
| 309 | + FILE *f = _wfopen(reinterpret_cast<const wchar_t *>(filePath.constBegin()), L"rtN"); |
| 310 | +#else |
| 311 | + FILE *f = QT_FOPEN(QFile::encodeName(filePath).constBegin(), "re"); |
| 312 | +#endif |
| 313 | + if (f) { |
273 | 314 | QLoggingSettingsParser parser;
|
274 |
| - parser.setContent(stream); |
| 315 | + parser.setContent(f); |
| 316 | + fclose(f); |
275 | 317 | if (qtLoggingDebug())
|
276 |
| - debugMsg("Loaded %td rules", static_cast<ptrdiff_t>(parser.rules().size())); |
| 318 | + debugMsg("Loaded %td rules from \"%ls\"", static_cast<ptrdiff_t>(parser.rules().size()), |
| 319 | + qUtf16Printable(filePath)); |
277 | 320 | return parser.rules();
|
| 321 | + } else if (int err = errno; err != ENOENT) { |
| 322 | + warnMsg("Failed to load file \"%ls\": %ls", qUtf16Printable(filePath), |
| 323 | + qUtf16Printable(qt_error_string(err))); |
278 | 324 | }
|
279 | 325 | return QList<QLoggingRule>();
|
280 | 326 | }
|
|
0 commit comments