Files
qt-creator/src/libs/utils/json.h

419 lines
11 KiB
C
Raw Normal View History

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "utils_global.h"
#include <QHash>
#include <QVector>
#include <QStringList>
#include <QDateTime>
QT_FORWARD_DECLARE_CLASS(QVariant)
namespace Utils {
class JsonStringValue;
class JsonDoubleValue;
class JsonIntValue;
class JsonObjectValue;
class JsonArrayValue;
class JsonBooleanValue;
class JsonNullValue;
class QTCREATOR_UTILS_EXPORT JsonMemoryPool
{
public:
~JsonMemoryPool();
inline void *allocate(size_t size)
{
char *obj = new char[size];
_objs.append(obj);
return obj;
}
private:
QVector<char *> _objs;
};
/*!
* \brief The JsonValue class
*/
class QTCREATOR_UTILS_EXPORT JsonValue
{
public:
enum Kind {
String,
Double,
Int,
Object,
Array,
Boolean,
Null,
Unknown
};
virtual ~JsonValue();
Kind kind() const { return m_kind; }
static QString kindToString(Kind kind);
virtual JsonStringValue *toString() { return nullptr; }
virtual JsonDoubleValue *toDouble() { return nullptr; }
virtual JsonIntValue *toInt() { return nullptr; }
virtual JsonObjectValue *toObject() { return nullptr; }
virtual JsonArrayValue *toArray() { return nullptr; }
virtual JsonBooleanValue *toBoolean() { return nullptr; }
virtual JsonNullValue *toNull() { return nullptr; }
static JsonValue *create(const QString &s, JsonMemoryPool *pool);
void *operator new(size_t size, JsonMemoryPool *pool);
void operator delete(void *);
void operator delete(void *, JsonMemoryPool *);
protected:
JsonValue(Kind kind);
private:
static JsonValue *build(const QVariant &varixant, JsonMemoryPool *pool);
Kind m_kind;
};
/*!
* \brief The JsonStringValue class
*/
class QTCREATOR_UTILS_EXPORT JsonStringValue : public JsonValue
{
public:
JsonStringValue(const QString &value)
: JsonValue(String)
, m_value(value)
{}
JsonStringValue *toString() override { return this; }
const QString &value() const { return m_value; }
private:
QString m_value;
};
/*!
* \brief The JsonDoubleValue class
*/
class QTCREATOR_UTILS_EXPORT JsonDoubleValue : public JsonValue
{
public:
JsonDoubleValue(double value)
: JsonValue(Double)
, m_value(value)
{}
JsonDoubleValue *toDouble() override { return this; }
double value() const { return m_value; }
private:
double m_value;
};
/*!
* \brief The JsonIntValue class
*/
class QTCREATOR_UTILS_EXPORT JsonIntValue : public JsonValue
{
public:
JsonIntValue(int value)
: JsonValue(Int)
, m_value(value)
{}
JsonIntValue *toInt() override { return this; }
int value() const { return m_value; }
private:
int m_value;
};
/*!
* \brief The JsonObjectValue class
*/
class QTCREATOR_UTILS_EXPORT JsonObjectValue : public JsonValue
{
public:
JsonObjectValue()
: JsonValue(Object)
{}
JsonObjectValue *toObject() override { return this; }
void addMember(const QString &name, JsonValue *value) { m_members.insert(name, value); }
bool hasMember(const QString &name) const { return m_members.contains(name); }
JsonValue *member(const QString &name) const { return m_members.value(name); }
QHash<QString, JsonValue *> members() const { return m_members; }
bool isEmpty() const { return m_members.isEmpty(); }
protected:
JsonObjectValue(Kind kind)
: JsonValue(kind)
{}
private:
QHash<QString, JsonValue *> m_members;
};
/*!
* \brief The JsonArrayValue class
*/
class QTCREATOR_UTILS_EXPORT JsonArrayValue : public JsonValue
{
public:
JsonArrayValue()
: JsonValue(Array)
{}
JsonArrayValue *toArray() override { return this; }
void addElement(JsonValue *value) { m_elements.append(value); }
QList<JsonValue *> elements() const { return m_elements; }
int size() const { return m_elements.size(); }
private:
QList<JsonValue *> m_elements;
};
/*!
* \brief The JsonBooleanValue class
*/
class QTCREATOR_UTILS_EXPORT JsonBooleanValue : public JsonValue
{
public:
JsonBooleanValue(bool value)
: JsonValue(Boolean)
, m_value(value)
{}
JsonBooleanValue *toBoolean() override { return this; }
bool value() const { return m_value; }
private:
bool m_value;
};
class QTCREATOR_UTILS_EXPORT JsonNullValue : public JsonValue
{
public:
JsonNullValue()
: JsonValue(Null)
{}
JsonNullValue *toNull() override { return this; }
};
class JsonSchemaManager;
/*!
* \brief The JsonSchema class
*
* [NOTE: This is an incomplete implementation and a work in progress.]
*
* This class provides an interface for traversing and evaluating a JSON schema, as described
* in the draft http://tools.ietf.org/html/draft-zyp-json-schema-03.
*
* JSON schemas are recursive in concept. This means that a particular attribute from a schema
* might be also another schema. Therefore, the basic working principle of this API is that
* from within some schema, one can investigate its attributes and if necessary "enter" a
* corresponding nested schema. Afterwards, it's expected that one would "leave" such nested
* schema.
*
* All functions assume that the current "context" is a valid schema. Once an instance of this
* class is created the root schema is put on top of the stack.
*
*/
class QTCREATOR_UTILS_EXPORT JsonSchema
{
public:
bool isTypeConstrained() const;
bool acceptsType(const QString &type) const;
QStringList validTypes() const;
// Applicable on schemas of any type.
bool required() const;
bool hasTypeSchema() const;
void enterNestedTypeSchema();
bool hasUnionSchema() const;
int unionSchemaSize() const;
bool maybeEnterNestedUnionSchema(int index);
void leaveNestedSchema();
// Applicable on schemas of type number/integer.
bool hasMinimum() const;
bool hasMaximum() const;
bool hasExclusiveMinimum();
bool hasExclusiveMaximum();
double minimum() const;
double maximum() const;
// Applicable on schemas of type string.
QString pattern() const;
int minimumLength() const;
int maximumLength() const;
// Applicable on schemas of type object.
QStringList properties() const;
bool hasPropertySchema(const QString &property) const;
void enterNestedPropertySchema(const QString &property);
// Applicable on schemas of type array.
bool hasAdditionalItems() const;
bool hasItemSchema() const;
void enterNestedItemSchema();
bool hasItemArraySchema() const;
int itemArraySchemaSize() const;
bool maybeEnterNestedArraySchema(int index);
private:
friend class JsonSchemaManager;
JsonSchema(JsonObjectValue *rootObject, const JsonSchemaManager *manager);
Q_DISABLE_COPY(JsonSchema)
enum EvaluationMode {
Normal,
Array,
Union
};
void enter(JsonObjectValue *ov, EvaluationMode eval = Normal, int index = -1);
bool maybeEnter(JsonValue *v, EvaluationMode eval, int index);
void evaluate(EvaluationMode eval, int index);
void leave();
JsonObjectValue *resolveReference(JsonObjectValue *ov) const;
JsonObjectValue *resolveBase(JsonObjectValue *ov) const;
JsonObjectValue *currentValue() const;
int currentIndex() const;
JsonObjectValue *rootValue() const;
static JsonStringValue *getStringValue(const QString &name, JsonObjectValue *value);
static JsonObjectValue *getObjectValue(const QString &name, JsonObjectValue *value);
static JsonBooleanValue *getBooleanValue(const QString &name, JsonObjectValue *value);
static JsonArrayValue *getArrayValue(const QString &name, JsonObjectValue *value);
static JsonDoubleValue *getDoubleValue(const QString &name, JsonObjectValue *value);
static QStringList validTypes(JsonObjectValue *v);
static bool typeMatches(const QString &expected, const QString &actual);
static bool isCheckableType(const QString &s);
QStringList properties(JsonObjectValue *v) const;
JsonObjectValue *propertySchema(const QString &property, JsonObjectValue *v) const;
// TODO: Similar functions for other attributes which require looking into base schemas.
static bool maybeSchemaName(const QString &s);
static QString kType();
static QString kProperties();
static QString kPatternProperties();
static QString kAdditionalProperties();
static QString kItems();
static QString kAdditionalItems();
static QString kRequired();
static QString kDependencies();
static QString kMinimum();
static QString kMaximum();
static QString kExclusiveMinimum();
static QString kExclusiveMaximum();
static QString kMinItems();
static QString kMaxItems();
static QString kUniqueItems();
static QString kPattern();
static QString kMinLength();
static QString kMaxLength();
static QString kTitle();
static QString kDescription();
static QString kExtends();
static QString kRef();
struct Context
{
JsonObjectValue *m_value;
EvaluationMode m_eval;
int m_index;
};
QVector<Context> m_schemas;
const JsonSchemaManager *m_manager;
};
/*!
* \brief The JsonSchemaManager class
*/
class QTCREATOR_UTILS_EXPORT JsonSchemaManager
{
public:
JsonSchemaManager(const QStringList &searchPaths);
~JsonSchemaManager();
JsonSchema *schemaForFile(const QString &fileName) const;
JsonSchema *schemaByName(const QString &baseName) const;
private:
struct JsonSchemaData
{
JsonSchemaData(const QString &absoluteFileName, JsonSchema *schema = nullptr)
: m_absoluteFileName(absoluteFileName)
, m_schema(schema)
{}
QString m_absoluteFileName;
JsonSchema *m_schema;
QDateTime m_lastParseAttempt;
};
JsonSchema *parseSchema(const QString &schemaFileName) const;
QStringList m_searchPaths;
mutable QHash<QString, JsonSchemaData> m_schemas;
mutable JsonMemoryPool m_pool;
};
} // namespace Utils