Skip to content

Commit e307746

Browse files
QLoggingRegistry: replace QTextStream and QFile with <stdio.h>
This is to avoid the need to use QFile (which is a QObject) in this early code, especially since QObject itself may use category-logging. Task-number: QTBUG-135326 Change-Id: Idc05974d06c2c0a973f6fffdadcc0ecbf76c5cbc Reviewed-by: Kai Köhne <[email protected]> Reviewed-by: Edward Welbourne <[email protected]>
1 parent b99671c commit e307746

File tree

2 files changed

+58
-12
lines changed

2 files changed

+58
-12
lines changed

src/corelib/io/qloggingregistry.cpp

+57-11
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
#include <QtCore/qfile.h>
77
#include <QtCore/qlibraryinfo.h>
88
#include <QtCore/private/qlocking_p.h>
9+
#include <QtCore/qscopedvaluerollback.h>
910
#include <QtCore/qstandardpaths.h>
1011
#include <QtCore/qstringtokenizer.h>
11-
#include <QtCore/qtextstream.h>
1212
#include <QtCore/qdir.h>
1313
#include <QtCore/qcoreapplication.h>
14-
#include <QtCore/qscopedvaluerollback.h>
14+
#include <qplatformdefs.h>
1515

1616
#if QT_CONFIG(settings)
1717
#include <QtCore/qsettings.h>
@@ -163,12 +163,39 @@ void QLoggingSettingsParser::setContent(QStringView content, char16_t separator)
163163
\internal
164164
Parses configuration from \a stream.
165165
*/
166-
void QLoggingSettingsParser::setContent(QTextStream &stream)
166+
void QLoggingSettingsParser::setContent(FILE *stream)
167167
{
168168
_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));
172199
}
173200

174201
/*!
@@ -262,19 +289,38 @@ static bool qtLoggingDebug()
262289

263290
static QList<QLoggingRule> loadRulesFromFile(const QString &filePath)
264291
{
292+
Q_ASSERT(!filePath.isEmpty());
265293
if (qtLoggingDebug()) {
266294
debugMsg("Checking \"%s\" for rules",
267295
QDir::toNativeSeparators(filePath).toUtf8().constData());
268296
}
269297

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) {
273314
QLoggingSettingsParser parser;
274-
parser.setContent(stream);
315+
parser.setContent(f);
316+
fclose(f);
275317
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));
277320
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)));
278324
}
279325
return QList<QLoggingRule>();
280326
}

src/corelib/io/qloggingregistry_p.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ class Q_AUTOTEST_EXPORT QLoggingSettingsParser
8282
void setImplicitRulesSection(bool inRulesSection) { m_inRulesSection = inRulesSection; }
8383

8484
void setContent(QStringView content, char16_t separator = u'\n');
85-
void setContent(QTextStream &stream);
85+
void setContent(FILE *stream);
8686

8787
QList<QLoggingRule> rules() const { return _rules; }
8888

0 commit comments

Comments
 (0)