forked from qt-creator/qt-creator
Add JSON parsing support to qmake.
Add qjson* implementation files from corelib/json to the qmake build. Add a read-only compile mode, enabled by defining QT_JSON_READONLY. Add qmake built-in function parseJson(file, into) which parses a json file into the given variable. qmake uses a flat key -> value-list implementation for storing variables, which means that some hackery is need to represent arbitrarily nested JSON. Use a special "_KEYS_" variable for arrays and objects: Arrays: ["item1", "item2"] $${array._KEYS_} -> 0 1 2 $${array.0} -> "item1" $${array.1} -> "item2" Objects: { "key1" : "value1", "key2" : "value2" } $${object._KEYS_} -> key1 key2 $${object.key1} -> value1 $${object.key2} -> value2 Change-Id: I0aa2e4e4ae14fa25be8242bc16d3cffce32504d2 Reviewed-by: Lars Knoll <lars.knoll@digia.com> (cherry picked from qtbase/89ef515177fd5a0b5d95dcffd5fd0b0669e3625a) Reviewed-by: Daniel Teske <daniel.teske@digia.com> Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
This commit is contained in:
committed by
Oswald Buddenhagen
parent
38b530953f
commit
2ee6fbbd74
@@ -44,6 +44,11 @@
|
||||
#include <qset.h>
|
||||
#include <qstringlist.h>
|
||||
#include <qtextstream.h>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
# include <qjsondocument.h>
|
||||
# include <qjsonobject.h>
|
||||
# include <qjsonarray.h>
|
||||
#endif
|
||||
#ifdef PROEVALUATOR_THREAD_SAFE
|
||||
# include <qthreadpool.h>
|
||||
#endif
|
||||
@@ -89,7 +94,7 @@ enum TestFunc {
|
||||
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
|
||||
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
|
||||
T_DEFINED, T_CONTAINS, T_INFILE,
|
||||
T_COUNT, T_ISEMPTY, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
||||
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
|
||||
T_MKPATH, T_WRITE_FILE, T_TOUCH, T_CACHE
|
||||
};
|
||||
|
||||
@@ -166,6 +171,9 @@ void QMakeEvaluator::initFunctionStatics()
|
||||
{ "infile", T_INFILE },
|
||||
{ "count", T_COUNT },
|
||||
{ "isEmpty", T_ISEMPTY },
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
{ "parseJson", T_PARSE_JSON },
|
||||
#endif
|
||||
{ "load", T_LOAD },
|
||||
{ "include", T_INCLUDE },
|
||||
{ "debug", T_DEBUG },
|
||||
@@ -274,6 +282,75 @@ quoteValue(const ProString &val)
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map);
|
||||
|
||||
static void insertJsonKeyValue(const QString &key, const QStringList &values, ProValueMap *map)
|
||||
{
|
||||
map->insert(ProKey(key), ProStringList(values));
|
||||
}
|
||||
|
||||
static void addJsonArray(const QJsonArray &array, const QString &keyPrefix, ProValueMap *map)
|
||||
{
|
||||
QStringList keys;
|
||||
for (int i = 0; i < array.count(); ++i) {
|
||||
keys.append(QString::number(i));
|
||||
addJsonValue(array.at(i), keyPrefix + QString::number(i), map);
|
||||
}
|
||||
insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), keys, map);
|
||||
}
|
||||
|
||||
static void addJsonObject(const QJsonObject &object, const QString &keyPrefix, ProValueMap *map)
|
||||
{
|
||||
foreach (const QString &key, object.keys())
|
||||
addJsonValue(object.value(key), keyPrefix + key, map);
|
||||
|
||||
insertJsonKeyValue(keyPrefix + QLatin1String("_KEYS_"), object.keys(), map);
|
||||
}
|
||||
|
||||
static void addJsonValue(const QJsonValue &value, const QString &keyPrefix, ProValueMap *map)
|
||||
{
|
||||
switch (value.type()) {
|
||||
case QJsonValue::Bool:
|
||||
insertJsonKeyValue(keyPrefix, QStringList() << (value.toBool() ? QLatin1String("true") : QLatin1String("false")), map);
|
||||
break;
|
||||
case QJsonValue::Double:
|
||||
insertJsonKeyValue(keyPrefix, QStringList() << QString::number(value.toDouble()), map);
|
||||
break;
|
||||
case QJsonValue::String:
|
||||
insertJsonKeyValue(keyPrefix, QStringList() << value.toString(), map);
|
||||
break;
|
||||
case QJsonValue::Array:
|
||||
addJsonArray(value.toArray(), keyPrefix + QLatin1Char('.'), map);
|
||||
break;
|
||||
case QJsonValue::Object:
|
||||
addJsonObject(value.toObject(), keyPrefix + QLatin1Char('.'), map);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static QMakeEvaluator::VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value)
|
||||
{
|
||||
QJsonDocument document = QJsonDocument::fromJson(json);
|
||||
if (document.isNull())
|
||||
return QMakeEvaluator::ReturnFalse;
|
||||
|
||||
QString currentKey = into + QLatin1Char('.');
|
||||
|
||||
// top-level item is either an array or object
|
||||
if (document.isArray())
|
||||
addJsonArray(document.array(), currentKey, value);
|
||||
else if (document.isObject())
|
||||
addJsonObject(document.object(), currentKey, value);
|
||||
else
|
||||
return QMakeEvaluator::ReturnFalse;
|
||||
|
||||
return QMakeEvaluator::ReturnTrue;
|
||||
}
|
||||
#endif
|
||||
|
||||
QMakeEvaluator::VisitReturn
|
||||
QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode,
|
||||
const QString &contents)
|
||||
@@ -1266,6 +1343,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|
||||
m_valuemapStack.top()[var] = statics.fakeValue;
|
||||
return ReturnTrue;
|
||||
}
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
|
||||
case T_PARSE_JSON: {
|
||||
if (args.count() != 2) {
|
||||
evalError(fL1S("parseJson(variable, into) requires two arguments."));
|
||||
return ReturnFalse;
|
||||
}
|
||||
|
||||
QByteArray json = values(args.at(0).toKey()).join(QLatin1Char(' ')).toUtf8();
|
||||
QString parseInto = args.at(1).toQString(m_tmp2);
|
||||
return parseJsonInto(json, parseInto, &m_valuemapStack.top());
|
||||
}
|
||||
#endif
|
||||
case T_INCLUDE: {
|
||||
if (args.count() < 1 || args.count() > 3) {
|
||||
evalError(fL1S("include(file, [into, [silent]]) requires one, two or three arguments."));
|
||||
|
Reference in New Issue
Block a user