8#include "private/qcoreapplication_p.h"
9#include "private/qduplicatetracker_p.h"
10#include "private/qloggingregistry_p.h"
11#include "private/qobject_p.h"
30#include <qtcore_tracepoints_p.h>
50 InvalidMetaDataVersion = -2,
51 InvalidTopLevelItem = -3,
52 InvalidHeaderItem = -4,
61struct QFactoryLoaderIidSearch
64 bool matchesIid =
false;
72 return IterationResult::ContinueSearch;
79 matchesIid = (
reader.readAllString() == iid);
80 return IterationResult::FinishedSearch;
88struct QFactoryLoaderMetaDataKeysExtractor : QFactoryLoaderIidSearch
92 : QFactoryLoaderIidSearch(iid)
98 QFactoryLoaderIidSearch::operator()(
key, reader);
99 return IterationResult::ContinueSearch;
105 return IterationResult::FinishedSearch;
107 return IterationResult::InvalidHeaderItem;
108 if (!
reader.enterContainer())
109 return IterationResult::ParsingError;
110 while (
reader.isValid()) {
115 return IterationResult::InvalidHeaderItem;
116 keys = QCborValue::fromCbor(reader).toArray();
122 return IterationResult::FinishedSearch;
124 using QFactoryLoaderIidSearch::operator();
134 return IterationResult::InvalidMetaDataVersion;
137 raw = raw.sliced(
sizeof(
header));
140 if (reader.isInvalid())
141 return reader.lastError();
143 return IterationResult::InvalidTopLevelItem;
144 if (!reader.enterContainer())
145 return reader.lastError();
146 while (reader.isValid()) {
147 IterationResult::Result
r;
148 if (reader.isInteger()) {
153 return IterationResult::InvalidHeaderItem;
155 return reader.lastError();
157 }
else if (reader.isString()) {
160 return reader.lastError();
163 return IterationResult::InvalidTopLevelItem;
168 if (
r != IterationResult::ContinueSearch)
172 if (!reader.leaveContainer())
173 return reader.lastError();
174 return IterationResult::FinishedSearch;
179 QFactoryLoaderIidSearch search(iid);
181 return search.matchesIid;
189 if (
item.isInvalid())
190 return IterationResult::ParsingError;
191 if constexpr (std::is_enum_v<std::decay_t<
decltype(
key)>>)
195 return IterationResult::ContinueSearch;
199 case IterationResult::FinishedSearch:
200 case IterationResult::ContinueSearch:
204 case IterationResult::ParsingError:
205 return setError(QFactoryLoader::tr(
"Metadata parsing error: %1").
arg(
r.error.toString()));
206 case IterationResult::InvalidMetaDataVersion:
207 return setError(QFactoryLoader::tr(
"Invalid metadata version"));
208 case IterationResult::InvalidTopLevelItem:
209 case IterationResult::InvalidHeaderItem:
210 return setError(QFactoryLoader::tr(
"Unexpected metadata contents"));
214 auto header = qFromUnaligned<QPluginMetaData::Header>(raw.data());
216 DecodedArchRequirements archReq =
217 header.version == 0 ? decodeVersion0ArchRequirements(
header.plugin_arch_requirements)
218 : decodeVersion1ArchRequirements(
header.plugin_arch_requirements);
234 for (
auto it :
data.toMap()) {
236 if (
it.first.isInteger()) {
237 switch (
it.first.toInteger()) {
238#define CONVERT_TO_STRING(IntKey, StringKey, Description) \
239 case int(IntKey): key = QStringLiteral(StringKey); break;
243 key =
it.first.toString();
247 o.insert(
key,
it.second.toJsonValue());
259#if QT_CONFIG(library)
262 QDuplicateTracker<QString> loadedPaths;
263 std::vector<QLibraryPrivate::UniquePtr> libraries;
264 std::map<QString, QLibraryPrivate*>
keyMap;
269 void updateSinglePath(
const QString &pluginDir);
273#if QT_CONFIG(library)
276 "qt.core.plugin.factoryloader")
279struct QFactoryLoaderGlobals
284 QList<QFactoryLoader *> loaders;
290QFactoryLoaderPrivate::~QFactoryLoaderPrivate()
293inline void QFactoryLoaderPrivate::updateSinglePath(
const QString &
path)
295 struct LibraryReleaser {
297 {
if (library) library->
release(); }
301 if (loadedPaths.hasSeen(
path))
304 qCDebug(lcFactoryLoader) <<
"checking directory path" <<
path <<
"...";
309#elif defined(Q_OS_ANDROID)
314 for (
const auto &dirEntry : plugins) {
318 const bool isDebugLibrary =
327 if (isDebugPlugin != isDebugLibrary)
329#elif defined(Q_PROCESSOR_X86)
341 if (!library->isPlugin()) {
348 bool metaDataOk =
false;
355 const QCborArray k =
object.value(
"Keys"_L1).toArray();
359 qCDebug(lcFactoryLoader) <<
"Got keys from plugin meta data" <<
keys;
364 int keyUsageCount = 0;
370 constexpr int QtVersionNoPatch =
QT_VERSION_CHECK(QT_VERSION_MAJOR, QT_VERSION_MINOR, 0);
372 int prev_qt_version = 0;
376 if (!previous || (prev_qt_version > QtVersionNoPatch && qt_version <= QtVersionNoPatch)) {
377 previous = library.get();
381 if (keyUsageCount ||
keys.isEmpty()) {
384 libraries.push_back(std::move(library));
389void QFactoryLoader::update()
402 d->updateSinglePath(
path);
404 if (!
d->extraSearchPath.isEmpty())
405 d->updateSinglePath(
d->extraSearchPath);
408 qCDebug(lcFactoryLoader) <<
"ignoring" <<
d->iid
409 <<
"since plugins are disabled in static builds";
413QFactoryLoader::~QFactoryLoader()
415 if (!qt_factoryloader_global.isDestroyed()) {
417 qt_factoryloader_global->loaders.removeOne(
this);
421#if defined(Q_OS_UNIX) && !defined (Q_OS_DARWIN)
432void QFactoryLoader::refreshAll()
434 if (qt_factoryloader_global.exists()) {
449 "For historical reasons, the suffix must start with '/' (and it can't be empty)");
454#if QT_CONFIG(library)
458 if (!
d->suffix.isEmpty() &&
d->suffix.at(0) == u
'/')
464 qt_factoryloader_global->loaders.append(
this);
473#if QT_CONFIG(library)
475 if (
d->extraSearchPath ==
path)
479 QString oldPath = std::exchange(
d->extraSearchPath,
path);
480 if (oldPath.isEmpty()) {
482 d->updateSinglePath(
d->extraSearchPath);
485 d->loadedPaths.clear();
486 d->libraries.clear();
498 QList<QPluginParsedMetaData>
metaData;
499#if QT_CONFIG(library)
501 for (
const auto &library :
d->libraries)
508 QByteArrayView pluginData(
static_cast<const char *
>(plugin.rawMetaData), plugin.rawMetaDataSize);
524#if QT_CONFIG(library)
526 for (
const auto &library :
d->libraries) {
528 metaData.append(md[
"Keys"_L1].toArray());
535 QByteArrayView pluginData(
static_cast<const char *
>(plugin.rawMetaData),
536 plugin.rawMetaDataSize);
537 QFactoryLoaderMetaDataKeysExtractor
extractor{ iid };
554#if QT_CONFIG(library)
556 if (
size_t(
index) <
d->libraries.size()) {
566 index -=
static_cast<int>(
d->libraries.size());
573 QByteArrayView pluginData(
static_cast<const char *
>(plugin.rawMetaData), plugin.rawMetaDataSize);
578 return plugin.instance();
587 QMultiMap<int, QString>
result;
589 for (
int i = 0;
i < int(metaDataList.size()); ++
i) {
600 for (
int i = 0;
i < int(metaDataList.size()); ++
i) {
612#include "moc_qfactoryloader_p.cpp"
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
qint64 toInteger(qint64 defaultValue=0) const
Returns the integer value stored in this QCborValue, if it is of the integer type.
static QThread * mainThread()
The QDirListing class provides an STL-style iterator for directory entries.
void setExtraSearchPath(const QString &path)
int indexOf(const QString &needle) const
QMultiMap< int, QString > keyMap() const
QList< QPluginParsedMetaData > MetaDataList
QFactoryLoader(const char *iid, const QString &suffix=QString(), Qt::CaseSensitivity=Qt::CaseSensitive)
MetaDataList metaData() const
QList< QCborArray > metaDataKeys() const
QObject * instance(int index) const
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
QPluginParsedMetaData metaData
std::unique_ptr< QLibraryPrivate, Deleter > UniquePtr
QObject * pluginInstance()
static QLibraryPrivate * findOrCreate(const QString &fileName, const QString &version=QString(), QLibrary::LoadHints loadHints={ })
bool moveToThread(QThread *thread QT6_DECL_NEW_OVERLOAD_TAIL)
Changes the thread affinity for this object and its children and returns true on success.
static QList< QStaticPlugin > staticPlugins()
Returns a list of QStaticPlugins held by the plugin loader.
const_iterator cend() const noexcept
iterator find(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
QMap< QString, QString > map
[6]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
QTextStream & endl(QTextStream &stream)
Writes '\n' to the stream and flushes the stream.
QImageReader reader("image.png")
[1]
QList< QString > QStringList
Constructs a string list that contains the given string, str.
DBusConnection const char DBusError * error
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static bool isIidMatch(QByteArrayView raw, QLatin1StringView iid)
#define CONVERT_TO_STRING(IntKey, StringKey, Description)
static IterationResult iterateInPluginMetaData(QByteArrayView raw, F &&f)
#define Q_GLOBAL_STATIC(TYPE, NAME,...)
#define qCDebug(category,...)
#define Q_LOGGING_CATEGORY_WITH_ENV_OVERRIDE(name, env, categoryName)
GLsizei const GLfloat * v
[13]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei const GLuint * paths
GLsizei const GLchar *const * path
#define QT_PLUGIN_FOREACH_METADATA(F)
#define Q_ASSERT_X(cond, x, msg)
QBasicUtf8StringView< false > QUtf8StringView
#define QStringLiteral(str)
#define Q_TRACE_POINT(provider, tracepoint,...)
#define QT_VERSION_CHECK(major, minor, patch)
static const struct @450 keyMap[]
char * toString(const MyType &t)
[31]
\inmodule QtCore \inheaderfile QtCborCommon \reentrant